npm.io
2.4.1 • Published 5d ago

cookies-utils

Licence
MIT
Version
2.4.1
Deps
0
Size
98 kB
Vulns
0
Weekly
0
Stars
3

cookies-utils

NPM Version Coverage Build Status OpenSSF Scorecard MIT License

Use the native Cookie Store API on HTTPS pages when it is available, without writing your own document.cookie fallback. cookies-utils provides one typed, promise-based API across both backends, with shared defaults, runtime validation, and documented browser differences.

  • Selects a backend per call and uses document.cookie on non-HTTPS pages with cookie access.
  • Provides asynchronous get, getAll, has, set, and delete methods.
  • Defaults writes to the root path and SameSite=Lax.
  • Validates runtime inputs and reports validation and detectable backend errors as CookieError.
  • Ships ESM, CommonJS, and TypeScript declarations with zero runtime dependencies.

Why cookies-utils?

Choose When it fits
cookies-utils You want one async API, native Cookie Store where available, a document.cookie fallback, and runtime option validation.
js-cookie You want a mature synchronous helper around document.cookie.
Native cookieStore Your supported browsers provide it and you want to use the browser API directly.
document.cookie A synchronous browser interface is sufficient and manual parsing is acceptable.

The detailed comparison below covers the API and behavior each option provides.

Installation

npm install cookies-utils

For a browser script tag, the browser build is available from jsDelivr and unpkg. It exposes a cookiesUtils global.

<script src="https://cdn.jsdelivr.net/npm/cookies-utils/dist/cookies-utils.min.js"></script>
<script>
  cookiesUtils.delete("name").then(() => console.log("gone"));
</script>

Use https://unpkg.com/cookies-utils/dist/cookies-utils.min.js as the script source to load it from unpkg.

Quick start

import { cookies } from "cookies-utils";

await cookies.set("theme", "dark", {
  secure: true,
  sameSite: "lax",
});

const theme = await cookies.get("theme");
await cookies.delete("theme");

The API can also be imported by name:

import { get, set } from "cookies-utils";

await set("theme", "dark");
const theme = await get("theme");

Comparison

Capability cookies-utils js-cookie Native cookieStore document.cookie
API model Promise-based Synchronous Promise-based Synchronous string
Native Cookie Store Uses it when available No Yes No
Legacy fallback Automatic document.cookie fallback Uses document.cookie None N/A
Read same-name cookies getAll(name) returns readable matches No dedicated same-name list method getAll() supports filtering Caller parses the cookie string
Change events Window events when the native API supports them No built-in change event Native Window change events None
Runtime option validation Yes No shared validation contract Browser validates options Browser parses the cookie string
Error contract CookieError for validation and detectable failures No shared CookieError contract Browser errors Writes can fail silently
TypeScript Included declarations Community types through @types/js-cookie DOM types DOM types
Runtime dependencies None None N/A N/A

Cookie behavior still depends on browser capabilities. The library shares an API and defaults across backends, but cannot make browser behavior identical.

API

Method Result Description
cookies.get(name) Promise<string | undefined> Returns one matching value, or undefined.
cookies.getAll(name?) Promise<Cookie[]> Lists readable cookies, optionally filtered by name.
cookies.has(name) Promise<boolean> Reports whether a readable cookie with that name exists.
cookies.set(name, value, options?) Promise<void> Validates and writes a cookie.
cookies.delete(name, options?) Promise<void> Expires a cookie with the requested scope.
cookies.onChange(handler) Unsubscribe function Subscribes to native Window change events when supported.

The named exports behave the same way. The package also exports the Cookie, CookieAttributes, DeleteOptions, CookieChange, and CookieErrorCode types, plus the CookieError class and onChange function.

Behavior and guarantees

Defaults and scope

set defaults path to / and sameSite to lax. delete defaults path to /, so a bare delete targets a bare set written by this package.

Cookies with the same name can exist at different paths or domains, and browsers can also partition them. get(name) returns one match. Use getAll(name) when every readable match matters. The API cannot select a particular duplicate by path or domain when reading.

Delete a cookie using the same path and domain used when it was created. A scope mismatch is a silent no-op because deletion writes an expired cookie at that scope.

Options
Option Type Used by Default and behavior
path string set, delete /. An explicit path must be non-empty and start with /.
domain string set, delete None. The library checks syntax; the browser decides whether it matches the current origin.
expires Date|number set Absolute expiration as a Date or Unix time in milliseconds within the JavaScript Date range. Cannot be combined with maxAge.
maxAge number set Relative expiration in seconds. Must be an integer. Positive values must fit within the supported JavaScript Date range; zero or a negative value expires the cookie immediately. Cookie Store writes convert it to an absolute expiry.
secure boolean set None. The native Cookie Store backend always writes Secure cookies and rejects secure: false as unsupported.
sameSite "strict" | "lax" | "none" set lax. none requires secure: true.
partitioned boolean set, delete None. A partitioned cookie requires secure: true when set. Pass partitioned: true when deleting it.

The encoded name and value pair must fit within 4096 bytes. UTF-8 path and domain values must each fit within 1024 bytes.

The package validates __Secure- and __Host- prefix requirements before writing. It rejects __Http- and __Host-Http- names because browser JavaScript cannot create the required HttpOnly cookies.

Errors and environment support

Validation failures use CookieError before a browser write. Exceptions thrown by a backend operation are wrapped as CookieError with code OPERATION_FAILED and the original exception in cause. Browsers may silently ignore invalid document.cookie writes without throwing, so those failures cannot be reported.

Code Meaning
INVALID_NAME The name is empty, not a string, contains control characters or malformed Unicode, or exceeds its encoded size limit.
INVALID_VALUE The value is not a string or contains malformed Unicode.
INVALID_OPTIONS An option has the wrong type, conflicts with another option, or has an invalid value.
UNSUPPORTED The selected backend cannot perform the requested operation.
NO_COOKIE_ACCESS Neither Cookie Store nor a cookie-capable document is available.
OPERATION_FAILED Cookie Store access or a browser backend operation threw an error.

Importing the package is safe during server-side rendering. Cookie operations reject with NO_COOKIE_ACCESS when no browser cookie API exists. Change subscriptions are not available during server rendering.

There is no deleteAllCookies() method. The document.cookie fallback cannot report each cookie's path or domain, and those fields are not reliably available across Cookie Store implementations. JavaScript also cannot access HttpOnly cookies. Keep the names and scopes your application creates, then delete those explicitly.

Cookies used in cross-site embedded or subresource requests require SameSite=None and Secure:

await cookies.set("widget", "enabled", {
  sameSite: "none",
  secure: true,
});

A __Host- cookie must be Secure, have no Domain attribute, and use the root path:

await cookies.set("__Host-session-hint", "1", {
  secure: true,
  path: "/",
});

Partitioned cookies also require Secure:

await cookies.set("__Host-widget", "enabled", {
  secure: true,
  sameSite: "none",
  partitioned: true,
  path: "/",
});

Delete using the same scope that was used to set the cookie:

await cookies.delete("preferences", {
  path: "/account",
});

See SECURITY.md for cookie security limits and release verification.

In a Window with native Cookie Store change events, cookies.onChange() passes changed cookies with names and values, and deleted cookies with names only. It returns an unsubscribe function. The event data has no path or domain fields. Replacing a cookie can appear as a changed record without a separate deleted record.

const unsubscribe = cookies.onChange(({ changed, deleted }) => {
  for (const cookie of changed) console.log(cookie.name, cookie.value);
  for (const cookie of deleted) console.log(cookie.name, "deleted");
});

unsubscribe();

The document.cookie fallback, server environments, and service workers do not provide this Window event API. onChange() throws CookieError with code UNSUPPORTED there. The library does not poll document.cookie.

Browser support

The library selects a backend for each call.

Backend Used when Readable cookie fields
Cookie Store cookieStore is available, except on a non-HTTPS page with a cookie-capable document name and value are guaranteed by the API. Browsers may expose additional attributes.
document.cookie Cookie Store is unavailable, or the page is non-HTTPS and can carry cookies name and value only.

The real browser test suite runs against Chromium, Firefox, and WebKit. It exercises core operations through native Cookie Store and the document.cookie fallback. Browser-specific support for additional cookie attributes and partitioning can vary.

Cookie Store standardizes the cookie name and value fields; additional metadata is optional and may differ by browser. Treat fields such as path, domain, expiry, Secure, SameSite, and partitioning as optional when reading a Cookie. The fallback can report only names and values.

On a non-HTTPS page with a cookie-capable document, the library selects document.cookie even if Cookie Store is present. This avoids a persistence issue observed in WebKit on plain HTTP origins. On HTTPS pages, Cookie Store is selected when available. A Cookie Store write is Secure by construction, so secure: false is unsupported on that backend.

Security and release integrity

This package reads and writes browser cookies. It is not an authentication system and does not make client-readable values safe to trust. Releases from the current publishing workflow include npm provenance and artifacts for independent verification. See SECURITY.md.

Contributing

Use GitHub Issues for bug reports, enhancement requests, and feedback. See CONTRIBUTING.md to propose a change and run the project checks. Report suspected security vulnerabilities through SECURITY.md, not a public issue.

See ROADMAP.md for the project direction.

Keywords