cookie-es 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,8 +21,6 @@ npx nypm install cookie-es
21
21
 
22
22
  ## Import
23
23
 
24
- **ESM** (Node.js, Bun, Deno)
25
-
26
24
  ```js
27
25
  import {
28
26
  parseCookie,
@@ -33,18 +31,6 @@ import {
33
31
  } from "cookie-es";
34
32
  ```
35
33
 
36
- **CDN** (Deno, Bun and Browsers)
37
-
38
- ```js
39
- import {
40
- parseCookie,
41
- parseSetCookie,
42
- serializeCookie,
43
- stringifyCookie,
44
- splitSetCookieString,
45
- } from "https://esm.sh/cookie-es";
46
- ```
47
-
48
34
  ## API
49
35
 
50
36
  ### `parseCookie(str, options?)`
@@ -106,6 +92,8 @@ serializeCookie({
106
92
  // "foo=bar; Domain=example.com; Path=/; SameSite=Lax"
107
93
  ```
108
94
 
95
+ Non-string values are coerced to strings (`null` and `undefined` become empty string).
96
+
109
97
  Supported attributes: `maxAge`, `expires`, `domain`, `path`, `httpOnly`, `secure`, `sameSite`, `priority`, `partitioned`. Use `encode` option for custom value encoding (default: `encodeURIComponent`).
110
98
 
111
99
  > [!NOTE]
package/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- //#region src/cookie/types.d.ts
2
1
  /**
3
2
  * Parse options.
4
3
  */
@@ -45,6 +44,12 @@ interface CookieStringifyOptions {
45
44
  * @default encodeURIComponent
46
45
  */
47
46
  encode?: (str: string) => string;
47
+ /**
48
+ * Specifies a function that will be used to coerce non-string values to a string.
49
+ *
50
+ * @default JSON.stringify
51
+ */
52
+ stringify?: (value: unknown) => string;
48
53
  }
49
54
  /**
50
55
  * Set-Cookie object.
@@ -130,37 +135,46 @@ interface SetCookie {
130
135
  * Backward compatibility serialize options.
131
136
  */
132
137
  type CookieSerializeOptions = CookieStringifyOptions & Omit<SetCookie, "name" | "value">;
133
- //#endregion
134
- //#region src/cookie/parse.d.ts
135
138
  /**
136
- * Parse a `Cookie` header.
139
+ * Parse a `Cookie` header string into an object.
137
140
  *
138
- * Parse the given cookie header string into an object
139
- * The object has the various cookies as keys(names) => values
141
+ * The object has cookie names as keys and decoded values as values.
142
+ * First occurrence wins for duplicate names unless `allowMultiple` is set.
143
+ *
144
+ * @param str - The `Cookie` header string to parse.
145
+ * @param options - Parsing options (`decode`, `filter`, `allowMultiple`).
146
+ * @returns A prototype-less object of cookie name-value pairs.
140
147
  */
141
148
  declare function parse(str: string, options: CookieParseOptions & {
142
149
  allowMultiple: true;
143
150
  }): MultiCookies;
144
151
  declare function parse(str: string, options?: CookieParseOptions): Cookies;
145
- //#endregion
146
- //#region src/cookie/serialize.d.ts
147
152
  /**
148
- * Stringifies an object into an HTTP `Cookie` header.
153
+ * Stringify a cookies object into an HTTP `Cookie` header string.
154
+ *
155
+ * @param cookie - An object of cookie name-value pairs.
156
+ * @param options - Stringify options (`encode`).
157
+ * @returns A `Cookie` header string (e.g. `"foo=bar; baz=qux"`).
149
158
  */
150
159
  declare function stringifyCookie(cookie: Cookies, options?: CookieStringifyOptions): string;
151
160
  /**
152
- * Serialize data into a cookie header.
161
+ * Serialize a cookie into a `Set-Cookie` header string.
153
162
  *
154
- * Serialize a name value pair into a cookie string suitable for
155
- * http headers. An optional options object specifies cookie parameters.
163
+ * Accepts either a name-value pair with options or a `SetCookie` object.
164
+ * Non-string values are coerced to strings. Validates name, value, domain,
165
+ * and path against RFC 6265bis.
156
166
  *
157
- * serialize('foo', 'bar', { httpOnly: true })
158
- * => "foo=bar; httpOnly"
167
+ * @example
168
+ * ```js
169
+ * serialize("foo", "bar", { httpOnly: true });
170
+ * // => "foo=bar; HttpOnly"
171
+ *
172
+ * serialize({ name: "foo", value: "bar", secure: true });
173
+ * // => "foo=bar; Secure"
174
+ * ```
159
175
  */
160
176
  declare function serialize(cookie: SetCookie, options?: CookieStringifyOptions): string;
161
- declare function serialize(name: string, val: string, options?: CookieSerializeOptions): string;
162
- //#endregion
163
- //#region src/set-cookie/types.d.ts
177
+ declare function serialize(name: string, val: unknown, options?: CookieSerializeOptions): string;
164
178
  interface SetCookieParseOptions {
165
179
  /**
166
180
  * Custom decode function to use on cookie values.
@@ -225,20 +239,27 @@ interface SetCookie$1 {
225
239
  priority?: "low" | "medium" | "high" | undefined;
226
240
  [key: string]: unknown;
227
241
  }
228
- //#endregion
229
- //#region src/set-cookie/parse.d.ts
230
242
  /**
231
- * Parse a [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) header string into an object.
243
+ * Parse a [`Set-Cookie`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) header string into an object.
244
+ *
245
+ * Returns `undefined` for cookies with forbidden names (prototype pollution protection)
246
+ * or when both name and value are empty (RFC 6265bis sec 5.7).
247
+ *
248
+ * @param str - The `Set-Cookie` header string to parse.
249
+ * @param options - Parsing options (`decode`).
250
+ * @returns A `SetCookie` object with all parsed attributes, or `undefined`.
232
251
  */
233
252
  declare function parseSetCookie(str: string, options?: SetCookieParseOptions): SetCookie$1 | undefined;
234
- //#endregion
235
- //#region src/set-cookie/split.d.ts
236
253
  /**
237
- * Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
238
- * that are within a single set-cookie field-value, such as in the Expires portion.
254
+ * Split comma-joined `Set-Cookie` header strings into individual cookie strings.
255
+ *
256
+ * Correctly handles commas within cookie attributes like `Expires` dates
257
+ * by checking for `=` after a comma to determine if it's a cookie separator.
258
+ *
259
+ * @param cookiesString - A comma-joined `Set-Cookie` string or array of strings.
260
+ * @returns An array of individual `Set-Cookie` strings.
239
261
  *
240
- * See https://tools.ietf.org/html/rfc2616#section-4.2
262
+ * @see https://tools.ietf.org/html/rfc2616#section-4.2
241
263
  */
242
264
  declare function splitSetCookieString(cookiesString: string | string[]): string[];
243
- //#endregion
244
265
  export { type CookieParseOptions, type CookieSerializeOptions, type CookieStringifyOptions, type Cookies, type MultiCookies, type SetCookie, type SetCookieParseOptions, parse, parse as parseCookie, parseSetCookie, serialize, serialize as serializeCookie, splitSetCookieString, stringifyCookie };
package/dist/index.mjs CHANGED
@@ -1,25 +1,12 @@
1
- //#region src/_utils.ts
2
- /**
3
- * RFC 6265bis cookie-age-limit: 400 days in seconds.
4
- */
5
1
  const COOKIE_MAX_AGE_LIMIT = 400 * 24 * 60 * 60;
6
- /**
7
- * Find the `;` character between `min` and `len` in str.
8
- */
9
2
  function endIndex(str, min, len) {
10
3
  const index = str.indexOf(";", min);
11
4
  return index === -1 ? len : index;
12
5
  }
13
- /**
14
- * Find the `=` character between `min` and `max` in str.
15
- */
16
6
  function eqIndex(str, min, max) {
17
7
  const index = str.indexOf("=", min);
18
8
  return index < max ? index : -1;
19
9
  }
20
- /**
21
- * Slice out a value between start to max.
22
- */
23
10
  function valueSlice(str, min, max) {
24
11
  if (min === max) return "";
25
12
  let start = min;
@@ -35,8 +22,6 @@ function valueSlice(str, min, max) {
35
22
  }
36
23
  return str.slice(start, end);
37
24
  }
38
- //#endregion
39
- //#region src/cookie/parse.ts
40
25
  const NullObject = /* @__PURE__ */ (() => {
41
26
  const C = function() {};
42
27
  C.prototype = Object.create(null);
@@ -73,9 +58,6 @@ function parse(str, options) {
73
58
  } while (index < len);
74
59
  return obj;
75
60
  }
76
- /**
77
- * URL-decode string value. Optimized to skip native call when no %.
78
- */
79
61
  function decode(str) {
80
62
  if (!str.includes("%")) return str;
81
63
  try {
@@ -84,72 +66,11 @@ function decode(str) {
84
66
  return str;
85
67
  }
86
68
  }
87
- //#endregion
88
- //#region src/cookie/serialize.ts
89
- /**
90
- * RegExp to match cookie-name in RFC 6265bis sec 4.1.1
91
- * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
92
- * which has been replaced by the token definition in RFC 7230 appendix B.
93
- *
94
- * cookie-name = token
95
- * token = 1*tchar
96
- * tchar = "!" / "#" / "$" / "%" / "&" / "'" /
97
- * "*" / "+" / "-" / "." / "^" / "_" /
98
- * "`" / "|" / "~" / DIGIT / ALPHA
99
- *
100
- * Note: Allowing more characters - https://github.com/jshttp/cookie/issues/191
101
- * Allow same range as cookie value, except `=`, which delimits end of name.
102
- */
103
69
  const cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
104
- /**
105
- * RegExp to match cookie-value in RFC 6265bis sec 4.1.1
106
- *
107
- * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
108
- * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
109
- * ; US-ASCII characters excluding CTLs,
110
- * ; whitespace DQUOTE, comma, semicolon,
111
- * ; and backslash
112
- *
113
- * Allowing more characters: https://github.com/jshttp/cookie/issues/191
114
- * Comma, backslash, and DQUOTE are not part of the parsing algorithm.
115
- */
116
70
  const cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/;
117
- /**
118
- * RegExp to match domain-value in RFC 6265bis sec 4.1.1
119
- *
120
- * domain-value = <subdomain>
121
- * ; defined in [RFC1034], Section 3.5, as
122
- * ; enhanced by [RFC1123], Section 2.1
123
- * <subdomain> = <label> | <subdomain> "." <label>
124
- * <label> = <let-dig> [ [ <ldh-str> ] <let-dig> ]
125
- * Labels must be 63 characters or less.
126
- * 'let-dig' not 'letter' in the first char, per RFC1123
127
- * <ldh-str> = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
128
- * <let-dig-hyp> = <let-dig> | "-"
129
- * <let-dig> = <letter> | <digit>
130
- * <letter> = any one of the 52 alphabetic characters A through Z in
131
- * upper case and a through z in lower case
132
- * <digit> = any one of the ten digits 0 through 9
133
- *
134
- * Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
135
- *
136
- * > (Note that a leading %x2E ("."), if present, is ignored even though that
137
- * character is not permitted, but a trailing %x2E ("."), if present, will
138
- * cause the user agent to ignore the attribute.)
139
- */
140
71
  const domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
141
- /**
142
- * RegExp to match path-value in RFC 6265bis sec 4.1.1
143
- *
144
- * path-value = <any CHAR except CTLs or ";">
145
- * CHAR = %x01-7F
146
- * ; defined in RFC 5234 appendix B.1
147
- */
148
72
  const pathValueRegExp = /^[\u0020-\u003A\u003C-\u007E]*$/;
149
73
  const __toString = Object.prototype.toString;
150
- /**
151
- * Stringifies an object into an HTTP `Cookie` header.
152
- */
153
74
  function stringifyCookie(cookie, options) {
154
75
  const enc = options?.encode || encodeURIComponent;
155
76
  const keys = Object.keys(cookie);
@@ -165,13 +86,16 @@ function stringifyCookie(cookie, options) {
165
86
  }
166
87
  return str;
167
88
  }
168
- function serialize(_name, _val, _opts) {
169
- const cookie = typeof _name === "object" ? _name : {
170
- ..._opts,
171
- name: _name,
172
- value: String(_val)
89
+ function serialize(_a0, _a1, _a2) {
90
+ const isObj = typeof _a0 === "object" && _a0 !== null;
91
+ const options = isObj ? _a1 : _a2;
92
+ const stringify = options?.stringify || JSON.stringify;
93
+ const cookie = isObj ? _a0 : {
94
+ ..._a2,
95
+ name: _a0,
96
+ value: _a1 == void 0 ? "" : typeof _a1 === "string" ? _a1 : stringify(_a1)
173
97
  };
174
- const enc = (typeof _val === "object" ? _val : _opts)?.encode || encodeURIComponent;
98
+ const enc = options?.encode || encodeURIComponent;
175
99
  if (!cookieNameRegExp.test(cookie.name)) throw new TypeError(`argument name is invalid: ${cookie.name}`);
176
100
  const value = cookie.value ? enc(cookie.value) : "";
177
101
  if (!cookieValueRegExp.test(value)) throw new TypeError(`argument val is invalid: ${cookie.value}`);
@@ -234,22 +158,11 @@ function serialize(_name, _val, _opts) {
234
158
  }
235
159
  return str;
236
160
  }
237
- /**
238
- * Determine if value is a Date.
239
- */
240
161
  function isDate(val) {
241
162
  return __toString.call(val) === "[object Date]";
242
163
  }
243
- //#endregion
244
- //#region src/set-cookie/parse.ts
245
- /**
246
- * RegExp to match max-age-value in RFC 6265 sec 5.6.2
247
- */
248
164
  const maxAgeRegExp = /^-?\d+$/;
249
165
  const _nullProto = Object.getPrototypeOf({});
250
- /**
251
- * Parse a [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) header string into an object.
252
- */
253
166
  function parseSetCookie(str, options) {
254
167
  const len = str.length;
255
168
  let _endIdx = len;
@@ -354,14 +267,6 @@ function _decode(value, decode) {
354
267
  return value;
355
268
  }
356
269
  }
357
- //#endregion
358
- //#region src/set-cookie/split.ts
359
- /**
360
- * Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
361
- * that are within a single set-cookie field-value, such as in the Expires portion.
362
- *
363
- * See https://tools.ietf.org/html/rfc2616#section-4.2
364
- */
365
270
  function splitSetCookieString(cookiesString) {
366
271
  if (Array.isArray(cookiesString)) return cookiesString.flatMap((c) => splitSetCookieString(c));
367
272
  if (typeof cookiesString !== "string") return [];
@@ -403,5 +308,4 @@ function splitSetCookieString(cookiesString) {
403
308
  }
404
309
  return cookiesStrings;
405
310
  }
406
- //#endregion
407
311
  export { parse, parse as parseCookie, parseSetCookie, serialize, serialize as serializeCookie, splitSetCookieString, stringifyCookie };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cookie-es",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "license": "MIT",
5
5
  "repository": "unjs/cookie-es",
6
6
  "files": [
@@ -27,10 +27,12 @@
27
27
  "changelogen": "^0.6.2",
28
28
  "cookie": "^1.1.1",
29
29
  "eslint-config-unjs": "^0.6.2",
30
+ "magic-string": "^0.30.21",
30
31
  "mitata": "^1.0.34",
31
32
  "obuild": "^0.4.32",
32
33
  "oxfmt": "^0.41.0",
33
34
  "oxlint": "^1.56.0",
35
+ "rolldown": "1.0.0-rc.11",
34
36
  "typescript": "^6.0.2",
35
37
  "vitest": "^4.1.1"
36
38
  },