@web-widget/flags-kit
Version:
Flags SDK by Vercel - The feature flags toolkit for Next.js, SvelteKit, and Web Router - Enhanced fork with improved Web Router support
1 lines • 27.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/sveltekit/index.ts","../src/sveltekit/precompute.ts","../src/sveltekit/env.ts"],"names":["flag","serialize","deserialize","flagImpl","valuePromise","value","entities","encryptFlagValues","decryptFlagValues","encryptOverrides","decryptOverrides","encryptFlagDefinitions","decryptFlagDefinitions","precompute","generatePermutations"],"mappings":"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","sourcesContent":["import {\n error,\n json,\n type Handle,\n type RequestEvent,\n type RequestHandler,\n} from '@sveltejs/kit';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n type ApiData,\n reportValue,\n safeJsonStringify,\n verifyAccess,\n type JsonValue,\n type FlagDefinitionsType,\n encryptFlagValues as _encryptFlagValues,\n decryptFlagValues as _decryptFlagValues,\n encryptOverrides as _encryptOverrides,\n decryptOverrides as _decryptOverrides,\n encryptFlagDefinitions as _encryptFlagDefinitions,\n decryptFlagDefinitions as _decryptFlagDefinitions,\n version,\n} from '..';\nimport {\n Decide,\n FlagDeclaration,\n FlagOverridesType,\n FlagValuesType,\n Identify,\n} 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';\nimport { Flag, FlagsArray } from './types';\nimport {\n generatePermutations as _generatePermutations,\n getPrecomputed,\n precompute as _precompute,\n} from './precompute';\nimport { tryGetSecret } from './env';\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(\n headers,\n 'Headers cannot be modified in SvelteKit. Headers are read-only during request processing.',\n );\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(\n new RequestCookies(headers),\n 'Cookies cannot be modified in SvelteKit. Use the cookies API from @sveltejs/kit to set cookies. Read more: https://kit.svelte.dev/docs/load#cookies',\n );\n cookiesMap.set(headers, sealed);\n return sealed;\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(`flags: No decide function provided for ${definition.key}`);\n };\n}\n\nfunction getIdentify<ValueType, EntitiesType>(\n definition: FlagDeclaration<ValueType, EntitiesType>,\n): Identify<EntitiesType> | undefined {\n if (typeof definition.identify === 'function') {\n return definition.identify;\n }\n if (typeof definition.adapter?.identify === 'function') {\n return definition.adapter.identify;\n }\n}\n\n/**\n * Used when a flag is called outside of a request context, i.e. outside of the lifecycle of the `handle` hook.\n * This could be the case when the flag is called from edge middleware.\n */\nconst requestMap = new WeakMap<Request, AsyncLocalContext>();\n\n/**\n * Declares a feature flag\n */\nexport function flag<\n ValueType extends JsonValue = boolean | string | number,\n EntitiesType = any,\n>(definition: FlagDeclaration<ValueType, EntitiesType>): Flag<ValueType> {\n const decide = getDecide<ValueType, EntitiesType>(definition);\n const identify = getIdentify(definition);\n\n const flagImpl = async function flagImpl(\n requestOrCode?: string | Request,\n flagsArrayOrSecret?: string | Flag<any>[],\n ): Promise<ValueType> {\n let store = flagStorage.getStore();\n\n if (!store) {\n if (requestOrCode instanceof Request) {\n store = requestMap.get(requestOrCode);\n if (!store) {\n store = createContext(\n requestOrCode,\n (flagsArrayOrSecret as string) ?? (await tryGetSecret()),\n );\n requestMap.set(requestOrCode, store);\n }\n } else {\n throw new Error('flags: Neither context found nor Request provided');\n }\n }\n\n if (\n typeof requestOrCode === 'string' &&\n Array.isArray(flagsArrayOrSecret)\n ) {\n return getPrecomputed(\n definition.key,\n flagsArrayOrSecret,\n requestOrCode,\n store.secret,\n );\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<ValueType>;\n }\n }\n\n const headers = sealHeaders(store.request.headers);\n const cookies = sealCookies(store.request.headers);\n\n const overridesCookie = cookies.get('vercel-flag-overrides')?.value;\n const overrides = overridesCookie\n ? await _decryptOverrides(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 let entities: EntitiesType | undefined;\n if (identify) {\n // Deduplicate calls to identify, key being the function itself\n if (!store.identifiers.has(identify)) {\n const entities = identify({\n headers,\n cookies,\n });\n store.identifiers.set(identify, entities);\n }\n\n entities = (await store.identifiers.get(identify)) as EntitiesType;\n }\n\n const valuePromise = decide({\n headers,\n cookies,\n entities,\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 = normalizeOptions(definition.options);\n flagImpl.decide = decide;\n flagImpl.identify = identify;\n\n return flagImpl;\n}\n\nexport function getProviderData(flags: Record<string, Flag<any>>): 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 request: Request;\n secret: string;\n params: Record<string, string>;\n usedFlags: Record<string, Promise<JsonValue>>;\n identifiers: Map<Identify<unknown>, ReturnType<Identify<unknown>>>;\n}\n\nfunction createContext(\n request: Request,\n secret: string,\n params?: Record<string, string>,\n): AsyncLocalContext {\n return {\n request,\n secret,\n params: params ?? {},\n usedFlags: {},\n identifiers: new Map(),\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 'flags/sveltekit';\n * import * as flags from '$lib/flags';\n *\n * export const handle = createHandle({ 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<any>>;\n}): Handle {\n return async function handle({ event, resolve }) {\n secret ??= await tryGetSecret(secret);\n\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(\n event.request,\n secret,\n event.params as Record<string, string>,\n );\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 _encryptFlagValues(\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<any>>,\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 const providerData = getProviderData(flags);\n return Response.json(providerData, {\n headers: { 'x-flags-sdk-version': version },\n });\n}\n\nexport async function encryptFlagValues(\n value: FlagValuesType,\n secret?: string,\n) {\n return _encryptFlagValues(value, await tryGetSecret(secret));\n}\n\nexport async function decryptFlagValues(\n encryptedData: string,\n secret?: string,\n) {\n return _decryptFlagValues(encryptedData, await tryGetSecret(secret));\n}\n\nexport async function encryptOverrides(\n overrides: FlagOverridesType,\n secret?: string,\n) {\n return _encryptOverrides(overrides, await tryGetSecret(secret));\n}\n\nexport async function decryptOverrides(encryptedData: string, secret?: string) {\n return _decryptOverrides(encryptedData, await tryGetSecret(secret));\n}\n\nexport async function encryptFlagDefinitions(\n value: FlagDefinitionsType,\n secret?: string,\n) {\n return _encryptFlagDefinitions(value, await tryGetSecret(secret));\n}\n\nexport async function decryptFlagDefinitions(\n encryptedData: string,\n secret?: string,\n) {\n return _decryptFlagDefinitions(encryptedData, await tryGetSecret(secret));\n}\n\n/**\n * Evaluate a list of feature flags and generate a signed string representing their values.\n *\n * This convenience function call combines `evaluate` and `serialize`.\n *\n * @param flags - list of flags\n * @returns - a string representing evaluated flags\n */\nexport async function precompute<T extends FlagsArray>(\n flags: T,\n request: Request,\n secret?: string,\n): Promise<string> {\n return _precompute(flags, request, await tryGetSecret(secret));\n}\n\n/**\n * Generates all permutations given a list of feature flags based on the options declared on each flag.\n * @param flags - The list of feature flags\n * @param filter - An optional filter function which gets called with each permutation.\n * @param secret - The secret sign the generated permutation with\n * @returns An array of strings representing each permutation\n */\nexport async function generatePermutations(\n flags: FlagsArray,\n filter: ((permutation: Record<string, JsonValue>) => boolean) | null = null,\n secret?: string,\n): Promise<string[]> {\n return _generatePermutations(flags, filter, await tryGetSecret(secret));\n}\n\n/**\n * Creates a well-known flags endpoint for SvelteKit.\n * @param getApiData a function returning the API data\n * @param options accepts a secret\n * @returns a RequestHandler\n */\nexport function createFlagsDiscoveryEndpoint(\n getApiData: (event: RequestEvent) => Promise<ApiData> | ApiData,\n options?: {\n secret?: string | undefined;\n },\n) {\n const requestHandler: RequestHandler = async (event) => {\n const access = await verifyAccess(\n event.request.headers.get('Authorization'),\n options?.secret,\n );\n if (!access) error(401);\n\n const apiData = await getApiData(event);\n return json(apiData, { headers: { 'x-flags-sdk-version': version } });\n };\n\n return requestHandler;\n}\n","import type { Flag, FlagsArray } from './types';\nimport type { JsonValue } from '..';\nimport * as s from '../lib/serialization';\n\ntype ValuesArray = readonly any[];\n\n/**\n * Resolves a list of flags\n * @param flags - list of flags\n * @returns - an array of evaluated flag values with one entry per flag\n */\nasync function evaluate<T extends FlagsArray>(\n flags: T,\n request: Request,\n): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>> }> {\n return Promise.all(flags.map((flag) => flag(request))) as Promise<{\n [K in keyof T]: Awaited<ReturnType<T[K]>>;\n }>;\n}\n\n/**\n * Evaluate a list of feature flags and generate a signed string representing their values.\n *\n * This convenience function call combines `evaluate` and `serialize`.\n *\n * @param flags - list of flags\n * @returns - a string representing evaluated flags\n */\nexport async function precompute<T extends FlagsArray>(\n flags: T,\n request: Request,\n secret: string,\n): Promise<string> {\n const values = await evaluate(flags, request);\n return serialize(flags, values, secret);\n}\n\n/**\n * Combines flag declarations with values.\n * @param flags - flag declarations\n * @param values - flag values\n * @returns - A record where the keys are flag keys and the values are flag values.\n */\nfunction combine(flags: FlagsArray, values: ValuesArray) {\n return Object.fromEntries(flags.map((flag, i) => [flag.key, values[i]]));\n}\n\n/**\n * Takes a list of feature flag declarations and their values and turns them into a short, signed string.\n *\n * The returned string is signed to avoid enumeration attacks.\n *\n * When a feature flag's `options` contains the value the flag resolved to, then the encoding will store it's index only, leading to better compression. Boolean values and null are compressed even when the options are not declared on the flag.\n *\n * @param flags - A list of feature flags\n * @param values - A list of the values of the flags declared in ´flags`\n * @param secret - The secret to use for signing the result\n * @returns - A short string representing the values.\n */\nasync function serialize(\n flags: FlagsArray,\n values: ValuesArray,\n secret: string,\n) {\n return s.serialize(combine(flags, values), flags, secret);\n}\n\n/**\n * Decodes all flags given the list of flags used to encode. Returns an object consisting of each flag's key and its resolved value.\n * @param flags - Flags used when `code` was generated by `precompute` or `serialize`.\n * @param code - The code returned from `serialize`\n * @param secret - The secret to use for signing the result\n * @returns - An object consisting of each flag's key and its resolved value.\n */\nasync function deserialize(flags: FlagsArray, code: string, secret: string) {\n return s.deserialize(code, flags, secret);\n}\n\n/**\n * Decodes the value of one or multiple flags given the list of flags used to encode and the code.\n *\n * @param flagKey - Flag or list of flags to decode\n * @param precomputeFlags - Flags used when `code` was generated by `serialize`\n * @param code - The code returned from `serialize`\n * @param secret - The secret to use for verifying the signature\n */\nexport async function getPrecomputed<T extends JsonValue>(\n flagKey: Flag<T>['key'],\n precomputeFlags: FlagsArray,\n code: string,\n secret: string,\n): Promise<T> {\n const flagSet = await deserialize(precomputeFlags, code, secret);\n\n return flagSet[flagKey];\n}\n\n// see https://stackoverflow.com/a/44344803\nfunction* cartesianIterator<T>(items: T[][]): Generator<T[]> {\n const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];\n for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];\n}\n\n/**\n * Generates all permutations given a list of feature flags based on the options declared on each flag.\n * @param flags - The list of feature flags\n * @param filter - An optional filter function which gets called with each permutation.\n * @param secret - The secret sign the generated permutation with\n * @returns An array of strings representing each permutation\n */\nexport async function generatePermutations(\n flags: FlagsArray,\n filter: ((permutation: Record<string, JsonValue>) => boolean) | null = null,\n secret: string,\n): Promise<string[]> {\n const options = flags.map((flag) => {\n // infer boolean permutations if you don't declare any options.\n //\n // to explicitly opt out you need to use \"filter\"\n if (!flag.options) return [false, true];\n return flag.options.map((option) => option.value);\n });\n\n const list: Record<string, JsonValue>[] = [];\n\n for (const permutation of cartesianIterator(options)) {\n const permObject = permutation.reduce<Record<string, JsonValue>>(\n (acc, value, index) => {\n acc[flags[index]!.key] = value;\n return acc;\n },\n {},\n );\n if (!filter || filter(permObject)) list.push(permObject);\n }\n\n return Promise.all(list.map((values) => s.serialize(values, flags, secret)));\n}\n","// We're doing this dance so that the flags package is usable both in the SvelteKit environment\n// as well as other environments that don't know about '$env/dynamic/private', such as Edge Middleware\nlet default_secret: string | undefined = process.env.FLAGS_SECRET;\n\nexport async function tryGetSecret(secret?: string): Promise<string> {\n if (!default_secret) {\n try {\n // @ts-expect-error SvelteKit will know about this\n // use static instead of dynamic because only the latter is available during prerendering,\n // and in case it's not available through that it should be via process.env above.\n const env = await import('$env/static/private');\n default_secret = env.FLAGS_SECRET;\n } catch (e) {\n // ignore, could happen when importing from an environment that doesn't know this import\n }\n }\n\n secret = secret || default_secret;\n\n if (!secret) {\n throw new Error(\n 'flags: No secret provided. Set an environment variable FLAGS_SECRET or provide a secret to the function.',\n );\n }\n\n return secret;\n}\n"]}