{"version":3,"sources":["../../../../../../src/server/web/spec-extension/adapters/request-cookies.ts"],"sourcesContent":["import { RequestCookies } from '../cookies'\n\nimport { ResponseCookies } from '../cookies'\nimport { ReflectAdapter } from './reflect'\nimport { workAsyncStorage } from '../../../app-render/work-async-storage.external'\nimport type { RequestStore } from '../../../app-render/work-unit-async-storage.external'\nimport { ActionDidRevalidateStaticAndDynamic } from '../../../../shared/lib/action-revalidation-kind'\n\n/**\n * @internal\n */\nexport class ReadonlyRequestCookiesError extends Error {\n  constructor() {\n    super(\n      'Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#options'\n    )\n  }\n\n  public static callable() {\n    throw new ReadonlyRequestCookiesError()\n  }\n}\n\n// We use this to type some APIs but we don't construct instances directly\nexport type { ResponseCookies }\n\n// The `cookies()` API is a mix of request and response cookies. For `.get()` methods,\n// we want to return the request cookie if it exists. For mutative methods like `.set()`,\n// we want to return the response cookie.\nexport type ReadonlyRequestCookies = Omit<\n  RequestCookies,\n  'set' | 'clear' | 'delete'\n> &\n  Pick<ResponseCookies, 'set' | 'delete'>\n\nexport class RequestCookiesAdapter {\n  public static seal(cookies: RequestCookies): ReadonlyRequestCookies {\n    return new Proxy(cookies as any, {\n      get(target, prop, receiver) {\n        switch (prop) {\n          case 'clear':\n          case 'delete':\n          case 'set':\n            return ReadonlyRequestCookiesError.callable\n          default:\n            return ReflectAdapter.get(target, prop, receiver)\n        }\n      },\n    })\n  }\n}\n\nconst SYMBOL_MODIFY_COOKIE_VALUES = Symbol.for('next.mutated.cookies')\n\nexport function getModifiedCookieValues(\n  cookies: ResponseCookies\n): ResponseCookie[] {\n  const modified: ResponseCookie[] | undefined = (cookies as unknown as any)[\n    SYMBOL_MODIFY_COOKIE_VALUES\n  ]\n  if (!modified || !Array.isArray(modified) || modified.length === 0) {\n    return []\n  }\n\n  return modified\n}\n\ntype SetCookieArgs =\n  | [key: string, value: string, cookie?: Partial<ResponseCookie>]\n  | [options: ResponseCookie]\n\nexport function appendMutableCookies(\n  headers: Headers,\n  mutableCookies: ResponseCookies\n): boolean {\n  const modifiedCookieValues = getModifiedCookieValues(mutableCookies)\n  if (modifiedCookieValues.length === 0) {\n    return false\n  }\n\n  // Return a new response that extends the response with\n  // the modified cookies as fallbacks. `res` cookies\n  // will still take precedence.\n  const resCookies = new ResponseCookies(headers)\n  const returnedCookies = resCookies.getAll()\n\n  // Set the modified cookies as fallbacks.\n  for (const cookie of modifiedCookieValues) {\n    resCookies.set(cookie)\n  }\n\n  // Set the original cookies as the final values.\n  for (const cookie of returnedCookies) {\n    resCookies.set(cookie)\n  }\n\n  return true\n}\n\ntype ResponseCookie = NonNullable<\n  ReturnType<InstanceType<typeof ResponseCookies>['get']>\n>\n\nexport class MutableRequestCookiesAdapter {\n  public static wrap(\n    cookies: RequestCookies,\n    onUpdateCookies?: (cookies: string[]) => void\n  ): ResponseCookies {\n    const responseCookies = new ResponseCookies(new Headers())\n    for (const cookie of cookies.getAll()) {\n      responseCookies.set(cookie)\n    }\n\n    let modifiedValues: ResponseCookie[] = []\n    const modifiedCookies = new Set<string>()\n    const updateResponseCookies = () => {\n      // TODO-APP: change method of getting workStore\n      const workStore = workAsyncStorage.getStore()\n      if (workStore) {\n        workStore.pathWasRevalidated = ActionDidRevalidateStaticAndDynamic\n      }\n\n      const allCookies = responseCookies.getAll()\n      modifiedValues = allCookies.filter((c) => modifiedCookies.has(c.name))\n      if (onUpdateCookies) {\n        const serializedCookies: string[] = []\n        for (const cookie of modifiedValues) {\n          const tempCookies = new ResponseCookies(new Headers())\n          tempCookies.set(cookie)\n          serializedCookies.push(tempCookies.toString())\n        }\n\n        onUpdateCookies(serializedCookies)\n      }\n    }\n\n    const wrappedCookies = new Proxy(responseCookies, {\n      get(target, prop, receiver) {\n        switch (prop) {\n          // A special symbol to get the modified cookie values\n          case SYMBOL_MODIFY_COOKIE_VALUES:\n            return modifiedValues\n\n          // TODO: Throw error if trying to set a cookie after the response\n          // headers have been set.\n          case 'delete':\n            return function (...args: [string] | [ResponseCookie]) {\n              modifiedCookies.add(\n                typeof args[0] === 'string' ? args[0] : args[0].name\n              )\n              try {\n                target.delete(...args)\n                return wrappedCookies\n              } finally {\n                updateResponseCookies()\n              }\n            }\n          case 'set':\n            return function (...args: SetCookieArgs) {\n              modifiedCookies.add(\n                typeof args[0] === 'string' ? args[0] : args[0].name\n              )\n              try {\n                target.set(...args)\n                return wrappedCookies\n              } finally {\n                updateResponseCookies()\n              }\n            }\n\n          default:\n            return ReflectAdapter.get(target, prop, receiver)\n        }\n      },\n    })\n\n    return wrappedCookies\n  }\n}\n\nexport function createCookiesWithMutableAccessCheck(\n  requestStore: RequestStore\n): ResponseCookies {\n  const wrappedCookies = new Proxy(requestStore.mutableCookies, {\n    get(target, prop, receiver) {\n      switch (prop) {\n        case 'delete':\n          return function (...args: [string] | [ResponseCookie]) {\n            ensureCookiesAreStillMutable(requestStore, 'cookies().delete')\n            target.delete(...args)\n            return wrappedCookies\n          }\n        case 'set':\n          return function (...args: SetCookieArgs) {\n            ensureCookiesAreStillMutable(requestStore, 'cookies().set')\n            target.set(...args)\n            return wrappedCookies\n          }\n\n        default:\n          return ReflectAdapter.get(target, prop, receiver)\n      }\n    },\n  })\n  return wrappedCookies\n}\n\nexport function areCookiesMutableInCurrentPhase(requestStore: RequestStore) {\n  return requestStore.phase === 'action'\n}\n\n/** Ensure that cookies() starts throwing on mutation\n * if we changed phases and can no longer mutate.\n *\n * This can happen when going:\n *   'render' -> 'after'\n *   'action' -> 'render'\n * */\nfunction ensureCookiesAreStillMutable(\n  requestStore: RequestStore,\n  _callingExpression: string\n) {\n  if (!areCookiesMutableInCurrentPhase(requestStore)) {\n    // TODO: maybe we can give a more precise error message based on callingExpression?\n    throw new ReadonlyRequestCookiesError()\n  }\n}\n\nexport function responseCookiesToRequestCookies(\n  responseCookies: ResponseCookies\n): RequestCookies {\n  const requestCookies = new RequestCookies(new Headers())\n  for (const cookie of responseCookies.getAll()) {\n    requestCookies.set(cookie)\n  }\n  return requestCookies\n}\n"],"names":["RequestCookies","ResponseCookies","ReflectAdapter","workAsyncStorage","ActionDidRevalidateStaticAndDynamic","ReadonlyRequestCookiesError","Error","constructor","callable","RequestCookiesAdapter","seal","cookies","Proxy","get","target","prop","receiver","SYMBOL_MODIFY_COOKIE_VALUES","Symbol","for","getModifiedCookieValues","modified","Array","isArray","length","appendMutableCookies","headers","mutableCookies","modifiedCookieValues","resCookies","returnedCookies","getAll","cookie","set","MutableRequestCookiesAdapter","wrap","onUpdateCookies","responseCookies","Headers","modifiedValues","modifiedCookies","Set","updateResponseCookies","workStore","getStore","pathWasRevalidated","allCookies","filter","c","has","name","serializedCookies","tempCookies","push","toString","wrappedCookies","args","add","delete","createCookiesWithMutableAccessCheck","requestStore","ensureCookiesAreStillMutable","areCookiesMutableInCurrentPhase","phase","_callingExpression","responseCookiesToRequestCookies","requestCookies"],"mappings":"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","ignoreList":[0]}