UNPKG

tough-cookie

Version:

RFC6265 Cookies and Cookie Jar for node.js

1 lines 216 kB
{"version":3,"sources":["../lib/cookie/index.ts","../lib/pathMatch.ts","../lib/getPublicSuffix.ts","../lib/permuteDomain.ts","../lib/store.ts","../lib/utils.ts","../lib/memstore.ts","../lib/validators.ts","../lib/version.ts","../lib/cookie/constants.ts","../lib/cookie/canonicalDomain.ts","../lib/cookie/formatDate.ts","../lib/cookie/parseDate.ts","../lib/cookie/cookie.ts","../lib/cookie/cookieCompare.ts","../lib/cookie/defaultPath.ts","../lib/cookie/domainMatch.ts","../lib/cookie/secureContext.ts","../lib/cookie/cookieJar.ts","../lib/cookie/permutePath.ts"],"sourcesContent":["export { MemoryCookieStore, type MemoryCookieStoreIndex } from '../memstore.js'\nexport { pathMatch } from '../pathMatch.js'\nexport { permuteDomain } from '../permuteDomain.js'\nexport {\n getPublicSuffix,\n type GetPublicSuffixOptions,\n} from '../getPublicSuffix.js'\nexport { Store } from '../store.js'\nexport { ParameterError } from '../validators.js'\nexport { version } from '../version.js'\nexport { type Callback, type ErrorCallback, type Nullable } from '../utils.js'\nexport { canonicalDomain } from './canonicalDomain.js'\nexport {\n PrefixSecurityEnum,\n type SerializedCookie,\n type SerializedCookieJar,\n} from './constants.js'\nexport {\n Cookie,\n type CreateCookieOptions,\n type ParseCookieOptions,\n} from './cookie.js'\nexport { cookieCompare } from './cookieCompare.js'\nexport {\n CookieJar,\n type CreateCookieJarOptions,\n type GetCookiesOptions,\n type SetCookieOptions,\n} from './cookieJar.js'\nexport { defaultPath } from './defaultPath.js'\nexport { domainMatch } from './domainMatch.js'\nexport { formatDate } from './formatDate.js'\nexport { parseDate } from './parseDate.js'\nexport { permutePath } from './permutePath.js'\n\nimport { Cookie, ParseCookieOptions } from './cookie.js'\n\n/**\n * {@inheritDoc Cookie.parse}\n * @public\n */\nexport function parse(\n str: string,\n options?: ParseCookieOptions,\n): Cookie | undefined {\n return Cookie.parse(str, options)\n}\n\n/**\n * {@inheritDoc Cookie.fromJSON}\n * @public\n */\nexport function fromJSON(str: unknown): Cookie | undefined {\n return Cookie.fromJSON(str)\n}\n","/**\n * Answers \"does the request-path path-match a given cookie-path?\" as per {@link https://www.rfc-editor.org/rfc/rfc6265.html#section-5.1.4 | RFC6265 Section 5.1.4}.\n * This is essentially a prefix-match where cookiePath is a prefix of reqPath.\n *\n * @remarks\n * A request-path path-matches a given cookie-path if at least one of\n * the following conditions holds:\n *\n * - The cookie-path and the request-path are identical.\n * - The cookie-path is a prefix of the request-path, and the last character of the cookie-path is %x2F (\"/\").\n * - The cookie-path is a prefix of the request-path, and the first character of the request-path that is not included in the cookie-path is a %x2F (\"/\") character.\n *\n * @param reqPath - the path of the request\n * @param cookiePath - the path of the cookie\n * @public\n */\nexport function pathMatch(reqPath: string, cookiePath: string): boolean {\n // \"o The cookie-path and the request-path are identical.\"\n if (cookiePath === reqPath) {\n return true\n }\n\n const idx = reqPath.indexOf(cookiePath)\n if (idx === 0) {\n // \"o The cookie-path is a prefix of the request-path, and the last\n // character of the cookie-path is %x2F (\"/\").\"\n if (cookiePath[cookiePath.length - 1] === '/') {\n return true\n }\n\n // \" o The cookie-path is a prefix of the request-path, and the first\n // character of the request-path that is not included in the cookie- path\n // is a %x2F (\"/\") character.\"\n if (reqPath.startsWith(cookiePath) && reqPath[cookiePath.length] === '/') {\n return true\n }\n }\n\n return false\n}\n","import { getDomain } from 'tldts'\n\n// RFC 6761\nconst SPECIAL_USE_DOMAINS = ['local', 'example', 'invalid', 'localhost', 'test']\n\nconst SPECIAL_TREATMENT_DOMAINS = ['localhost', 'invalid']\n\n/**\n * Options for configuring how {@link getPublicSuffix} behaves.\n * @public\n */\nexport interface GetPublicSuffixOptions {\n /**\n * If set to `true` then the following {@link https://www.rfc-editor.org/rfc/rfc6761.html | Special Use Domains} will\n * be treated as if they were valid public suffixes ('local', 'example', 'invalid', 'localhost', 'test').\n *\n * @remarks\n * In testing scenarios it's common to configure the cookie store with so that `http://localhost` can be used as a domain:\n * ```json\n * {\n * allowSpecialUseDomain: true,\n * rejectPublicSuffixes: false\n * }\n * ```\n *\n * @defaultValue false\n */\n allowSpecialUseDomain?: boolean | undefined\n /**\n * If set to `true` then any errors that occur while executing {@link getPublicSuffix} will be silently ignored.\n *\n * @defaultValue false\n */\n ignoreError?: boolean | undefined\n}\n\nconst defaultGetPublicSuffixOptions: GetPublicSuffixOptions = {\n allowSpecialUseDomain: false,\n ignoreError: false,\n}\n\n/**\n * Returns the public suffix of this hostname. The public suffix is the shortest domain\n * name upon which a cookie can be set.\n *\n * @remarks\n * A \"public suffix\" is a domain that is controlled by a\n * public registry, such as \"com\", \"co.uk\", and \"pvt.k12.wy.us\".\n * This step is essential for preventing attacker.com from\n * disrupting the integrity of example.com by setting a cookie\n * with a Domain attribute of \"com\". Unfortunately, the set of\n * public suffixes (also known as \"registry controlled domains\")\n * changes over time. If feasible, user agents SHOULD use an\n * up-to-date public suffix list, such as the one maintained by\n * the Mozilla project at http://publicsuffix.org/.\n * (See {@link https://www.rfc-editor.org/rfc/rfc6265.html#section-5.3 | RFC6265 - Section 5.3})\n *\n * @example\n * ```\n * getPublicSuffix('www.example.com') === 'example.com'\n * getPublicSuffix('www.subdomain.example.com') === 'example.com'\n * ```\n *\n * @param domain - the domain attribute of a cookie\n * @param options - optional configuration for controlling how the public suffix is determined\n * @public\n */\nexport function getPublicSuffix(\n domain: string,\n options: GetPublicSuffixOptions = {},\n): string | undefined {\n options = { ...defaultGetPublicSuffixOptions, ...options }\n const domainParts = domain.split('.')\n const topLevelDomain = domainParts[domainParts.length - 1]\n const allowSpecialUseDomain = !!options.allowSpecialUseDomain\n const ignoreError = !!options.ignoreError\n\n if (\n allowSpecialUseDomain &&\n topLevelDomain !== undefined &&\n SPECIAL_USE_DOMAINS.includes(topLevelDomain)\n ) {\n if (domainParts.length > 1) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const secondLevelDomain = domainParts[domainParts.length - 2]!\n // In aforementioned example, the eTLD/pubSuf will be apple.localhost\n return `${secondLevelDomain}.${topLevelDomain}`\n } else if (SPECIAL_TREATMENT_DOMAINS.includes(topLevelDomain)) {\n // For a single word special use domain, e.g. 'localhost' or 'invalid', per RFC 6761,\n // \"Application software MAY recognize {localhost/invalid} names as special, or\n // MAY pass them to name resolution APIs as they would for other domain names.\"\n return topLevelDomain\n }\n }\n\n if (\n !ignoreError &&\n topLevelDomain !== undefined &&\n SPECIAL_USE_DOMAINS.includes(topLevelDomain)\n ) {\n throw new Error(\n `Cookie has domain set to the public suffix \"${topLevelDomain}\" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain: true, rejectPublicSuffixes: false}.`,\n )\n }\n\n const publicSuffix = getDomain(domain, {\n allowIcannDomains: true,\n allowPrivateDomains: true,\n })\n if (publicSuffix) return publicSuffix\n}\n","import { getPublicSuffix } from './getPublicSuffix.js'\n\n/**\n * Generates the permutation of all possible values that {@link domainMatch} the given `domain` parameter. The\n * array is in shortest-to-longest order. Useful when building custom {@link Store} implementations.\n *\n * @example\n * ```\n * permuteDomain('foo.bar.example.com')\n * // ['example.com', 'bar.example.com', 'foo.bar.example.com']\n * ```\n *\n * @public\n * @param domain - the domain to generate permutations for\n * @param allowSpecialUseDomain - flag to control if {@link https://www.rfc-editor.org/rfc/rfc6761.html | Special Use Domains} such as `localhost` should be allowed\n */\nexport function permuteDomain(\n domain: string,\n allowSpecialUseDomain?: boolean,\n): string[] | undefined {\n const pubSuf = getPublicSuffix(domain, {\n allowSpecialUseDomain: allowSpecialUseDomain,\n })\n\n if (!pubSuf) {\n return undefined\n }\n if (pubSuf == domain) {\n return [domain]\n }\n\n // Nuke trailing dot\n if (domain.slice(-1) == '.') {\n domain = domain.slice(0, -1)\n }\n\n const prefix = domain.slice(0, -(pubSuf.length + 1)) // \".example.com\"\n const parts = prefix.split('.').reverse()\n let cur = pubSuf\n const permutations = [cur]\n while (parts.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const part = parts.shift()!\n cur = `${part}.${cur}`\n permutations.push(cur)\n }\n return permutations\n}\n","// disabling this lint on this whole file because Store should be abstract\n// but we have implementations in the wild that may not implement all features\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport type { Cookie } from './cookie/index.js'\nimport type { Callback, ErrorCallback, Nullable } from './utils.js'\n\n/**\n * Base class for {@link CookieJar} stores.\n *\n * The storage model for each {@link CookieJar} instance can be replaced with a custom implementation. The default is\n * {@link MemoryCookieStore}.\n *\n * @remarks\n * - Stores should inherit from the base Store class, which is available as a top-level export.\n *\n * - Stores are asynchronous by default, but if {@link Store.synchronous} is set to true, then the `*Sync` methods\n * of the containing {@link CookieJar} can be used.\n *\n * @public\n */\nexport class Store {\n /**\n * Store implementations that support synchronous methods must return `true`.\n */\n synchronous: boolean\n\n constructor() {\n this.synchronous = false\n }\n\n /**\n * Retrieve a {@link Cookie} with the given `domain`, `path`, and `key` (`name`). The RFC maintains that exactly\n * one of these cookies should exist in a store. If the store is using versioning, this means that the latest or\n * newest such cookie should be returned.\n *\n * Callback takes an error and the resulting Cookie object. If no cookie is found then null MUST be passed instead (that is, not an error).\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n */\n findCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n ): Promise<Cookie | undefined>\n /**\n * Retrieve a {@link Cookie} with the given `domain`, `path`, and `key` (`name`). The RFC maintains that exactly\n * one of these cookies should exist in a store. If the store is using versioning, this means that the latest or\n * newest such cookie should be returned.\n *\n * Callback takes an error and the resulting Cookie object. If no cookie is found then null MUST be passed instead (that is, not an error).\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n * @param callback - A function to call with either the found cookie or an error.\n */\n findCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n callback: Callback<Cookie | undefined>,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n findCookie(\n _domain: Nullable<string>,\n _path: Nullable<string>,\n _key: Nullable<string>,\n _callback?: Callback<Cookie | undefined>,\n ): unknown {\n throw new Error('findCookie is not implemented')\n }\n\n /**\n * Locates all {@link Cookie} values matching the given `domain` and `path`.\n *\n * The resulting list is checked for applicability to the current request according to the RFC (`domain-match`, `path-match`,\n * `http-only-flag`, `secure-flag`, `expiry`, and so on), so it's OK to use an optimistic search algorithm when implementing\n * this method. However, the search algorithm used SHOULD try to find cookies that {@link domainMatch} the `domain` and\n * {@link pathMatch} the `path` in order to limit the amount of checking that needs to be done.\n *\n * @remarks\n * - As of version `0.9.12`, the `allPaths` option to cookiejar.getCookies() above causes the path here to be `null`.\n *\n * - If the `path` is `null`, `path-matching` MUST NOT be performed (that is, `domain-matching` only).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param allowSpecialUseDomain - If `true` then special-use domain suffixes, will be allowed in matches. Defaults to `false`.\n */\n findCookies(\n domain: Nullable<string>,\n path: Nullable<string>,\n allowSpecialUseDomain?: boolean,\n ): Promise<Cookie[]>\n /**\n * Locates all {@link Cookie} values matching the given `domain` and `path`.\n *\n * The resulting list is checked for applicability to the current request according to the RFC (`domain-match`, `path-match`,\n * `http-only-flag`, `secure-flag`, `expiry`, and so on), so it's OK to use an optimistic search algorithm when implementing\n * this method. However, the search algorithm used SHOULD try to find cookies that {@link domainMatch} the `domain` and\n * {@link pathMatch} the `path` in order to limit the amount of checking that needs to be done.\n *\n * @remarks\n * - As of version `0.9.12`, the `allPaths` option to cookiejar.getCookies() above causes the path here to be `null`.\n *\n * - If the `path` is `null`, `path-matching` MUST NOT be performed (that is, `domain-matching` only).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param allowSpecialUseDomain - If `true` then special-use domain suffixes, will be allowed in matches. Defaults to `false`.\n * @param callback - A function to call with either the found cookies or an error.\n */\n findCookies(\n domain: Nullable<string>,\n path: Nullable<string>,\n allowSpecialUseDomain?: boolean,\n callback?: Callback<Cookie[]>,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n findCookies(\n _domain: Nullable<string>,\n _path: Nullable<string>,\n _allowSpecialUseDomain: boolean | Callback<Cookie[]> = false,\n _callback?: Callback<Cookie[]>,\n ): unknown {\n throw new Error('findCookies is not implemented')\n }\n\n /**\n * Adds a new {@link Cookie} to the store. The implementation SHOULD replace any existing cookie with the same `domain`,\n * `path`, and `key` properties.\n *\n * @remarks\n * - Depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie`\n * that a duplicate `putCookie` can occur.\n *\n * - The {@link Cookie} object MUST NOT be modified; as the caller has already updated the `creation` and `lastAccessed` properties.\n *\n * @param cookie - The cookie to store.\n */\n putCookie(cookie: Cookie): Promise<void>\n /**\n * Adds a new {@link Cookie} to the store. The implementation SHOULD replace any existing cookie with the same `domain`,\n * `path`, and `key` properties.\n *\n * @remarks\n * - Depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie`\n * that a duplicate `putCookie` can occur.\n *\n * - The {@link Cookie} object MUST NOT be modified; as the caller has already updated the `creation` and `lastAccessed` properties.\n *\n * @param cookie - The cookie to store.\n * @param callback - A function to call when the cookie has been stored or an error has occurred.\n */\n putCookie(cookie: Cookie, callback: ErrorCallback): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n putCookie(_cookie: Cookie, _callback?: ErrorCallback): unknown {\n throw new Error('putCookie is not implemented')\n }\n\n /**\n * Update an existing {@link Cookie}. The implementation MUST update the `value` for a cookie with the same `domain`,\n * `path`, and `key`. The implementation SHOULD check that the old value in the store is equivalent to oldCookie -\n * how the conflict is resolved is up to the store.\n *\n * @remarks\n * - The `lastAccessed` property is always different between the two objects (to the precision possible via JavaScript's clock).\n *\n * - Both `creation` and `creationIndex` are guaranteed to be the same.\n *\n * - Stores MAY ignore or defer the `lastAccessed` change at the cost of affecting how cookies are selected for automatic deletion.\n *\n * - Stores may wish to optimize changing the `value` of the cookie in the store versus storing a new cookie.\n *\n * - The `newCookie` and `oldCookie` objects MUST NOT be modified.\n *\n * @param oldCookie - the cookie that is already present in the store.\n * @param newCookie - the cookie to replace the one already present in the store.\n */\n updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void>\n /**\n * Update an existing {@link Cookie}. The implementation MUST update the `value` for a cookie with the same `domain`,\n * `path`, and `key`. The implementation SHOULD check that the old value in the store is equivalent to oldCookie -\n * how the conflict is resolved is up to the store.\n *\n * @remarks\n * - The `lastAccessed` property is always different between the two objects (to the precision possible via JavaScript's clock).\n *\n * - Both `creation` and `creationIndex` are guaranteed to be the same.\n *\n * - Stores MAY ignore or defer the `lastAccessed` change at the cost of affecting how cookies are selected for automatic deletion.\n *\n * - Stores may wish to optimize changing the `value` of the cookie in the store versus storing a new cookie.\n *\n * - The `newCookie` and `oldCookie` objects MUST NOT be modified.\n *\n * @param oldCookie - the cookie that is already present in the store.\n * @param newCookie - the cookie to replace the one already present in the store.\n * @param callback - A function to call when the cookie has been updated or an error has occurred.\n */\n updateCookie(\n oldCookie: Cookie,\n newCookie: Cookie,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n updateCookie(\n _oldCookie: Cookie,\n _newCookie: Cookie,\n _callback?: ErrorCallback,\n ): unknown {\n // recommended default implementation:\n // return this.putCookie(newCookie, cb);\n throw new Error('updateCookie is not implemented')\n }\n\n /**\n * Remove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n */\n removeCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n ): Promise<void>\n /**\n * Remove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n * @param callback - A function to call when the cookie has been removed or an error occurs.\n */\n removeCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n removeCookie(\n _domain: Nullable<string>,\n _path: Nullable<string>,\n _key: Nullable<string>,\n _callback?: ErrorCallback,\n ): unknown {\n throw new Error('removeCookie is not implemented')\n }\n\n /**\n * Removes matching cookies from the store. The `path` parameter is optional and if missing,\n * means all paths in a domain should be removed.\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n */\n removeCookies(domain: string, path: Nullable<string>): Promise<void>\n /**\n * Removes matching cookies from the store. The `path` parameter is optional and if missing,\n * means all paths in a domain should be removed.\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param callback - A function to call when the cookies have been removed or an error occurs.\n */\n removeCookies(\n domain: string,\n path: Nullable<string>,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n removeCookies(\n _domain: string,\n _path: Nullable<string>,\n _callback?: ErrorCallback,\n ): unknown {\n throw new Error('removeCookies is not implemented')\n }\n\n /**\n * Removes all cookies from the store.\n */\n removeAllCookies(): Promise<void>\n /**\n * Removes all cookies from the store.\n *\n * @param callback - A function to call when all the cookies have been removed or an error occurs.\n */\n removeAllCookies(callback: ErrorCallback): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n removeAllCookies(_callback?: ErrorCallback): unknown {\n throw new Error('removeAllCookies is not implemented')\n }\n\n /**\n * Gets all the cookies in the store.\n *\n * @remarks\n * - Cookies SHOULD be returned in creation order to preserve sorting via {@link cookieCompare}.\n */\n getAllCookies(): Promise<Cookie[]>\n /**\n * Gets all the cookies in the store.\n *\n * @remarks\n * - Cookies SHOULD be returned in creation order to preserve sorting via {@link cookieCompare}.\n *\n * @param callback - A function to call when all the cookies have been retrieved or an error occurs.\n */\n getAllCookies(callback: Callback<Cookie[]>): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n getAllCookies(_callback?: Callback<Cookie[]>): unknown {\n throw new Error(\n 'getAllCookies is not implemented (therefore jar cannot be serialized)',\n )\n }\n}\n","/**\n * A callback function that accepts an error or a result.\n * @public\n */\nexport interface Callback<T> {\n (error: Error, result?: never): void\n (error: null, result: T): void\n}\n\n/**\n * A callback function that only accepts an error.\n * @public\n */\nexport interface ErrorCallback {\n (error: Error | null): void\n}\n\n/**\n * The inverse of NonNullable<T>.\n * @public\n */\nexport type Nullable<T> = T | null | undefined\n\n/** Wrapped `Object.prototype.toString`, so that you don't need to remember to use `.call()`. */\nexport const objectToString = (obj: unknown): string =>\n Object.prototype.toString.call(obj)\n\n/**\n * Converts an array to string, safely handling symbols, null prototype objects, and recursive arrays.\n */\nconst safeArrayToString = (\n arr: unknown[],\n seenArrays: WeakSet<object>,\n): string => {\n // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString#description\n if (typeof arr.join !== 'function') return objectToString(arr)\n seenArrays.add(arr)\n const mapped = arr.map((val) =>\n val === null || val === undefined || seenArrays.has(val)\n ? ''\n : safeToStringImpl(val, seenArrays),\n )\n return mapped.join()\n}\n\nconst safeToStringImpl = (val: unknown, seenArrays = new WeakSet()): string => {\n // Using .toString() fails for null/undefined and implicit conversion (val + \"\") fails for symbols\n // and objects with null prototype\n if (typeof val !== 'object' || val === null) {\n return String(val)\n } else if (typeof val.toString === 'function') {\n return Array.isArray(val)\n ? // Arrays have a weird custom toString that we need to replicate\n safeArrayToString(val, seenArrays)\n : // eslint-disable-next-line @typescript-eslint/no-base-to-string\n String(val)\n } else {\n // This case should just be objects with null prototype, so we can just use Object#toString\n return objectToString(val)\n }\n}\n\n/** Safely converts any value to string, using the value's own `toString` when available. */\nexport const safeToString = (val: unknown): string => safeToStringImpl(val)\n\n/** Utility object for promise/callback interop. */\nexport interface PromiseCallback<T> {\n promise: Promise<T>\n callback: Callback<T>\n resolve: (value: T) => Promise<T>\n reject: (error: Error) => Promise<T>\n}\n\n/** Converts a callback into a utility object where either a callback or a promise can be used. */\nexport function createPromiseCallback<T>(cb?: Callback<T>): PromiseCallback<T> {\n let callback: Callback<T>\n let resolve: (result: T) => void\n let reject: (error: Error) => void\n\n const promise = new Promise<T>((_resolve, _reject) => {\n resolve = _resolve\n reject = _reject\n })\n\n if (typeof cb === 'function') {\n callback = (err, result): void => {\n try {\n if (err) cb(err)\n // If `err` is null, we know `result` must be `T`\n // The assertion isn't *strictly* correct, as `T` could be nullish, but, ehh, good enough...\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n else cb(null, result!)\n } catch (e) {\n reject(e instanceof Error ? e : new Error())\n }\n }\n } else {\n callback = (err, result): void => {\n try {\n // If `err` is null, we know `result` must be `T`\n // The assertion isn't *strictly* correct, as `T` could be nullish, but, ehh, good enough...\n if (err) reject(err)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n else resolve(result!)\n } catch (e) {\n reject(e instanceof Error ? e : new Error())\n }\n }\n }\n\n return {\n promise,\n callback,\n resolve: (value: T): Promise<T> => {\n callback(null, value)\n return promise\n },\n reject: (error: Error): Promise<T> => {\n callback(error)\n return promise\n },\n }\n}\n\nexport function inOperator<K extends string, T extends object>(\n k: K,\n o: T,\n): o is T & Record<K, unknown> {\n return k in o\n}\n","import type { Cookie } from './cookie/cookie.js'\nimport { pathMatch } from './pathMatch.js'\nimport { permuteDomain } from './permuteDomain.js'\nimport { Store } from './store.js'\nimport {\n Callback,\n createPromiseCallback,\n ErrorCallback,\n Nullable,\n} from './utils.js'\n\n/**\n * The internal structure used in {@link MemoryCookieStore}.\n * @internal\n */\nexport type MemoryCookieStoreIndex = {\n [domain: string]: {\n [path: string]: {\n [key: string]: Cookie\n }\n }\n}\n\n/**\n * An in-memory {@link Store} implementation for {@link CookieJar}. This is the default implementation used by\n * {@link CookieJar} and supports both async and sync operations. Also supports serialization, getAllCookies, and removeAllCookies.\n * @public\n */\nexport class MemoryCookieStore extends Store {\n /**\n * This value is `true` since {@link MemoryCookieStore} implements synchronous functionality.\n */\n override synchronous: boolean\n\n /**\n * @internal\n */\n idx: MemoryCookieStoreIndex\n\n /**\n * Create a new {@link MemoryCookieStore}.\n */\n constructor() {\n super()\n this.synchronous = true\n this.idx = Object.create(null) as MemoryCookieStoreIndex\n }\n\n /**\n * Retrieve a {@link Cookie} with the given `domain`, `path`, and `key` (`name`). The RFC maintains that exactly\n * one of these cookies should exist in a store. If the store is using versioning, this means that the latest or\n * newest such cookie should be returned.\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n */\n override findCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n ): Promise<Cookie | undefined>\n /**\n * Retrieve a {@link Cookie} with the given `domain`, `path`, and `key` (`name`). The RFC maintains that exactly\n * one of these cookies should exist in a store. If the store is using versioning, this means that the latest or\n * newest such cookie should be returned.\n *\n * Callback takes an error and the resulting Cookie object. If no cookie is found then null MUST be passed instead (that is, not an error).\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n * @param callback - A function to call with either the found cookie or an error.\n */\n override findCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n callback: Callback<Cookie | undefined>,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override findCookie(\n domain: Nullable<string>,\n path: Nullable<string>,\n key: Nullable<string>,\n callback?: Callback<Cookie | undefined>,\n ): unknown {\n const promiseCallback = createPromiseCallback(callback)\n if (domain == null || path == null || key == null) {\n return promiseCallback.resolve(undefined)\n }\n const result = this.idx[domain]?.[path]?.[key]\n return promiseCallback.resolve(result)\n }\n\n /**\n * Locates all {@link Cookie} values matching the given `domain` and `path`.\n *\n * The resulting list is checked for applicability to the current request according to the RFC (`domain-match`, `path-match`,\n * `http-only-flag`, `secure-flag`, `expiry`, and so on), so it's OK to use an optimistic search algorithm when implementing\n * this method. However, the search algorithm used SHOULD try to find cookies that {@link domainMatch} the `domain` and\n * {@link pathMatch} the `path` in order to limit the amount of checking that needs to be done.\n *\n * @remarks\n * - As of version `0.9.12`, the `allPaths` option to cookiejar.getCookies() above causes the path here to be `null`.\n *\n * - If the `path` is `null`, `path-matching` MUST NOT be performed (that is, `domain-matching` only).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param allowSpecialUseDomain - If `true` then special-use domain suffixes, will be allowed in matches. Defaults to `false`.\n */\n override findCookies(\n domain: string,\n path: string,\n allowSpecialUseDomain?: boolean,\n ): Promise<Cookie[]>\n /**\n * Locates all {@link Cookie} values matching the given `domain` and `path`.\n *\n * The resulting list is checked for applicability to the current request according to the RFC (`domain-match`, `path-match`,\n * `http-only-flag`, `secure-flag`, `expiry`, and so on), so it's OK to use an optimistic search algorithm when implementing\n * this method. However, the search algorithm used SHOULD try to find cookies that {@link domainMatch} the `domain` and\n * {@link pathMatch} the `path` in order to limit the amount of checking that needs to be done.\n *\n * @remarks\n * - As of version `0.9.12`, the `allPaths` option to cookiejar.getCookies() above causes the path here to be `null`.\n *\n * - If the `path` is `null`, `path-matching` MUST NOT be performed (that is, `domain-matching` only).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param allowSpecialUseDomain - If `true` then special-use domain suffixes, will be allowed in matches. Defaults to `false`.\n * @param callback - A function to call with either the found cookies or an error.\n */\n override findCookies(\n domain: string,\n path: string,\n allowSpecialUseDomain?: boolean,\n callback?: Callback<Cookie[]>,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override findCookies(\n domain: string,\n path: string,\n allowSpecialUseDomain: boolean | Callback<Cookie[]> = false,\n callback?: Callback<Cookie[]>,\n ): unknown {\n if (typeof allowSpecialUseDomain === 'function') {\n callback = allowSpecialUseDomain\n // TODO: It's weird that `allowSpecialUseDomain` defaults to false with no callback,\n // but true with a callback. This is legacy behavior from v4.\n allowSpecialUseDomain = true\n }\n\n const results: Cookie[] = []\n const promiseCallback = createPromiseCallback<Cookie[]>(callback)\n\n if (!domain) {\n return promiseCallback.resolve([])\n }\n\n let pathMatcher: (\n domainIndex: MemoryCookieStoreIndex[string] | undefined,\n ) => void\n if (!path) {\n // null means \"all paths\"\n pathMatcher = function matchAll(domainIndex): void {\n for (const curPath in domainIndex) {\n const pathIndex = domainIndex[curPath]\n for (const key in pathIndex) {\n const value = pathIndex[key]\n if (value) {\n results.push(value)\n }\n }\n }\n }\n } else {\n pathMatcher = function matchRFC(domainIndex): void {\n //NOTE: we should use path-match algorithm from S5.1.4 here\n //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)\n for (const cookiePath in domainIndex) {\n if (pathMatch(path, cookiePath)) {\n const pathIndex = domainIndex[cookiePath]\n for (const key in pathIndex) {\n const value = pathIndex[key]\n if (value) {\n results.push(value)\n }\n }\n }\n }\n }\n }\n\n const domains = permuteDomain(domain, allowSpecialUseDomain) || [domain]\n const idx = this.idx\n domains.forEach((curDomain) => {\n const domainIndex = idx[curDomain]\n if (!domainIndex) {\n return\n }\n pathMatcher(domainIndex)\n })\n\n return promiseCallback.resolve(results)\n }\n\n /**\n * Adds a new {@link Cookie} to the store. The implementation SHOULD replace any existing cookie with the same `domain`,\n * `path`, and `key` properties.\n *\n * @remarks\n * - Depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie`\n * that a duplicate `putCookie` can occur.\n *\n * - The {@link Cookie} object MUST NOT be modified; as the caller has already updated the `creation` and `lastAccessed` properties.\n *\n * @param cookie - The cookie to store.\n */\n override putCookie(cookie: Cookie): Promise<void>\n /**\n * Adds a new {@link Cookie} to the store. The implementation SHOULD replace any existing cookie with the same `domain`,\n * `path`, and `key` properties.\n *\n * @remarks\n * - Depending on the nature of the implementation, it's possible that between the call to `fetchCookie` and `putCookie`\n * that a duplicate `putCookie` can occur.\n *\n * - The {@link Cookie} object MUST NOT be modified; as the caller has already updated the `creation` and `lastAccessed` properties.\n *\n * @param cookie - The cookie to store.\n * @param callback - A function to call when the cookie has been stored or an error has occurred.\n */\n override putCookie(cookie: Cookie, callback: ErrorCallback): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override putCookie(cookie: Cookie, callback?: ErrorCallback): unknown {\n const promiseCallback = createPromiseCallback<undefined>(callback)\n\n const { domain, path, key } = cookie\n\n // Guarding against invalid input\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (domain == null || path == null || key == null) {\n return promiseCallback.resolve(undefined)\n }\n\n const domainEntry =\n this.idx[domain] ??\n (Object.create(null) as MemoryCookieStoreIndex[string])\n\n this.idx[domain] = domainEntry\n\n const pathEntry =\n domainEntry[path] ??\n (Object.create(null) as MemoryCookieStoreIndex[string][string])\n\n domainEntry[path] = pathEntry\n\n pathEntry[key] = cookie\n\n return promiseCallback.resolve(undefined)\n }\n\n /**\n * Update an existing {@link Cookie}. The implementation MUST update the `value` for a cookie with the same `domain`,\n * `path`, and `key`. The implementation SHOULD check that the old value in the store is equivalent to oldCookie -\n * how the conflict is resolved is up to the store.\n *\n * @remarks\n * - The `lastAccessed` property is always different between the two objects (to the precision possible via JavaScript's clock).\n *\n * - Both `creation` and `creationIndex` are guaranteed to be the same.\n *\n * - Stores MAY ignore or defer the `lastAccessed` change at the cost of affecting how cookies are selected for automatic deletion.\n *\n * - Stores may wish to optimize changing the `value` of the cookie in the store versus storing a new cookie.\n *\n * - The `newCookie` and `oldCookie` objects MUST NOT be modified.\n *\n * @param oldCookie - the cookie that is already present in the store.\n * @param newCookie - the cookie to replace the one already present in the store.\n */\n override updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void>\n /**\n * Update an existing {@link Cookie}. The implementation MUST update the `value` for a cookie with the same `domain`,\n * `path`, and `key`. The implementation SHOULD check that the old value in the store is equivalent to oldCookie -\n * how the conflict is resolved is up to the store.\n *\n * @remarks\n * - The `lastAccessed` property is always different between the two objects (to the precision possible via JavaScript's clock).\n *\n * - Both `creation` and `creationIndex` are guaranteed to be the same.\n *\n * - Stores MAY ignore or defer the `lastAccessed` change at the cost of affecting how cookies are selected for automatic deletion.\n *\n * - Stores may wish to optimize changing the `value` of the cookie in the store versus storing a new cookie.\n *\n * - The `newCookie` and `oldCookie` objects MUST NOT be modified.\n *\n * @param oldCookie - the cookie that is already present in the store.\n * @param newCookie - the cookie to replace the one already present in the store.\n * @param callback - A function to call when the cookie has been updated or an error has occurred.\n */\n override updateCookie(\n oldCookie: Cookie,\n newCookie: Cookie,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override updateCookie(\n _oldCookie: Cookie,\n newCookie: Cookie,\n callback?: ErrorCallback,\n ): unknown {\n // updateCookie() may avoid updating cookies that are identical. For example,\n // lastAccessed may not be important to some stores and an equality\n // comparison could exclude that field.\n // Don't return a value when using a callback, so that the return type is truly \"void\"\n if (callback) this.putCookie(newCookie, callback)\n else return this.putCookie(newCookie)\n }\n\n /**\n * Remove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n */\n override removeCookie(\n domain: string,\n path: string,\n key: string,\n ): Promise<void>\n /**\n * Remove a cookie from the store (see notes on `findCookie` about the uniqueness constraint).\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param key - The cookie name to match against.\n * @param callback - A function to call when the cookie has been removed or an error occurs.\n */\n override removeCookie(\n domain: string,\n path: string,\n key: string,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override removeCookie(\n domain: string,\n path: string,\n key: string,\n callback?: ErrorCallback,\n ): unknown {\n const promiseCallback = createPromiseCallback<undefined>(callback)\n delete this.idx[domain]?.[path]?.[key]\n return promiseCallback.resolve(undefined)\n }\n\n /**\n * Removes matching cookies from the store. The `path` parameter is optional and if missing,\n * means all paths in a domain should be removed.\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n */\n override removeCookies(domain: string, path: string): Promise<void>\n /**\n * Removes matching cookies from the store. The `path` parameter is optional and if missing,\n * means all paths in a domain should be removed.\n *\n * @param domain - The cookie domain to match against.\n * @param path - The cookie path to match against.\n * @param callback - A function to call when the cookies have been removed or an error occurs.\n */\n override removeCookies(\n domain: string,\n path: string,\n callback: ErrorCallback,\n ): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override removeCookies(\n domain: string,\n path: string,\n callback?: ErrorCallback,\n ): unknown {\n const promiseCallback = createPromiseCallback<undefined>(callback)\n\n const domainEntry = this.idx[domain]\n if (domainEntry) {\n if (path) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete domainEntry[path]\n } else {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete this.idx[domain]\n }\n }\n\n return promiseCallback.resolve(undefined)\n }\n\n /**\n * Removes all cookies from the store.\n */\n override removeAllCookies(): Promise<void>\n /**\n * Removes all cookies from the store.\n *\n * @param callback - A function to call when all the cookies have been removed or an error occurs.\n */\n override removeAllCookies(callback: ErrorCallback): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override removeAllCookies(callback?: ErrorCallback): unknown {\n const promiseCallback = createPromiseCallback<undefined>(callback)\n this.idx = Object.create(null) as MemoryCookieStoreIndex\n return promiseCallback.resolve(undefined)\n }\n\n /**\n * Gets all the cookies in the store.\n *\n * @remarks\n * - Cookies SHOULD be returned in creation order to preserve sorting via {@link cookieCompare}.\n */\n override getAllCookies(): Promise<Cookie[]>\n /**\n * Gets all the cookies in the store.\n *\n * @remarks\n * - Cookies SHOULD be returned in creation order to preserve sorting via {@link cookieCompare}.\n *\n * @param callback - A function to call when all the cookies have been retrieved or an error occurs.\n */\n override getAllCookies(callback: Callback<Cookie[]>): void\n /**\n * @internal No doc because this is an overload that supports the implementation\n */\n override getAllCookies(callback?: Callback<Cookie[]>): unknown {\n const promiseCallback = createPromiseCallback<Cookie[]>(callback)\n\n const cookies: Cookie[] = []\n const idx = this.idx\n\n const domains = Object.keys(idx)\n domains.forEach((domain) => {\n const domainEntry = idx[domain] ?? {}\n const paths = Object.keys(domainEntry)\n paths.forEach((path) => {\n const pathEntry = domainEntry[path] ?? {}\n const keys = Object.keys(pathEntry)\n keys.forEach((key) => {\n const keyEntry = pathEntry[key]\n if (keyEntry != null) {\n cookies.push(keyEntry)\n }\n })\n })\n })\n\n // Sort by creationIndex so deserializing retains the creation order.\n // When implementing your own store, this SHOULD retain the order too\n cookies.sort((a, b) => {\n return (a.creationIndex || 0) - (b.creationIndex || 0)\n })\n\n return promiseCallback.resolve(cookies)\n }\n}\n","/* ************************************************************************************\nExtracted from check-types.js\nhttps://gitlab.com/philbooth/check-types.js\n\nMIT License\n\nCopyright (c) 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Phil Booth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n************************************************************************************ */\n\nimport { Callback, objectToString, safeToString } from './utils.js'\n\n/* Validation functions copied from check-types package - https://www.npmjs.com/package/check-types */\n\n/** Determines whether the argument is a non-empty string. */\nexport function isNonEmptyString(data: unknown): boolean {\n return isString(data) && data !== ''\n}\n\n/** Determines whether the argument is a *valid* Date. */\nexport function isDate(data: unknown): boolean {\n return data instanceof Date && isInteger(data.getTime())\n}\n\n/** Determines whether the argument is the empty string. */\nexport function isEmptyString(data: unknown): boolean {\n return data === '' || (data instanceof String && data.toString() === '')\n}\n\n/** Determines whether the argument is a string. */\nexport function isString(data: unknown): boolean {\n return typeof data === 'string' || data instanceof String\n}\n\n/** Determines whether the string representation of the argument is \"[object Object]\". */\nexport function isObject(data: unknown): boolean {\n return objectToString(data) === '[object Object]'\n}\n\n/** Determines whether the argument is an integer. */\nexport function isInteger(data: unknown): boolean {\n return typeof data === 'number' && data % 1 === 0\n}\n\n/* -- End validation functions -- */\n\n/**\n * When the first argument is false, an error is created with the given message. If a callback is\n * provided, the error is passed to the callback, otherwise the error is thrown.\n */\nexport function validate(\n bool: boolean,\n cbOrMessage?: Callback<never> | string,\n message?: string,\n): void {\n if (bool) return // Validation passes\n const cb = typeof cbOrMessage === 'function' ? cbOrMessage : undefined\n let options = typeof cbOrMessage === 'function' ? message : cbOrMessage\n // The default message prior to v5 was '[object Object]' due to a bug, and the message is kept\n // for backwards compatibility.\n if (!isObject(options)) options = '[object Object]'\n\n const err = new ParameterError(safeToString(options))\n if (cb) cb(err)\n else throw err\n}\n\n/**\n * Represents a validation error.\n * @public\n */\nexport class ParameterError extends Error {}\n","/**\n * The version of `tough-cookie`\n * @public\n */\nexport const version = '6.0.0'\n","/**\n * Cookie prefixes are a way to indicate that a given cookie was set with a set of attributes simply by inspecting the\n * first few characters of the cookie's name. These are defined in {@link https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-13#section-4.1.3 | RFC6265bis - Section 4.1.3}.\n *\n * The following values can be used to configure how a {@link CookieJar} enforces attribute restrictions for Cookie prefixes:\n *\n * - `silent` - Enable cookie prefix