{"version":3,"sources":["../src/sveltekit/index.ts"],"names":["flagImpl","valuePromise","value"],"mappings":"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","sourcesContent":["import type { Handle, RequestEvent } from '@sveltejs/kit';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n  type ApiData,\n  decrypt,\n  encrypt,\n  reportValue,\n  safeJsonStringify,\n  verifyAccess,\n  type JsonValue,\n  type FlagDefinitionsType,\n} from '..';\nimport { Decide, FlagDeclaration, GenerousOption } from '../types';\nimport {\n  type ReadonlyHeaders,\n  HeadersAdapter,\n} from '../spec-extension/adapters/headers';\nimport {\n  type ReadonlyRequestCookies,\n  RequestCookiesAdapter,\n} from '../spec-extension/adapters/request-cookies';\nimport { normalizeOptions } from '../lib/normalize-options';\nimport { RequestCookies } from '@edge-runtime/cookies';\n\nfunction hasOwnProperty<X extends {}, Y extends PropertyKey>(\n  obj: X,\n  prop: Y,\n): obj is X & Record<Y, unknown> {\n  return obj.hasOwnProperty(prop);\n}\n\nconst headersMap = new WeakMap<Headers, ReadonlyHeaders>();\nconst cookiesMap = new WeakMap<Headers, ReadonlyRequestCookies>();\n\nfunction sealHeaders(headers: Headers): ReadonlyHeaders {\n  const cached = headersMap.get(headers);\n  if (cached !== undefined) return cached;\n\n  const sealed = HeadersAdapter.seal(headers);\n  headersMap.set(headers, sealed);\n  return sealed;\n}\n\nfunction sealCookies(headers: Headers): ReadonlyRequestCookies {\n  const cached = cookiesMap.get(headers);\n  if (cached !== undefined) return cached;\n\n  const sealed = RequestCookiesAdapter.seal(new RequestCookies(headers));\n  cookiesMap.set(headers, sealed);\n  return sealed;\n}\n\ntype Flag<ReturnValue> = (() => ReturnValue | Promise<ReturnValue>) & {\n  key: string;\n  description?: string;\n  origin?: string | Record<string, unknown>;\n  options?: GenerousOption<ReturnValue>[];\n};\n\ntype PromisesMap<T> = {\n  [K in keyof T]: Promise<T[K]>;\n};\n\nasync function resolveObjectPromises<T>(obj: PromisesMap<T>): Promise<T> {\n  // Convert the object into an array of [key, promise] pairs\n  const entries = Object.entries(obj) as [keyof T, Promise<any>][];\n\n  // Use Promise.all to wait for all the promises to resolve\n  const resolvedEntries = await Promise.all(\n    entries.map(async ([key, promise]) => {\n      const value = await promise;\n      return [key, value] as [keyof T, T[keyof T]];\n    }),\n  );\n\n  // Convert the array of resolved [key, value] pairs back into an object\n  return Object.fromEntries(resolvedEntries) as T;\n}\n\nfunction getDecide<ValueType, EntitiesType>(\n  definition: FlagDeclaration<ValueType, EntitiesType>,\n): Decide<ValueType, EntitiesType> {\n  return function decide(params) {\n    if (typeof definition.decide === 'function') {\n      return definition.decide(params);\n    }\n    if (typeof definition.adapter?.decide === 'function') {\n      return definition.adapter.decide({ key: definition.key, ...params });\n    }\n    throw new Error(\n      `@vercel/flags: No decide function provided for ${definition.key}`,\n    );\n  };\n}\n\n/**\n * Declares a feature flag\n */\nexport function flag<T>(definition: FlagDeclaration<T, unknown>): Flag<T> {\n  const decide = getDecide<T, unknown>(definition);\n\n  const flagImpl = async function flagImpl(): Promise<T> {\n    const store = flagStorage.getStore();\n\n    if (!store) {\n      throw new Error('@vercel/flags: context not found');\n    }\n\n    if (hasOwnProperty(store.usedFlags, definition.key)) {\n      const valuePromise = store.usedFlags[definition.key];\n      if (typeof valuePromise !== 'undefined') {\n        return valuePromise as Promise<T>;\n      }\n    }\n\n    const overridesCookie = store.event.cookies.get('vercel-flag-overrides');\n    const overrides = overridesCookie\n      ? await decrypt<Record<string, T>>(overridesCookie, store.secret)\n      : undefined;\n\n    if (overrides && hasOwnProperty(overrides, definition.key)) {\n      const value = overrides[definition.key];\n      if (typeof value !== 'undefined') {\n        reportValue(definition.key, value);\n        store.usedFlags[definition.key] = Promise.resolve(value as JsonValue);\n        return value;\n      }\n    }\n\n    const valuePromise = decide(\n      {\n        headers: sealHeaders(store.event.request.headers),\n        cookies: sealCookies(store.event.request.headers),\n      },\n      // @ts-expect-error not part of the type, but we supply it for convenience\n      { event: store.event },\n    );\n    store.usedFlags[definition.key] = valuePromise as Promise<JsonValue>;\n\n    const value = await valuePromise;\n    reportValue(definition.key, value);\n    return value;\n  };\n\n  flagImpl.key = definition.key;\n  flagImpl.defaultValue = definition.defaultValue;\n  flagImpl.origin = definition.origin;\n  flagImpl.description = definition.description;\n  flagImpl.options = definition.options;\n  flagImpl.decide = decide;\n  // flagImpl.identify = definition.identify;\n\n  return flagImpl;\n}\n\nexport function getProviderData(\n  flags: Record<string, Flag<JsonValue>>,\n): ApiData {\n  const definitions = Object.values(flags).reduce<FlagDefinitionsType>(\n    (acc, d) => {\n      acc[d.key] = {\n        options: normalizeOptions(d.options),\n        origin: d.origin,\n        description: d.description,\n      };\n      return acc;\n    },\n    {},\n  );\n\n  return { definitions, hints: [] };\n}\n\ninterface AsyncLocalContext {\n  event: RequestEvent<Partial<Record<string, string>>, string | null>;\n  secret: string;\n  usedFlags: Record<string, Promise<JsonValue>>;\n}\n\nfunction createContext(\n  event: RequestEvent<Partial<Record<string, string>>, string | null>,\n  secret: string,\n): AsyncLocalContext {\n  return {\n    event,\n    secret,\n    usedFlags: {},\n  };\n}\n\nconst flagStorage = new AsyncLocalStorage<AsyncLocalContext>();\n\n/**\n * Establishes context for flags, so they have access to the\n * request and cookie.\n *\n * Also registers evaluated flags, except for flags used only after `resolve` calls in other handlers.\n *\n * @example Usage example in src/hooks.server.ts\n *\n * ```ts\n * import { createHandle } from '@vercel/flags/sveltekit';\n * import { FLAGS_SECRET } from '$env/static/private';\n * import * as flags from '$lib/flags';\n *\n * export const handle = createHandle({ secret: FLAGS_SECRET, flags });\n * ```\n *\n * @example Usage example in src/hooks.server.ts with other handlers\n *\n * Note that when composing `createHandle` with `sequence` then `createHandle` should come first. Only handlers after it will be able to access feature flags.\n */\nexport function createHandle({\n  secret,\n  flags,\n}: {\n  secret: string;\n  flags?: Record<string, Flag<JsonValue>>;\n}): Handle {\n  return function handle({ event, resolve }) {\n    if (\n      flags &&\n      // avoid creating the URL object for every request by checking with includes() first\n      event.request.url.includes('/.well-known/') &&\n      new URL(event.request.url).pathname === '/.well-known/vercel/flags'\n    ) {\n      return handleWellKnownFlagsRoute(event, secret, flags);\n    }\n\n    const flagContext = createContext(event, secret);\n    return flagStorage.run(flagContext, () =>\n      resolve(event, {\n        transformPageChunk: async ({ html }) => {\n          const store = flagStorage.getStore();\n          if (!store || Object.keys(store.usedFlags).length === 0) return html;\n\n          // This is for reporting which flags were used when this page was generated,\n          // so the value shows up in Vercel Toolbar, without the client ever being\n          // aware of this feature flag.\n          const encryptedFlagValues = await encrypt(\n            await resolveObjectPromises(store.usedFlags),\n            secret,\n          );\n\n          return html.replace(\n            '</body>',\n            `<script type=\"application/json\" data-flag-values>${safeJsonStringify(encryptedFlagValues)}</script></body>`,\n          );\n        },\n      }),\n    );\n  };\n}\n\nasync function handleWellKnownFlagsRoute(\n  event: RequestEvent<Partial<Record<string, string>>, string | null>,\n  secret: string,\n  flags: Record<string, Flag<JsonValue>>,\n) {\n  const access = await verifyAccess(\n    event.request.headers.get('Authorization'),\n    secret,\n  );\n  if (!access) return new Response(null, { status: 401 });\n  return Response.json(getProviderData(flags));\n}\n"]}