diff --git a/.changeset/chilly-berries-press.md b/.changeset/chilly-berries-press.md new file mode 100644 index 000000000000..fb53f51a060a --- /dev/null +++ b/.changeset/chilly-berries-press.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +chore: upgrade to cookie 1.0.2 diff --git a/packages/kit/package.json b/packages/kit/package.json index c361f509f320..a56d231fe521 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -18,8 +18,7 @@ "homepage": "https://svelte.dev", "type": "module", "dependencies": { - "@types/cookie": "^0.6.0", - "cookie": "^0.6.0", + "cookie": "^1.0.2", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 0d5888be0699..c54ff9f984b0 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -215,13 +215,13 @@ export interface Cookies { * @param name the name of the cookie * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) */ - get: (name: string, opts?: import('cookie').CookieParseOptions) => string | undefined; + get: (name: string, opts?: import('cookie').ParseOptions) => string | undefined; /** * Gets all cookies that were previously set with `cookies.set`, or from the request headers. * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) */ - getAll: (opts?: import('cookie').CookieParseOptions) => Array<{ name: string; value: string }>; + getAll: (opts?: import('cookie').ParseOptions) => Array<{ name: string; value: string }>; /** * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request. @@ -236,7 +236,7 @@ export interface Cookies { set: ( name: string, value: string, - opts: import('cookie').CookieSerializeOptions & { path: string } + opts: import('cookie').SerializeOptions & { path: string } ) => void; /** @@ -246,7 +246,7 @@ export interface Cookies { * @param name the name of the cookie * @param opts the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) */ - delete: (name: string, opts: import('cookie').CookieSerializeOptions & { path: string }) => void; + delete: (name: string, opts: import('cookie').SerializeOptions & { path: string }) => void; /** * Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response. @@ -262,7 +262,7 @@ export interface Cookies { serialize: ( name: string, value: string, - opts: import('cookie').CookieSerializeOptions & { path: string } + opts: import('cookie').SerializeOptions & { path: string } ) => string; } diff --git a/packages/kit/src/runtime/server/cookie.js b/packages/kit/src/runtime/server/cookie.js index 0dc74f5a613b..4221966b41d9 100644 --- a/packages/kit/src/runtime/server/cookie.js +++ b/packages/kit/src/runtime/server/cookie.js @@ -1,9 +1,6 @@ import { parse, serialize } from 'cookie'; import { add_data_suffix, normalize_path, resolve } from '../../utils/url.js'; -// eslint-disable-next-line no-control-regex -- control characters are invalid in cookie names -const INVALID_COOKIE_CHARACTER_REGEX = /[\x00-\x1F\x7F()<>@,;:"/[\]?={} \t]/; - /** * Tracks all cookies set during dev mode so we can emit warnings * when we detect that there's likely cookie misusage due to wrong paths @@ -32,14 +29,16 @@ function validate_options(options) { */ export function get_cookies(request, url, trailing_slash) { const header = request.headers.get('cookie') ?? ''; - const initial_cookies = parse(header, { decode: (value) => value }); + const initial_cookies = /** @type {Record} */ ( + parse(header, { decode: (value) => value }) + ); const normalized_url = normalize_path(url.pathname, trailing_slash); /** @type {Record} */ const new_cookies = {}; - /** @type {import('cookie').CookieSerializeOptions} */ + /** @type {import('cookie').SerializeOptions} */ const defaults = { httpOnly: true, sameSite: 'lax', @@ -55,7 +54,7 @@ export function get_cookies(request, url, trailing_slash) { /** * @param {string} name - * @param {import('cookie').CookieParseOptions} [opts] + * @param {import('cookie').ParseOptions} [opts] */ get(name, opts) { const c = new_cookies[name]; @@ -91,7 +90,7 @@ export function get_cookies(request, url, trailing_slash) { }, /** - * @param {import('cookie').CookieParseOptions} [opts] + * @param {import('cookie').ParseOptions} [opts] */ getAll(opts) { const cookies = parse(header, { decode: opts?.decode }); @@ -105,7 +104,11 @@ export function get_cookies(request, url, trailing_slash) { } } - return Object.entries(cookies).map(([name, value]) => ({ name, value })); + return /** @type {Array<{ name: string; value: string }>} */ ( + Object.entries(cookies) + .filter(([, value]) => value != null) + .map(([name, value]) => ({ name, value })) + ); }, /** @@ -114,16 +117,6 @@ export function get_cookies(request, url, trailing_slash) { * @param {import('./page/types.js').Cookie['options']} options */ set(name, value, options) { - // TODO: remove this check in 3.0 - const illegal_characters = name.match(INVALID_COOKIE_CHARACTER_REGEX); - if (illegal_characters) { - console.warn( - `The cookie name "${name}" will be invalid in SvelteKit 3.0 as it contains ${illegal_characters.join( - ' and ' - )}. See RFC 2616 for more details https://datatracker.ietf.org/doc/html/rfc2616#section-2.2` - ); - } - validate_options(options); set_internal(name, value, { ...defaults, ...options }); }, @@ -178,7 +171,9 @@ export function get_cookies(request, url, trailing_slash) { // explicit header has highest precedence if (header) { - const parsed = parse(header, { decode: (value) => value }); + const parsed = /** @type {Record} */ ( + parse(header, { decode: (value) => value }) + ); for (const name in parsed) { combined_cookies[name] = parsed[name]; } diff --git a/packages/kit/src/runtime/server/fetch.js b/packages/kit/src/runtime/server/fetch.js index 417b59c93063..107e04d10542 100644 --- a/packages/kit/src/runtime/server/fetch.js +++ b/packages/kit/src/runtime/server/fetch.js @@ -153,7 +153,7 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade set_internal(name, value, { path, encode: (value) => value, - .../** @type {import('cookie').CookieSerializeOptions} */ (options) + .../** @type {import('cookie').SerializeOptions} */ (options) }); } } diff --git a/packages/kit/src/runtime/server/page/types.d.ts b/packages/kit/src/runtime/server/page/types.d.ts index 7e501b1ab418..cabe33fd60c3 100644 --- a/packages/kit/src/runtime/server/page/types.d.ts +++ b/packages/kit/src/runtime/server/page/types.d.ts @@ -1,4 +1,4 @@ -import { CookieSerializeOptions } from 'cookie'; +import { SerializeOptions } from 'cookie'; import { SSRNode, CspDirectives, ServerDataNode } from 'types'; export interface Fetched { @@ -32,5 +32,5 @@ export interface CspOpts { export interface Cookie { name: string; value: string; - options: CookieSerializeOptions & { path: string }; + options: SerializeOptions & { path: string }; } diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index a7b9cf1e4a09..4dcdc32c5544 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -197,13 +197,13 @@ declare module '@sveltejs/kit' { * @param name the name of the cookie * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) */ - get: (name: string, opts?: import('cookie').CookieParseOptions) => string | undefined; + get: (name: string, opts?: import('cookie').ParseOptions) => string | undefined; /** * Gets all cookies that were previously set with `cookies.set`, or from the request headers. * @param opts the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) */ - getAll: (opts?: import('cookie').CookieParseOptions) => Array<{ name: string; value: string }>; + getAll: (opts?: import('cookie').ParseOptions) => Array<{ name: string; value: string }>; /** * Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request. @@ -218,7 +218,7 @@ declare module '@sveltejs/kit' { set: ( name: string, value: string, - opts: import('cookie').CookieSerializeOptions & { path: string } + opts: import('cookie').SerializeOptions & { path: string } ) => void; /** @@ -228,7 +228,7 @@ declare module '@sveltejs/kit' { * @param name the name of the cookie * @param opts the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) */ - delete: (name: string, opts: import('cookie').CookieSerializeOptions & { path: string }) => void; + delete: (name: string, opts: import('cookie').SerializeOptions & { path: string }) => void; /** * Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response. @@ -244,7 +244,7 @@ declare module '@sveltejs/kit' { serialize: ( name: string, value: string, - opts: import('cookie').CookieSerializeOptions & { path: string } + opts: import('cookie').SerializeOptions & { path: string } ) => string; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e918a1764f38..0bc7e9d54b43 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -342,12 +342,9 @@ importers: packages/kit: dependencies: - '@types/cookie': - specifier: ^0.6.0 - version: 0.6.0 cookie: - specifier: ^0.6.0 - version: 0.6.0 + specifier: ^1.0.2 + version: 1.0.2 devalue: specifier: ^5.1.0 version: 5.1.0 @@ -1972,9 +1969,6 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/cookie@0.6.0': - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - '@types/eslint@8.56.12': resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} @@ -2272,9 +2266,9 @@ packages: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} - cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} @@ -4402,8 +4396,6 @@ snapshots: dependencies: '@types/node': 18.19.50 - '@types/cookie@0.6.0': {} - '@types/eslint@8.56.12': dependencies: '@types/estree': 1.0.6 @@ -4721,7 +4713,7 @@ snapshots: cookie@0.5.0: {} - cookie@0.6.0: {} + cookie@1.0.2: {} cross-env@7.0.3: dependencies: