๐ช Cookies implementation for Meteor.js in Server, Client, Browser, Cordova, Desktop and other environments
๊ฐ์
![Meteor.js][meteor-url] ![Release][release-url] ![CI][ci-url]  ![License: BSD-3-Clause][license-url] ![TypeScript][ts-url] ![zero dependencies][meteor-url] ![Last commit][commits-url] ![OpenSSF Scorecard][scorecard-url] ![Sponsor][sponsor-url] ![Donate][donate-url] Isomorphic and bulletproof ๐ช cookie management for Meteor applications with support for Client, Server, Browser, Cordova, Meteor-Desktop, and other Meteor environments. - ๐จโ๐ป Stable codebase - ๐ 400,000+ downloads - ๐จโ๐ฌ TDD with Tinytest, CI fails below 95% coverage (npm run test:coverage) - ๐ฆ No external dependencies (no underscore, jQuery, or Blaze) - ๐ฅ Consistent API across Server and Client environments - ๐ฑ Compatible with Cordova, Browser, Meteor-Desktop, and other client platforms - ใ๏ธ Full Unicode support for cookie values - ๐จโ๐ป Supports String, Number, Array, Object, Boolean, and null as cookie value types - โฟ IE support, thanks to @derwok - ๐ฆ Shipped with TypeScript types -...
README
Cookies for Meteor
Isomorphic and bulletproof ๐ช cookie management for Meteor applications with support for Client, Server, Browser, Cordova, Meteor-Desktop, and other Meteor environments.
- ๐จโ๐ป Stable codebase
- ๐ 400,000+ downloads
- ๐จโ๐ฌ TDD with Tinytest, CI fails below 95% coverage (
npm run test:coverage) - ๐ฆ No external dependencies (no
underscore,jQuery, orBlaze) - ๐ฅ Consistent API across Server and Client environments
- ๐ฑ Compatible with Cordova, Browser, Meteor-Desktop, and other client platforms
- ใ๏ธ Full Unicode support for cookie values
- ๐จโ๐ป Supports
String,Number,Array,Object,Boolean, andnullas cookie value types - โฟ IE support, thanks to @derwok
- ๐ฆ Shipped with TypeScript types
- ๐ค Shipped with an AI agent skill for Claude Code, Codex, Cursor, and other coding agents
- ๐ฆ Looking for persistent Client (Browser) storage? Try the
ClientStoragepackage.
ToC:
- Installation
- Import
- AI agent skill
- FAQ
- API
new Cookies()constructor โ Create a newCookiesinstance.get()โ Read a cookie.set()โ Set a cookie.remove()โ Remove one or all cookies.has()โ Check if a cookie exists.keys()โ List all cookie keys.send()โ Sync cookies with the server.sendAsync()โ Sync cookies asynchronously.middleware()โ Register cookie middleware manually.destroy()โ Unregister hooks, callbacks, and middlewarenew CookiesCore()constructor โ Low-level class that can be used to directly parse and manage cookies
- Examples
- Running Tests
- Security
- Support our open source contributions
Installation
meteor add ostrio:cookies
Upgrading from v2? See docs/migration-v3.md
ES6 Import
import { Cookies } from 'meteor/ostrio:cookies';
AI agent skill
The ostrio-cookies skill gives a coding agent the API, the common client and server mistakes, the Cordova setup, and the migration notes for the package version in your app. It follows the Agent Skills format.
Run in the root of your Meteor app:
npx skills add veliovgroup/Meteor-Cookies --skill ostrio-cookies
Or copy the file without extra tools:
mkdir -p .agents/skills/ostrio-cookies
curl -fsSL https://raw.githubusercontent.com/veliovgroup/Meteor-Cookies/master/.agents/skills/ostrio-cookies/SKILL.md -o .agents/skills/ostrio-cookies/SKILL.md
Claude Code reads skills from .claude/skills/. For a manual copy, use that directory instead of .agents/skills/.
FAQ
- Cordova and Meteor-Desktop: Server-set cookies work out of the box. To send cookies from Client to Server, set
{ allowQueryStringCookies: true, allowedCordovaOrigins: true }on both Client and Server. See docs/cordova.md - Cookies missing on Server? Call
new Cookies()before registering routes, and placeostrio:cookiesabove community packages in.meteor/packages. See docs/server.md
API
[!NOTE] On the Server,
new Cookies()registers one middleware that setsreq.Cookies, aCookiesCoreinstance.req.Cookies.set()adds aSet-Cookieheader to the current response. A Client instance sees the new cookie after a page reload or aftersend()/sendAsync()resolvesMany
new Cookies()instances share that one middleware. See docs/server.md
new Cookies() Constructor
Create a new instance of Cookies (available on both Client and Server).
Arguments:
opts{CookiesOptions} - Config object
Available CookiesOptions:
opts.auto{boolean} โ [Server] Auto-bind asreq.Cookies(default:true)opts.handler{function} โ [Server] Custom middleware handler; receives aCookiesCoreinstanceopts.onCookies{function} โ [Server] Callback triggered after.send()or.sendAsync()is called and the cookies are received by the server. Runs only in the auto-registered middleware, not in a manual.middleware()opts.TTL{number | boolean} โ Default expiration time (max-age) in milliseconds. Set tofalsefor session cookiesopts.runOnServer{boolean} โ Set tofalseto disable server usage (default:true)opts.allowQueryStringCookies{boolean} โ Allow passing cookies via query string (primarily for Cordova)opts.allowedCordovaOrigins{RegExp | boolean} โ [Server] Allow setting cookies from specific origins (defaults to^http:\/\/localhost:12[0-9]{3}$iftrue)opts.name{string} - Sets.NAMEproperty of Cookies & CookiesCore instances, use it for instance identification, defaultCOOKIES
Example:
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies({
TTL: 31557600000 // One year TTL
});
.get()
(Anywhere) Read a cookie. Returns undefined if the cookie is not found
Arguments:
key{string} โ The name of the cookie.
cookies.get('age'); // undefined if not found
cookies.set('age', 25); // returns true
cookies.get('age'); // returns 25
Cookies store text. After a page reload, and on the Server, a number comes back as a string ('25'). true, false, null, objects, and arrays keep their type.
.set()
(Anywhere) Create or update a cookie
Arguments:
key{string} โ The cookie namevalue{string | number | boolean | null | object | array} โ The cookie valueopts{CookieOptions} โ Optional settings
Supported CookieOptions:
opts.expires{number | Date | Infinity}: Cookie expiration as aDateor a timestamp in milliseconds.0creates a session cookie and overridesTTLopts.maxAge{number}: Maximum age in secondsopts.path{string}: Cookie path (default:/)opts.domain{string}: Cookie domainopts.secure{boolean}: Transmit only over HTTPSopts.httpOnly{boolean}: Inaccessible to client-side JavaScriptopts.sameSite{boolean | โNoneโ | โStrictโ | โLaxโ}: Cross-site cookie policyopts.partitioned{boolean}: SpecifiesPartitionedattribute inSet-Cookieheader. When enabled, clients will only send the cookie back when the current domain and top-level domain matchesopts.priority{โLowโ | โMediumโ | โHighโ}: Specifies the value for thePriorityattribute inSet-Cookieheaderopts.firstPartyOnly{boolean}: Deprecated (usesameSiteinstead)
cookies.set('age', 25, {
path: '/',
secure: true
});
.remove()
(Anywhere) Remove cookie(s)
remove()โ Removes all cookies on the current domain. Only a call without arguments does this;remove('')andremove(null)returnfalseremove(key)โ Removes the specified cookieremove(key, path, domain)โ Removes a cookie with the given key, path, and domain
Arguments:
key{string} - [Optional] The name of the cookie to removepath{string} - [Optional] The path from where the cookie was readable. E.g., โ/โ, โ/mydirโ; if not specified, defaults to/. The path must be absolute (see RFC 2965). For more information on how to use relative paths in this argument, read moredomain{string} - [Optional] The domain from where the cookie was readable. E.g., โexample.comโ, โ.example.comโ (includes all subdomains) or โsubdomain.example.comโ; if not specified, defaults to the host portion of the current document location (string or null)
const isRemoved = cookies.remove(key, path, domain); // boolean
const isRemoved = cookies.remove('age', '/'); // boolean
const isRemoved = cookies.remove(key, '/', 'example.com'); // boolean
.has()
(Anywhere) Check if a cookie exists
Arguments:
key{string} โ The name of the cookie
const hasKey = cookies.has(key); // boolean
const hasKey = cookies.has('age'); // boolean
.keys()
(Anywhere) Returns an array of all cookie names
const cookieKeys = cookies.keys(); // string[] (e.g., ['locale', 'country', 'gender'])
.send()
(Client only) Send all current cookies to the server via fetch and callback. The server runs onCookies hooks, and cookies set by hooks are available on the client when the callback runs. Requires runOnServer: true (default)
Arguments:
callback{function} โ Callback with signature(error, response).
cookies.send((error, response) => {
if (error) {
console.error(error);
} else {
console.log('Cookies synced:', response);
}
});
.sendAsync()
(Client only) Same as .send(), returns a Promise. Rejects with Meteor.Error when runOnServer is false
const response = await cookies.sendAsync();
console.log('Cookies synced:', response);
.middleware()
(Server only) Returns a middleware function to integrate cookies into your serverโs request pipeline.
Usage: Register this middleware with your Meteor server (e.g., via WebApp.connectHandlers.use).
import { WebApp } from 'meteor/webapp';
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies({
auto: false,
handler(cookiesInstance) {
// Custom processing with cookiesInstance (of type CookiesCore)
}
});
WebApp.connectHandlers.use(cookies.middleware());
.destroy()
(Server only) Unregisters hooks, callbacks, and middleware
cookies.isDestroyed // false
cookies.destroy(); // true
cookies.isDestroyed // true
cookies.destroy(); // false โ returns `false` as instance was already destroyed
new CookiesCore() constructor
CookiesCore is low-level constructor that can be used to directly parse and manage cookies
Arguments:
opts{CookiesCoreOptions} โ Optional settings
Supported CookiesCoreOptions:
_cookies{string | CookieDict} - Cookies string fromdocument.cookie,Set-Cookieheader, or{ [key: string]: unknown }ObjectsetCookie{boolean} - Set totruewhen_cookiesoption derives fromSet-Cookieheaderresponse{ServerResponse} - HTTP server response objectTTL{number | false} - Default cookies expiration time (max-age) in milliseconds. If false, the cookie lasts for the sessionrunOnServer{boolean} - Client only. Iftrueโ enablessendandsendAsyncfrom clientallowQueryStringCookies{boolean} - If true, allow passing cookies via query string (used primarily in Cordova)allowedCordovaOrigins{RegExp | boolean} - A regular expression or boolean to allow cookies from specific originsname{string} - Sets.NAMEproperty of CookiesCore instances, use it for instance identification, defaultCOOKIES_CORE
[!NOTE]
CookiesCoreinstance has the same methods asCookiesclass except.destroy()and.middleware()
import { CookiesCore } from 'meteor/ostrio:cookies';
// Parse a Set-Cookie header
const cookies = new CookiesCore({
_cookies: 'session=abc; Path=/; HttpOnly, theme=dark; Path=/',
setCookie: true
});
cookies.get('theme'); // 'dark'
cookies.keys(); // ['session', 'theme']
[!NOTE] An object passed as
_cookiesis kept in memory only. On the Client it isnโt written todocument.cookie, so.send()doesnโt transfer it. Use.set()to store a cookie in the browser
Server usage without middleware: docs/server.md
Examples
Use new Cookies() on Client and Server separately or in the same file
Example: Client Usage
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies();
cookies.set('locale', 'en');
cookies.set('country', 'usa');
cookies.set('gender', 'male');
console.log(cookies.get('gender')); // "male"
console.log(cookies.has('locale')); // true
console.log(cookies.keys()); // ['locale', 'country', 'gender']
cookies.remove('locale');
console.log(cookies.get('locale')); // undefined
Example: Server Usage
import { Cookies } from 'meteor/ostrio:cookies';
import { WebApp } from 'meteor/webapp';
new Cookies();
WebApp.connectHandlers.use((req, res, next) => {
const cookiesInstance = req.Cookies;
cookiesInstance.set('locale', 'en');
cookiesInstance.set('country', 'usa');
cookiesInstance.set('gender', 'male');
console.log(cookiesInstance.get('gender')); // "male"
next();
});
More examples
- Multiple handlers across modules
- Set cookies based on URL
- Manual middleware registration
- Cordova and Meteor-Desktop
Running Tests
- Clone the package repository.
- Open a terminal in the cloned directory.
- Run tests using:
Meteor/Tinytest
# Default, headless Tinytest runner
npm test
# Direct command
mtest --package ./ --port=8888 --once
# Coverage report (text, coverage/index.html, coverage/lcov.info)
npm run test:coverage
# Type definitions
npm run test:types
# Browser fallback
meteor test-packages ./ --once --driver-package test-in-console
On Apple Silicon, the Chromium bundled with mtest is x86-only. Point it to a local Chromium-based browser:
PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" npm test
Security
Report vulnerabilities privately, see SECURITY.md.
Support our open source contributions
- Try ๐ Bridge CDN - A SEO-focused alternative to Cloudflare. CDN, DNS, IndexNow, Prerender, SEO, Edge Computing.
- Upload and share files using โ๏ธ meteor-files.com โ Continue interrupted file uploads without losing any progress. There is nothing that will stop Meteor from delivering your file to the desired destination
- Use โฒ ostr.io for Server Monitoring, Web Analytics, WebSec, Web-CRON and SEO Pre-rendering of a website
- Star on GitHub
- Star on Atmosphere
- Sponsor via GitHub
- Support via PayPal
์ถ์ฒ ๋๊ตฌ
๋ค๋ฅธ ํค์๋๋ฅผ ์ ๋ ฅํ๊ฑฐ๋ ํํฐ๋ฅผ ์ ๊ฑฐํด ๋ณด์ธ์.
์ค์น
npx skillfish add veliovgroup/meteor-cookies