@vercel/flags-core 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.next-js.ts","../src/evaluate.ts","../src/types.ts","../package.json","../src/lib/report-value.ts","../src/controller-fns.ts","../src/create-raw-client.ts","../src/utils/read-bundled-definitions.ts","../src/utils/ingest.ts","../src/utils/backoff.ts","../src/utils/request-context.ts","../src/utils/scheduler.ts","../src/utils/usage/flags-config-read.ts","../src/utils/usage/flags-evaluation.ts","../src/utils/usage-tracker.ts","../src/errors.ts","../src/controller/bundled-source.ts","../src/controller/fetch-datafile.ts","../src/controller/normalized-options.ts","../src/controller/typed-emitter.ts","../src/controller/polling-source.ts","../src/utils/sleep.ts","../src/controller/stream-connection.ts","../src/controller/stream-source.ts","../src/controller/tagged-data.ts","../src/controller/index.ts","../src/controller/auth.ts","../src/utils/sdk-keys.ts","../src/index.make.ts"],"sourcesContent":["/**\n * Exports for Next.js App Router\n *\n * There is also index.default.ts which targets Next.js specifically.\n * If you update this file, please update index.default.ts as well.\n *\n * Try keeping this file small. Export through index.common and index.make.\n *\n * This file should stay equivalent to index.default.ts, except that it\n * declares \"use cache\".\n */\n\nimport { cacheLife } from 'next/cache';\nimport * as fns from './controller-fns';\nimport { createCreateRawClient } from './create-raw-client';\nimport { make } from './index.make';\n\nfunction setCacheLife(): void {\n try {\n // Working around a limitation of cacheLife in older Next.js versions\n // where stale was required to be greater than expire if set concurrently.\n // Instead we do this over two calls.\n cacheLife({ revalidate: 0, expire: 0 });\n cacheLife({ stale: 60 });\n } catch {\n // if we error setting cache life it means we are not in a cache scope\n // The only time that might happen is if next-js entrypoint is used\n // in a context that doesn't process the \"use cache\" directive.\n // In these contexts we don't really need the cache life to be set because there\n // is no Cache Component semantics\n }\n}\n\nconst cachedFns: Parameters<typeof createCreateRawClient>[0] = {\n initialize: async (...args) => {\n 'use cache';\n setCacheLife();\n\n return fns.initialize(...args);\n },\n shutdown: async (...args) => {\n 'use cache';\n setCacheLife();\n return fns.shutdown(...args);\n },\n getDatafile: async (...args) => {\n 'use cache';\n setCacheLife();\n return fns.getDatafile(...args);\n },\n getFallbackDatafile: async (...args) => {\n 'use cache';\n setCacheLife();\n return fns.getFallbackDatafile(...args);\n },\n evaluate: async (...args) => {\n 'use cache';\n setCacheLife();\n return fns.evaluate(...args);\n },\n bulkEvaluate: async (...args) => {\n 'use cache';\n setCacheLife();\n return fns.bulkEvaluate(...args);\n },\n};\n\nexport * from './index.common';\n\n// no JSDoc needed here since editors will use the one if index.default.ts\nexport const { flagsClient, resetDefaultFlagsClient, createClient } = make(\n createCreateRawClient(cachedFns),\n);\n","import { xxHash32 as hashInput } from 'js-xxhash';\nimport {\n Comparator,\n type EvaluationParams,\n type EvaluationResult,\n OutcomeType,\n Packed,\n ResolutionReason,\n type VariantId,\n} from './types';\n\ntype PathArray = (string | number)[];\n\nconst MAX_REGEX_INPUT_LENGTH = 10_000;\n\n/**\n * Bucket space for all traffic splitting. `hashInput` (xxHash32) returns exactly\n * `2**32` distinct values, so we use `2**32` as the space and compare the raw\n * hash against boundaries in it — no modulo (which would bias low buckets), and\n * the final variant's boundary is exactly `2**32` so nothing falls through.\n */\nconst HASH_SPACE = 2 ** 32;\n\n/** Denominator for promille values (rollout slots and segment `passPromille`). */\nconst PROMILLE_SCALE = 100_000;\n\n/**\n * Maps the fraction `numerator / denominator` to a cut point in `[0, HASH_SPACE]`;\n * a hash is \"below\" the fraction iff `hash < boundaryFor(…)`. Splits, rollouts,\n * and segments all cut with this one function, so a rollout at promille `p` is\n * bit-for-bit identical to the split `{ rollFrom: PROMILLE_SCALE - p, rollTo: p }`\n * — which is what lets a flag switch between split and rollout without reassigning\n * anyone. `denominator === 0` yields `NaN`, so evaluation falls through to default.\n */\nfunction boundaryFor(numerator: number, denominator: number): number {\n return Math.floor((numerator / denominator) * HASH_SPACE);\n}\n\n// WeakMaps keyed by datafile objects, so those objects stay pristine (no\n// symbol-keyed props) and serialize cleanly across the RSC boundary; entries\n// are GC'd with the datafile. Split boundaries are static per outcome, so the\n// cumulative cut points are computed once and reused across evaluations.\nconst splitBoundariesCache = new WeakMap<Packed.SplitOutcome, number[]>();\nconst compiledRegexCache = new WeakMap<object, RegExp>();\n\n/**\n * Cumulative hash boundaries for a split, one per variant in index order.\n * Variant `i` is served for hashes in `[boundaries[i-1], boundaries[i])`.\n */\nfunction getSplitBoundaries(outcome: Packed.SplitOutcome): number[] {\n const cached = splitBoundariesCache.get(outcome);\n if (cached) return cached;\n const total = sum(outcome.weights);\n const boundaries: number[] = [];\n let cumulative = 0;\n for (const weight of outcome.weights) {\n cumulative += weight;\n boundaries.push(boundaryFor(cumulative, total));\n }\n splitBoundariesCache.set(outcome, boundaries);\n return boundaries;\n}\n\nfunction getCompiledRegex(rhs: { pattern: string; flags: string }): RegExp {\n const cached = compiledRegexCache.get(rhs);\n if (cached) return cached;\n const compiled = new RegExp(rhs.pattern, rhs.flags.replace(/[gy]/, ''));\n compiledRegexCache.set(rhs, compiled);\n return compiled;\n}\n\nfunction exhaustivenessCheck(_: never): never {\n throw new Error('Exhaustiveness check failed');\n}\n\nfunction getProperty(obj: any, pathArray: PathArray): any {\n return pathArray.reduce((acc: any, key: string | number) => {\n if (acc && key in acc) {\n return acc[key];\n }\n return undefined; // Return undefined if the property is not found\n }, obj);\n}\n\n/**\n * Accesses the value of the given lhs on the provided entities.\n *\n * This must return unknown as we don't know what the library users will pass.\n */\n\nfunction access<T>(lhs: Packed.LHS, params: EvaluationParams<T>): any {\n // we're dealing with an entity\n if (Array.isArray(lhs)) return getProperty(params.entities, lhs);\n\n // Code should never end up here as the segment accessor is handled\n // earlier in the matchConditions() function.\n if (lhs === Packed.AccessorType.SEGMENT)\n throw new Error('Unexpected segment');\n\n throw new Error('Accessor not implemented');\n}\n\nfunction isString(input: unknown): input is string {\n return typeof input === 'string';\n}\n\nfunction isNumber(input: unknown): input is number {\n return typeof input === 'number';\n}\n\nfunction isArray(input: unknown): input is unknown[] {\n return Array.isArray(input);\n}\n\nfunction lower<T>(input: T): T {\n if (typeof input === 'string') return input.toLowerCase() as T;\n if (Array.isArray(input)) return input.map(lower) as T;\n return input;\n}\n\nconst IGNORE_CASE_COMPARATORS: ReadonlySet<Comparator> = new Set([\n Comparator.EQ,\n Comparator.NOT_EQ,\n Comparator.ONE_OF,\n Comparator.NOT_ONE_OF,\n Comparator.CONTAINS_ALL_OF,\n Comparator.CONTAINS_ANY_OF,\n Comparator.CONTAINS_NONE_OF,\n Comparator.STARTS_WITH,\n Comparator.NOT_STARTS_WITH,\n Comparator.ENDS_WITH,\n Comparator.NOT_ENDS_WITH,\n Comparator.CONTAINS,\n Comparator.NOT_CONTAINS,\n]);\n\nfunction matchTargetList<T>(\n targets: Packed.TargetList,\n params: EvaluationParams<T>,\n): boolean {\n for (const kind in targets) {\n const attributes = targets[kind]!;\n for (const attribute in attributes) {\n const entity = access([kind, attribute], params);\n if (isString(entity) && attributes[attribute]!.includes(entity))\n return true;\n }\n }\n return false;\n}\n\nfunction matchSegment<T>(segment: Packed.Segment, params: EvaluationParams<T>) {\n if (segment.include && matchTargetList(segment.include, params)) return true;\n if (segment.exclude && matchTargetList(segment.exclude, params)) return false;\n if (!segment.rules?.length) return false;\n\n const firstMatchingRule = segment.rules.find((rule) =>\n matchConditions(rule.conditions, params),\n );\n\n if (!firstMatchingRule) return false;\n\n return handleSegmentOutcome(params, firstMatchingRule.outcome);\n}\n\nfunction matchSegmentCondition<T>(\n cmp: Comparator,\n rhs: Packed.RHS,\n params: EvaluationParams<T>,\n) {\n switch (cmp) {\n case Comparator.EQ: {\n const segment = params.segments?.[rhs as string];\n if (!segment) return false;\n return matchSegment<T>(segment, params);\n }\n case Comparator.NOT_EQ: {\n const segment = params.segments?.[rhs as string];\n if (!segment) return false;\n return !matchSegment<T>(segment, params);\n }\n case Comparator.ONE_OF: {\n if (!isArray(rhs)) return false;\n const segmentIds = rhs;\n return segmentIds.some((segmentId) => {\n const segment = params.segments?.[segmentId];\n if (!segment) return false;\n return matchSegment<T>(segment, params);\n });\n }\n case Comparator.NOT_ONE_OF: {\n const segmentIds = rhs as string[];\n return segmentIds.every((segmentId) => {\n const segment = params.segments?.[segmentId];\n if (!segment) return false;\n return !matchSegment<T>(segment, params);\n });\n }\n default:\n throw new Error(`Comparator ${cmp} not implemented for segment`);\n }\n}\n\nfunction matchConditions<T>(\n conditions: Packed.Condition[],\n params: EvaluationParams<T>,\n): boolean {\n return conditions.every((condition) => {\n const [lhsAccessor, cmpKey, rawRhs, options] = condition;\n const hasIgnoreCaseFlag =\n typeof options === 'string' && options.includes('i');\n const hasIgnoreCaseOption =\n typeof options === 'object' && options !== null && options.i === true;\n const ignoreCase =\n IGNORE_CASE_COMPARATORS.has(cmpKey) &&\n (hasIgnoreCaseFlag || hasIgnoreCaseOption);\n\n // ignoreCase is not applicable to segment conditions (segments are internal IDs)\n if (lhsAccessor === Packed.AccessorType.SEGMENT) {\n return rawRhs && matchSegmentCondition(cmpKey, rawRhs, params);\n }\n\n const lhs = ignoreCase\n ? lower(access(lhsAccessor, params))\n : access(lhsAccessor, params);\n const rhs = ignoreCase ? lower(rawRhs) : rawRhs;\n\n try {\n switch (cmpKey) {\n case Comparator.EQ:\n return lhs === rhs;\n case Comparator.NOT_EQ:\n return lhs !== rhs;\n case Comparator.ONE_OF:\n return isArray(rhs) && rhs.includes(lhs);\n case Comparator.NOT_ONE_OF:\n // lhs would be undefined when the value was not provided, in which\n // case we should not match the rule\n return (\n isArray(rhs) && typeof lhs !== 'undefined' && !rhs.includes(lhs)\n );\n case Comparator.CONTAINS_ALL_OF: {\n if (!Array.isArray(rhs) || !Array.isArray(lhs)) return false;\n\n const lhsSet = new Set(lhs.filter(isString));\n\n // try to use a set if the lhs is a list of strings - O(1)\n // otherwise we need to iterate over the values - O(n)\n if (lhsSet.size === lhs.length) {\n return rhs.filter(isString).every((item) => lhsSet.has(item));\n }\n\n // this shouldn't happen since we only allow string[] on the lhs\n return rhs.every((item) => lhs.includes(item));\n }\n case Comparator.CONTAINS_ANY_OF: {\n if (!Array.isArray(rhs) || !Array.isArray(lhs)) return false;\n\n const rhsSet = new Set(rhs.filter(isString));\n return lhs.some(\n rhsSet.size === rhs.length\n ? // try to use a set if the rhs is a list of strings - O(1)\n (item) => rhsSet.has(item)\n : // otherwise we need to iterate over the values - O(n)\n (item) => rhs.includes(item),\n );\n }\n case Comparator.CONTAINS_NONE_OF: {\n // if the rhs is not an array something went wrong and we should not match\n if (!Array.isArray(rhs)) return false;\n\n // if it's not an array it doesn't contain any of the values\n if (!Array.isArray(lhs)) return true;\n\n const rhsSet = new Set(rhs.filter(isString));\n return lhs.every(\n rhsSet.size === rhs.length\n ? // try to use a set if the rhs is a list of strings - O(1)\n (item) => !rhsSet.has(item)\n : // otherwise we need to iterate over the values - O(n)\n (item) => !rhs.includes(item),\n );\n }\n case Comparator.STARTS_WITH:\n return isString(lhs) && isString(rhs) && lhs.startsWith(rhs);\n case Comparator.NOT_STARTS_WITH:\n return isString(lhs) && isString(rhs) && !lhs.startsWith(rhs);\n case Comparator.ENDS_WITH:\n return isString(lhs) && isString(rhs) && lhs.endsWith(rhs);\n case Comparator.NOT_ENDS_WITH:\n return isString(lhs) && isString(rhs) && !lhs.endsWith(rhs);\n case Comparator.CONTAINS:\n return isString(lhs) && isString(rhs) && lhs.includes(rhs);\n case Comparator.NOT_CONTAINS:\n return isString(lhs) && isString(rhs) && !lhs.includes(rhs);\n case Comparator.EXISTS:\n return lhs !== undefined && lhs !== null;\n case Comparator.NOT_EXISTS:\n return lhs === undefined || lhs === null;\n case Comparator.GT:\n // NaN will return false for any comparisons\n if (lhs === null || lhs === undefined) return false;\n return (isNumber(rhs) || isString(rhs)) && lhs > rhs;\n case Comparator.GTE:\n if (lhs === null || lhs === undefined) return false;\n return (isNumber(rhs) || isString(rhs)) && lhs >= rhs;\n case Comparator.LT:\n if (lhs === null || lhs === undefined) return false;\n return (isNumber(rhs) || isString(rhs)) && lhs < rhs;\n case Comparator.LTE:\n if (lhs === null || lhs === undefined) return false;\n return (isNumber(rhs) || isString(rhs)) && lhs <= rhs;\n case Comparator.REGEX:\n if (\n isString(lhs) &&\n lhs.length <= MAX_REGEX_INPUT_LENGTH &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return getCompiledRegex(rhs).test(lhs);\n }\n return false;\n\n case Comparator.NOT_REGEX:\n if (\n isString(lhs) &&\n lhs.length <= MAX_REGEX_INPUT_LENGTH &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return !getCompiledRegex(rhs).test(lhs);\n }\n return false;\n case Comparator.BEFORE: {\n if (!isString(lhs) || !isString(rhs)) return false;\n const a = new Date(lhs);\n const b = new Date(rhs);\n // if any date fails to parse getTime will return NaN, which will cause\n // comparisons to fail.\n return a.getTime() < b.getTime();\n }\n case Comparator.AFTER: {\n if (!isString(lhs) || !isString(rhs)) return false;\n const a = new Date(lhs);\n const b = new Date(rhs);\n return a.getTime() > b.getTime();\n }\n default: {\n const _x: never = cmpKey; // exhaustive check\n return false;\n }\n }\n } catch (error) {\n console.error('flags: Error matching conditions', error);\n return false;\n }\n });\n}\n\nfunction sum(list: number[]) {\n return list.reduce((acc, n) => acc + n, 0);\n}\n\nfunction handleSegmentOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.SegmentOutcome,\n) {\n // when everyone is flagged in the segment we can return true immediately\n if (outcome === 1) return true;\n\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n\n // exclude from segment if the lhs is not a string\n if (typeof lhs !== 'string') return false;\n\n // bypass hashing for common values and edges\n if (outcome.passPromille <= 0) return false;\n if (outcome.passPromille >= PROMILLE_SCALE) return true;\n\n const bucket = hashInput(lhs, params.definition.seed);\n return bucket < boundaryFor(outcome.passPromille, PROMILLE_SCALE);\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\nfunction getVariant<T>(\n definition: Packed.FlagDefinition,\n index: number,\n): { value: T; variantId: VariantId | null } {\n const { variants, variantIds } = definition;\n\n if (index < 0 || index >= variants.length) {\n throw new Error(\n `@vercel/flags-core: Invalid variant index ${index}, variants length is ${variants.length}`,\n );\n }\n\n let variantId: VariantId | null = null;\n if (variantIds && index < variantIds.length) {\n variantId = variantIds[index] ?? null;\n }\n\n return {\n value: variants[index] as T,\n variantId,\n };\n}\n\nfunction handleOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.Outcome,\n): {\n value: T;\n outcomeType: OutcomeType;\n variantId: VariantId | null;\n} {\n if (typeof outcome === 'number') {\n const variant = getVariant<T>(params.definition, outcome);\n return {\n ...variant,\n outcomeType: OutcomeType.VALUE,\n };\n }\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = getVariant<T>(\n params.definition,\n outcome.defaultVariant,\n );\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return {\n ...defaultOutcome,\n outcomeType: OutcomeType.SPLIT,\n };\n }\n\n const bucket = hashInput(lhs, params.definition.seed);\n const boundaries = getSplitBoundaries(outcome);\n\n // Return the first variant whose cumulative boundary covers the bucket.\n for (let index = 0; index < boundaries.length; index++) {\n if (bucket < (boundaries[index] as number)) {\n return {\n ...getVariant<T>(params.definition, index),\n outcomeType: OutcomeType.SPLIT,\n };\n }\n }\n\n // Only reached when the weights sum to 0 (every boundary is NaN).\n return {\n ...defaultOutcome,\n outcomeType: OutcomeType.SPLIT,\n };\n }\n case 'rollout': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = getVariant<T>(\n params.definition,\n outcome.defaultVariant,\n );\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return { ...defaultOutcome, outcomeType: OutcomeType.ROLLOUT };\n }\n\n // Determine active slot based on elapsed time\n const now = Date.now();\n const elapsed = now - outcome.startTimestamp;\n\n const rollFromVariant = getVariant<T>(\n params.definition,\n outcome.rollFromVariant,\n );\n\n // Before rollout starts or no slots, serve rollFromVariant\n if (elapsed < 0 || outcome.slots.length === 0) {\n return {\n ...rollFromVariant,\n outcomeType: OutcomeType.ROLLOUT,\n };\n }\n\n // Walk slots to find current promille.\n // Each slot's durationMs is how long that slot is served before\n // moving to the next one. Once all slots are exhausted the\n // rollout is complete (100% to rollToVariant).\n let cumulativeDuration = 0;\n let currentPromille = 0;\n let exhausted = true;\n for (const [promille, durationMs] of outcome.slots) {\n currentPromille = promille;\n cumulativeDuration += durationMs;\n if (cumulativeDuration > elapsed) {\n exhausted = false;\n break;\n }\n }\n if (exhausted) currentPromille = PROMILLE_SCALE;\n\n // short-circuit common edges\n if (currentPromille <= 0) {\n return {\n ...rollFromVariant,\n outcomeType: OutcomeType.ROLLOUT,\n };\n }\n const rollToVariant = getVariant<T>(\n params.definition,\n outcome.rollToVariant,\n );\n if (currentPromille >= PROMILLE_SCALE) {\n return {\n ...rollToVariant,\n outcomeType: OutcomeType.ROLLOUT,\n };\n }\n\n const bucket = hashInput(lhs, params.definition.seed);\n\n // Equivalent to the split { rollFrom: PROMILLE_SCALE - p, rollTo: p }: the\n // lower-index variant takes the low buckets, matching where the split\n // places it (see boundaryFor). So rollTo holds `[0, boundary(p))` when it\n // has the lower index, otherwise rollFrom holds the low buckets.\n if (outcome.rollToVariant < outcome.rollFromVariant) {\n const rollToBoundary = boundaryFor(currentPromille, PROMILLE_SCALE);\n return {\n ...(bucket < rollToBoundary ? rollToVariant : rollFromVariant),\n outcomeType: OutcomeType.ROLLOUT,\n };\n }\n const rollFromBoundary = boundaryFor(\n PROMILLE_SCALE - currentPromille,\n PROMILLE_SCALE,\n );\n return {\n ...(bucket < rollFromBoundary ? rollFromVariant : rollToVariant),\n outcomeType: OutcomeType.ROLLOUT,\n };\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\n/**\n * Evaluates a single feature flag.\n *\n * This function should never throw for expected errors, instead it returns\n * { reason: Reason.ERROR, errorMessage: ... }.\n *\n * The function can however throw for situations which should not happen under\n * normal circumstances, for example if the environment config is not found.\n */\nexport function evaluate<T>(\n /**\n * The params used for the evaluation\n */\n params: EvaluationParams<T>,\n /** Tracks visited environments to detect circular reuse. */\n _visited?: Set<string>,\n): EvaluationResult<T> {\n const envConfig = params.definition.environments[params.environment];\n\n // handle shortcut where a value is a number directly\n if (typeof envConfig === 'number') {\n return Object.assign(handleOutcome<T>(params, envConfig), {\n reason: ResolutionReason.PAUSED as const,\n }) satisfies EvaluationResult<T>;\n }\n\n if (!envConfig) {\n return {\n reason: ResolutionReason.ERROR,\n errorMessage: `Could not find envConfig for \"${params.environment}\"`,\n value: params.defaultValue,\n variantId: null,\n };\n }\n\n if ('reuse' in envConfig) {\n const reuseEnvConfig = params.definition.environments[envConfig.reuse];\n\n if (reuseEnvConfig === undefined) {\n // this is an unexpected error as this should have never been saved in\n // the first place\n throw new Error(\n `Could not find envConfig for \"${envConfig.reuse}\" when reusing`,\n );\n }\n\n const visited = _visited ?? new Set<string>();\n if (visited.has(envConfig.reuse)) {\n return {\n reason: ResolutionReason.ERROR,\n errorMessage: `Circular environment reuse detected: \"${envConfig.reuse}\"`,\n value: params.defaultValue,\n variantId: null,\n };\n }\n visited.add(params.environment);\n\n return evaluate<T>({ ...params, environment: envConfig.reuse }, visited);\n }\n\n if (envConfig.targets) {\n const matchedIndex = envConfig.targets.findIndex((targetList) =>\n matchTargetList(targetList, params),\n );\n\n if (matchedIndex > -1) {\n return Object.assign(handleOutcome<T>(params, matchedIndex), {\n reason: ResolutionReason.TARGET_MATCH as const,\n }) satisfies EvaluationResult<T>;\n }\n }\n\n const firstMatchingRule = envConfig.rules\n ? envConfig.rules.find((rule) => matchConditions(rule.conditions, params))\n : undefined;\n\n if (firstMatchingRule) {\n return Object.assign(handleOutcome<T>(params, firstMatchingRule.outcome), {\n reason: ResolutionReason.RULE_MATCH as const,\n }) satisfies EvaluationResult<T>;\n }\n\n return Object.assign(handleOutcome<T>(params, envConfig.fallthrough), {\n reason: ResolutionReason.FALLTHROUGH as const,\n }) satisfies EvaluationResult<T>;\n}\n\nexport type BulkEvaluationInput<T> = {\n definition: Packed.FlagDefinition;\n defaultValue?: T;\n};\n\n/**\n * Evaluates multiple feature flags against the same entities, segments, and\n * environment.\n *\n * Reuses a single shared `EvaluationParams` object across flags so callers\n * avoid the overhead of constructing one per call (and don't need to spawn\n * parallel promises just to fan out independent sync evaluations).\n */\nexport function bulkEvaluate<T = unknown>(\n flags: Record<string, BulkEvaluationInput<T>>,\n shared: {\n entities?: Record<string, unknown>;\n environment: string;\n segments?: EvaluationParams<T>['segments'];\n },\n): Record<string, EvaluationResult<T>> {\n const params: EvaluationParams<T> = {\n entities: shared.entities,\n environment: shared.environment,\n segments: shared.segments,\n definition: undefined as unknown as Packed.FlagDefinition,\n defaultValue: undefined,\n };\n\n const results: Record<string, EvaluationResult<T>> = {};\n for (const key in flags) {\n const flag = flags[key]!;\n params.definition = flag.definition;\n params.defaultValue = flag.defaultValue;\n results[key] = evaluate<T>(params);\n }\n return results;\n}\n","export type MetricEnvironment = 'development' | 'preview' | 'production';\n\n/**\n * Options for stream connection behavior\n */\nexport type StreamOptions = {\n /** Timeout in ms to wait for initial stream connection before falling back */\n initTimeoutMs: number;\n};\n\n/**\n * Options for polling behavior\n */\nexport type PollingOptions = {\n /** Interval in ms between polling requests */\n intervalMs: number;\n /** Timeout in ms to wait for initial poll before falling back */\n initTimeoutMs: number;\n};\n\n/** Input type for creating a datafile (without metrics) */\nexport type DatafileInput = Packed.Data & {\n /**\n * If a data source is used with a specific sdk key then\n * the sdk key or data source might contain information\n * about the environment to be evaluated\n */\n environment: string;\n /** Vercel project id of the source of these flags */\n projectId: string;\n /**\n * Some older responses might return a string instead of a number. Both will be timestamps.\n */\n configUpdatedAt?: number | string;\n /** Version number of the data */\n revision?: number;\n};\n\n/** Datafile with metrics attached (returned by the client) */\nexport type Datafile = DatafileInput & {\n /** Metrics about how the data was retrieved */\n metrics: Metrics;\n};\n\n/** Flag Definitions of a Vercel project */\nexport type BundledDefinitions = DatafileInput & {\n /** when the data was last updated */\n configUpdatedAt: number;\n /** hash of the data */\n digest: string;\n /** version number of the data */\n revision: number;\n};\n\nexport type BundledDefinitionsResult =\n | { definitions: BundledDefinitions; state: 'ok' }\n | { definitions: null; state: 'missing-file' | 'missing-entry' }\n | { definitions: null; state: 'unexpected-error'; error: unknown };\n\n/**\n * Metrics about how data was retrieved and evaluated\n */\nexport type Metrics = {\n /** Time in ms to read the datafile */\n readMs: number;\n /** Where the data came from */\n source: 'in-memory' | 'embedded' | 'remote';\n /** Whether data was already cached, or stale (fallback used) */\n cacheStatus: 'HIT' | 'MISS' | 'STALE';\n /** Whether the stream is currently connected */\n connectionState: 'connected' | 'disconnected';\n /** The current operating mode of the client */\n mode: 'streaming' | 'polling' | 'build' | 'offline';\n /** Time in ms for the pure flag evaluation logic (only present on EvaluationResult) */\n evaluationMs?: number;\n};\n\n/**\n * DataSource interface for the Vercel Flags client\n */\nexport interface ControllerInterface {\n /**\n * Initialize the data source by fetching the initial file or setting up polling or\n * subscriptions.\n *\n * @see https://openfeature.dev/specification/sections/providers#requirement-241\n */\n initialize: () => Promise<void>;\n\n /**\n * Returns the in-memory data file, which was loaded from initialize and maybe updated from streams.\n */\n read(): Promise<Datafile>;\n\n /**\n * End polling or subscriptions. Flush any remaining data.\n */\n shutdown(): void;\n\n /**\n * Return the actual datafile containing flag definitions.\n */\n getDatafile(): Promise<Datafile>;\n\n /**\n * Returns the bundled fallback definitions.\n * Throws FallbackNotFoundError if the fallback file doesn't exist.\n * Throws FallbackEntryNotFoundError if the file exists but has no entry for the SDK key.\n */\n getFallbackDatafile?(): Promise<BundledDefinitions>;\n}\n\nexport type Source = {\n orgId: string;\n orgSlug: string;\n projectId: string;\n projectSlug: string;\n};\n\n/**\n * Input for a single flag in a bulk evaluation call.\n */\nexport type BulkEvaluateInput<T = Value> = {\n key: string;\n defaultValue?: T;\n};\n\n/**\n * A client for Vercel Flags\n */\nexport type FlagsClient<Entities = Record<string, unknown>> = {\n /**\n * Origin information for this client.\n * sdkKey is only present when the client was explicitly created with one.\n */\n origin?: {\n provider: string;\n sdkKey?: string;\n };\n /**\n * Evaluate a feature flag\n *\n * Requires initialize() to have been called and awaited first.\n *\n * @param flagKey\n * @param defaultValue\n * @param entities\n * @returns\n */\n evaluate: <T = Value, E = Entities>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ) => Promise<EvaluationResult<T>>;\n /**\n * Evaluate multiple feature flags against the same entities in a single call.\n *\n * Avoids the per-flag overhead of separate `evaluate()` invocations (in particular,\n * the parallel promises and repeated datafile reads they would entail).\n *\n * Requires initialize() to have been called and awaited first.\n *\n * @param flags Array of `{ key, defaultValue? }` entries to evaluate.\n * @param entities Shared entities used for every flag in the bulk call.\n * @returns Object mapping each key to its EvaluationResult.\n */\n bulkEvaluate: <T = Value, E = Entities>(\n flags: BulkEvaluateInput<T>[],\n entities?: E,\n ) => Promise<Record<string, EvaluationResult<T>>>;\n /**\n * Retrieve the latest datafile during startup, and set up subscriptions if needed.\n */\n initialize(): void | Promise<void>;\n /**\n * Facilitates a clean shutdown process which may include flushing telemetry information, or closing remote connections.\n */\n shutdown(): void | Promise<void>;\n /**\n * Returns the actual datafile containing flag definitions\n */\n getDatafile(): Promise<Datafile>;\n /**\n * Returns the bundled fallback definitions.\n * Throws FallbackNotFoundError if the fallback file doesn't exist.\n * Throws FallbackEntryNotFoundError if the file exists but has no entry for the SDK key.\n */\n getFallbackDatafile(): Promise<BundledDefinitions>;\n};\n\nexport type EvaluationParams<T> = {\n entities?: Record<string, unknown>;\n environment: string;\n segments?: Record<SegmentId, Packed.Segment>;\n definition: Packed.FlagDefinition;\n defaultValue?: T;\n};\n\n// Copied from the OpenFeature ErrorCode and commented out unused types\n/**\n * ErrorCodes that can happen during evaluation\n */\nexport enum ErrorCode {\n /**\n * The value was resolved before the provider was ready.\n */\n // PROVIDER_NOT_READY = 'PROVIDER_NOT_READY',\n /**\n * The provider has entered an irrecoverable error state.\n */\n // PROVIDER_FATAL = 'PROVIDER_FATAL',\n /**\n * The flag could not be found.\n */\n FLAG_NOT_FOUND = 'FLAG_NOT_FOUND',\n /**\n * An error was encountered parsing data, such as a flag configuration.\n */\n // PARSE_ERROR = 'PARSE_ERROR',\n /**\n * The type of the flag value does not match the expected type.\n */\n // TYPE_MISMATCH = 'TYPE_MISMATCH',\n /**\n * The provider requires a targeting key and one was not provided in the evaluation context.\n */\n // TARGETING_KEY_MISSING = 'TARGETING_KEY_MISSING',\n /**\n * The evaluation context does not meet provider requirements.\n */\n // INVALID_CONTEXT = 'INVALID_CONTEXT',\n /**\n * An error with an unspecified code.\n */\n // GENERAL = 'GENERAL',\n}\n\n/**\n * The detailed result of a flag evaluation as returned by the client's `evaluate` function.\n */\nexport type EvaluationResult<T> =\n | {\n /**\n * In case of successful evaluations this holds the evaluated value\n */\n value: T;\n /**\n * Indicates whether the outcome was a single variant or a split\n */\n outcomeType?: OutcomeType;\n /**\n * The variant we want to report for o11y\n */\n variantId: VariantId | null;\n /**\n * Indicates why the flag evaluated to a certain value\n */\n reason: Exclude<ResolutionReason, ResolutionReason.ERROR>;\n errorMessage?: never;\n errorCode?: never;\n /** Metrics about the evaluation (optional) */\n metrics?: Metrics;\n }\n | {\n reason: ResolutionReason.ERROR;\n errorMessage: string;\n errorCode?: ErrorCode;\n outcomeType?: never;\n /**\n * The variant we want to report for o11y\n */\n variantId: VariantId | null;\n /**\n * In cases of errors this is the defaultValue if one was provided\n */\n value?: T;\n /** Metrics about the evaluation (optional) */\n metrics?: Metrics;\n };\n\nexport type FlagKey = string;\nexport type VariantId = string;\nexport type EnvironmentKey = string;\nexport type SegmentId = string;\n\n/**\n * The value of a feature flag variant\n */\nexport type Value =\n | string\n | number\n | boolean\n | null\n | { [key: string]: Value }\n | Value[];\n\nexport enum ResolutionReason {\n PAUSED = 'paused',\n TARGET_MATCH = 'target_match',\n RULE_MATCH = 'rule_match',\n FALLTHROUGH = 'fallthrough',\n ERROR = 'error',\n}\n\nexport enum OutcomeType {\n /** When the outcome type was a single variant */\n VALUE = 'value',\n /** When the outcome type was a split */\n SPLIT = 'split',\n /** When the outcome type was a progressive rollout */\n ROLLOUT = 'rollout',\n}\n\n/**\n * Vercel Flags\n * - is equal to (eq)\n * - is not equal to (!eq)\n * - is one of (oneOf)\n * - is not one of (!oneOf)\n * - contains (contains)\n * - does not contain (!contains)\n * - starts with (startsWith)\n * - does not start with (!startsWith)\n * - ends with (endsWith)\n * - does not end with (!endsWith)\n * - exists (ex)\n * - does not exist (!ex)\n * - is greater than (gt)\n * - is greater than or equal to (gte)\n * - is lower than (lt)\n * - is lower than or equal to (lte)\n * - matches regex (regex)\n * - does not match regex (!regex)\n * - is before (before)\n * - is after (after)\n */\n\nexport enum Comparator {\n /**\n * lhs must be string | number\n * rhs must be string | number\n * does a strict equality check\n */\n EQ = 'eq',\n /**\n * lhs must be string | number\n * rhs must be string | number\n * does a strict equality check\n */\n NOT_EQ = '!eq',\n /**\n * lhs must be string\n * rhs must be string[]\n */\n ONE_OF = 'oneOf',\n /**\n * lhs must be string\n * rhs must be string[]\n */\n NOT_ONE_OF = '!oneOf',\n /**\n * lhs must be string[]\n * rhs must be string[]\n */\n CONTAINS_ALL_OF = 'containsAllOf',\n /**\n * lhs must be string[]\n * rhs must be string[]\n */\n CONTAINS_ANY_OF = 'containsAnyOf',\n /**\n * lhs must be string[]\n * rhs must be string[]\n */\n CONTAINS_NONE_OF = 'containsNoneOf',\n /**\n * lhs must be string\n * rhs must be string\n *\n * other comparisons have to be handled with a regex\n */\n STARTS_WITH = 'startsWith',\n /**\n * lhs must be string\n * rhs must be string\n *\n * other comparisons have to be handled with a regex\n */\n NOT_STARTS_WITH = '!startsWith',\n /**\n * lhs must be string\n * rhs must be string\n *\n * other comparisons have to be handled with a regex\n */\n ENDS_WITH = 'endsWith',\n /**\n * lhs must be string\n * rhs must be string\n *\n * other comparisons have to be handled with a regex\n */\n NOT_ENDS_WITH = '!endsWith',\n /**\n * lhs must be string\n * rhs must be string\n *\n * checks if lhs contains rhs as a substring\n */\n CONTAINS = 'contains',\n /**\n * lhs must be string\n * rhs must be string\n *\n * checks if lhs does not contain rhs as a substring\n */\n NOT_CONTAINS = '!contains',\n /**\n * lhs must be string\n * rhs must be never\n */\n EXISTS = 'ex',\n /**\n * lhs must be string\n * rhs must be never\n */\n NOT_EXISTS = '!ex',\n /**\n * lhs must be string | number\n * rhs must be string | number\n */\n GT = 'gt',\n /**\n * lhs must be string | number\n * rhs must be string | number\n */\n GTE = 'gte',\n /** */\n /**\n * lhs must be string | number\n * rhs must be string | number\n */\n LT = 'lt',\n /**\n * lhs must be string | number\n * rhs must be string | number\n */\n LTE = 'lte',\n /**\n * lhs must be string\n * rhs must be string\n */\n REGEX = 'regex',\n /**\n * lhs must be string\n * rhs must be string\n */\n NOT_REGEX = '!regex',\n /**\n * lhs must be date string\n * rhs must be date string\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format\n */\n BEFORE = 'before',\n /**\n * lhs must be date string\n * rhs must be date string\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format\n */\n AFTER = 'after',\n}\n\n// -----------------------------------------------------------------------------\n// Original data\n// -----------------------------------------------------------------------------\n\nexport namespace Original {\n export type Data = {\n definitions: Record<string, FlagDefinition>;\n segments?: Original.Segment[];\n };\n\n export enum AccessorType {\n SEGMENT = 'segment',\n ENTITY = 'entity',\n }\n\n export type SegmentOutcome = SegmentAllOutcome | SegmentSplitOutcome;\n\n export type Outcome =\n | {\n type: 'variant';\n variantId: VariantId;\n }\n | {\n type: 'split';\n /**\n * Based on which attribute the traffic should be split\n */\n base: EntityAccessor;\n /**\n * The distribution for each variant\n */\n weights: Record<VariantId, number>;\n /**\n * This variant will be used when the base attribute does not exist\n */\n defaultVariantId: VariantId;\n }\n | {\n type: 'rollout';\n /**\n * Based on which attribute the traffic should be split\n */\n base: EntityAccessor;\n /**\n * Epoch ms when the rollout begins\n */\n startTimestamp: number;\n /**\n * The variant to roll away from\n */\n rollFromVariantId: VariantId;\n /**\n * The variant to roll towards\n */\n rollToVariantId: VariantId;\n /**\n * This variant will be used when the base attribute does not exist\n */\n defaultVariantId: VariantId;\n /**\n * Progressive rollout slots. Each slot has a promille value (0-100_000)\n * representing the traffic for rollToVariant and a duration (how long\n * it is served before moving to the next slot).\n * 1 = 0.001%\n * 1_000 = 1%\n * 100_000 = 100%\n *\n * Once all slots are exhausted, the rollout is complete (100% rollToVariant).\n */\n slots: { promille: number; durationMs: number }[];\n };\n\n export type SegmentAllOutcome = {\n type: 'all';\n };\n\n export type SegmentSplitOutcome = {\n type: 'split';\n /**\n * Based on which attribute the passing percentage should be split.\n *\n * When the attribute does not exist the segment will not match.\n */\n base: EntityAccessor;\n /**\n * The promille that should pass the segment\n * 1 = 0.001%\n * 1_000 = 1%\n * 100_000 = 100%\n */\n passPromille: number;\n };\n\n export type EntityAccessor = {\n type: AccessorType.ENTITY;\n kind: string;\n attribute: string;\n };\n export type SegmentAccessor = { type: AccessorType.SEGMENT };\n\n export type List = {\n // backwards compatibility, we should only use \"list\" going forward\n type: 'list/inline' | 'list';\n items: { note?: string; value: string | number }[];\n id?: never;\n };\n\n export type LHS = SegmentAccessor | EntityAccessor;\n export type RHS =\n | string\n | number\n | boolean\n | List\n | { type: 'regex'; pattern: string; flags: string };\n\n export type Condition = {\n lhs: LHS;\n cmp: Comparator;\n rhs: RHS;\n /** When true, string comparisons are case-insensitive. */\n i?: boolean;\n };\n\n export type Rule = {\n conditions: Condition[];\n outcome: Outcome;\n };\n\n export type SegmentRule = {\n conditions: Condition[];\n outcome: SegmentAllOutcome | SegmentSplitOutcome;\n };\n\n export type FlagVariant = {\n id: string;\n label?: string;\n description?: string;\n value: Value;\n };\n\n export type EnvironmentConfig = {\n active: boolean;\n pausedOutcome: Outcome;\n /**\n * If enabled, the flag will be reused from the given environment.\n *\n * The flag will not be evaluated, and the outcome will be the same as the given environment.\n * This environment must be active and the flag must be active in this environment.\n */\n reuse: {\n active: boolean;\n environment: EnvironmentKey;\n };\n targets: Record<VariantId, TargetList>;\n rules: Rule[];\n fallthrough: Outcome;\n };\n\n /**\n * A list of targets\n *\n * @example\n * {\n * user: { id: { note?: string; value: string }[] }\n * }\n */\n export type TargetList = Record<\n string,\n Record<string, { note?: string; value: string }[]>\n >;\n\n /**\n * reusable conditions, with no outcome attached\n */\n export type Segment = {\n id: string;\n rules: SegmentRule[];\n /**\n * Explicitly include targets. Included targets will bypass conditions and exclusion.\n *\n * @example\n * include: {\n * user: { id: { note?: string, value: string }[] }\n * }\n */\n include: TargetList;\n /**\n * Explicitly exclude targets. Excluded targets will not be included in the segment, and bypass conditions.\n *\n * @example\n * exclude: {\n * user: { id: { note?: string, value: string }[] }\n * }\n */\n exclude: TargetList;\n };\n\n export type FlagDefinition = {\n variants: FlagVariant[];\n environments: Record<EnvironmentKey, EnvironmentConfig>;\n\n /**\n * A random seed to prevent split points in different flags\n * from having the same targets. Otherwise the same set of ids would be\n * opted into all flags for every rollout. By using a different seed for\n * each flag the distribution is different for every flag.\n *\n * We don't use the slug as it might change, but we don't want the distribution\n * to change when the slug changes.\n *\n * We don't use the id or createdAt etc as we want to be able to redistirbute\n * by changing the seed.\n */\n seed: number;\n };\n}\n\n// -----------------------------------------------------------------------------\n// Packed data\n// -----------------------------------------------------------------------------\n\nexport namespace Packed {\n /**\n * Idenitifies a variant based on its index in the variants array.\n */\n export type VariantIndex = number;\n\n export type Data = {\n /** map of flag keys to definitions */\n definitions: Record<FlagKey, FlagDefinition>;\n /** segments keyed by id */\n segments?: Record<SegmentId, Segment>;\n };\n\n export enum AccessorType {\n SEGMENT = 'segment',\n ENTITY = 'entity',\n }\n\n export type SplitOutcome = {\n type: 'split';\n /**\n * Based on which attribute the traffic should be split.\n */\n base: EntityAccessor;\n /**\n * The distribution of the individual groups.\n *\n * We use a single number array as the numbers will be placed in the\n * same order as the variant list.\n *\n * So index 0 here is the distribution for variant 0, and so on.\n */\n weights: number[];\n /**\n * This variant will be used when the lhs does not exist\n */\n defaultVariant: VariantIndex;\n };\n\n export type RolloutOutcome = {\n type: 'rollout';\n /**\n * Based on which attribute the traffic should be split.\n */\n base: EntityAccessor;\n /**\n * Epoch ms when the rollout begins.\n */\n startTimestamp: number;\n /**\n * Variant index to roll away from.\n */\n rollFromVariant: VariantIndex;\n /**\n * Variant index to roll towards.\n */\n rollToVariant: VariantIndex;\n /**\n * This variant will be used when the base attribute does not exist.\n */\n defaultVariant: VariantIndex;\n /**\n * Progressive rollout slots.\n * Each tuple: [promille 0-100_000 for rollToVariant, durationMs (how long this slot is served)]\n * 1 = 0.001%\n * 1_000 = 1%\n * 100_000 = 100%\n *\n * Once all slots are exhausted, the rollout is complete (100% rollToVariant).\n */\n slots: [number, number][];\n };\n\n export type SegmentAllOutcome = 1;\n\n export type SegmentSplitOutcome = {\n type: 'split';\n /**\n * Based on which attribute the traffic should be split.\n *\n * When the attribute does not exist the segment will not match.\n */\n base: EntityAccessor;\n /**\n * The promille that should pass the segment (1 = 0.001%; 1000 = 1%)\n */\n passPromille: number;\n };\n\n export type SegmentOutcome = SegmentAllOutcome | SegmentSplitOutcome;\n\n export type Outcome = VariantIndex | SplitOutcome | RolloutOutcome;\n\n // an array means it's an entity, the string \"segment\" means a segment\n export type EntityAccessor = (string | number)[];\n export type SegmentAccessor = 'segment';\n\n /**\n * An array means an entity\n */\n export type LHS = EntityAccessor | SegmentAccessor;\n\n /**\n * undefined when the rhs is not used by the comparator\n * string[] when the rhs is a list of segments\n * { type: 'regex'; pattern: string; flags: string } when the rhs is a regex\n */\n export type RHS =\n | undefined\n | string\n | number\n | boolean\n | (string | number)[]\n | { type: 'regex'; pattern: string; flags: string };\n\n export type ConditionOptions = {\n /** When true, string comparisons are case-insensitive. */\n i?: boolean;\n };\n\n export type Condition =\n | [LHS, Comparator, RHS]\n | [LHS, Comparator, RHS, ConditionOptions | 'i']\n | [LHS, Comparator.EXISTS]\n | [LHS, Comparator.NOT_EXISTS];\n\n export type Rule = {\n conditions: Condition[];\n outcome: Outcome;\n };\n\n export type SegmentRule = {\n conditions: Condition[];\n outcome: SegmentAllOutcome | SegmentSplitOutcome;\n };\n\n export type EnvironmentConfig =\n /**\n * Paused flags contain the pausedOutcome only.\n */\n | number\n /** Allows reusing the configuration of another environment */\n | { reuse: EnvironmentKey }\n /**\n * Active flags don't contain an explicit \"active\" state.\n * The fact that they have a config means they are active.\n */\n | {\n /**\n * Each array item represents a variant.\n *\n * Each slot holds the targets for that variant.\n *\n * So the target list at index 0 is the targets for variant 0, and so on.\n */\n targets?: TargetList[];\n rules?: Rule[];\n fallthrough: Outcome;\n };\n\n /**\n * A list of targets\n *\n * @example\n * {\n * user: { id: string[] }\n * }\n */\n export type TargetList = Record<string, Record<string, string[]>>;\n\n /**\n * reusable conditions, with no outcome attached\n */\n export type Segment = {\n rules?: SegmentRule[];\n /**\n * Explicitly include targets. Included targets will bypass conditions and exclusion.\n *\n * @example\n * include: {\n * user: { id: string[] }\n * }\n */\n include?: TargetList;\n /**\n * Explicitly exclude targets. Excluded targets will not be included in the segment, and bypass conditions.\n *\n * @example\n * exclude: {\n * user: { id: string[] }\n * }\n */\n exclude?: TargetList;\n };\n\n export type FlagDefinition = {\n /** for backwards compatibility with HappyKit */\n variantIds?: string[];\n /** variants, packed down to just their values */\n variants: Value[];\n /** environments */\n environments: Record<EnvironmentKey, EnvironmentConfig>;\n /**\n * A random seed to prevent split points in different flags\n * from having the same targets. Otherwise the same set of ids would be\n * opted into all flags for every rollout. By using a different seed for\n * each flag the distribution is different for every flag.\n *\n * We don't use the slug as it might change, but we don't want the distribution\n * to change when the slug changes.\n *\n * We don't use the id or createdAt etc as we want to be able to redistirbute\n * by changing the seed.\n */\n seed?: number;\n };\n}\n","{\n \"name\": \"@vercel/flags-core\",\n \"version\": \"1.8.0\",\n \"description\": \"A server-side client for Vercel Flags\",\n \"keywords\": [\n \"vercel\",\n \"flags\",\n \"vercel flags\",\n \"feature flags\",\n \"flags sdk\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/vercel/flags.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"Dominik Ferber <dominik@vercel.com>\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"next-js\": {\n \"types\": \"./dist/index.next-js.d.ts\",\n \"default\": \"./dist/index.next-js.js\"\n },\n \"import\": {\n \"types\": \"./dist/index.default.d.ts\",\n \"default\": \"./dist/index.default.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.default.d.cts\",\n \"default\": \"./dist/index.default.cjs\"\n }\n },\n \"./openfeature\": {\n \"next-js\": {\n \"types\": \"./dist/openfeature.next-js.d.ts\",\n \"default\": \"./dist/openfeature.next-js.js\"\n },\n \"import\": {\n \"types\": \"./dist/openfeature.default.d.ts\",\n \"default\": \"./dist/openfeature.default.js\"\n },\n \"require\": {\n \"types\": \"./dist/openfeature.default.d.cts\",\n \"default\": \"./dist/openfeature.default.cjs\"\n }\n }\n },\n \"main\": \"./dist/index.default.js\",\n \"typesVersions\": {\n \"*\": {\n \".\": [\n \"dist/index.default.d.ts\",\n \"dist/index.default.d.cts\"\n ],\n \"openfeature\": [\n \"dist/openfeature.default.d.ts\",\n \"dist/openfeature.default.d.cts\"\n ]\n }\n },\n \"files\": [\n \"dist\",\n \"CHANGELOG.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"check\": \"biome check\",\n \"test\": \"vitest --run\",\n \"test:watch\": \"vitest\",\n \"type-check\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@vercel/functions\": \"^3.4.3\",\n \"@vercel/oidc\": \"3.5.0\",\n \"jose\": \"5.2.1\",\n \"js-xxhash\": \"4.0.0\"\n },\n \"devDependencies\": {\n \"@arethetypeswrong/cli\": \"0.18.2\",\n \"@types/node\": \"22.14.0\",\n \"next\": \"^16.2.12\",\n \"tsup\": \"8.5.1\",\n \"typescript\": \"5.6.3\",\n \"vite\": \"8.1.5\",\n \"vitest\": \"4.1.10\"\n },\n \"peerDependencies\": {\n \"@openfeature/server-sdk\": \"1.18.0\",\n \"next\": \"*\"\n },\n \"peerDependenciesMeta\": {\n \"@openfeature/server-sdk\": {\n \"optional\": true\n },\n \"next\": {\n \"optional\": true\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import { version } from '../../package.json';\nimport type { OutcomeType, ResolutionReason } from '../types';\n\n/**\n * Only used internally for now.\n */\nexport function internalReportValue(\n key: string,\n value: unknown,\n data: {\n originProjectId?: string;\n originProvider?: 'vercel';\n outcomeType?: OutcomeType;\n reason?: ResolutionReason | 'override';\n },\n) {\n const symbol = Symbol.for('@vercel/request-context');\n const ctx = Reflect.get(globalThis, symbol)?.get();\n const reportFlagValue = ctx?.flags?.reportValue;\n if (typeof reportFlagValue !== 'function') return;\n\n reportFlagValue.call(ctx.flags, key, value, {\n sdkVersion: version,\n ...data,\n });\n}\n","import {\n type BulkEvaluationInput,\n bulkEvaluate as bulkEvalFlags,\n evaluate as evalFlag,\n} from './evaluate';\nimport { internalReportValue } from './lib/report-value';\nimport type {\n BulkEvaluateInput,\n BundledDefinitions,\n ControllerInterface,\n Datafile,\n EvaluationResult,\n Metrics,\n Packed,\n} from './types';\nimport { ErrorCode, ResolutionReason } from './types';\nimport type { TrackEvaluationOptions } from './utils/usage/flags-evaluation';\n\nexport type ControllerInstance = {\n controller: ControllerInterface;\n initialized: boolean;\n initPromise: Promise<void> | null;\n};\n\nexport const controllerInstanceMap = new Map<number, ControllerInstance>();\n\ntype EvaluationTrackingController = ControllerInterface & {\n trackEvaluation?: (options: TrackEvaluationOptions) => void;\n};\n\nfunction getInstance(id: number): ControllerInstance {\n const instance = controllerInstanceMap.get(id);\n if (!instance) {\n throw new Error(\n `@vercel/flags-core: Client instance ${id} not found. It may have been shut down.`,\n );\n }\n return instance;\n}\n\nexport function initialize(id: number): Promise<void> {\n return getInstance(id).controller.initialize();\n}\n\nexport function shutdown(id: number): void | Promise<void> {\n return getInstance(id).controller.shutdown();\n}\n\nexport function getDatafile(id: number) {\n return getInstance(id).controller.getDatafile();\n}\n\nexport function getFallbackDatafile(id: number): Promise<BundledDefinitions> {\n const ds = getInstance(id).controller;\n if (ds.getFallbackDatafile) return ds.getFallbackDatafile();\n throw new Error('flags: This data source does not support fallbacks');\n}\n\nfunction trackEvaluation(\n controller: EvaluationTrackingController,\n options: TrackEvaluationOptions,\n): void {\n controller.trackEvaluation?.(options);\n}\n\nexport async function evaluate<T, E = Record<string, unknown>>(\n id: number,\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n): Promise<EvaluationResult<T>> {\n const controller = getInstance(id).controller as EvaluationTrackingController;\n\n let datafile: Datafile;\n try {\n datafile = await controller.read();\n } catch (error) {\n // All data sources failed. Fall back to defaultValue if provided.\n if (defaultValue !== undefined) {\n const result: EvaluationResult<T> = {\n value: defaultValue,\n variantId: null,\n reason: ResolutionReason.ERROR,\n errorMessage:\n error instanceof Error ? error.message : 'Failed to read datafile',\n };\n\n trackEvaluation(controller, {\n flagKey,\n variant: null,\n reason: result.reason,\n });\n\n return result;\n }\n throw error;\n }\n\n const flagDefinition = datafile.definitions[flagKey] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n if (datafile.projectId) {\n internalReportValue(flagKey, defaultValue, {\n originProjectId: datafile.projectId,\n originProvider: 'vercel',\n reason: ResolutionReason.ERROR,\n });\n }\n\n const result: EvaluationResult<T> = {\n value: defaultValue,\n variantId: null,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `@vercel/flags-core: Definition not found for flag \"${flagKey}\"`,\n metrics: {\n evaluationMs: 0,\n readMs: datafile.metrics.readMs,\n source: datafile.metrics.source,\n cacheStatus: datafile.metrics.cacheStatus,\n connectionState: datafile.metrics.connectionState,\n mode: datafile.metrics.mode,\n },\n };\n trackEvaluation(controller, {\n flagKey,\n variant: null,\n reason: result.reason,\n });\n return result;\n }\n\n const evalStartTime = Date.now();\n const result = evalFlag<T>({\n defaultValue,\n definition: flagDefinition,\n environment: datafile.environment,\n entities: entities ?? {},\n segments: datafile.segments,\n });\n const evaluationDurationMs = Date.now() - evalStartTime;\n\n if (datafile.projectId) {\n internalReportValue(flagKey, result.value, {\n originProjectId: datafile.projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n\n trackEvaluation(controller, {\n flagKey,\n variant: result.variantId,\n reason: result.reason,\n });\n\n return Object.assign(result, {\n metrics: {\n evaluationMs: evaluationDurationMs,\n readMs: datafile.metrics.readMs,\n source: datafile.metrics.source,\n cacheStatus: datafile.metrics.cacheStatus,\n connectionState: datafile.metrics.connectionState,\n mode: datafile.metrics.mode,\n },\n });\n}\n\nexport async function bulkEvaluate<T, E = Record<string, unknown>>(\n id: number,\n flags: BulkEvaluateInput<T>[],\n entities?: E,\n): Promise<Record<string, EvaluationResult<T>>> {\n const controller = getInstance(id).controller as EvaluationTrackingController;\n\n let datafile: Datafile;\n try {\n datafile = await controller.read();\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to read datafile';\n\n const results: Record<string, EvaluationResult<T>> = {};\n for (const flag of flags) {\n results[flag.key] = {\n value: flag.defaultValue,\n reason: ResolutionReason.ERROR,\n errorMessage,\n variantId: null,\n };\n trackEvaluation(controller, {\n flagKey: flag.key,\n variant: null,\n reason: ResolutionReason.ERROR,\n });\n }\n return results;\n }\n\n const baseMetrics: Metrics = {\n readMs: datafile.metrics.readMs,\n source: datafile.metrics.source,\n cacheStatus: datafile.metrics.cacheStatus,\n connectionState: datafile.metrics.connectionState,\n mode: datafile.metrics.mode,\n };\n\n const projectId = datafile.projectId;\n const results: Record<string, EvaluationResult<T>> = {};\n const toEvaluate: Record<string, BulkEvaluationInput<T>> = {};\n\n for (const flag of flags) {\n const { key, defaultValue } = flag;\n const flagDefinition = datafile.definitions[key] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n if (projectId) {\n internalReportValue(key, defaultValue, {\n originProjectId: projectId,\n originProvider: 'vercel',\n reason: ResolutionReason.ERROR,\n });\n }\n results[key] = {\n value: defaultValue,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `@vercel/flags-core: Definition not found for flag \"${key}\"`,\n metrics: { evaluationMs: 0, ...baseMetrics },\n variantId: null,\n };\n trackEvaluation(controller, {\n flagKey: key,\n variant: null,\n reason: ResolutionReason.ERROR,\n });\n continue;\n }\n\n toEvaluate[key] = { definition: flagDefinition, defaultValue };\n }\n\n const evalStartTime = Date.now();\n const evaluated = bulkEvalFlags<T>(toEvaluate, {\n entities: (entities ?? {}) as Record<string, unknown>,\n environment: datafile.environment,\n segments: datafile.segments,\n });\n const evaluationDurationMs = Date.now() - evalStartTime;\n\n for (const key in toEvaluate) {\n const result = evaluated[key]!;\n if (projectId) {\n internalReportValue(key, result.value, {\n originProjectId: projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n trackEvaluation(controller, {\n flagKey: key,\n variant: result.variantId,\n reason: result.reason,\n });\n results[key] = Object.assign(result, {\n metrics: { evaluationMs: evaluationDurationMs, ...baseMetrics },\n });\n }\n\n return results;\n}\n","import type {\n bulkEvaluate,\n evaluate,\n getDatafile,\n getFallbackDatafile,\n initialize,\n shutdown,\n} from './controller-fns';\nimport {\n type ControllerInstance,\n controllerInstanceMap,\n} from './controller-fns';\nimport type {\n BulkEvaluateInput,\n BundledDefinitions,\n ControllerInterface,\n EvaluationResult,\n FlagsClient,\n Value,\n} from './types';\n\nlet idCount = 0;\n\nasync function performInitialize(\n instance: ControllerInstance,\n initFn: () => Promise<void>,\n): Promise<void> {\n try {\n await initFn();\n instance.initialized = true;\n } catch (error) {\n // Clear so next call can retry\n instance.initPromise = null;\n throw error;\n }\n}\n\nexport function createCreateRawClient(fns: {\n initialize: typeof initialize;\n shutdown: typeof shutdown;\n getFallbackDatafile: typeof getFallbackDatafile;\n evaluate: typeof evaluate;\n bulkEvaluate: typeof bulkEvaluate;\n getDatafile: typeof getDatafile;\n}) {\n return function createRawClient<Entities = Record<string, unknown>>({\n controller,\n origin,\n }: {\n controller: ControllerInterface;\n origin?: { provider: string; sdkKey?: string };\n }): FlagsClient<Entities> {\n const id = idCount++;\n controllerInstanceMap.set(id, {\n controller,\n initialized: false,\n initPromise: null,\n });\n\n const api = {\n origin,\n initialize: async () => {\n let instance = controllerInstanceMap.get(id);\n if (!instance) {\n instance = { controller, initialized: false, initPromise: null };\n controllerInstanceMap.set(id, instance);\n }\n\n // skip if already initialized\n if (instance.initialized) return;\n\n if (!instance.initPromise) {\n instance.initPromise = performInitialize(instance, () =>\n fns.initialize(id),\n );\n }\n\n return instance.initPromise;\n },\n shutdown: async () => {\n await fns.shutdown(id);\n controllerInstanceMap.delete(id);\n },\n getDatafile: async () => {\n const instance = controllerInstanceMap.get(id);\n if (instance?.initPromise) {\n try {\n await instance.initPromise;\n } catch {\n // Initialization failed — let getDatafile handle its own fallbacks\n }\n }\n return fns.getDatafile(id);\n },\n getFallbackDatafile: (): Promise<BundledDefinitions> => {\n return fns.getFallbackDatafile(id);\n },\n evaluate: async <T = Value, E = Entities>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ): Promise<EvaluationResult<T>> => {\n const instance = controllerInstanceMap.get(id);\n if (!instance?.initialized) {\n try {\n await api.initialize();\n } catch {\n // Initialization failed — let evaluate() handle the fallback\n // chain (last known value → datafile → bundled → defaultValue → throw)\n }\n }\n return fns.evaluate<T, E>(id, flagKey, defaultValue, entities);\n },\n bulkEvaluate: async <T = Value, E = Entities>(\n flags: BulkEvaluateInput<T>[],\n entities?: E,\n ): Promise<Record<string, EvaluationResult<T>>> => {\n const instance = controllerInstanceMap.get(id);\n if (!instance?.initialized) {\n try {\n await api.initialize();\n } catch {\n // Initialization failed — let bulkEvaluate() handle the fallback\n // chain (last known value → datafile → bundled → defaultValue → throw)\n }\n }\n return fns.bulkEvaluate<T, E>(id, flags, entities);\n },\n };\n return api;\n };\n}\n","// The @vercel/flags-definitions module is created at build time by Vercel CLI\n// in node_modules/. This is a fallback mechanism used so the app can always\n// fall back to a bundled version of the definitions, even if the flags network\n// is degraded or unavailable.\n//\n\nimport type { Auth, BundledDefinitionsLookup } from '../controller/auth';\nimport type { BundledDefinitions, BundledDefinitionsResult } from '../types';\n\n/** In-memory cache of SDK key to its hashed value, so we don't re-hash repeatedly. */\nconst sdkKeyHashCache = new Map<string, Promise<string>>();\n\n/** Computes a SHA-256 hex digest of the given SDK key. */\nasync function computeHash(sdkKey: string): Promise<string> {\n const hashBuffer = await crypto.subtle.digest(\n 'SHA-256',\n new TextEncoder().encode(sdkKey),\n );\n const hashArray = new Uint8Array(hashBuffer);\n return Array.from(hashArray)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/** Returns a cached promise for the SHA-256 hash of the given SDK key. */\nfunction hashSdkKey(sdkKey: string): Promise<string> {\n const cached = sdkKeyHashCache.get(sdkKey);\n if (cached) return cached;\n\n const promise = computeHash(sdkKey);\n sdkKeyHashCache.set(sdkKey, promise);\n return promise;\n}\n\n/**\n * Reads the local definitions that get bundled at build time.\n */\nexport async function readBundledDefinitions(\n auth: Auth,\n): Promise<BundledDefinitionsResult> {\n let get: (sdkKey: string) => BundledDefinitions | null;\n try {\n const module = await import(\n /* turbopackOptional: true */\n '@vercel/flags-definitions'\n );\n get = module.get as (sdkKey: string) => BundledDefinitions | null;\n } catch (error) {\n // If the module doesn't exist, the prepare script didn't run\n if (\n error &&\n typeof error === 'object' &&\n 'code' in error &&\n error.code === 'MODULE_NOT_FOUND'\n ) {\n return { definitions: null, state: 'missing-file' };\n }\n\n return { definitions: null, state: 'unexpected-error', error };\n }\n\n if (typeof get !== 'function') {\n return { definitions: null, state: 'missing-file' };\n }\n\n let lookup: BundledDefinitionsLookup;\n try {\n lookup = await auth.resolveBundledDefinitionsLookup();\n } catch (error) {\n return { definitions: null, state: 'unexpected-error', error };\n }\n\n if (lookup.type === 'project-id') {\n const entry = get(lookup.projectId);\n return entry\n ? { definitions: entry, state: 'ok' }\n : { definitions: null, state: 'missing-entry' };\n }\n\n // Try plain sdk key first for bundles created by older CLI versions.\n const entry = get(lookup.sdkKey);\n if (entry) return { definitions: entry, state: 'ok' };\n\n // try hashed key but catch any errors\n try {\n const hashedKey = await hashSdkKey(lookup.sdkKey);\n // try original key (older cli versions) and hashed key (newer cli versions)\n const hashedEntry = get(hashedKey);\n if (hashedEntry) return { definitions: hashedEntry, state: 'ok' };\n } catch (error) {\n return { definitions: null, state: 'unexpected-error', error };\n }\n\n return { definitions: null, state: 'missing-entry' };\n}\n","import { getVercelOidcToken } from '@vercel/oidc';\nimport { version } from '../../package.json';\nimport type { Auth } from '../controller/auth';\nimport type { MetricEnvironment } from '../types';\nimport { getRetryDelayMs } from './backoff';\nimport type { FlushReason } from './scheduler';\nimport type { IngestEvent, UsageEvent } from './usage/events';\n\nconst MAX_RETRIES = 3;\n\n/**\n * Maximum number of events sent in a single POST to the ingest endpoint.\n *\n * Flushes are cut purely by time (see Scheduler), so a single flush can carry\n * arbitrarily many events. Chunking each send is what bounds the request size:\n * the server rejects request bodies with more events than its `maxItems` cap, so this\n * constant must stay below that cap.\n */\nexport const MAX_EVENTS_PER_REQUEST = 2000;\n\nexport const EVALUATING_OIDC_TOKEN_HEADER = 'X-Vercel-Flags-OIDC-Token';\nexport const FLUSH_REASON_HEADER = 'X-Vercel-Flags-Flush-Reason';\n\nconst isDebugMode = process.env.DEBUG?.includes('@vercel/flags-core');\n\nconst debugLog = (...args: any[]) => {\n if (!isDebugMode) return;\n console.log(...args);\n};\n\nexport interface IngestOptions {\n auth: Auth;\n host: string;\n fetch: typeof fetch;\n metricEnvironment?: MetricEnvironment;\n}\n\nasync function getEvaluatingOidcToken(auth: Auth): Promise<string | undefined> {\n if (!auth.sdkKey) return undefined;\n\n try {\n return await getVercelOidcToken();\n } catch {\n return undefined;\n }\n}\n\nasync function getIngestHeaders(\n options: IngestOptions,\n flushReason: FlushReason,\n): Promise<Record<string, string>> {\n const token = await options.auth.resolveToken();\n const evaluatingOidcToken = await getEvaluatingOidcToken(options.auth);\n\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n 'User-Agent': `VercelFlagsCore/${version}`,\n [FLUSH_REASON_HEADER]: flushReason,\n ...((options.metricEnvironment ?? process.env.VERCEL_ENV)\n ? {\n 'X-Vercel-Env':\n options.metricEnvironment ?? (process.env.VERCEL_ENV as string),\n }\n : null),\n ...(evaluatingOidcToken\n ? { [EVALUATING_OIDC_TOKEN_HEADER]: evaluatingOidcToken }\n : null),\n ...(isDebugMode ? { 'x-vercel-debug-ingest': '1' } : null),\n };\n}\n\nexport async function sendIngestEvents(\n options: IngestOptions,\n events: UsageEvent[],\n flushId: number,\n flushReason: FlushReason,\n): Promise<void> {\n const eventsToSend = events.map((event) => event.ingestEvent());\n\n for (let i = 0; i < eventsToSend.length; i += MAX_EVENTS_PER_REQUEST) {\n await sendIngestChunk(\n options,\n eventsToSend.slice(i, i + MAX_EVENTS_PER_REQUEST),\n flushId,\n flushReason,\n );\n }\n}\n\nasync function sendIngestChunk(\n options: IngestOptions,\n eventsToSend: IngestEvent[],\n flushId: number,\n flushReason: FlushReason,\n): Promise<void> {\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n const response = await options.fetch(`${options.host}/v1/ingest`, {\n method: 'POST',\n headers: await getIngestHeaders(options, flushReason),\n body: JSON.stringify(eventsToSend),\n });\n\n debugLog(\n `@vercel/flags-core: Ingest response ${response.status} for ${eventsToSend.length} events on ${response.headers.get('x-vercel-id')}`,\n );\n\n if (response.ok) {\n break;\n }\n\n throw new Error(\n `Ingest endpoint responded with status ${response.status} for ${eventsToSend.length} events on request ${response.headers.get('x-vercel-id')}.\\n` +\n `Response body: ${await response.text().catch(() => null)}`,\n );\n } catch (error) {\n console.error(\n `@vercel/flags-core: Error sending events (attempt=${attempt}/${MAX_RETRIES} flushId=${flushId}):`,\n error,\n );\n if (attempt < MAX_RETRIES) {\n const delayMs = getRetryDelayMs(attempt);\n await new Promise((res) => setTimeout(res, delayMs));\n } else {\n // All retries exhausted - surface a structured warning so consumers\n // can alert on dropped batches. The events are not persisted anywhere.\n console.error(\n `@vercel/flags-core: Dropped ${eventsToSend.length} events after ${MAX_RETRIES} attempts (flushId=${flushId})`,\n );\n }\n }\n }\n}\n","/**\n * Backoff and jitter utilities for retry loops.\n *\n * The functions here are intentionally generic so they can be used wherever\n * the SDK retries an operation. They use `Math.random` directly; mock it from\n * tests if you need deterministic behaviour.\n */\n\nconst DEFAULT_BASE_MS = 250;\nconst DEFAULT_CAP_MS = 5000;\n\nexport interface RetryDelayOptions {\n /**\n * The base delay in milliseconds. With Full Jitter, the first failed attempt\n * sleeps in `[0, baseMs)`, the second in `[0, baseMs * 2)`, etc.\n * Defaults to 250ms.\n */\n baseMs?: number;\n /**\n * Hard ceiling on the computed delay. Defaults to 5000ms.\n */\n capMs?: number;\n}\n\n/**\n * Returns the sleep duration before the next retry attempt using AWS-style\n * \"Full Jitter\" exponential backoff.\n *\n * @param attempt The 1-indexed attempt number that just failed.\n * @see https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter\n */\nexport function getRetryDelayMs(\n attempt: number,\n options: RetryDelayOptions = {},\n): number {\n const baseMs = options.baseMs ?? DEFAULT_BASE_MS;\n const capMs = options.capMs ?? DEFAULT_CAP_MS;\n\n const ceiling = Math.min(capMs, baseMs * 2 ** Math.max(0, attempt - 1));\n return Math.floor(Math.random() * ceiling);\n}\n\n/**\n * Returns `baseMs` perturbed by `±ratio` of itself, drawn uniformly from\n * `[baseMs * (1 - ratio), baseMs * (1 + ratio))`. Useful for desynchronizing\n * fixed-interval timers across independent processes.\n *\n * @param baseMs The target mean wait, in milliseconds.\n * @param ratio The fractional jitter to apply on each side, in `[0, 1)`.\n */\nexport function getJitteredWaitMs(baseMs: number, ratio: number): number {\n const min = baseMs * (1 - ratio);\n const span = baseMs * 2 * ratio;\n return Math.floor(min + Math.random() * span);\n}\n","interface RequestContext {\n ctx: object | undefined;\n headers: Record<string, string> | undefined;\n}\n\nconst SYMBOL_FOR_REQ_CONTEXT = Symbol.for('@vercel/request-context');\nconst fromSymbol = globalThis as typeof globalThis & {\n [key: symbol]:\n | { get?: () => { headers?: Record<string, string> } }\n | undefined;\n};\n\n/**\n * Gets the Vercel request context and headers from the global symbol.\n */\nexport function getRequestContext(): RequestContext {\n try {\n const ctx = fromSymbol[SYMBOL_FOR_REQ_CONTEXT]?.get?.();\n if (ctx && Object.hasOwn(ctx, 'headers')) {\n return {\n ctx,\n headers: ctx.headers as Record<string, string>,\n };\n }\n return { ctx, headers: undefined };\n } catch {\n return { ctx: undefined, headers: undefined };\n }\n}\n","import { waitUntil } from '@vercel/functions';\nimport { getJitteredWaitMs } from './backoff';\n\nconst IDLE_FLUSH_WAIT_MS = 5000;\nconst IDLE_FLUSH_JITTER_RATIO = 0.2;\nconst MAX_FLUSH_WAIT_MS = 60000;\n\nexport type FlushReason = 'idle_timeout' | 'max_timeout' | 'shutdown';\n\n/**\n * Schedule helper that flushes when any of the following occur:\n * - the idle window elapses ({@link IDLE_FLUSH_WAIT_MS}, reset on every event), or\n * - the max window elapses ({@link MAX_FLUSH_WAIT_MS}, starts with the batch and is\n * never reset, so a batch always flushes under continuous traffic).\n *\n * Flushing is purely time-based; batches are only cut down to size when the\n * ingest events are sent (see MAX_EVENTS_PER_REQUEST in ingest.ts).\n *\n * The scheduled flush awaits {@link onFlush} (including its ingest send + retries),\n * so the promise handed to `waitUntil` does not resolve until ingest completes.\n */\nexport class Scheduler {\n private resolveWait: ((reason: FlushReason) => void) | null = null;\n private pending: null | Promise<void> = null;\n private idleTimeout: null | ReturnType<typeof setTimeout> = null;\n private maxTimeout: null | ReturnType<typeof setTimeout> = null;\n\n constructor(\n private readonly onFlush: (reason: FlushReason) => void | Promise<void>,\n ) {}\n\n scheduleFlush(): void {\n if (!this.pending) {\n this.pending = (async () => {\n // wait for a timeout or the event count to reach the batch size\n const reason = await new Promise<FlushReason>((res) => {\n this.resolveWait = res;\n });\n\n // free state so new events start a fresh batch while ingest runs\n this.reset();\n\n // genuinely await ingest (incl. retries) so waitUntil covers the send\n await this.onFlush(reason);\n })();\n\n try {\n waitUntil(this.pending);\n } catch {\n // waitUntil is best-effort; falling through leaves a floating promise\n }\n\n // max window: starts with the batch and is never reset\n this.maxTimeout = setTimeout(\n () => this.resolveScheduledFlush('max_timeout'),\n MAX_FLUSH_WAIT_MS,\n );\n }\n\n // idle window: reset on every event\n this.resetIdleTimeout();\n }\n\n /**\n * Resolves any in-flight scheduled flush and waits for its ingest to finish.\n */\n async shutdown(): Promise<void> {\n this.clearTimeouts();\n const pending = this.pending;\n this.resolveScheduledFlush('shutdown');\n if (pending) await pending;\n }\n\n private resetIdleTimeout(): void {\n if (this.idleTimeout) clearTimeout(this.idleTimeout);\n this.idleTimeout = setTimeout(\n () => this.resolveScheduledFlush('idle_timeout'),\n getJitteredWaitMs(IDLE_FLUSH_WAIT_MS, IDLE_FLUSH_JITTER_RATIO),\n );\n }\n\n private resolveScheduledFlush(reason: FlushReason): void {\n this.clearTimeouts();\n this.resolveWait?.(reason);\n }\n\n private reset(): void {\n this.pending = null;\n this.resolveWait = null;\n this.clearTimeouts();\n }\n\n private clearTimeouts(): void {\n if (this.idleTimeout) {\n clearTimeout(this.idleTimeout);\n this.idleTimeout = null;\n }\n if (this.maxTimeout) {\n clearTimeout(this.maxTimeout);\n this.maxTimeout = null;\n }\n }\n}\n","import type { UsageEvent } from './events';\n\nexport interface TrackReadOptions {\n /** Whether the config was read from in-memory cache or embedded bundle */\n configOrigin: 'in-memory' | 'embedded';\n /** HIT when definitions exist in memory, MISS when not, BYPASS when using fallback as primary source */\n cacheStatus?: 'HIT' | 'MISS' | 'BYPASS';\n /** FOLLOWING when streaming, REFRESHING when polling, NONE otherwise */\n cacheAction?: 'REFRESHING' | 'FOLLOWING' | 'NONE';\n /** True for the very first getData call */\n cacheIsFirstRead?: boolean;\n /** Whether the cache read was blocking */\n cacheIsBlocking?: boolean;\n /** Duration in milliseconds from start of getData until trackRead */\n duration?: number;\n /** Timestamp when the config was last updated */\n configUpdatedAt?: number;\n /** The mode the SDK is operating in */\n mode?: 'poll' | 'stream' | 'build' | 'offline';\n /** Revision of the config */\n revision?: number;\n}\n\nexport class FlagsConfigReadEvent implements UsageEvent {\n private readonly ts = Date.now();\n\n private payload: {\n deploymentId?: string;\n region?: string;\n invocationHost?: string;\n vercelRequestId?: string;\n cacheStatus?: 'HIT' | 'MISS' | 'BYPASS' | 'STALE';\n cacheAction?: 'REFRESHING' | 'FOLLOWING' | 'NONE';\n cacheIsBlocking?: boolean;\n cacheIsFirstRead?: boolean;\n duration?: number;\n configUpdatedAt?: number;\n configOrigin?: 'in-memory' | 'embedded' | 'poll' | 'stream' | 'constructor';\n mode?: 'poll' | 'stream' | 'build' | 'offline';\n revision?: string;\n environment?: string;\n };\n\n constructor(\n headers: Record<string, string> | undefined,\n options?: TrackReadOptions,\n ) {\n this.payload = {\n deploymentId: process.env.VERCEL_DEPLOYMENT_ID,\n region: process.env.VERCEL_REGION,\n };\n\n if (headers) {\n this.payload.vercelRequestId = headers['x-vercel-id'] ?? undefined;\n this.payload.invocationHost = headers.host ?? undefined;\n }\n\n if (options) {\n this.payload.configOrigin = options.configOrigin;\n if (options.cacheStatus !== undefined) {\n this.payload.cacheStatus = options.cacheStatus;\n }\n if (options.cacheAction !== undefined) {\n this.payload.cacheAction = options.cacheAction;\n }\n if (options.cacheIsFirstRead !== undefined) {\n this.payload.cacheIsFirstRead = options.cacheIsFirstRead;\n }\n if (options.cacheIsBlocking !== undefined) {\n this.payload.cacheIsBlocking = options.cacheIsBlocking;\n }\n if (options.duration !== undefined) {\n this.payload.duration = options.duration;\n }\n if (options.configUpdatedAt !== undefined) {\n this.payload.configUpdatedAt = options.configUpdatedAt;\n }\n if (options.mode !== undefined) {\n this.payload.mode = options.mode;\n }\n if (options.revision !== undefined) {\n this.payload.revision = String(options.revision);\n }\n }\n\n const environment =\n process.env.VERCEL_ENV || process.env.NODE_ENV || undefined;\n if (environment) {\n this.payload.environment = environment;\n }\n }\n\n ingestEvent() {\n return {\n type: 'FLAGS_CONFIG_READ' as const,\n ts: this.ts,\n payload: this.payload,\n };\n }\n}\n","import type { ResolutionReason, VariantId } from '../../types';\nimport type { UsageEvent } from './events';\n\nexport interface TrackEvaluationOptions {\n flagKey: string;\n variant: VariantId | null;\n reason: ResolutionReason;\n clientName?: string;\n}\n\nconst MINUTE_MS = 60_000;\n\nexport function minuteBucketTs(ts = Date.now()): number {\n return Math.floor(ts / MINUTE_MS) * MINUTE_MS;\n}\n\nexport type BucketedTrackEvaluationOptions = TrackEvaluationOptions & {\n bucketTs: number;\n};\n\nexport function evaluationBatchKey(\n options: BucketedTrackEvaluationOptions,\n): string {\n return JSON.stringify([\n options.flagKey,\n options.variant,\n options.reason,\n options.clientName ?? null,\n options.bucketTs,\n ]);\n}\n\nexport class FlagsEvaluationEvent implements UsageEvent {\n private readonly ts = Date.now();\n\n payload: {\n flagKey: string;\n variant?: string;\n reason: ResolutionReason;\n clientName?: string;\n evaluationCount: number;\n periodStartedAt: number;\n };\n\n constructor(eventOptions: BucketedTrackEvaluationOptions) {\n this.payload = {\n flagKey: eventOptions.flagKey,\n variant: eventOptions.variant ?? undefined,\n reason: eventOptions.reason,\n evaluationCount: 1,\n periodStartedAt: eventOptions.bucketTs,\n };\n\n if (eventOptions.clientName) {\n this.payload.clientName = eventOptions.clientName;\n }\n }\n\n increment(): void {\n this.payload.evaluationCount += 1;\n }\n\n ingestEvent() {\n return {\n type: 'FLAG_EVALUATION' as const,\n ts: this.ts,\n payload: this.payload,\n };\n }\n}\n","import { type IngestOptions, sendIngestEvents } from './ingest';\nimport { getRequestContext } from './request-context';\nimport { type FlushReason, Scheduler } from './scheduler';\nimport {\n FlagsConfigReadEvent,\n type TrackReadOptions,\n} from './usage/flags-config-read';\nimport {\n evaluationBatchKey,\n FlagsEvaluationEvent,\n minuteBucketTs,\n type TrackEvaluationOptions,\n} from './usage/flags-evaluation';\n\n/**\n * Tracks usage events and batches them for submission to the ingest endpoint.\n */\nexport class UsageTracker {\n private flushCount: number = 0;\n\n private options: IngestOptions;\n private scheduler: Scheduler;\n\n private trackedRequests = new WeakSet<object>();\n\n private readEvents: FlagsConfigReadEvent[] = [];\n private evaluationEvents = new Map<string, FlagsEvaluationEvent>();\n\n constructor(options: IngestOptions) {\n this.options = options;\n this.scheduler = new Scheduler((reason) => this.flushEvents(reason));\n }\n\n /**\n * Triggers an immediate flush of any pending events.\n * Returns a promise that resolves when the flush completes.\n */\n async shutdown() {\n // Drain any in-flight scheduled batch (incl. its ingest send).\n await this.scheduler.shutdown();\n\n // Safety net for events tracked after the drained batch reset; if the\n // drained flush already sent everything this returns early (maps cleared).\n await this.flushEvents('shutdown');\n }\n\n /**\n * Tracks a config read event. Deduplicates by request context.\n */\n trackRead(options?: TrackReadOptions): void {\n try {\n const { ctx, headers } = getRequestContext();\n\n // Skip if request context can't be inferred\n if (!ctx) return;\n\n // Skip if we've already tracked this request\n if (this.trackedRequests.has(ctx)) return;\n this.trackedRequests.add(ctx);\n\n this.readEvents.push(new FlagsConfigReadEvent(headers, options));\n\n this.scheduler.scheduleFlush();\n } catch (error) {\n // trackRead should never throw, but log the error\n console.error('@vercel/flags-core: Failed to record event:', error);\n }\n }\n\n /**\n * Tracks a flag evaluation event.\n */\n trackEvaluation(options: TrackEvaluationOptions): void {\n try {\n const bucketedOptions = {\n ...options,\n bucketTs: minuteBucketTs(),\n };\n const batchKey = evaluationBatchKey(bucketedOptions);\n\n const existingEvent = this.evaluationEvents.get(batchKey);\n // increment if we already have an event for this batch key\n if (existingEvent) {\n existingEvent.increment();\n } else {\n this.evaluationEvents.set(\n batchKey,\n new FlagsEvaluationEvent(bucketedOptions),\n );\n }\n\n // always schedule to reset the timer\n this.scheduler.scheduleFlush();\n } catch (error) {\n console.error(\n '@vercel/flags-core: Failed to record evaluation event:',\n error,\n );\n }\n }\n\n /**\n * Send all events to the ingest service\n */\n private async flushEvents(flushReason: FlushReason) {\n const events = [...this.readEvents, ...this.evaluationEvents.values()];\n if (events.length === 0) return;\n\n this.flushCount += 1;\n const flushId = this.flushCount;\n\n this.readEvents = [];\n this.evaluationEvents.clear();\n\n await sendIngestEvents(this.options, events, flushId, flushReason);\n }\n}\n","/**\n * Error thrown when the fallback definitions file does not exist.\n * This typically means the \"vercel-flags prepare\" command was not run before building.\n */\nexport class FallbackNotFoundError extends Error {\n constructor() {\n super('@vercel/flags-core: Bundled definitions file not found.');\n this.name = 'FallbackNotFoundError';\n }\n}\n\n/**\n * Error thrown when the fallback definitions file exists but has no entry for the SDK key.\n * This means the SDK key was not included when running \"vercel-flags prepare\".\n */\nexport class FallbackEntryNotFoundError extends Error {\n constructor() {\n super('@vercel/flags-core: No bundled definitions found for SDK key.');\n this.name = 'FallbackEntryNotFoundError';\n }\n}\n","import { FallbackEntryNotFoundError, FallbackNotFoundError } from '../errors';\nimport type {\n BundledDefinitions,\n BundledDefinitionsResult,\n DatafileInput,\n} from '../types';\nimport type { readBundledDefinitions } from '../utils/read-bundled-definitions';\nimport type { Auth } from './auth';\n\n/**\n * Manages loading of bundled flag definitions.\n * Wraps readBundledDefinitions() with caching.\n */\nexport class BundledSource {\n private promise: Promise<BundledDefinitionsResult> | undefined;\n\n constructor(\n private options: {\n auth: Auth;\n readBundledDefinitions: typeof readBundledDefinitions;\n },\n ) {}\n\n /**\n * Load bundled definitions.\n * Throws if bundled definitions are not available.\n */\n async load(): Promise<DatafileInput> {\n const result = await this.getResult();\n\n if (result.state === 'ok' && result.definitions) {\n return result.definitions;\n }\n\n throw new Error(\n '@vercel/flags-core: No flag definitions available. ' +\n 'Bundled definitions not found.',\n );\n }\n\n /**\n * Get the raw BundledDefinitions (for getFallbackDatafile).\n * Throws typed errors if not available.\n */\n async getRaw(): Promise<BundledDefinitions> {\n const result = await this.getResult();\n\n switch (result.state) {\n case 'ok':\n return result.definitions;\n case 'missing-file':\n throw new FallbackNotFoundError();\n case 'missing-entry':\n throw new FallbackEntryNotFoundError();\n case 'unexpected-error':\n throw new Error(\n '@vercel/flags-core: Failed to read bundled definitions: ' +\n String(result.error),\n );\n }\n }\n\n /**\n * Check if bundled definitions loaded successfully (without throwing).\n */\n async tryLoad(): Promise<DatafileInput | undefined> {\n const result = await this.getResult();\n if (result?.state === 'ok' && result.definitions) {\n return result.definitions;\n }\n return undefined;\n }\n\n private getResult(): Promise<BundledDefinitionsResult> {\n if (!this.promise) {\n this.promise = this.options.readBundledDefinitions(this.options.auth);\n }\n return this.promise;\n }\n}\n","import { version } from '../../package.json';\nimport type { BundledDefinitions } from '../types';\nimport type { Auth } from './auth';\n\nconst DEFAULT_FETCH_TIMEOUT_MS = 10_000;\n\n/**\n * Fetches the datafile from the flags service.\n */\nexport async function fetchDatafile(options: {\n host: string;\n auth: Auth;\n fetch: typeof globalThis.fetch;\n signal?: AbortSignal;\n}): Promise<BundledDefinitions> {\n const token = await options.auth.resolveToken();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n DEFAULT_FETCH_TIMEOUT_MS,\n );\n\n // Abort the internal controller when the external signal fires\n const onExternalAbort = () => controller.abort();\n if (options.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutId);\n throw new Error('Fetch aborted');\n }\n options.signal.addEventListener('abort', onExternalAbort, { once: true });\n }\n\n try {\n const res = await options.fetch(`${options.host}/v1/datafile`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'User-Agent': `VercelFlagsCore/${version}`,\n ...(process.env.VERCEL_ENV\n ? { 'X-Vercel-Env': process.env.VERCEL_ENV }\n : null),\n },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n options.signal?.removeEventListener('abort', onExternalAbort);\n\n if (!res.ok) {\n throw new Error(`Failed to fetch data: ${res.statusText}`);\n }\n\n return res.json() as Promise<BundledDefinitions>;\n } catch (error) {\n clearTimeout(timeoutId);\n options.signal?.removeEventListener('abort', onExternalAbort);\n throw error instanceof Error ? error : new Error('Unknown fetch error');\n }\n}\n","import type {\n DatafileInput,\n MetricEnvironment,\n PollingOptions,\n StreamOptions,\n} from '../types';\nimport type { Auth } from './auth';\n\nconst DEFAULT_STREAM_INIT_TIMEOUT_MS = 3000;\nconst DEFAULT_POLLING_INTERVAL_MS = 30_000;\nconst MIN_POLLING_INTERVAL_MS = 30_000;\nconst DEFAULT_POLLING_INIT_TIMEOUT_MS = 3_000;\n\n/**\n * Configuration options for Controller\n */\nexport type ControllerOptions = {\n /** Authentication which resolves the token for requests */\n auth: Auth;\n\n /**\n * Initial datafile to use immediately\n * - At runtime: used while waiting for stream/poll, then updated in background\n * - At build step: used as primary source (skips network)\n */\n datafile?: DatafileInput;\n\n /**\n * Configure streaming connection (runtime only, ignored during build step)\n * - `true`: Enable with default options (initTimeoutMs: 3000)\n * - `false`: Disable streaming\n * - `{ initTimeoutMs: number }`: Enable with custom timeout\n * @default true\n */\n stream?: boolean | StreamOptions;\n\n /**\n * Configure polling fallback (runtime only, ignored during build step)\n * - `true`: Enable with default options (intervalMs: 30000, initTimeoutMs: 3000)\n * - `false`: Disable polling\n * - `{ intervalMs: number, initTimeoutMs: number }`: Enable with custom options\n * @default true\n */\n polling?: boolean | PollingOptions;\n\n /**\n * Override build step detection\n * - `true`: Treat as build step (use datafile/bundled only, no network)\n * - `false`: Treat as runtime (try stream/poll first)\n * @default auto-detected via CI=1 or NEXT_PHASE=phase-production-build\n */\n buildStep?: boolean;\n\n /**\n * Custom fetch function for making HTTP requests.\n * Useful for testing (e.g. resolving to a different IP).\n * @default globalThis.fetch\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Environment included with evaluation metrics sent to the ingest endpoint.\n * Falls back to the `VERCEL_ENV` environment variable when not set.\n * This does not select the environment used for flag evaluation.\n */\n metricEnvironment?: MetricEnvironment;\n\n /**\n * Custom client name included in evaluation telemetry.\n */\n clientName?: string;\n\n /**\n * Disable evaluation metrics for this client.\n * @default false\n */\n disableMetrics?: boolean;\n};\n\nexport type NormalizedOptions = {\n auth: Auth;\n datafile: DatafileInput | undefined;\n stream: { enabled: boolean; initTimeoutMs: number };\n polling: { enabled: boolean; intervalMs: number; initTimeoutMs: number };\n buildStep: boolean;\n fetch: typeof globalThis.fetch;\n host: string;\n metricEnvironment: MetricEnvironment | undefined;\n clientName: string | undefined;\n disableMetrics: boolean;\n};\n\nexport function normalizeOptions(\n options: ControllerOptions,\n): NormalizedOptions {\n const autoDetectedBuildStep =\n process.env.CI === '1' ||\n process.env.NEXT_PHASE === 'phase-production-build';\n const buildStep = options.buildStep ?? autoDetectedBuildStep;\n\n let stream: NormalizedOptions['stream'];\n if (options.stream === undefined || options.stream === true) {\n stream = { enabled: true, initTimeoutMs: DEFAULT_STREAM_INIT_TIMEOUT_MS };\n } else if (options.stream === false) {\n stream = { enabled: false, initTimeoutMs: 0 };\n } else {\n stream = { enabled: true, initTimeoutMs: options.stream.initTimeoutMs };\n }\n\n let polling: NormalizedOptions['polling'];\n if (options.polling === undefined || options.polling === true) {\n polling = {\n enabled: true,\n intervalMs: DEFAULT_POLLING_INTERVAL_MS,\n initTimeoutMs: DEFAULT_POLLING_INIT_TIMEOUT_MS,\n };\n } else if (options.polling === false) {\n polling = { enabled: false, intervalMs: 0, initTimeoutMs: 0 };\n } else {\n if (options.polling.intervalMs < MIN_POLLING_INTERVAL_MS) {\n throw new Error(\n `@vercel/flags-core: Polling interval must be at least ${MIN_POLLING_INTERVAL_MS}ms, got ${options.polling.intervalMs}ms.`,\n );\n }\n polling = {\n enabled: true,\n intervalMs: options.polling.intervalMs,\n initTimeoutMs: options.polling.initTimeoutMs,\n };\n }\n\n return {\n auth: options.auth,\n datafile: options.datafile,\n stream,\n polling,\n buildStep,\n fetch: options.fetch ?? globalThis.fetch,\n host: 'https://flags.vercel.com',\n metricEnvironment: options.metricEnvironment,\n clientName: options.clientName,\n disableMetrics: options.disableMetrics ?? false,\n };\n}\n","/**\n * Lightweight typed event emitter base class.\n * Each source module extends this to emit typed events.\n */\nexport class TypedEmitter<\n Events extends Record<string, (...args: any[]) => void>,\n> {\n private handlers = new Map<keyof Events, Set<Events[keyof Events]>>();\n\n on<E extends keyof Events>(event: E, handler: Events[E]): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler as Events[keyof Events]);\n }\n\n off<E extends keyof Events>(event: E, handler: Events[E]): void {\n this.handlers.get(event)?.delete(handler as Events[keyof Events]);\n }\n\n protected emit<E extends keyof Events>(\n event: E,\n ...args: Parameters<Events[E]>\n ): void {\n const set = this.handlers.get(event);\n if (set) {\n for (const handler of set) {\n (handler as (...a: any[]) => void)(...args);\n }\n }\n }\n}\n","import type { DatafileInput } from '../types';\nimport type { Auth } from './auth';\nimport { fetchDatafile } from './fetch-datafile';\nimport { TypedEmitter } from './typed-emitter';\n\nexport type PollingSourceConfig = {\n host: string;\n auth: Auth;\n polling: {\n intervalMs: number;\n };\n fetch: typeof globalThis.fetch;\n};\n\nexport type PollingSourceEvents = {\n data: (data: DatafileInput) => void;\n error: (error: Error) => void;\n};\n\n/**\n * Manages interval-based polling for flag data.\n * Wraps fetchDatafile() and emits typed events.\n */\nexport class PollingSource extends TypedEmitter<PollingSourceEvents> {\n private config: PollingSourceConfig;\n private intervalId: ReturnType<typeof setInterval> | undefined;\n private abortController: AbortController | undefined;\n\n constructor(config: PollingSourceConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Perform a single poll request.\n * Emits 'data' on success, 'error' on failure.\n */\n async poll(): Promise<void> {\n if (this.abortController?.signal.aborted) return;\n\n try {\n const data = await fetchDatafile({\n ...this.config,\n signal: this.abortController?.signal,\n });\n this.emit('data', data);\n } catch (error) {\n const err =\n error instanceof Error ? error : new Error('Unknown poll error');\n this.emit('error', err);\n }\n }\n\n /**\n * Start interval-based polling.\n * Polls at the configured interval. Does not perform an initial poll —\n * callers should call poll() first if an immediate poll is needed.\n */\n startInterval(): void {\n if (this.intervalId) return;\n\n this.abortController = new AbortController();\n\n // Start interval\n this.intervalId = setInterval(\n () => void this.poll(),\n this.config.polling.intervalMs,\n );\n }\n\n /**\n * Stop interval-based polling.\n */\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n this.abortController?.abort();\n this.abortController = undefined;\n }\n}\n","export function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { version } from '../../package.json';\nimport type { BundledDefinitions } from '../types';\nimport { sleep } from '../utils/sleep';\n\nexport type PrimedMessage = {\n type: 'primed';\n revision: number;\n projectId: string;\n environment: string;\n};\n\nexport type StreamMessage =\n | { type: 'datafile'; data: BundledDefinitions }\n | PrimedMessage\n | { type: 'ping' };\n\nconst MAX_RETRY_COUNT = 15;\nconst BASE_RETRY_DELAY_MS = 1000;\nconst MAX_RETRY_DELAY_MS = 60_000;\nconst PING_TIMEOUT_MS = 90_000;\n\nfunction backoff(retryCount: number): number {\n if (retryCount === 1) return 0;\n const delay = Math.min(\n BASE_RETRY_DELAY_MS * 2 ** (retryCount - 2),\n MAX_RETRY_DELAY_MS,\n );\n return delay + Math.random() * 1000;\n}\n\nexport class UnauthorizedError extends Error {\n constructor() {\n super('stream: unauthorized (401)');\n this.name = 'UnauthorizedError';\n }\n}\n\nclass TokenResolutionError extends Error {\n constructor(error: unknown) {\n super('stream: token resolution failed', { cause: error });\n this.name = 'TokenResolutionError';\n }\n}\n\nexport type StreamCallbacks = {\n onDatafile: (data: BundledDefinitions) => void;\n onPrimed?: (message: PrimedMessage) => void;\n onDisconnect?: () => void;\n};\n\nexport type StreamConfig = {\n host: string;\n abortController: AbortController;\n fetch?: typeof globalThis.fetch;\n /** Returns the current revision number to send as X-Revision header */\n revision?: () => number | undefined;\n resolveToken: () => Promise<string>;\n};\n\n/**\n * Connects to the flags stream endpoint and handles reconnection with backoff.\n * Resolves when the first datafile message is received.\n * Rejects if the connection fails before receiving any data.\n */\nexport async function connectStream(\n config: StreamConfig,\n callbacks: StreamCallbacks,\n): Promise<void> {\n const { host, abortController, fetch: fetchFn = globalThis.fetch } = config;\n const { onDatafile, onPrimed, onDisconnect } = callbacks;\n let retryCount = 0;\n let lastAttemptTime = 0;\n\n let resolveInit: () => void;\n let rejectInit: (error: unknown) => void;\n const initPromise = new Promise<void>((resolve, reject) => {\n resolveInit = resolve;\n rejectInit = reject;\n });\n\n void (async () => {\n let initialDataReceived = false;\n let lastError: unknown;\n\n while (!abortController.signal.aborted) {\n if (retryCount > MAX_RETRY_COUNT) {\n console.error(\n '@vercel/flags-core: Max retry count exceeded',\n lastError ?? 'stream closed repeatedly without an error',\n );\n if (!initialDataReceived) {\n rejectInit!(\n new Error('stream: max retry count exceeded before receiving data'),\n );\n }\n abortController.abort();\n break;\n }\n\n // Per-connection abort controller — allows ping timeout to abort a single\n // connection without stopping the entire retry loop.\n const connectionAbort = new AbortController();\n const onMainAbort = (): void => connectionAbort.abort();\n abortController.signal.addEventListener('abort', onMainAbort, {\n once: true,\n });\n\n let pingTimeoutId: ReturnType<typeof setTimeout> | undefined;\n // Reference to the response body so the ping timeout can cancel it\n // to break out of the for-await loop.\n let responseBody: ReadableStream<Uint8Array> | undefined;\n const resetPingTimeout = (): void => {\n if (pingTimeoutId !== undefined) clearTimeout(pingTimeoutId);\n if (!initialDataReceived) return;\n pingTimeoutId = setTimeout(() => {\n responseBody?.cancel().catch(() => {});\n connectionAbort.abort();\n }, PING_TIMEOUT_MS);\n };\n\n try {\n lastAttemptTime = Date.now();\n const token = await config.resolveToken().catch((error) => {\n throw new TokenResolutionError(error);\n });\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n 'User-Agent': `VercelFlagsCore/${version}`,\n 'X-Retry-Attempt': String(retryCount),\n };\n const vercelEnv = process.env.VERCEL_ENV;\n if (vercelEnv) {\n headers['X-Vercel-Env'] = vercelEnv;\n }\n const revision = config.revision?.();\n if (revision !== undefined) {\n headers['X-Revision'] = String(revision);\n }\n const response = await fetchFn(`${host}/v1/stream`, {\n headers,\n signal: connectionAbort.signal,\n });\n\n if (!response.ok) {\n if (response.status === 401) {\n if (!initialDataReceived) {\n rejectInit!(new UnauthorizedError());\n }\n abortController.abort();\n break;\n }\n\n throw new Error(`stream was not ok: ${response.status}`);\n }\n\n if (!response.body) {\n throw new Error('stream body was not present');\n }\n\n responseBody = response.body;\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const bufferChunks: string[] = [];\n\n // Allow the ping timeout (or main abort) to cancel the reader,\n // which breaks the read loop immediately even on a zombie connection.\n const onConnectionAbort = (): void => {\n reader.cancel().catch(() => {});\n };\n connectionAbort.signal.addEventListener('abort', onConnectionAbort, {\n once: true,\n });\n\n try {\n while (true) {\n const { done, value: chunk } = await reader.read();\n if (done || abortController.signal.aborted) break;\n\n bufferChunks.push(decoder.decode(chunk, { stream: true }));\n const combined = bufferChunks.join('');\n bufferChunks.length = 0;\n const lines = combined.split('\\n');\n bufferChunks.push(lines.pop()!);\n\n for (const line of lines) {\n if (line === '') continue;\n\n let message: StreamMessage;\n try {\n message = JSON.parse(line) as StreamMessage;\n } catch {\n console.warn(\n '@vercel/flags-core: Failed to parse stream message, skipping',\n );\n continue;\n }\n\n if (message.type === 'datafile') {\n onDatafile(message.data);\n retryCount = 0;\n if (!initialDataReceived) {\n initialDataReceived = true;\n resolveInit!();\n }\n resetPingTimeout();\n }\n\n // Primed means the server confirmed our revision is current,\n // so no full datafile is needed. Treat it like initial data\n // for init resolution purposes.\n if (message.type === 'primed') {\n onPrimed?.(message);\n retryCount = 0;\n if (!initialDataReceived) {\n initialDataReceived = true;\n resolveInit!();\n }\n resetPingTimeout();\n }\n\n // Pings prove the connection is alive — reset retry count\n // once initial data has been received\n if (message.type === 'ping' && initialDataReceived) {\n retryCount = 0;\n resetPingTimeout();\n }\n }\n }\n } finally {\n connectionAbort.signal.removeEventListener(\n 'abort',\n onConnectionAbort,\n );\n }\n\n // Stream ended normally (server closed connection) - reconnect\n clearTimeout(pingTimeoutId);\n abortController.signal.removeEventListener('abort', onMainAbort);\n if (!abortController.signal.aborted) {\n onDisconnect?.();\n retryCount++;\n const elapsed = Date.now() - lastAttemptTime;\n const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);\n await sleep(Math.max(backoff(retryCount), minGap));\n continue;\n }\n } catch (error) {\n clearTimeout(pingTimeoutId);\n abortController.signal.removeEventListener('abort', onMainAbort);\n if (abortController.signal.aborted) {\n break;\n }\n if (error instanceof TokenResolutionError && !initialDataReceived) {\n rejectInit!(error.cause);\n abortController.abort();\n break;\n }\n // Ping timeout aborts only the per-connection controller; this is\n // an expected reconnect, not a real error. Stay silent on retryable\n // failures too — the error is only logged once retries are exhausted.\n if (!connectionAbort.signal.aborted) {\n lastError = error;\n }\n onDisconnect?.();\n retryCount++;\n const elapsed = Date.now() - lastAttemptTime;\n const minGap = Math.max(0, BASE_RETRY_DELAY_MS - elapsed);\n await sleep(Math.max(backoff(retryCount), minGap));\n }\n }\n\n // Reject the init promise if the loop exited without receiving data\n // (e.g. aborted externally before any data arrived)\n if (!initialDataReceived) {\n rejectInit!(new Error('stream: aborted before receiving data'));\n }\n })();\n\n return initPromise;\n}\n","import type { DatafileInput } from '../types';\nimport type { NormalizedOptions } from './normalized-options';\nimport { connectStream, type PrimedMessage } from './stream-connection';\nimport { TypedEmitter } from './typed-emitter';\n\nexport type StreamSourceEvents = {\n data: (data: DatafileInput) => void;\n primed: (message: PrimedMessage) => void;\n connected: () => void;\n disconnected: () => void;\n};\n\n/**\n * Manages a streaming connection to the flags service.\n * Wraps connectStream() and emits typed events.\n */\nexport class StreamSource extends TypedEmitter<StreamSourceEvents> {\n private options: NormalizedOptions;\n private revision: () => number | undefined;\n private abortController: AbortController | undefined;\n private promise: Promise<void> | undefined;\n\n constructor(options: NormalizedOptions, revision: () => number | undefined) {\n super();\n this.options = options;\n this.revision = revision;\n }\n\n /**\n * Start the stream connection.\n * Returns a promise that resolves when the first datafile or primed message arrives.\n * If already started, returns the existing promise.\n */\n start(): Promise<void> {\n if (this.promise) return this.promise;\n\n const abortController = new AbortController();\n this.abortController = abortController;\n\n // Clear cached state when the stream terminates so that a subsequent\n // start() call creates a fresh connection instead of returning a stale\n // resolved promise.\n abortController.signal.addEventListener(\n 'abort',\n () => {\n if (this.abortController === abortController) {\n this.promise = undefined;\n this.abortController = undefined;\n }\n },\n { once: true },\n );\n\n try {\n const promise = connectStream(\n {\n host: this.options.host,\n resolveToken: () => this.options.auth.resolveToken(),\n abortController,\n fetch: this.options.fetch,\n revision: this.revision,\n },\n {\n onDatafile: (newData) => {\n this.emit('data', newData);\n this.emit('connected');\n },\n onPrimed: (message) => {\n this.emit('primed', message);\n this.emit('connected');\n },\n onDisconnect: () => {\n this.emit('disconnected');\n },\n },\n );\n\n this.promise = promise;\n return promise;\n } catch (error) {\n this.promise = undefined;\n this.abortController = undefined;\n throw error;\n }\n }\n\n /**\n * Stop the stream connection.\n */\n stop(): void {\n this.abortController?.abort();\n this.abortController = undefined;\n this.promise = undefined;\n }\n}\n","import type { DatafileInput, Metrics } from '../types';\n\n/**\n * Internal origin tracking for how data was obtained.\n * This flows with the data from point of origin through to metrics.\n */\nexport type DataOrigin = 'stream' | 'poll' | 'bundled' | 'provided' | 'fetched';\n\n/**\n * DatafileInput with origin metadata attached at the point of arrival.\n * Internal only — stripped before returning to consumers.\n */\nexport type TaggedData = DatafileInput & {\n _origin: DataOrigin;\n};\n\n/**\n * Tags a DatafileInput with its origin.\n */\nexport function tagData(data: DatafileInput, origin: DataOrigin): TaggedData {\n return Object.assign(data, { _origin: origin }) as TaggedData;\n}\n\n/**\n * Maps internal DataOrigin to the public Metrics.source value.\n */\nexport function originToMetricsSource(origin: DataOrigin): Metrics['source'] {\n switch (origin) {\n case 'stream':\n case 'poll':\n case 'provided':\n return 'in-memory';\n case 'fetched':\n return 'remote';\n case 'bundled':\n return 'embedded';\n }\n}\n","import type {\n BundledDefinitions,\n ControllerInterface,\n Datafile,\n DatafileInput,\n Metrics,\n} from '../types';\nimport { readBundledDefinitions } from '../utils/read-bundled-definitions';\nimport type { TrackReadOptions } from '../utils/usage/flags-config-read';\nimport type { TrackEvaluationOptions } from '../utils/usage/flags-evaluation';\nimport { UsageTracker } from '../utils/usage-tracker';\nimport { BundledSource } from './bundled-source';\nimport { fetchDatafile } from './fetch-datafile';\nimport {\n type ControllerOptions,\n type NormalizedOptions,\n normalizeOptions,\n} from './normalized-options';\nimport { PollingSource } from './polling-source';\nimport { UnauthorizedError } from './stream-connection';\nimport { StreamSource } from './stream-source';\nimport { originToMetricsSource, type TaggedData, tagData } from './tagged-data';\n\nexport { BundledSource } from './bundled-source';\nexport type { ControllerOptions } from './normalized-options';\nexport { PollingSource } from './polling-source';\nexport { StreamSource } from './stream-source';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Parses a configUpdatedAt value (number or string) into a numeric timestamp.\n * Returns undefined if the value is missing or cannot be parsed.\n */\nfunction parseConfigUpdatedAt(value: unknown): number | undefined {\n if (typeof value === 'number') return value;\n if (typeof value === 'string') {\n const parsed = Number(value);\n return Number.isNaN(parsed) ? undefined : parsed;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\n/**\n * Explicit states for the controller state machine.\n */\ntype State =\n | 'idle'\n | 'initializing:stream'\n | 'initializing:polling'\n | 'initializing:fallback'\n | 'streaming'\n | 'polling'\n | 'degraded'\n | 'build:loading'\n | 'build:ready'\n | 'shutdown';\n\n// ---------------------------------------------------------------------------\n// Controller\n// ---------------------------------------------------------------------------\n\n/**\n * Connects to flags.vercel.com and manages flag definitions.\n *\n * Implemented as a state machine controller that delegates all I/O to\n * source modules (StreamSource, PollingSource, BundledSource).\n *\n * **Build step** (CI=1 or Next.js build, or buildStep: true):\n * - Uses datafile (if provided), bundled definitions, or one-time fetch as fallback\n * - No streaming or polling\n *\n * **Runtime — streaming mode** (stream enabled):\n * - Uses streaming exclusively; polling is never started, even if configured\n * - Init fallback (no data yet): constructor datafile → bundled → throw\n * - Read fallback (post-init): in-memory value → constructor datafile → bundled → throw\n *\n * **Runtime — polling mode** (polling enabled, stream disabled):\n * - Uses polling exclusively\n * - Same fallback chains as streaming mode\n *\n * **Runtime — offline mode** (neither stream nor polling):\n * - Init fallback: constructor datafile → bundled → one-time fetch → throw\n * - Read fallback: in-memory value → constructor datafile → bundled → one-time fetch → throw\n */\nexport class Controller implements ControllerInterface {\n private options: NormalizedOptions;\n\n // State machine\n private state: State = 'idle';\n\n // Data state — tagged with origin\n private data: TaggedData | undefined;\n\n // Memoized data spread for read() / getDatafile().\n // Rebuilt only when `this.data` reference changes (e.g. on stream/poll update).\n // Holds the result of stripping `_origin`; metrics are appended per-call.\n private dataViewSource: TaggedData | undefined = undefined;\n private dataViewBase: DatafileInput | undefined = undefined;\n\n // Sources (I/O delegates)\n private streamSource: StreamSource;\n private pollingSource: PollingSource;\n private bundledSource: BundledSource;\n\n // Usage tracking\n private usageTracker: UsageTracker;\n private isFirstGetData: boolean = true;\n\n // Build-step deduplication\n private buildDataPromise: Promise<TaggedData> | null = null;\n private buildReadTracked = false;\n\n // Suppresses usage tracking when the SDK key is unauthorized\n private unauthorized = false;\n\n constructor(options: ControllerOptions) {\n this.options = normalizeOptions(options);\n\n // Create source modules\n this.streamSource = new StreamSource(\n this.options,\n () => this.data?.revision,\n );\n\n this.pollingSource = new PollingSource(this.options);\n\n this.bundledSource = new BundledSource({\n auth: this.options.auth,\n readBundledDefinitions,\n });\n\n // Wire source events to state machine\n this.wireSourceEvents();\n\n // If datafile provided, use it immediately\n if (this.options.datafile) {\n this.data = tagData(this.options.datafile, 'provided');\n }\n\n this.usageTracker = new UsageTracker(this.options);\n }\n\n // Source event handlers (stored for cleanup)\n private onStreamData = (data: DatafileInput) => {\n if (this.isNewerData(data)) {\n this.data = tagData(data, 'stream');\n }\n };\n private onStreamPrimed = () => {\n // The server confirmed our revision is current — no new data needed.\n // Transition to streaming like a normal connected event.\n if (this.state === 'degraded' || this.state === 'initializing:stream') {\n this.transition('streaming');\n }\n };\n private onStreamConnected = () => {\n if (this.state === 'degraded' || this.state === 'initializing:stream') {\n this.transition('streaming');\n }\n };\n private onStreamDisconnected = () => {\n if (this.state === 'streaming') {\n this.transition('degraded');\n }\n };\n private onPollData = (data: DatafileInput) => {\n if (this.isNewerData(data)) {\n this.data = tagData(data, 'poll');\n }\n };\n private onPollError = (error: Error) => {\n console.error('@vercel/flags-core: Poll failed:', error);\n };\n\n // ---------------------------------------------------------------------------\n // Source event wiring\n // ---------------------------------------------------------------------------\n\n private wireSourceEvents(): void {\n this.streamSource.on('data', this.onStreamData);\n this.streamSource.on('primed', this.onStreamPrimed);\n this.streamSource.on('connected', this.onStreamConnected);\n this.streamSource.on('disconnected', this.onStreamDisconnected);\n this.pollingSource.on('data', this.onPollData);\n this.pollingSource.on('error', this.onPollError);\n }\n\n private unwireSourceEvents(): void {\n this.streamSource.off('data', this.onStreamData);\n this.streamSource.off('primed', this.onStreamPrimed);\n this.streamSource.off('connected', this.onStreamConnected);\n this.streamSource.off('disconnected', this.onStreamDisconnected);\n this.pollingSource.off('data', this.onPollData);\n this.pollingSource.off('error', this.onPollError);\n }\n\n // ---------------------------------------------------------------------------\n // State machine\n // ---------------------------------------------------------------------------\n\n private transition(to: State): void {\n this.state = to;\n }\n\n private get isConnected(): boolean {\n return this.state === 'streaming';\n }\n\n private get mode(): Metrics['mode'] {\n if (this.options.buildStep) return 'build';\n switch (this.state) {\n case 'streaming':\n return 'streaming';\n case 'polling':\n return 'polling';\n default:\n return 'offline';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API (DataSource interface)\n // ---------------------------------------------------------------------------\n\n /**\n * Initializes the data source.\n *\n * Build step: datafile → bundled → one-time fetch\n * Streaming mode: stream → datafile → bundled\n * Polling mode (no stream): poll → datafile → bundled\n * Offline mode (neither): datafile → bundled → one-time fetch\n */\n async initialize(): Promise<void> {\n if (this.options.buildStep) {\n this.transition('build:loading');\n await this.initializeForBuildStep();\n this.transition('build:ready');\n return;\n }\n\n // Hydrate from provided datafile if not already set (e.g., after shutdown)\n if (!this.data && this.options.datafile) {\n this.data = tagData(this.options.datafile, 'provided');\n }\n\n // If no data yet, try loading bundled definitions eagerly so we can\n // send the revision to the stream and potentially get a lightweight\n // \"primed\" response instead of a full datafile.\n if (!this.data) {\n try {\n const bundled = await this.bundledSource.tryLoad();\n if (bundled) {\n this.data = tagData(bundled, 'bundled');\n }\n } catch {\n // Bundled definitions not available — proceed without revision\n }\n }\n\n // If we already have data (from provided datafile or bundled definitions),\n // start updates. Both streaming and polling wait for initial data before\n // being considered initialized, so we know we have fresh data.\n // For no-updates (offline), return immediately since we already have usable data.\n if (this.data) {\n if (this.options.stream.enabled) {\n this.transition('initializing:stream');\n await this.tryInitializeStream();\n } else if (this.options.polling.enabled) {\n this.transition('initializing:polling');\n await this.tryInitializePolling();\n } else {\n this.transition('degraded');\n }\n return;\n }\n\n // Try the configured primary source (stream or poll, never both)\n if (this.options.stream.enabled) {\n this.transition('initializing:stream');\n const streamSuccess = await this.tryInitializeStream();\n if (streamSuccess) {\n this.transition('streaming');\n return;\n }\n } else if (this.options.polling.enabled) {\n this.transition('initializing:polling');\n const pollingSuccess = await this.tryInitializePolling();\n if (pollingSuccess) {\n this.transition('polling');\n return;\n }\n }\n\n // Fallback chain: datafile → bundled → one-time fetch (offline only)\n await this.initializeFromFallbacks();\n }\n\n /**\n * Reads the current datafile with metrics.\n */\n async read(): Promise<Datafile> {\n const startTime = Date.now();\n const cacheHadDefinitions = this.data !== undefined;\n const isFirstRead = this.isFirstGetData;\n this.isFirstGetData = false;\n\n const [result, cacheStatus] = await this.resolveData();\n\n const readMs = Date.now() - startTime;\n const source = originToMetricsSource(result._origin);\n this.trackRead(startTime, cacheHadDefinitions, isFirstRead, source);\n\n if (this.dataViewSource !== result) {\n const { _origin, ...rest } = result;\n this.dataViewBase = rest;\n this.dataViewSource = result;\n }\n\n return {\n ...(this.dataViewBase as DatafileInput),\n metrics: {\n readMs,\n source,\n cacheStatus,\n connectionState: this.isConnected\n ? ('connected' as const)\n : ('disconnected' as const),\n mode: this.mode,\n },\n } satisfies Datafile;\n }\n\n /**\n * Shuts down the data source and releases resources.\n */\n async shutdown(): Promise<void> {\n this.unwireSourceEvents();\n this.streamSource.stop();\n this.pollingSource.stop();\n this.data = this.options.datafile\n ? tagData(this.options.datafile, 'provided')\n : undefined;\n this.transition('shutdown');\n await this.usageTracker.shutdown();\n }\n\n /**\n * Returns the datafile with metrics.\n * Uses in-memory data if available, otherwise falls back to bundled,\n * then to a one-time fetch if called without prior initialization.\n */\n async getDatafile(): Promise<Datafile> {\n const startTime = Date.now();\n this.isFirstGetData = false;\n\n let result: TaggedData;\n let cacheStatus: Metrics['cacheStatus'];\n\n if (this.options.buildStep) {\n [result, cacheStatus] = await this.resolveDataForBuildStep();\n } else if (this.data) {\n cacheStatus = this.isConnected ? 'HIT' : 'STALE';\n result = this.data;\n } else {\n // No in-memory data — try bundled, then one-time fetch\n const bundled = await this.bundledSource.tryLoad();\n if (bundled) {\n this.data = tagData(bundled, 'bundled');\n result = this.data;\n cacheStatus = 'MISS';\n } else {\n // One-time fetch as last resort\n try {\n const fetched = await fetchDatafile({\n host: this.options.host,\n auth: this.options.auth,\n fetch: this.options.fetch,\n });\n this.data = tagData(fetched, 'fetched');\n result = this.data;\n cacheStatus = 'MISS';\n } catch {\n throw new Error(\n '@vercel/flags-core: No flag definitions available. ' +\n 'Initialize the client or provide a datafile.',\n );\n }\n }\n }\n\n const source = originToMetricsSource(result._origin);\n\n if (this.dataViewSource !== result) {\n const { _origin, ...rest } = result;\n this.dataViewBase = rest;\n this.dataViewSource = result;\n }\n\n return {\n ...(this.dataViewBase as DatafileInput),\n metrics: {\n readMs: Date.now() - startTime,\n source,\n cacheStatus,\n connectionState: this.isConnected\n ? ('connected' as const)\n : ('disconnected' as const),\n mode: this.mode,\n },\n } satisfies Datafile;\n }\n\n /**\n * Returns the bundled fallback datafile.\n */\n async getFallbackDatafile(): Promise<BundledDefinitions> {\n return this.bundledSource.getRaw();\n }\n\n // ---------------------------------------------------------------------------\n // Data resolution (shared by read() and getDatafile())\n // ---------------------------------------------------------------------------\n\n /**\n * Resolves the current data, using the appropriate strategy for the\n * current mode. Returns tagged data and cache status.\n *\n * Build step: cached → bundled → one-time fetch\n * Runtime with cache: return cached data\n * Runtime without cache: stream/poll → datafile → bundled → fetch → throw\n */\n private async resolveData(): Promise<[TaggedData, Metrics['cacheStatus']]> {\n if (this.options.buildStep) {\n return this.resolveDataForBuildStep();\n }\n\n if (this.data) {\n const cacheStatus = this.isConnected ? 'HIT' : 'STALE';\n return [this.data, cacheStatus];\n }\n\n return this.resolveDataWithFallbacks();\n }\n\n // ---------------------------------------------------------------------------\n // Stream initialization\n // ---------------------------------------------------------------------------\n\n /**\n * Attempts to initialize via stream with timeout.\n * Returns true if stream connected successfully within timeout.\n */\n private async tryInitializeStream(): Promise<boolean> {\n if (this.options.stream.initTimeoutMs <= 0) {\n try {\n await this.streamSource.start();\n return true;\n } catch (error) {\n if (error instanceof UnauthorizedError) {\n this.unauthorized = true;\n }\n return false;\n }\n }\n\n // Race against timeout\n let timeoutId: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<'timeout'>((resolve) => {\n timeoutId = setTimeout(\n () => resolve('timeout'),\n this.options.stream.initTimeoutMs,\n );\n });\n\n try {\n const result = await Promise.race([\n this.streamSource.start(),\n timeoutPromise,\n ]);\n clearTimeout(timeoutId!);\n\n if (result === 'timeout') {\n console.warn(\n '@vercel/flags-core: Stream initialization timeout, falling back while continuing to connect in the background',\n );\n // Don't stop stream - let it continue trying in background.\n // Swallow the rejection from the background stream promise to\n // avoid unhandled promise rejections when it is eventually aborted.\n void this.streamSource.start().catch(() => {});\n return false;\n }\n\n return true;\n } catch (error) {\n clearTimeout(timeoutId!);\n if (error instanceof Error && error.message.includes('401')) {\n this.unauthorized = true;\n }\n return false;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Polling initialization\n // ---------------------------------------------------------------------------\n\n /**\n * Attempts to initialize via polling with timeout.\n * Returns true if first poll succeeded within timeout.\n *\n * Only used when streaming is disabled and polling is the primary source.\n */\n private async tryInitializePolling(): Promise<boolean> {\n const pollPromise = this.pollingSource.poll();\n\n if (this.options.polling.initTimeoutMs <= 0) {\n try {\n await pollPromise;\n if (this.data) {\n this.pollingSource.startInterval();\n return true;\n }\n return false;\n } catch {\n return false;\n }\n }\n\n // Race against timeout\n let timeoutId: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<'timeout'>((resolve) => {\n timeoutId = setTimeout(\n () => resolve('timeout'),\n this.options.polling.initTimeoutMs,\n );\n });\n\n try {\n const result = await Promise.race([pollPromise, timeoutPromise]);\n clearTimeout(timeoutId!);\n\n if (result === 'timeout') {\n console.warn(\n '@vercel/flags-core: Polling initialization timeout, falling back while continuing to poll in the background',\n );\n return false;\n }\n\n if (this.data) {\n this.pollingSource.startInterval();\n return true;\n }\n return false;\n } catch {\n clearTimeout(timeoutId!);\n return false;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Build step helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Initializes data for build step environments.\n */\n private async initializeForBuildStep(): Promise<void> {\n if (this.data) return;\n\n if (!this.buildDataPromise) {\n this.buildDataPromise = this.loadBuildData();\n }\n this.data = await this.buildDataPromise;\n }\n\n /**\n * Retrieves data during build steps.\n * Concurrent callers share a single load promise. The first caller to\n * populate `this.data` gets cacheStatus MISS; subsequent callers get HIT.\n */\n private async resolveDataForBuildStep(): Promise<\n [TaggedData, Metrics['cacheStatus']]\n > {\n if (this.data) {\n return [this.data, 'HIT'];\n }\n\n if (!this.buildDataPromise) {\n this.buildDataPromise = this.loadBuildData();\n }\n\n const data = await this.buildDataPromise;\n\n if (!this.data) {\n this.data = data;\n return [data, 'MISS'];\n }\n return [this.data, 'HIT'];\n }\n\n /**\n * Loads data for a build step: bundled → one-time fetch.\n */\n private async loadBuildData(): Promise<TaggedData> {\n const bundled = await this.bundledSource.tryLoad();\n if (bundled) return tagData(bundled, 'bundled');\n\n // Fallback: one-time fetch\n try {\n const fetched = await fetchDatafile({\n host: this.options.host,\n auth: this.options.auth,\n fetch: this.options.fetch,\n });\n return tagData(fetched, 'fetched');\n } catch {\n // fetch failed — fall through to throw\n }\n\n throw new Error(\n '@vercel/flags-core: No flag definitions available during build. ' +\n 'Provide a datafile or bundled definitions.',\n );\n }\n\n // ---------------------------------------------------------------------------\n // Fallback helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Shared fallback chain used by both initialize() and resolveData().\n */\n private async initializeFromFallbacks(): Promise<void> {\n this.transition('initializing:fallback');\n\n if (this.data) {\n this.transition('degraded');\n return;\n }\n\n const bundled = await this.bundledSource.tryLoad();\n if (bundled) {\n this.data = tagData(bundled, 'bundled');\n this.transition('degraded');\n return;\n }\n\n // Last resort: one-time fetch (only when no stream/poll configured)\n if (!this.options.stream.enabled && !this.options.polling.enabled) {\n try {\n const fetched = await fetchDatafile({\n host: this.options.host,\n auth: this.options.auth,\n fetch: this.options.fetch,\n });\n this.data = tagData(fetched, 'fetched');\n this.transition('degraded');\n return;\n } catch {\n // fetch failed — fall through to throw\n }\n }\n\n throw new Error(\n '@vercel/flags-core: No flag definitions available. ' +\n 'Bundled definitions not found.',\n );\n }\n\n /**\n * Retrieves data using the fallback chain (called when no cached data exists).\n * Streaming mode: stream → datafile → bundled.\n * Polling mode: poll → datafile → bundled.\n * Offline mode: datafile → bundled → one-time fetch.\n */\n private async resolveDataWithFallbacks(): Promise<\n [TaggedData, Metrics['cacheStatus']]\n > {\n // Try the configured primary source\n if (this.options.stream.enabled) {\n this.transition('initializing:stream');\n const streamSuccess = await this.tryInitializeStream();\n if (streamSuccess && this.data) {\n this.transition('streaming');\n return [this.data, 'MISS'];\n }\n } else if (this.options.polling.enabled) {\n this.transition('initializing:polling');\n const pollingSuccess = await this.tryInitializePolling();\n if (pollingSuccess && this.data) {\n this.transition('polling');\n return [this.data, 'MISS'];\n }\n }\n\n // Fallback chain: datafile → bundled → one-time fetch\n this.transition('initializing:fallback');\n\n if (this.options.datafile) {\n this.data = tagData(this.options.datafile, 'provided');\n this.transition('degraded');\n return [this.data, 'STALE'];\n }\n\n const bundled = await this.bundledSource.tryLoad();\n if (bundled) {\n console.warn('@vercel/flags-core: Using bundled definitions as fallback');\n this.data = tagData(bundled, 'bundled');\n this.transition('degraded');\n return [this.data, 'STALE'];\n }\n\n // Last resort: one-time fetch (only when no stream/poll configured)\n if (!this.options.stream.enabled && !this.options.polling.enabled) {\n try {\n const fetched = await fetchDatafile({\n host: this.options.host,\n auth: this.options.auth,\n fetch: this.options.fetch,\n });\n this.data = tagData(fetched, 'fetched');\n this.transition('degraded');\n return [this.data, 'MISS'];\n } catch {\n // fetch failed — fall through to throw\n }\n }\n\n throw new Error(\n '@vercel/flags-core: No flag definitions available. ' +\n 'Provide a datafile or bundled definitions.',\n );\n }\n\n // ---------------------------------------------------------------------------\n // Data comparison\n // ---------------------------------------------------------------------------\n\n /**\n * Checks if the incoming data is newer than the current in-memory data.\n * Returns true if the update should proceed, false if it should be skipped.\n *\n * Always accepts the update if:\n * - There is no current data\n * - The current data has no configUpdatedAt\n * - The incoming data has no configUpdatedAt\n *\n * Skips the update only when both have configUpdatedAt and incoming is not newer.\n */\n private isNewerData(incoming: DatafileInput): boolean {\n if (!this.data) return true;\n\n const currentTs = parseConfigUpdatedAt(this.data.configUpdatedAt);\n const incomingTs = parseConfigUpdatedAt(incoming.configUpdatedAt);\n\n if (currentTs === undefined || incomingTs === undefined) {\n return true;\n }\n\n return incomingTs > currentTs;\n }\n\n // ---------------------------------------------------------------------------\n // Usage tracking\n // ---------------------------------------------------------------------------\n\n /**\n * Tracks a read operation for usage analytics.\n * During build steps, only the first read is tracked.\n */\n private trackRead(\n startTime: number,\n cacheHadDefinitions: boolean,\n isFirstRead: boolean,\n source: Metrics['source'],\n ): void {\n if (this.unauthorized) return;\n if (this.options.buildStep && this.buildReadTracked) return;\n if (this.options.buildStep) this.buildReadTracked = true;\n\n const configOrigin: 'in-memory' | 'embedded' =\n source === 'embedded' ? 'embedded' : 'in-memory';\n const cacheAction: 'FOLLOWING' | 'REFRESHING' | 'NONE' =\n this.state === 'streaming'\n ? 'FOLLOWING'\n : this.state === 'polling'\n ? 'REFRESHING'\n : 'NONE';\n const mode = this.mode;\n const trackOptions: TrackReadOptions = {\n configOrigin,\n cacheStatus: cacheHadDefinitions ? 'HIT' : 'MISS',\n cacheAction,\n cacheIsBlocking: !cacheHadDefinitions,\n duration: Date.now() - startTime,\n mode:\n mode === 'streaming' ? 'stream' : mode === 'polling' ? 'poll' : mode,\n };\n const configUpdatedAt = this.data?.configUpdatedAt;\n if (typeof configUpdatedAt === 'number') {\n trackOptions.configUpdatedAt = configUpdatedAt;\n }\n const revision = this.data?.revision;\n if (typeof revision === 'number') {\n trackOptions.revision = revision;\n }\n if (isFirstRead) {\n trackOptions.cacheIsFirstRead = true;\n }\n this.usageTracker.trackRead(trackOptions);\n }\n\n /**\n * Tracks a flag evaluation for usage analytics.\n */\n trackEvaluation(options: TrackEvaluationOptions): void {\n if (this.unauthorized || this.options.disableMetrics) return;\n\n this.usageTracker.trackEvaluation({\n ...options,\n clientName: options.clientName ?? this.options.clientName,\n });\n }\n}\n","import { getVercelOidcToken } from '@vercel/oidc';\nimport { parseSdkKeyFromFlagsConnectionString } from '../utils/sdk-keys';\n\nexport type BundledDefinitionsLookup =\n | { type: 'sdk-key'; sdkKey: string }\n | { type: 'project-id'; projectId: string };\n\nexport interface Auth {\n sdkKey?: string;\n resolveToken(): Promise<string>;\n resolveBundledDefinitionsLookup(): Promise<BundledDefinitionsLookup>;\n}\n\nasync function getOidcToken(): Promise<string> {\n try {\n return await getVercelOidcToken();\n } catch {\n throw new Error(\n [\n '@vercel/flags-core: Failed to get OIDC token.',\n 'Are you running in a Vercel Environment where OIDC tokens are available?',\n 'Did you mean to use an SDK Key instead? Use the environment variable FLAGS or pass it directly to the client.',\n ].join(' '),\n );\n }\n}\n\nfunction getProjectIdFromOidcToken(oidcToken: string): string {\n const tokenParts = oidcToken.split('.');\n if (tokenParts.length !== 3 || !tokenParts[1]) {\n throw new Error('@vercel/flags-core: Invalid OIDC token');\n }\n\n const payload = JSON.parse(\n Buffer.from(tokenParts[1], 'base64url').toString('utf8'),\n ) as { project_id?: unknown };\n\n if (typeof payload.project_id !== 'string' || !payload.project_id) {\n throw new Error(\n '@vercel/flags-core: Missing project_id claim in OIDC token',\n );\n }\n\n return payload.project_id;\n}\n\nexport class Authentication implements Auth {\n public readonly sdkKey?: string;\n\n constructor(sdkKeyOrConnectionString: string | undefined) {\n // validate sdk key format\n if (sdkKeyOrConnectionString !== undefined) {\n if (typeof sdkKeyOrConnectionString !== 'string') {\n throw new Error(\n `@vercel/flags-core: Invalid sdkKey. Expected string, got ${typeof sdkKeyOrConnectionString}`,\n );\n }\n\n // Parse connection string if needed (e.g., \"flags:edgeConfigId=...&sdkKey=vf_xxx\")\n const parsed = parseSdkKeyFromFlagsConnectionString(\n sdkKeyOrConnectionString,\n );\n if (!parsed) {\n throw new Error('@vercel/flags-core: Missing sdkKey');\n }\n\n this.sdkKey = parsed;\n }\n }\n\n public async resolveToken() {\n if (this.sdkKey) {\n return this.sdkKey;\n }\n\n return await getOidcToken();\n }\n\n public async resolveBundledDefinitionsLookup(): Promise<BundledDefinitionsLookup> {\n if (this.sdkKey) {\n return { type: 'sdk-key', sdkKey: this.sdkKey };\n }\n\n const oidcToken = await this.resolveToken();\n return {\n type: 'project-id',\n projectId: getProjectIdFromOidcToken(oidcToken),\n };\n }\n}\n","/**\n * Regex to match valid Vercel Flags SDK keys.\n * SDK keys must follow the format: vf_server_* or vf_client_*\n * This avoids false positives with third-party identifiers that happen\n * to start with 'vf_' (e.g., Stripe identity flow IDs like 'vf_1PyH...').\n */\nconst SDK_KEY_REGEX = /^vf_(?:server|client)_/;\n\n/**\n * Checks if a string is a valid Vercel Flags SDK key.\n */\nexport function isValidSdkKey(value: string): boolean {\n return SDK_KEY_REGEX.test(value);\n}\n\n/**\n * Parses sdk keys from connection strings with the following format:\n * `flags:edgeConfigId=ecfg_abcd&edgeConfigToken=xxx&sdkKey=xxx`\n */\nexport function parseSdkKeyFromFlagsConnectionString(\n text: string,\n): string | null {\n if (SDK_KEY_REGEX.test(text)) return text;\n\n try {\n if (!text.startsWith('flags:')) return null;\n const params = new URLSearchParams(text.slice(6));\n const sdkKey = params.get('sdkKey');\n if (sdkKey && SDK_KEY_REGEX.test(sdkKey)) return sdkKey;\n } catch {\n // no-op\n }\n\n return null;\n}\n","/**\n * Factory functions for exports of index.default.ts and index.next-js.ts\n */\n\nimport { Controller, type ControllerOptions } from './controller';\nimport { Authentication } from './controller/auth';\nimport type { createCreateRawClient } from './create-raw-client';\nimport type { FlagsClient } from './types';\n\n/**\n * Options for createClient\n */\nexport type CreateClientOptions = Omit<ControllerOptions, 'auth'>;\n\ntype CreateClient = {\n <Entities = Record<string, unknown>>(\n options: CreateClientOptions,\n ): FlagsClient<Entities>;\n <Entities = Record<string, unknown>>(\n sdkKeyOrConnectionString?: string,\n options?: CreateClientOptions,\n ): FlagsClient<Entities>;\n};\n\nexport function make(\n createRawClient: ReturnType<typeof createCreateRawClient>,\n): {\n flagsClient: FlagsClient;\n resetDefaultFlagsClient: () => void;\n createClient: CreateClient;\n} {\n let _defaultFlagsClient: FlagsClient | null = null;\n\n // Insights\n // - data source must specify the environment & projectId as sdkKey has that info\n // - \"reuse\" functionality relies on the data source having the data for all envs\n function createClient<Entities = Record<string, unknown>>(\n options: CreateClientOptions,\n ): FlagsClient<Entities>;\n function createClient<Entities = Record<string, unknown>>(\n sdkKeyOrConnectionString?: string,\n options?: CreateClientOptions,\n ): FlagsClient<Entities>;\n function createClient<Entities = Record<string, unknown>>(\n sdkKeyOrConnectionStringOrOptions?: string | CreateClientOptions,\n options?: CreateClientOptions,\n ): FlagsClient<Entities> {\n const optionsOnly =\n typeof sdkKeyOrConnectionStringOrOptions === 'object' &&\n sdkKeyOrConnectionStringOrOptions !== null;\n const sdkKeyOrConnectionString = optionsOnly\n ? undefined\n : sdkKeyOrConnectionStringOrOptions;\n const createClientOptions = optionsOnly\n ? sdkKeyOrConnectionStringOrOptions\n : options;\n\n const auth = new Authentication(sdkKeyOrConnectionString);\n\n // sdk key contains the environment\n const controller = new Controller({ auth, ...createClientOptions });\n return createRawClient<Entities>({\n controller,\n origin: { provider: 'vercel', sdkKey: auth.sdkKey },\n });\n }\n\n function resetDefaultFlagsClient() {\n _defaultFlagsClient = null;\n }\n\n const flagsClient: FlagsClient = new Proxy({} as FlagsClient, {\n get(_, prop) {\n if (!_defaultFlagsClient) {\n _defaultFlagsClient = createClient(process.env.FLAGS);\n }\n return _defaultFlagsClient[prop as keyof FlagsClient];\n },\n });\n\n return {\n flagsClient,\n resetDefaultFlagsClient,\n createClient,\n };\n}\n"],"mappings":"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","names":["ResolutionReason","Original","AccessorType","Packed","evaluate","result","bulkEvaluate","results","entry","getVercelOidcToken","getVercelOidcToken","createClient","resetDefaultFlagsClient","flagsClient","evaluate","bulkEvaluate"]}
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkZ7PTTGMKcjs = require('./chunk-Z7PTTGMK.cjs');
10
+ var _chunkC3FUDFOPcjs = require('./chunk-C3FUDFOP.cjs');
11
11
 
12
12
 
13
13
 
@@ -18,5 +18,5 @@ var _chunkZ7PTTGMKcjs = require('./chunk-Z7PTTGMK.cjs');
18
18
 
19
19
 
20
20
 
21
- exports.Controller = _chunkZ7PTTGMKcjs.Controller; exports.FallbackEntryNotFoundError = _chunkZ7PTTGMKcjs.FallbackEntryNotFoundError; exports.FallbackNotFoundError = _chunkZ7PTTGMKcjs.FallbackNotFoundError; exports.FlagNetworkDataSource = _chunkZ7PTTGMKcjs.Controller; exports.Reason = _chunkZ7PTTGMKcjs.ResolutionReason; exports.createClient = _chunkZ7PTTGMKcjs.createClient; exports.evaluate = _chunkZ7PTTGMKcjs.evaluate; exports.flagsClient = _chunkZ7PTTGMKcjs.flagsClient; exports.resetDefaultFlagsClient = _chunkZ7PTTGMKcjs.resetDefaultFlagsClient;
21
+ exports.Controller = _chunkC3FUDFOPcjs.Controller; exports.FallbackEntryNotFoundError = _chunkC3FUDFOPcjs.FallbackEntryNotFoundError; exports.FallbackNotFoundError = _chunkC3FUDFOPcjs.FallbackNotFoundError; exports.FlagNetworkDataSource = _chunkC3FUDFOPcjs.Controller; exports.Reason = _chunkC3FUDFOPcjs.ResolutionReason; exports.createClient = _chunkC3FUDFOPcjs.createClient; exports.evaluate = _chunkC3FUDFOPcjs.evaluate; exports.flagsClient = _chunkC3FUDFOPcjs.flagsClient; exports.resetDefaultFlagsClient = _chunkC3FUDFOPcjs.resetDefaultFlagsClient;
22
22
  //# sourceMappingURL=index.default.cjs.map
@@ -1,5 +1,5 @@
1
- import { V as VariantId, R as ResolutionReason, D as DatafileInput, S as StreamOptions, P as PollingOptions, C as ControllerInterface, a as Datafile, B as BundledDefinitions, E as EvaluationParams, b as EvaluationResult, F as FlagsClient } from './types-DxdTzPS2.cjs';
2
- export { c as Packed, d as Value } from './types-DxdTzPS2.cjs';
1
+ import { V as VariantId, R as ResolutionReason, D as DatafileInput, S as StreamOptions, P as PollingOptions, M as MetricEnvironment, C as ControllerInterface, a as Datafile, B as BundledDefinitions, E as EvaluationParams, b as EvaluationResult, F as FlagsClient } from './types-C2-sIv2D.cjs';
2
+ export { c as Packed, d as Value } from './types-C2-sIv2D.cjs';
3
3
 
4
4
  interface TrackEvaluationOptions {
5
5
  flagKey: string;
@@ -62,6 +62,12 @@ type ControllerOptions = {
62
62
  * @default globalThis.fetch
63
63
  */
64
64
  fetch?: typeof globalThis.fetch;
65
+ /**
66
+ * Environment included with evaluation metrics sent to the ingest endpoint.
67
+ * Falls back to the `VERCEL_ENV` environment variable when not set.
68
+ * This does not select the environment used for flag evaluation.
69
+ */
70
+ metricEnvironment?: MetricEnvironment;
65
71
  /**
66
72
  * Custom client name included in evaluation telemetry.
67
73
  */
@@ -264,7 +270,7 @@ declare const
264
270
  * A lazily-initialized default flags client.
265
271
  *
266
272
  * - relies on process.env.FLAGS
267
- * - does not use process.env.EDGE_CONFIG
273
+ * - does not use process.env.GLOBAL_CONFIG
268
274
  */
269
275
  flagsClient: FlagsClient;
270
276
  declare const /**
@@ -1,5 +1,5 @@
1
- import { V as VariantId, R as ResolutionReason, D as DatafileInput, S as StreamOptions, P as PollingOptions, C as ControllerInterface, a as Datafile, B as BundledDefinitions, E as EvaluationParams, b as EvaluationResult, F as FlagsClient } from './types-DxdTzPS2.js';
2
- export { c as Packed, d as Value } from './types-DxdTzPS2.js';
1
+ import { V as VariantId, R as ResolutionReason, D as DatafileInput, S as StreamOptions, P as PollingOptions, M as MetricEnvironment, C as ControllerInterface, a as Datafile, B as BundledDefinitions, E as EvaluationParams, b as EvaluationResult, F as FlagsClient } from './types-C2-sIv2D.js';
2
+ export { c as Packed, d as Value } from './types-C2-sIv2D.js';
3
3
 
4
4
  interface TrackEvaluationOptions {
5
5
  flagKey: string;
@@ -62,6 +62,12 @@ type ControllerOptions = {
62
62
  * @default globalThis.fetch
63
63
  */
64
64
  fetch?: typeof globalThis.fetch;
65
+ /**
66
+ * Environment included with evaluation metrics sent to the ingest endpoint.
67
+ * Falls back to the `VERCEL_ENV` environment variable when not set.
68
+ * This does not select the environment used for flag evaluation.
69
+ */
70
+ metricEnvironment?: MetricEnvironment;
65
71
  /**
66
72
  * Custom client name included in evaluation telemetry.
67
73
  */
@@ -264,7 +270,7 @@ declare const
264
270
  * A lazily-initialized default flags client.
265
271
  *
266
272
  * - relies on process.env.FLAGS
267
- * - does not use process.env.EDGE_CONFIG
273
+ * - does not use process.env.GLOBAL_CONFIG
268
274
  */
269
275
  flagsClient: FlagsClient;
270
276
  declare const /**
@@ -7,7 +7,7 @@ import {
7
7
  evaluate,
8
8
  flagsClient,
9
9
  resetDefaultFlagsClient
10
- } from "./chunk-PLRBLION.js";
10
+ } from "./chunk-ZROGU3V7.js";
11
11
  export {
12
12
  Controller,
13
13
  FallbackEntryNotFoundError,
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkY7HU5ZNTcjs = require('./chunk-Y7HU5ZNT.cjs');
10
+ var _chunkID4ZKPA3cjs = require('./chunk-ID4ZKPA3.cjs');
11
11
 
12
12
 
13
13
 
@@ -18,5 +18,5 @@ var _chunkY7HU5ZNTcjs = require('./chunk-Y7HU5ZNT.cjs');
18
18
 
19
19
 
20
20
 
21
- exports.Controller = _chunkY7HU5ZNTcjs.Controller; exports.FallbackEntryNotFoundError = _chunkY7HU5ZNTcjs.FallbackEntryNotFoundError; exports.FallbackNotFoundError = _chunkY7HU5ZNTcjs.FallbackNotFoundError; exports.FlagNetworkDataSource = _chunkY7HU5ZNTcjs.Controller; exports.Reason = _chunkY7HU5ZNTcjs.ResolutionReason; exports.createClient = _chunkY7HU5ZNTcjs.createClient; exports.evaluate = _chunkY7HU5ZNTcjs.evaluate; exports.flagsClient = _chunkY7HU5ZNTcjs.flagsClient; exports.resetDefaultFlagsClient = _chunkY7HU5ZNTcjs.resetDefaultFlagsClient;
21
+ exports.Controller = _chunkID4ZKPA3cjs.Controller; exports.FallbackEntryNotFoundError = _chunkID4ZKPA3cjs.FallbackEntryNotFoundError; exports.FallbackNotFoundError = _chunkID4ZKPA3cjs.FallbackNotFoundError; exports.FlagNetworkDataSource = _chunkID4ZKPA3cjs.Controller; exports.Reason = _chunkID4ZKPA3cjs.ResolutionReason; exports.createClient = _chunkID4ZKPA3cjs.createClient; exports.evaluate = _chunkID4ZKPA3cjs.evaluate; exports.flagsClient = _chunkID4ZKPA3cjs.flagsClient; exports.resetDefaultFlagsClient = _chunkID4ZKPA3cjs.resetDefaultFlagsClient;
22
22
  //# sourceMappingURL=index.next-js.cjs.map