@vercel/flags-core 0.1.6 → 0.1.8
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.
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-NSFJTIVL.js → chunk-4IFGPGNY.js} +2 -2
- package/dist/{chunk-NSFJTIVL.js.map → chunk-4IFGPGNY.js.map} +1 -1
- package/dist/{chunk-OWBLBSGO.cjs → chunk-6ZAELH3K.cjs} +2 -2
- package/dist/{chunk-OWBLBSGO.cjs.map → chunk-6ZAELH3K.cjs.map} +1 -1
- package/dist/{client-27m_QPJ8.d.cts → client-BxFTPk0J.d.cts} +0 -2
- package/dist/{client-27m_QPJ8.d.ts → client-BxFTPk0J.d.ts} +0 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/openfeature.cjs +2 -2
- package/dist/openfeature.d.cts +1 -1
- package/dist/openfeature.d.ts +1 -1
- package/dist/openfeature.js +1 -1
- package/package.json +3 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @vercel/flags-core
|
|
2
2
|
|
|
3
|
+
## 0.1.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 620974c: [internal] change label to note
|
|
8
|
+
|
|
9
|
+
## 0.1.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 43293a3: depend directly on @vercel/edge-config (removed as peer dep)
|
|
14
|
+
|
|
3
15
|
## 0.1.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -362,7 +362,7 @@ function findWeightedIndex(weights, value, maxValue) {
|
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
// package.json
|
|
365
|
-
var version = "0.1.
|
|
365
|
+
var version = "0.1.8";
|
|
366
366
|
|
|
367
367
|
// src/lib/report-value.ts
|
|
368
368
|
function internalReportValue(key, value, data) {
|
|
@@ -563,4 +563,4 @@ export {
|
|
|
563
563
|
getDefaultFlagsClient,
|
|
564
564
|
getFlagsEnvironment
|
|
565
565
|
};
|
|
566
|
-
//# sourceMappingURL=chunk-
|
|
566
|
+
//# sourceMappingURL=chunk-4IFGPGNY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/evaluate.ts","../src/types.ts","../src/utils.ts","../package.json","../src/lib/report-value.ts","../src/client.ts","../src/store.ts","../src/data-source/edge-config-data-source.ts","../src/data-source/in-memory-data-source.ts"],"sourcesContent":["import { createClient as createEdgeConfigClient } from '@vercel/edge-config';\nimport { createClient, type FlagsClient } from './client';\nimport { EdgeConfigDataSource } from './data-source/edge-config-data-source';\nimport { InMemoryDataSource } from './data-source/in-memory-data-source';\nimport type { DataSource } from './data-source/interface';\nimport type { ConnectionOptions } from './types';\n\nexport {\n createClient,\n type FlagsClient,\n} from './client';\nexport { EdgeConfigDataSource, InMemoryDataSource };\nexport { store } from './store';\nexport { type Packed, ResolutionReason as Reason } from './types';\nexport type { DataSource };\nexport { evaluate } from './evaluate';\n\nlet defaultFlagsClient: FlagsClient | null = null;\n\n// TODO this should possibly be a generic parser for the URL, which\n// can be used with sources other than Edge Config at some point\nexport function parseFlagsConnectionString(\n connectionString: string,\n): ConnectionOptions {\n const errorMessage = 'flags: Invalid connection string';\n\n try {\n const params = new URLSearchParams(connectionString.slice(6));\n const edgeConfigId = params.get('edgeConfigId');\n const edgeConfigToken = params.get('edgeConfigToken');\n const projectId = params.get('projectId');\n if (!edgeConfigId || !edgeConfigToken || !projectId) {\n throw new Error(errorMessage);\n }\n\n return {\n edgeConfigId,\n edgeConfigToken,\n projectId,\n edgeConfigItemKey: params.get('edgeConfigItemKey'),\n env: params.get('env'),\n };\n } catch {\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Internal function for testing purposes\n */\nexport function resetDefaultFlagsClient() {\n defaultFlagsClient = null;\n}\n\nexport function createClientFromConnectionString(connectionString: string) {\n if (!connectionString) {\n throw new Error('flags: Missing connection string');\n }\n\n const connectionOptions = parseFlagsConnectionString(connectionString);\n const edgeConfigItemKey = connectionOptions.edgeConfigItemKey || 'flags';\n\n if (!connectionOptions.edgeConfigId || !connectionOptions.edgeConfigToken) {\n throw new Error('flags: Missing edge config connection information');\n }\n\n // TODO use latest connection string format\n // const edgeConfigConnectionString = `edge-config:id=${connectionOptions.edgeConfigId}&token=${connectionOptions.edgeConfigToken}`;\n const edgeConfigConnectionString = `https://edge-config.vercel.com/${connectionOptions.edgeConfigId}?token=${connectionOptions.edgeConfigToken}`;\n\n const edgeConfigClient = createEdgeConfigClient(edgeConfigConnectionString);\n\n const dataSource = new EdgeConfigDataSource({\n edgeConfigClient,\n edgeConfigItemKey,\n projectId: connectionOptions.projectId,\n });\n\n const environment = getFlagsEnvironment(connectionOptions.env);\n return createClient({ dataSource, environment });\n}\n\n/**\n * This function is for internal use only.\n *\n * Produces a default flags client reading from a default edge config.\n *\n * - relies on process.env.FLAGS\n * - does not use process.env.EDGE_CONFIG\n *\n * @param connectionString - usually from process.env.FLAGS\n * @returns - a flags client\n */\nexport function getDefaultFlagsClient() {\n if (defaultFlagsClient) return defaultFlagsClient;\n\n if (!process.env.FLAGS) {\n throw new Error('flags: Missing environment variable FLAGS');\n }\n\n defaultFlagsClient = createClientFromConnectionString(process.env.FLAGS);\n return defaultFlagsClient;\n}\n\n/**\n * Resolve the Flags environment. If connectionOptionsEnv is provided, use it as-is.\n *\n * Fall back to VERCEL_ENV if it is a known Vercel environment (production, preview, development)\n * If VERCEL_ENV is unset, it will resolve 'development' (Vercel provides it in preview and production)\n * If VERCEL_ENV is not one of the known values, it will resolve 'preview'\n */\nexport function getFlagsEnvironment(connectionOptionsEnv: string | null) {\n if (connectionOptionsEnv) {\n return connectionOptionsEnv;\n }\n const vercelEnv = process.env.VERCEL_ENV;\n if (!vercelEnv || vercelEnv === 'development') {\n return 'development';\n }\n if (vercelEnv === 'production') {\n return 'production';\n }\n return 'preview';\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} from './types';\nimport { exhaustivenessCheck } from './utils';\n\ntype PathArray = (string | number)[];\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 matchTargetList<T>(\n targets: Packed.TargetList,\n params: EvaluationParams<T>,\n): boolean {\n for (const [kind, attributes] of Object.entries(targets)) {\n for (const [attribute, values] of Object.entries(attributes)) {\n const entity = access([kind, attribute], params);\n if (isString(entity) && values.includes(entity)) 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, rhs] = condition;\n\n if (lhsAccessor === Packed.AccessorType.SEGMENT) {\n return rhs && matchSegmentCondition(cmpKey, rhs, params);\n }\n\n const lhs = access(lhsAccessor, params);\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.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 typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return new RegExp(rhs.pattern, rhs.flags).test(lhs);\n }\n return false;\n\n case Comparator.NOT_REGEX:\n if (\n isString(lhs) &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return !new RegExp(rhs.pattern, rhs.flags).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 const maxValue = 100_000;\n\n // bypass hashing for common values and edges\n if (outcome.passPromille <= 0) return false;\n if (outcome.passPromille >= maxValue) return true;\n\n const value = hashInput(lhs, params.definition.seed) % maxValue;\n return value < outcome.passPromille;\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\nfunction handleOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.Outcome,\n): {\n value: T;\n outcomeType: OutcomeType;\n} {\n if (typeof outcome === 'number') {\n return {\n value: params.definition.variants[outcome] as T,\n outcomeType: OutcomeType.VALUE,\n };\n }\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = params.definition.variants[outcome.defaultVariant];\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return { value: defaultOutcome as T, outcomeType: OutcomeType.SPLIT };\n }\n\n /** 2^32-1 */\n const maxValue = 4_294_967_295;\n /**\n * (xxHash32): turns the string into a number between 0 and 2^32-1 (max uint32 value)\n * Since we know the range of the hash function, we don't use modulo here. If we change\n * the hash function, or if the range changes, we should add a modulo here and/or adjust maxValue.\n */\n const value = hashInput(lhs, params.definition.seed);\n const sumOfWeights = sum(outcome.weights);\n const scaledWeights = outcome.weights.map(\n (weight) => (weight / sumOfWeights) * maxValue,\n );\n const variantIndex = findWeightedIndex(scaledWeights, value, maxValue);\n return {\n value:\n variantIndex === -1\n ? (defaultOutcome as T)\n : (params.definition.variants[variantIndex] as T),\n outcomeType: OutcomeType.SPLIT,\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): 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 {\n ...handleOutcome<T>(params, envConfig),\n reason: ResolutionReason.PAUSED,\n };\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 };\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 return evaluate<T>({ ...params, environment: envConfig.reuse });\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 {\n ...handleOutcome<T>(params, matchedIndex),\n reason: ResolutionReason.TARGET_MATCH,\n };\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 {\n ...handleOutcome<T>(params, firstMatchingRule.outcome),\n reason: ResolutionReason.RULE_MATCH,\n };\n }\n\n return {\n ...handleOutcome<T>(params, envConfig.fallthrough),\n reason: ResolutionReason.FALLTHROUGH,\n };\n}\n\n/**\n * Find the weighted index that the given value falls into.\n *\n * Takes a set of weights that add up to maxValue, and returns the index\n * that corresponds to the given value.\n *\n * @returns index or -1\n */\nexport function findWeightedIndex(\n weights: number[],\n value: number,\n maxValue: number,\n): number {\n if (value < 0 || value >= maxValue) return -1;\n\n let sum = 0;\n for (let i = 0; i < weights.length; i++) {\n sum += weights[i] as number;\n if (value < sum) return i;\n }\n\n return -1;\n}\n","export interface ConnectionOptions {\n edgeConfigId: string;\n edgeConfigToken: string;\n edgeConfigItemKey: string | null;\n env: string | null;\n projectId: string;\n}\n\n// -----------------------------------------------------------------------------\n// Shared data\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 `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 * Indicates why the flag evaluated to a certain value\n */\n reason: Exclude<ResolutionReason, ResolutionReason.ERROR>;\n errorMessage?: never;\n errorCode?: never;\n }\n | {\n reason: ResolutionReason.ERROR;\n errorMessage: string;\n errorCode?: ErrorCode;\n /**\n * In cases of errors this is the he defaultValue if one was provided\n */\n value?: T;\n };\n\nexport type FlagKey = string;\nexport type VariantId = string;\nexport type EnvironmentKey = string;\nexport type SegmentId = string;\nexport type Value = string | number | boolean;\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}\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 * - deos 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 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 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: { label: 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 };\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: { label: string; value: string }[] }\n * }\n */\n export type TargetList = Record<\n string,\n Record<string, { label: 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: { label: 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: { label: string, value: string }[] }\n * }\n */\n exclude: TargetList;\n };\n\n export type FlagDefinition = {\n happykitFlagId?: string;\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 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;\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 Condition =\n | [LHS, Comparator, RHS]\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 happykitFlagId?: string;\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 * This function is used to check for exhaustiveness in switch statements.\n *\n * @param _ - The value to check.\n *\n * @example\n * Given `type Union = 'a' | 'b' | 'c'`, the following code will not compile:\n * ```ts\n * switch (union) {\n * case 'a':\n * return 'a';\n * case 'b':\n * return 'b';\n * default:\n * exhaustivenessCheck(union); // This will throw an error\n * }\n * ```\n * This is because `value` has been narrowed to `'c'` by the `default` arm,\n * which is not assignable to `never`. If we covered the `'c'` case, the type\n * would narrow to `never`, which is assignable to `never` and would not cause an error.\n */\nexport function exhaustivenessCheck(_: never): never {\n throw new Error('Exhaustiveness check failed');\n}\n","{\n \"name\": \"@vercel/flags-core\",\n \"version\": \"0.1.6\",\n \"description\": \"\",\n \"keywords\": [],\n \"license\": \"MIT\",\n \"author\": \"\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openfeature\": {\n \"import\": \"./dist/openfeature.js\",\n \"require\": \"./dist/openfeature.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"typesVersions\": {\n \"*\": {\n \".\": [\n \"dist/*.d.ts\",\n \"dist/*.d.cts\"\n ],\n \"./openfeature\": [\n \"dist/openfeature.d.ts\",\n \"dist/openfeature.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 \"jose\": \"5.2.1\",\n \"js-xxhash\": \"4.0.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"20.11.17\",\n \"@vercel/edge-config\": \"^1.4.3\",\n \"flags\": \"workspace:*\",\n \"msw\": \"2.6.4\",\n \"tsup\": \"8.0.1\",\n \"typescript\": \"5.6.3\",\n \"vite\": \"6.0.3\",\n \"vitest\": \"2.1.8\"\n },\n \"peerDependencies\": {\n \"@vercel/edge-config\": \"^1.2.0\",\n \"flags\": \"*\",\n \"@openfeature/server-sdk\": \"1.18.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openfeature/server-sdk\": {\n \"optional\": true\n },\n \"@vercel/edge-config\": {\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 interally 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 ctx?.flags?.reportValue(key, value, {\n sdkVersion: version,\n ...data,\n });\n}\n","// TODO should we store the context schema (entities schema) in Edge Config and validate context?\n// TODO should we make evaluate return the variant ids as well?\nimport type { DataSource } from './data-source/interface';\nimport { evaluate } from './evaluate';\nimport { internalReportValue } from './lib/report-value';\nimport {\n ErrorCode,\n type EvaluationResult,\n type Packed,\n ResolutionReason,\n type Value,\n} from './types';\n\nexport type Source = {\n orgId: string;\n orgSlug: string;\n projectId: string;\n projectSlug: string;\n};\n\nexport type FlagsClient = {\n environment: string;\n dataSource: DataSource;\n evaluate: <T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ) => Promise<EvaluationResult<T>>;\n initialize(): void | Promise<void>;\n shutdown(): void | Promise<void>;\n};\n\n/**\n * Creates a Vercel Flags client\n *\n * @example\n * const edgeConfigClient = createClient('');\n * const flagsClient = createClient({\n * dataSource: new EdgeConfigDataSource({\n * edgeConfigItemKey: 'flags',\n * edgeConfigClient,\n * }),\n * environment: 'production',\n * });\n */\nexport function createClient({\n environment,\n dataSource,\n}: {\n environment: string;\n dataSource: DataSource;\n}): FlagsClient {\n return {\n dataSource,\n environment,\n initialize: () => {\n if (dataSource && typeof dataSource.initialize === 'function') {\n return dataSource.initialize();\n }\n },\n shutdown: () => {\n if (dataSource && typeof dataSource.shutdown === 'function') {\n return dataSource.shutdown();\n }\n },\n async evaluate<T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ): Promise<EvaluationResult<T>> {\n // TODO dataSource.getData should move into \"initialize\" and set up the subscription.\n //\n // From OpenFeature: \"It's recommended to provide non-blocking mechanisms for flag\n // evaluation, particularly in languages or environments wherein there's a\n // single thread of execution.\n const data = await dataSource.getData();\n\n const flagDefinition = data.definitions[flagKey] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n return {\n value: defaultValue,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `Definition not found for flag \"${flagKey}\"`,\n };\n }\n\n const result = evaluate<T>({\n defaultValue,\n definition: flagDefinition,\n environment: this.environment,\n entities: entities ?? {},\n segments: data.segments,\n });\n\n if (dataSource.projectId) {\n internalReportValue(flagKey, result.value, {\n originProjectId: dataSource.projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n\n return result;\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * A store to avoid reading the Edge Config for every flag evaluation,\n * and instead reading it once per request.\n */\nexport const store = new AsyncLocalStorage<WeakKey>();\n","import type { EdgeConfigClient } from '@vercel/edge-config';\nimport { store } from '../store';\nimport type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\n/**\n * Implements the DataSource interface for Edge Config.\n */\nexport class EdgeConfigDataSource implements DataSource {\n connectionString?: string;\n edgeConfigClient: EdgeConfigClient;\n edgeConfigItemKey: string;\n requestCache: WeakMap<WeakKey, Promise<Packed.Data | undefined>>;\n projectId?: string;\n\n constructor(options: {\n edgeConfigItemKey: string;\n edgeConfigClient: EdgeConfigClient;\n projectId?: string;\n }) {\n this.edgeConfigClient = options.edgeConfigClient;\n this.edgeConfigItemKey = options.edgeConfigItemKey;\n this.requestCache = new WeakMap();\n this.projectId = options.projectId;\n }\n\n // This is a temporary solution to avoid reading the Edge Config for every flag,\n // and instead reading it once per request.\n private async getCachedData() {\n const cacheKey = store.getStore();\n if (cacheKey) {\n const cached = this.requestCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n const promise = this.edgeConfigClient.get<Packed.Data>(\n this.edgeConfigItemKey,\n );\n\n if (cacheKey) this.requestCache.set(cacheKey, promise);\n\n return promise;\n }\n\n async getData() {\n const data = await this.getCachedData();\n\n if (!data) {\n throw new Error(\n `No definitions found in Edge Config under key \"${this.edgeConfigItemKey}\"`,\n );\n }\n\n return data;\n }\n}\n","import type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\nexport class InMemoryDataSource implements DataSource {\n private data: Packed.Data;\n public projectId?: string;\n\n constructor(data: Packed.Data, projectId?: string) {\n this.data = data;\n this.projectId = projectId;\n }\n\n async getData() {\n return this.data;\n }\n}\n"],"mappings":"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","names":["ResolutionReason","Original","AccessorType","Packed","_a","sum"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/evaluate.ts","../src/types.ts","../src/utils.ts","../package.json","../src/lib/report-value.ts","../src/client.ts","../src/store.ts","../src/data-source/edge-config-data-source.ts","../src/data-source/in-memory-data-source.ts"],"sourcesContent":["import { createClient as createEdgeConfigClient } from '@vercel/edge-config';\nimport { createClient, type FlagsClient } from './client';\nimport { EdgeConfigDataSource } from './data-source/edge-config-data-source';\nimport { InMemoryDataSource } from './data-source/in-memory-data-source';\nimport type { DataSource } from './data-source/interface';\nimport type { ConnectionOptions } from './types';\n\nexport {\n createClient,\n type FlagsClient,\n} from './client';\nexport { EdgeConfigDataSource, InMemoryDataSource };\nexport { store } from './store';\nexport { type Packed, ResolutionReason as Reason } from './types';\nexport type { DataSource };\nexport { evaluate } from './evaluate';\n\nlet defaultFlagsClient: FlagsClient | null = null;\n\n// TODO this should possibly be a generic parser for the URL, which\n// can be used with sources other than Edge Config at some point\nexport function parseFlagsConnectionString(\n connectionString: string,\n): ConnectionOptions {\n const errorMessage = 'flags: Invalid connection string';\n\n try {\n const params = new URLSearchParams(connectionString.slice(6));\n const edgeConfigId = params.get('edgeConfigId');\n const edgeConfigToken = params.get('edgeConfigToken');\n const projectId = params.get('projectId');\n if (!edgeConfigId || !edgeConfigToken || !projectId) {\n throw new Error(errorMessage);\n }\n\n return {\n edgeConfigId,\n edgeConfigToken,\n projectId,\n edgeConfigItemKey: params.get('edgeConfigItemKey'),\n env: params.get('env'),\n };\n } catch {\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Internal function for testing purposes\n */\nexport function resetDefaultFlagsClient() {\n defaultFlagsClient = null;\n}\n\nexport function createClientFromConnectionString(connectionString: string) {\n if (!connectionString) {\n throw new Error('flags: Missing connection string');\n }\n\n const connectionOptions = parseFlagsConnectionString(connectionString);\n const edgeConfigItemKey = connectionOptions.edgeConfigItemKey || 'flags';\n\n if (!connectionOptions.edgeConfigId || !connectionOptions.edgeConfigToken) {\n throw new Error('flags: Missing edge config connection information');\n }\n\n // TODO use latest connection string format\n // const edgeConfigConnectionString = `edge-config:id=${connectionOptions.edgeConfigId}&token=${connectionOptions.edgeConfigToken}`;\n const edgeConfigConnectionString = `https://edge-config.vercel.com/${connectionOptions.edgeConfigId}?token=${connectionOptions.edgeConfigToken}`;\n\n const edgeConfigClient = createEdgeConfigClient(edgeConfigConnectionString);\n\n const dataSource = new EdgeConfigDataSource({\n edgeConfigClient,\n edgeConfigItemKey,\n projectId: connectionOptions.projectId,\n });\n\n const environment = getFlagsEnvironment(connectionOptions.env);\n return createClient({ dataSource, environment });\n}\n\n/**\n * This function is for internal use only.\n *\n * Produces a default flags client reading from a default edge config.\n *\n * - relies on process.env.FLAGS\n * - does not use process.env.EDGE_CONFIG\n *\n * @param connectionString - usually from process.env.FLAGS\n * @returns - a flags client\n */\nexport function getDefaultFlagsClient() {\n if (defaultFlagsClient) return defaultFlagsClient;\n\n if (!process.env.FLAGS) {\n throw new Error('flags: Missing environment variable FLAGS');\n }\n\n defaultFlagsClient = createClientFromConnectionString(process.env.FLAGS);\n return defaultFlagsClient;\n}\n\n/**\n * Resolve the Flags environment. If connectionOptionsEnv is provided, use it as-is.\n *\n * Fall back to VERCEL_ENV if it is a known Vercel environment (production, preview, development)\n * If VERCEL_ENV is unset, it will resolve 'development' (Vercel provides it in preview and production)\n * If VERCEL_ENV is not one of the known values, it will resolve 'preview'\n */\nexport function getFlagsEnvironment(connectionOptionsEnv: string | null) {\n if (connectionOptionsEnv) {\n return connectionOptionsEnv;\n }\n const vercelEnv = process.env.VERCEL_ENV;\n if (!vercelEnv || vercelEnv === 'development') {\n return 'development';\n }\n if (vercelEnv === 'production') {\n return 'production';\n }\n return 'preview';\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} from './types';\nimport { exhaustivenessCheck } from './utils';\n\ntype PathArray = (string | number)[];\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 matchTargetList<T>(\n targets: Packed.TargetList,\n params: EvaluationParams<T>,\n): boolean {\n for (const [kind, attributes] of Object.entries(targets)) {\n for (const [attribute, values] of Object.entries(attributes)) {\n const entity = access([kind, attribute], params);\n if (isString(entity) && values.includes(entity)) 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, rhs] = condition;\n\n if (lhsAccessor === Packed.AccessorType.SEGMENT) {\n return rhs && matchSegmentCondition(cmpKey, rhs, params);\n }\n\n const lhs = access(lhsAccessor, params);\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.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 typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return new RegExp(rhs.pattern, rhs.flags).test(lhs);\n }\n return false;\n\n case Comparator.NOT_REGEX:\n if (\n isString(lhs) &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return !new RegExp(rhs.pattern, rhs.flags).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 const maxValue = 100_000;\n\n // bypass hashing for common values and edges\n if (outcome.passPromille <= 0) return false;\n if (outcome.passPromille >= maxValue) return true;\n\n const value = hashInput(lhs, params.definition.seed) % maxValue;\n return value < outcome.passPromille;\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\nfunction handleOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.Outcome,\n): {\n value: T;\n outcomeType: OutcomeType;\n} {\n if (typeof outcome === 'number') {\n return {\n value: params.definition.variants[outcome] as T,\n outcomeType: OutcomeType.VALUE,\n };\n }\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = params.definition.variants[outcome.defaultVariant];\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return { value: defaultOutcome as T, outcomeType: OutcomeType.SPLIT };\n }\n\n /** 2^32-1 */\n const maxValue = 4_294_967_295;\n /**\n * (xxHash32): turns the string into a number between 0 and 2^32-1 (max uint32 value)\n * Since we know the range of the hash function, we don't use modulo here. If we change\n * the hash function, or if the range changes, we should add a modulo here and/or adjust maxValue.\n */\n const value = hashInput(lhs, params.definition.seed);\n const sumOfWeights = sum(outcome.weights);\n const scaledWeights = outcome.weights.map(\n (weight) => (weight / sumOfWeights) * maxValue,\n );\n const variantIndex = findWeightedIndex(scaledWeights, value, maxValue);\n return {\n value:\n variantIndex === -1\n ? (defaultOutcome as T)\n : (params.definition.variants[variantIndex] as T),\n outcomeType: OutcomeType.SPLIT,\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): 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 {\n ...handleOutcome<T>(params, envConfig),\n reason: ResolutionReason.PAUSED,\n };\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 };\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 return evaluate<T>({ ...params, environment: envConfig.reuse });\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 {\n ...handleOutcome<T>(params, matchedIndex),\n reason: ResolutionReason.TARGET_MATCH,\n };\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 {\n ...handleOutcome<T>(params, firstMatchingRule.outcome),\n reason: ResolutionReason.RULE_MATCH,\n };\n }\n\n return {\n ...handleOutcome<T>(params, envConfig.fallthrough),\n reason: ResolutionReason.FALLTHROUGH,\n };\n}\n\n/**\n * Find the weighted index that the given value falls into.\n *\n * Takes a set of weights that add up to maxValue, and returns the index\n * that corresponds to the given value.\n *\n * @returns index or -1\n */\nexport function findWeightedIndex(\n weights: number[],\n value: number,\n maxValue: number,\n): number {\n if (value < 0 || value >= maxValue) return -1;\n\n let sum = 0;\n for (let i = 0; i < weights.length; i++) {\n sum += weights[i] as number;\n if (value < sum) return i;\n }\n\n return -1;\n}\n","export interface ConnectionOptions {\n edgeConfigId: string;\n edgeConfigToken: string;\n edgeConfigItemKey: string | null;\n env: string | null;\n projectId: string;\n}\n\n// -----------------------------------------------------------------------------\n// Shared data\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 `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 * Indicates why the flag evaluated to a certain value\n */\n reason: Exclude<ResolutionReason, ResolutionReason.ERROR>;\n errorMessage?: never;\n errorCode?: never;\n }\n | {\n reason: ResolutionReason.ERROR;\n errorMessage: string;\n errorCode?: ErrorCode;\n /**\n * In cases of errors this is the he defaultValue if one was provided\n */\n value?: T;\n };\n\nexport type FlagKey = string;\nexport type VariantId = string;\nexport type EnvironmentKey = string;\nexport type SegmentId = string;\nexport type Value = string | number | boolean;\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}\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 * - deos 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 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 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 };\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 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;\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 Condition =\n | [LHS, Comparator, RHS]\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 * This function is used to check for exhaustiveness in switch statements.\n *\n * @param _ - The value to check.\n *\n * @example\n * Given `type Union = 'a' | 'b' | 'c'`, the following code will not compile:\n * ```ts\n * switch (union) {\n * case 'a':\n * return 'a';\n * case 'b':\n * return 'b';\n * default:\n * exhaustivenessCheck(union); // This will throw an error\n * }\n * ```\n * This is because `value` has been narrowed to `'c'` by the `default` arm,\n * which is not assignable to `never`. If we covered the `'c'` case, the type\n * would narrow to `never`, which is assignable to `never` and would not cause an error.\n */\nexport function exhaustivenessCheck(_: never): never {\n throw new Error('Exhaustiveness check failed');\n}\n","{\n \"name\": \"@vercel/flags-core\",\n \"version\": \"0.1.8\",\n \"description\": \"\",\n \"keywords\": [],\n \"license\": \"MIT\",\n \"author\": \"\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openfeature\": {\n \"import\": \"./dist/openfeature.js\",\n \"require\": \"./dist/openfeature.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"typesVersions\": {\n \"*\": {\n \".\": [\n \"dist/*.d.ts\",\n \"dist/*.d.cts\"\n ],\n \"./openfeature\": [\n \"dist/openfeature.d.ts\",\n \"dist/openfeature.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 \"jose\": \"5.2.1\",\n \"js-xxhash\": \"4.0.0\",\n \"@vercel/edge-config\": \"^1.4.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"20.11.17\",\n \"flags\": \"workspace:*\",\n \"msw\": \"2.6.4\",\n \"tsup\": \"8.0.1\",\n \"typescript\": \"5.6.3\",\n \"vite\": \"6.0.3\",\n \"vitest\": \"2.1.8\"\n },\n \"peerDependencies\": {\n \"flags\": \"*\",\n \"@openfeature/server-sdk\": \"1.18.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openfeature/server-sdk\": {\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 interally 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 ctx?.flags?.reportValue(key, value, {\n sdkVersion: version,\n ...data,\n });\n}\n","// TODO should we store the context schema (entities schema) in Edge Config and validate context?\n// TODO should we make evaluate return the variant ids as well?\nimport type { DataSource } from './data-source/interface';\nimport { evaluate } from './evaluate';\nimport { internalReportValue } from './lib/report-value';\nimport {\n ErrorCode,\n type EvaluationResult,\n type Packed,\n ResolutionReason,\n type Value,\n} from './types';\n\nexport type Source = {\n orgId: string;\n orgSlug: string;\n projectId: string;\n projectSlug: string;\n};\n\nexport type FlagsClient = {\n environment: string;\n dataSource: DataSource;\n evaluate: <T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ) => Promise<EvaluationResult<T>>;\n initialize(): void | Promise<void>;\n shutdown(): void | Promise<void>;\n};\n\n/**\n * Creates a Vercel Flags client\n *\n * @example\n * const edgeConfigClient = createClient('');\n * const flagsClient = createClient({\n * dataSource: new EdgeConfigDataSource({\n * edgeConfigItemKey: 'flags',\n * edgeConfigClient,\n * }),\n * environment: 'production',\n * });\n */\nexport function createClient({\n environment,\n dataSource,\n}: {\n environment: string;\n dataSource: DataSource;\n}): FlagsClient {\n return {\n dataSource,\n environment,\n initialize: () => {\n if (dataSource && typeof dataSource.initialize === 'function') {\n return dataSource.initialize();\n }\n },\n shutdown: () => {\n if (dataSource && typeof dataSource.shutdown === 'function') {\n return dataSource.shutdown();\n }\n },\n async evaluate<T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ): Promise<EvaluationResult<T>> {\n // TODO dataSource.getData should move into \"initialize\" and set up the subscription.\n //\n // From OpenFeature: \"It's recommended to provide non-blocking mechanisms for flag\n // evaluation, particularly in languages or environments wherein there's a\n // single thread of execution.\n const data = await dataSource.getData();\n\n const flagDefinition = data.definitions[flagKey] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n return {\n value: defaultValue,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `Definition not found for flag \"${flagKey}\"`,\n };\n }\n\n const result = evaluate<T>({\n defaultValue,\n definition: flagDefinition,\n environment: this.environment,\n entities: entities ?? {},\n segments: data.segments,\n });\n\n if (dataSource.projectId) {\n internalReportValue(flagKey, result.value, {\n originProjectId: dataSource.projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n\n return result;\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * A store to avoid reading the Edge Config for every flag evaluation,\n * and instead reading it once per request.\n */\nexport const store = new AsyncLocalStorage<WeakKey>();\n","import type { EdgeConfigClient } from '@vercel/edge-config';\nimport { store } from '../store';\nimport type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\n/**\n * Implements the DataSource interface for Edge Config.\n */\nexport class EdgeConfigDataSource implements DataSource {\n connectionString?: string;\n edgeConfigClient: EdgeConfigClient;\n edgeConfigItemKey: string;\n requestCache: WeakMap<WeakKey, Promise<Packed.Data | undefined>>;\n projectId?: string;\n\n constructor(options: {\n edgeConfigItemKey: string;\n edgeConfigClient: EdgeConfigClient;\n projectId?: string;\n }) {\n this.edgeConfigClient = options.edgeConfigClient;\n this.edgeConfigItemKey = options.edgeConfigItemKey;\n this.requestCache = new WeakMap();\n this.projectId = options.projectId;\n }\n\n // This is a temporary solution to avoid reading the Edge Config for every flag,\n // and instead reading it once per request.\n private async getCachedData() {\n const cacheKey = store.getStore();\n if (cacheKey) {\n const cached = this.requestCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n const promise = this.edgeConfigClient.get<Packed.Data>(\n this.edgeConfigItemKey,\n );\n\n if (cacheKey) this.requestCache.set(cacheKey, promise);\n\n return promise;\n }\n\n async getData() {\n const data = await this.getCachedData();\n\n if (!data) {\n throw new Error(\n `No definitions found in Edge Config under key \"${this.edgeConfigItemKey}\"`,\n );\n }\n\n return data;\n }\n}\n","import type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\nexport class InMemoryDataSource implements DataSource {\n private data: Packed.Data;\n public projectId?: string;\n\n constructor(data: Packed.Data, projectId?: string) {\n this.data = data;\n this.projectId = projectId;\n }\n\n async getData() {\n return this.data;\n }\n}\n"],"mappings":"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","names":["ResolutionReason","Original","AccessorType","Packed","_a","sum"]}
|
|
@@ -362,7 +362,7 @@ function findWeightedIndex(weights, value, maxValue) {
|
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
// package.json
|
|
365
|
-
var version = "0.1.
|
|
365
|
+
var version = "0.1.8";
|
|
366
366
|
|
|
367
367
|
// src/lib/report-value.ts
|
|
368
368
|
function internalReportValue(key, value, data) {
|
|
@@ -563,4 +563,4 @@ function getFlagsEnvironment(connectionOptionsEnv) {
|
|
|
563
563
|
|
|
564
564
|
|
|
565
565
|
exports.ResolutionReason = ResolutionReason; exports.evaluate = evaluate; exports.createClient = createClient; exports.store = store; exports.EdgeConfigDataSource = EdgeConfigDataSource; exports.InMemoryDataSource = InMemoryDataSource; exports.parseFlagsConnectionString = parseFlagsConnectionString; exports.resetDefaultFlagsClient = resetDefaultFlagsClient; exports.createClientFromConnectionString = createClientFromConnectionString; exports.getDefaultFlagsClient = getDefaultFlagsClient; exports.getFlagsEnvironment = getFlagsEnvironment;
|
|
566
|
-
//# sourceMappingURL=chunk-
|
|
566
|
+
//# sourceMappingURL=chunk-6ZAELH3K.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/evaluate.ts","../src/types.ts","../src/utils.ts","../package.json","../src/lib/report-value.ts","../src/client.ts","../src/store.ts","../src/data-source/edge-config-data-source.ts","../src/data-source/in-memory-data-source.ts"],"names":["ResolutionReason","Original","AccessorType","Packed","_a","sum"],"mappings":";AAAA,SAAS,gBAAgB,8BAA8B;;;ACAvD,SAAS,YAAY,iBAAiB;;;AC+F/B,IAAK,mBAAL,kBAAKA,sBAAL;AACL,EAAAA,kBAAA,YAAS;AACT,EAAAA,kBAAA,kBAAe;AACf,EAAAA,kBAAA,gBAAa;AACb,EAAAA,kBAAA,iBAAc;AACd,EAAAA,kBAAA,WAAQ;AALE,SAAAA;AAAA,GAAA;AAsKL,IAAU;AAAA,CAAV,CAAUC,cAAV;AAME,MAAK;AAAL,IAAKC,kBAAL;AACL,IAAAA,cAAA,aAAU;AACV,IAAAA,cAAA,YAAS;AAAA,KAFC,eAAAD,UAAA,iBAAAA,UAAA;AAAA,GANG;AAsLV,IAAU;AAAA,CAAV,CAAUE,YAAV;AAaE,MAAK;AAAL,IAAKD,kBAAL;AACL,IAAAA,cAAA,aAAU;AACV,IAAAA,cAAA,YAAS;AAAA,KAFC,eAAAC,QAAA,iBAAAA,QAAA;AAAA,GAbG;;;ACtaV,SAAS,oBAAoB,GAAiB;AACnD,QAAM,IAAI,MAAM,6BAA6B;AAC/C;;;AFVA,SAAS,YAAY,KAAU,WAA2B;AACxD,SAAO,UAAU,OAAO,CAAC,KAAU,QAAyB;AAC1D,QAAI,OAAO,OAAO,KAAK;AACrB,aAAO,IAAI,GAAG;AAAA,IAChB;AACA,WAAO;AAAA,EACT,GAAG,GAAG;AACR;AAQA,SAAS,OAAU,KAAiB,QAAkC;AAEpE,MAAI,MAAM,QAAQ,GAAG;AAAG,WAAO,YAAY,OAAO,UAAU,GAAG;AAI/D,MAAI,QAAQ,OAAO,aAAa;AAC9B,UAAM,IAAI,MAAM,oBAAoB;AAEtC,QAAM,IAAI,MAAM,0BAA0B;AAC5C;AAEA,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,QAAQ,OAAoC;AACnD,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAEA,SAAS,gBACP,SACA,QACS;AACT,aAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,OAAO,GAAG;AACxD,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC5D,YAAM,SAAS,OAAO,CAAC,MAAM,SAAS,GAAG,MAAM;AAC/C,UAAI,SAAS,MAAM,KAAK,OAAO,SAAS,MAAM;AAAG,eAAO;AAAA,IAC1D;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAgB,SAAyB,QAA6B;AAjE/E;AAkEE,MAAI,QAAQ,WAAW,gBAAgB,QAAQ,SAAS,MAAM;AAAG,WAAO;AACxE,MAAI,QAAQ,WAAW,gBAAgB,QAAQ,SAAS,MAAM;AAAG,WAAO;AACxE,MAAI,GAAC,aAAQ,UAAR,mBAAe;AAAQ,WAAO;AAEnC,QAAM,oBAAoB,QAAQ,MAAM;AAAA,IAAK,CAAC,SAC5C,gBAAgB,KAAK,YAAY,MAAM;AAAA,EACzC;AAEA,MAAI,CAAC;AAAmB,WAAO;AAE/B,SAAO,qBAAqB,QAAQ,kBAAkB,OAAO;AAC/D;AAEA,SAAS,sBACP,KACA,KACA,QACA;AAnFF;AAoFE,UAAQ,KAAK;AAAA,IACX,oBAAoB;AAClB,YAAM,WAAU,YAAO,aAAP,mBAAkB;AAClC,UAAI,CAAC;AAAS,eAAO;AACrB,aAAO,aAAgB,SAAS,MAAM;AAAA,IACxC;AAAA,IACA,yBAAwB;AACtB,YAAM,WAAU,YAAO,aAAP,mBAAkB;AAClC,UAAI,CAAC;AAAS,eAAO;AACrB,aAAO,CAAC,aAAgB,SAAS,MAAM;AAAA,IACzC;AAAA,IACA,2BAAwB;AACtB,UAAI,CAAC,QAAQ,GAAG;AAAG,eAAO;AAC1B,YAAM,aAAa;AACnB,aAAO,WAAW,KAAK,CAAC,cAAc;AAlG5C,YAAAC;AAmGQ,cAAM,WAAUA,MAAA,OAAO,aAAP,gBAAAA,IAAkB;AAClC,YAAI,CAAC;AAAS,iBAAO;AACrB,eAAO,aAAgB,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,gCAA4B;AAC1B,YAAM,aAAa;AACnB,aAAO,WAAW,MAAM,CAAC,cAAc;AA1G7C,YAAAA;AA2GQ,cAAM,WAAUA,MAAA,OAAO,aAAP,gBAAAA,IAAkB;AAClC,YAAI,CAAC;AAAS,iBAAO;AACrB,eAAO,aAAgB,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA;AACE,YAAM,IAAI,MAAM,cAAc,GAAG,8BAA8B;AAAA,EACnE;AACF;AAEA,SAAS,gBACP,YACA,QACS;AACT,SAAO,WAAW,MAAM,CAAC,cAAc;AACrC,UAAM,CAAC,aAAa,QAAQ,GAAG,IAAI;AAEnC,QAAI,gBAAgB,OAAO,aAAa,SAAS;AAC/C,aAAO,OAAO,sBAAsB,QAAQ,KAAK,MAAM;AAAA,IACzD;AAEA,UAAM,MAAM,OAAO,aAAa,MAAM;AACtC,QAAI;AACF,cAAQ,QAAQ;AAAA,QACd;AACE,iBAAO,QAAQ;AAAA,QACjB;AACE,iBAAO,QAAQ;AAAA,QACjB;AACE,iBAAO,QAAQ,GAAG,KAAK,IAAI,SAAS,GAAG;AAAA,QACzC;AAGE,iBACE,QAAQ,GAAG,KAAK,OAAO,QAAQ,eAAe,CAAC,IAAI,SAAS,GAAG;AAAA,QAEnE,4CAAiC;AAC/B,cAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEvD,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAI3C,cAAI,OAAO,SAAS,IAAI,QAAQ;AAC9B,mBAAO,IAAI,OAAO,QAAQ,EAAE,MAAM,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC;AAAA,UAC9D;AAGA,iBAAO,IAAI,MAAM,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC;AAAA,QAC/C;AAAA,QACA,4CAAiC;AAC/B,cAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEvD,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAC3C,iBAAO,IAAI;AAAA,YACT,OAAO,SAAS,IAAI;AAAA;AAAA,cAEhB,CAAC,SAAS,OAAO,IAAI,IAAI;AAAA;AAAA;AAAA,cAEzB,CAAC,SAAS,IAAI,SAAS,IAAI;AAAA;AAAA,UACjC;AAAA,QACF;AAAA,QACA,8CAAkC;AAEhC,cAAI,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAGhC,cAAI,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEhC,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAC3C,iBAAO,IAAI;AAAA,YACT,OAAO,SAAS,IAAI;AAAA;AAAA,cAEhB,CAAC,SAAS,CAAC,OAAO,IAAI,IAAI;AAAA;AAAA;AAAA,cAE1B,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI;AAAA;AAAA,UAClC;AAAA,QACF;AAAA,QACA;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,IAAI,WAAW,GAAG;AAAA,QAC7D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,CAAC,IAAI,WAAW,GAAG;AAAA,QAC9D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG;AAAA,QAC3D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,CAAC,IAAI,SAAS,GAAG;AAAA,QAC5D;AACE,iBAAO,QAAQ,UAAa,QAAQ;AAAA,QACtC;AACE,iBAAO,QAAQ,UAAa,QAAQ;AAAA,QACtC;AAEE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM;AAAA,QACnD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,OAAO;AAAA,QACpD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM;AAAA,QACnD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,OAAO;AAAA,QACpD;AACE,cACE,SAAS,GAAG,KACZ,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,MAClB,2BAAK,UAAS,SACd;AACA,mBAAO,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,KAAK,GAAG;AAAA,UACpD;AACA,iBAAO;AAAA,QAET;AACE,cACE,SAAS,GAAG,KACZ,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,MAClB,2BAAK,UAAS,SACd;AACA,mBAAO,CAAC,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,KAAK,GAAG;AAAA,UACrD;AACA,iBAAO;AAAA,QACT,4BAAwB;AACtB,cAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,GAAG;AAAG,mBAAO;AAC7C,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,gBAAM,IAAI,IAAI,KAAK,GAAG;AAGtB,iBAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,QACjC;AAAA,QACA,0BAAuB;AACrB,cAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,GAAG;AAAG,mBAAO;AAC7C,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,iBAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,QACjC;AAAA,QACA,SAAS;AACP,gBAAM,KAAY;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,oCAAoC,KAAK;AACvD,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,SAAS,IAAI,MAAgB;AAC3B,SAAO,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAC3C;AAEA,SAAS,qBACP,QACA,SACA;AAEA,MAAI,YAAY;AAAG,WAAO;AAE1B,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,SAAS;AACZ,YAAM,MAAM,OAAO,QAAQ,MAAM,MAAM;AAGvC,UAAI,OAAO,QAAQ;AAAU,eAAO;AAEpC,YAAM,WAAW;AAGjB,UAAI,QAAQ,gBAAgB;AAAG,eAAO;AACtC,UAAI,QAAQ,gBAAgB;AAAU,eAAO;AAE7C,YAAM,QAAQ,UAAU,KAAK,OAAO,WAAW,IAAI,IAAI;AACvD,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,IACA,SAAS;AACP,YAAM,EAAE,KAAK,IAAI;AACjB,0BAAoB,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAAS,cACP,QACA,SAIA;AACA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,MACL,OAAO,OAAO,WAAW,SAAS,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,SAAS;AACZ,YAAM,MAAM,OAAO,QAAQ,MAAM,MAAM;AACvC,YAAM,iBAAiB,OAAO,WAAW,SAAS,QAAQ,cAAc;AAGxE,UAAI,OAAO,QAAQ,UAAU;AAC3B,eAAO,EAAE,OAAO,gBAAqB,iCAA+B;AAAA,MACtE;AAGA,YAAM,WAAW;AAMjB,YAAM,QAAQ,UAAU,KAAK,OAAO,WAAW,IAAI;AACnD,YAAM,eAAe,IAAI,QAAQ,OAAO;AACxC,YAAM,gBAAgB,QAAQ,QAAQ;AAAA,QACpC,CAAC,WAAY,SAAS,eAAgB;AAAA,MACxC;AACA,YAAM,eAAe,kBAAkB,eAAe,OAAO,QAAQ;AACrE,aAAO;AAAA,QACL,OACE,iBAAiB,KACZ,iBACA,OAAO,WAAW,SAAS,YAAY;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AACP,YAAM,EAAE,KAAK,IAAI;AACjB,0BAAoB,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAWO,SAAS,SAId,QACqB;AACrB,QAAM,YAAY,OAAO,WAAW,aAAa,OAAO,WAAW;AAGnE,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO;AAAA,MACL,GAAG,cAAiB,QAAQ,SAAS;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL;AAAA,MACA,cAAc,iCAAiC,OAAO,WAAW;AAAA,MACjE,OAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,WAAW,WAAW;AACxB,UAAM,iBAAiB,OAAO,WAAW,aAAa,UAAU,KAAK;AAErE,QAAI,mBAAmB,QAAW;AAGhC,YAAM,IAAI;AAAA,QACR,iCAAiC,UAAU,KAAK;AAAA,MAClD;AAAA,IACF;AAEA,WAAO,SAAY,EAAE,GAAG,QAAQ,aAAa,UAAU,MAAM,CAAC;AAAA,EAChE;AAEA,MAAI,UAAU,SAAS;AACrB,UAAM,eAAe,UAAU,QAAQ;AAAA,MAAU,CAAC,eAChD,gBAAgB,YAAY,MAAM;AAAA,IACpC;AAEA,QAAI,eAAe,IAAI;AACrB,aAAO;AAAA,QACL,GAAG,cAAiB,QAAQ,YAAY;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,UAAU,QAChC,UAAU,MAAM,KAAK,CAAC,SAAS,gBAAgB,KAAK,YAAY,MAAM,CAAC,IACvE;AAEJ,MAAI,mBAAmB;AACrB,WAAO;AAAA,MACL,GAAG,cAAiB,QAAQ,kBAAkB,OAAO;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG,cAAiB,QAAQ,UAAU,WAAW;AAAA,IACjD;AAAA,EACF;AACF;AAUO,SAAS,kBACd,SACA,OACA,UACQ;AACR,MAAI,QAAQ,KAAK,SAAS;AAAU,WAAO;AAE3C,MAAIC,OAAM;AACV,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,IAAAA,QAAO,QAAQ,CAAC;AAChB,QAAI,QAAQA;AAAK,aAAO;AAAA,EAC1B;AAEA,SAAO;AACT;;;AGvbE,cAAW;;;ACIN,SAAS,oBACd,KACA,OACA,MAMA;AAfF;AAgBE,QAAM,SAAS,OAAO,IAAI,yBAAyB;AACnD,QAAM,OAAM,aAAQ,IAAI,YAAY,MAAM,MAA9B,mBAAiC;AAC7C,mCAAK,UAAL,mBAAY,YAAY,KAAK,OAAO;AAAA,IAClC,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;;;ACuBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AACF,GAGgB;AACd,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM;AAChB,UAAI,cAAc,OAAO,WAAW,eAAe,YAAY;AAC7D,eAAO,WAAW,WAAW;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,UAAU,MAAM;AACd,UAAI,cAAc,OAAO,WAAW,aAAa,YAAY;AAC3D,eAAO,WAAW,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,MAAM,SACJ,SACA,cACA,UAC8B;AAM9B,YAAM,OAAO,MAAM,WAAW,QAAQ;AAEtC,YAAM,iBAAiB,KAAK,YAAY,OAAO;AAE/C,UAAI,mBAAmB,QAAW;AAChC,eAAO;AAAA,UACL,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,cAAc,kCAAkC,OAAO;AAAA,QACzD;AAAA,MACF;AAEA,YAAM,SAAS,SAAY;AAAA,QACzB;AAAA,QACA,YAAY;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,UAAU,YAAY,CAAC;AAAA,QACvB,UAAU,KAAK;AAAA,MACjB,CAAC;AAED,UAAI,WAAW,WAAW;AACxB,4BAAoB,SAAS,OAAO,OAAO;AAAA,UACzC,iBAAiB,WAAW;AAAA,UAC5B,gBAAgB;AAAA,UAChB,QAAQ,OAAO;AAAA,UACf,aACE,OAAO,iCACH,OAAO,cACP;AAAA,QACR,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/GA,SAAS,yBAAyB;AAM3B,IAAM,QAAQ,IAAI,kBAA2B;;;ACE7C,IAAM,uBAAN,MAAiD;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAIT;AACD,SAAK,mBAAmB,QAAQ;AAChC,SAAK,oBAAoB,QAAQ;AACjC,SAAK,eAAe,oBAAI,QAAQ;AAChC,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIA,MAAc,gBAAgB;AAC5B,UAAM,WAAW,MAAM,SAAS;AAChC,QAAI,UAAU;AACZ,YAAM,SAAS,KAAK,aAAa,IAAI,QAAQ;AAC7C,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,UAAU,KAAK,iBAAiB;AAAA,MACpC,KAAK;AAAA,IACP;AAEA,QAAI;AAAU,WAAK,aAAa,IAAI,UAAU,OAAO;AAErD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU;AACd,UAAM,OAAO,MAAM,KAAK,cAAc;AAEtC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR,kDAAkD,KAAK,iBAAiB;AAAA,MAC1E;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACrDO,IAAM,qBAAN,MAA+C;AAAA,EAC5C;AAAA,EACD;AAAA,EAEP,YAAY,MAAmB,WAAoB;AACjD,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAU;AACd,WAAO,KAAK;AAAA,EACd;AACF;;;ATEA,IAAI,qBAAyC;AAItC,SAAS,2BACd,kBACmB;AACnB,QAAM,eAAe;AAErB,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB,iBAAiB,MAAM,CAAC,CAAC;AAC5D,UAAM,eAAe,OAAO,IAAI,cAAc;AAC9C,UAAM,kBAAkB,OAAO,IAAI,iBAAiB;AACpD,UAAM,YAAY,OAAO,IAAI,WAAW;AACxC,QAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,WAAW;AACnD,YAAM,IAAI,MAAM,YAAY;AAAA,IAC9B;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,OAAO,IAAI,mBAAmB;AAAA,MACjD,KAAK,OAAO,IAAI,KAAK;AAAA,IACvB;AAAA,EACF,QAAQ;AACN,UAAM,IAAI,MAAM,YAAY;AAAA,EAC9B;AACF;AAKO,SAAS,0BAA0B;AACxC,uBAAqB;AACvB;AAEO,SAAS,iCAAiC,kBAA0B;AACzE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,QAAM,oBAAoB,2BAA2B,gBAAgB;AACrE,QAAM,oBAAoB,kBAAkB,qBAAqB;AAEjE,MAAI,CAAC,kBAAkB,gBAAgB,CAAC,kBAAkB,iBAAiB;AACzE,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAIA,QAAM,6BAA6B,kCAAkC,kBAAkB,YAAY,UAAU,kBAAkB,eAAe;AAE9I,QAAM,mBAAmB,uBAAuB,0BAA0B;AAE1E,QAAM,aAAa,IAAI,qBAAqB;AAAA,IAC1C;AAAA,IACA;AAAA,IACA,WAAW,kBAAkB;AAAA,EAC/B,CAAC;AAED,QAAM,cAAc,oBAAoB,kBAAkB,GAAG;AAC7D,SAAO,aAAa,EAAE,YAAY,YAAY,CAAC;AACjD;AAaO,SAAS,wBAAwB;AACtC,MAAI;AAAoB,WAAO;AAE/B,MAAI,CAAC,QAAQ,IAAI,OAAO;AACtB,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,uBAAqB,iCAAiC,QAAQ,IAAI,KAAK;AACvE,SAAO;AACT;AASO,SAAS,oBAAoB,sBAAqC;AACvE,MAAI,sBAAsB;AACxB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,CAAC,aAAa,cAAc,eAAe;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,cAAc,cAAc;AAC9B,WAAO;AAAA,EACT;AACA,SAAO;AACT","sourcesContent":["import { createClient as createEdgeConfigClient } from '@vercel/edge-config';\nimport { createClient, type FlagsClient } from './client';\nimport { EdgeConfigDataSource } from './data-source/edge-config-data-source';\nimport { InMemoryDataSource } from './data-source/in-memory-data-source';\nimport type { DataSource } from './data-source/interface';\nimport type { ConnectionOptions } from './types';\n\nexport {\n createClient,\n type FlagsClient,\n} from './client';\nexport { EdgeConfigDataSource, InMemoryDataSource };\nexport { store } from './store';\nexport { type Packed, ResolutionReason as Reason } from './types';\nexport type { DataSource };\nexport { evaluate } from './evaluate';\n\nlet defaultFlagsClient: FlagsClient | null = null;\n\n// TODO this should possibly be a generic parser for the URL, which\n// can be used with sources other than Edge Config at some point\nexport function parseFlagsConnectionString(\n connectionString: string,\n): ConnectionOptions {\n const errorMessage = 'flags: Invalid connection string';\n\n try {\n const params = new URLSearchParams(connectionString.slice(6));\n const edgeConfigId = params.get('edgeConfigId');\n const edgeConfigToken = params.get('edgeConfigToken');\n const projectId = params.get('projectId');\n if (!edgeConfigId || !edgeConfigToken || !projectId) {\n throw new Error(errorMessage);\n }\n\n return {\n edgeConfigId,\n edgeConfigToken,\n projectId,\n edgeConfigItemKey: params.get('edgeConfigItemKey'),\n env: params.get('env'),\n };\n } catch {\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Internal function for testing purposes\n */\nexport function resetDefaultFlagsClient() {\n defaultFlagsClient = null;\n}\n\nexport function createClientFromConnectionString(connectionString: string) {\n if (!connectionString) {\n throw new Error('flags: Missing connection string');\n }\n\n const connectionOptions = parseFlagsConnectionString(connectionString);\n const edgeConfigItemKey = connectionOptions.edgeConfigItemKey || 'flags';\n\n if (!connectionOptions.edgeConfigId || !connectionOptions.edgeConfigToken) {\n throw new Error('flags: Missing edge config connection information');\n }\n\n // TODO use latest connection string format\n // const edgeConfigConnectionString = `edge-config:id=${connectionOptions.edgeConfigId}&token=${connectionOptions.edgeConfigToken}`;\n const edgeConfigConnectionString = `https://edge-config.vercel.com/${connectionOptions.edgeConfigId}?token=${connectionOptions.edgeConfigToken}`;\n\n const edgeConfigClient = createEdgeConfigClient(edgeConfigConnectionString);\n\n const dataSource = new EdgeConfigDataSource({\n edgeConfigClient,\n edgeConfigItemKey,\n projectId: connectionOptions.projectId,\n });\n\n const environment = getFlagsEnvironment(connectionOptions.env);\n return createClient({ dataSource, environment });\n}\n\n/**\n * This function is for internal use only.\n *\n * Produces a default flags client reading from a default edge config.\n *\n * - relies on process.env.FLAGS\n * - does not use process.env.EDGE_CONFIG\n *\n * @param connectionString - usually from process.env.FLAGS\n * @returns - a flags client\n */\nexport function getDefaultFlagsClient() {\n if (defaultFlagsClient) return defaultFlagsClient;\n\n if (!process.env.FLAGS) {\n throw new Error('flags: Missing environment variable FLAGS');\n }\n\n defaultFlagsClient = createClientFromConnectionString(process.env.FLAGS);\n return defaultFlagsClient;\n}\n\n/**\n * Resolve the Flags environment. If connectionOptionsEnv is provided, use it as-is.\n *\n * Fall back to VERCEL_ENV if it is a known Vercel environment (production, preview, development)\n * If VERCEL_ENV is unset, it will resolve 'development' (Vercel provides it in preview and production)\n * If VERCEL_ENV is not one of the known values, it will resolve 'preview'\n */\nexport function getFlagsEnvironment(connectionOptionsEnv: string | null) {\n if (connectionOptionsEnv) {\n return connectionOptionsEnv;\n }\n const vercelEnv = process.env.VERCEL_ENV;\n if (!vercelEnv || vercelEnv === 'development') {\n return 'development';\n }\n if (vercelEnv === 'production') {\n return 'production';\n }\n return 'preview';\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} from './types';\nimport { exhaustivenessCheck } from './utils';\n\ntype PathArray = (string | number)[];\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 matchTargetList<T>(\n targets: Packed.TargetList,\n params: EvaluationParams<T>,\n): boolean {\n for (const [kind, attributes] of Object.entries(targets)) {\n for (const [attribute, values] of Object.entries(attributes)) {\n const entity = access([kind, attribute], params);\n if (isString(entity) && values.includes(entity)) 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, rhs] = condition;\n\n if (lhsAccessor === Packed.AccessorType.SEGMENT) {\n return rhs && matchSegmentCondition(cmpKey, rhs, params);\n }\n\n const lhs = access(lhsAccessor, params);\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.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 typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return new RegExp(rhs.pattern, rhs.flags).test(lhs);\n }\n return false;\n\n case Comparator.NOT_REGEX:\n if (\n isString(lhs) &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return !new RegExp(rhs.pattern, rhs.flags).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 const maxValue = 100_000;\n\n // bypass hashing for common values and edges\n if (outcome.passPromille <= 0) return false;\n if (outcome.passPromille >= maxValue) return true;\n\n const value = hashInput(lhs, params.definition.seed) % maxValue;\n return value < outcome.passPromille;\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\nfunction handleOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.Outcome,\n): {\n value: T;\n outcomeType: OutcomeType;\n} {\n if (typeof outcome === 'number') {\n return {\n value: params.definition.variants[outcome] as T,\n outcomeType: OutcomeType.VALUE,\n };\n }\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = params.definition.variants[outcome.defaultVariant];\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return { value: defaultOutcome as T, outcomeType: OutcomeType.SPLIT };\n }\n\n /** 2^32-1 */\n const maxValue = 4_294_967_295;\n /**\n * (xxHash32): turns the string into a number between 0 and 2^32-1 (max uint32 value)\n * Since we know the range of the hash function, we don't use modulo here. If we change\n * the hash function, or if the range changes, we should add a modulo here and/or adjust maxValue.\n */\n const value = hashInput(lhs, params.definition.seed);\n const sumOfWeights = sum(outcome.weights);\n const scaledWeights = outcome.weights.map(\n (weight) => (weight / sumOfWeights) * maxValue,\n );\n const variantIndex = findWeightedIndex(scaledWeights, value, maxValue);\n return {\n value:\n variantIndex === -1\n ? (defaultOutcome as T)\n : (params.definition.variants[variantIndex] as T),\n outcomeType: OutcomeType.SPLIT,\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): 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 {\n ...handleOutcome<T>(params, envConfig),\n reason: ResolutionReason.PAUSED,\n };\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 };\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 return evaluate<T>({ ...params, environment: envConfig.reuse });\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 {\n ...handleOutcome<T>(params, matchedIndex),\n reason: ResolutionReason.TARGET_MATCH,\n };\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 {\n ...handleOutcome<T>(params, firstMatchingRule.outcome),\n reason: ResolutionReason.RULE_MATCH,\n };\n }\n\n return {\n ...handleOutcome<T>(params, envConfig.fallthrough),\n reason: ResolutionReason.FALLTHROUGH,\n };\n}\n\n/**\n * Find the weighted index that the given value falls into.\n *\n * Takes a set of weights that add up to maxValue, and returns the index\n * that corresponds to the given value.\n *\n * @returns index or -1\n */\nexport function findWeightedIndex(\n weights: number[],\n value: number,\n maxValue: number,\n): number {\n if (value < 0 || value >= maxValue) return -1;\n\n let sum = 0;\n for (let i = 0; i < weights.length; i++) {\n sum += weights[i] as number;\n if (value < sum) return i;\n }\n\n return -1;\n}\n","export interface ConnectionOptions {\n edgeConfigId: string;\n edgeConfigToken: string;\n edgeConfigItemKey: string | null;\n env: string | null;\n projectId: string;\n}\n\n// -----------------------------------------------------------------------------\n// Shared data\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 `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 * Indicates why the flag evaluated to a certain value\n */\n reason: Exclude<ResolutionReason, ResolutionReason.ERROR>;\n errorMessage?: never;\n errorCode?: never;\n }\n | {\n reason: ResolutionReason.ERROR;\n errorMessage: string;\n errorCode?: ErrorCode;\n /**\n * In cases of errors this is the he defaultValue if one was provided\n */\n value?: T;\n };\n\nexport type FlagKey = string;\nexport type VariantId = string;\nexport type EnvironmentKey = string;\nexport type SegmentId = string;\nexport type Value = string | number | boolean;\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}\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 * - deos 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 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 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: { label: 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 };\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: { label: string; value: string }[] }\n * }\n */\n export type TargetList = Record<\n string,\n Record<string, { label: 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: { label: 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: { label: string, value: string }[] }\n * }\n */\n exclude: TargetList;\n };\n\n export type FlagDefinition = {\n happykitFlagId?: string;\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 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;\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 Condition =\n | [LHS, Comparator, RHS]\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 happykitFlagId?: string;\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 * This function is used to check for exhaustiveness in switch statements.\n *\n * @param _ - The value to check.\n *\n * @example\n * Given `type Union = 'a' | 'b' | 'c'`, the following code will not compile:\n * ```ts\n * switch (union) {\n * case 'a':\n * return 'a';\n * case 'b':\n * return 'b';\n * default:\n * exhaustivenessCheck(union); // This will throw an error\n * }\n * ```\n * This is because `value` has been narrowed to `'c'` by the `default` arm,\n * which is not assignable to `never`. If we covered the `'c'` case, the type\n * would narrow to `never`, which is assignable to `never` and would not cause an error.\n */\nexport function exhaustivenessCheck(_: never): never {\n throw new Error('Exhaustiveness check failed');\n}\n","{\n \"name\": \"@vercel/flags-core\",\n \"version\": \"0.1.6\",\n \"description\": \"\",\n \"keywords\": [],\n \"license\": \"MIT\",\n \"author\": \"\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openfeature\": {\n \"import\": \"./dist/openfeature.js\",\n \"require\": \"./dist/openfeature.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"typesVersions\": {\n \"*\": {\n \".\": [\n \"dist/*.d.ts\",\n \"dist/*.d.cts\"\n ],\n \"./openfeature\": [\n \"dist/openfeature.d.ts\",\n \"dist/openfeature.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 \"jose\": \"5.2.1\",\n \"js-xxhash\": \"4.0.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"20.11.17\",\n \"@vercel/edge-config\": \"^1.4.3\",\n \"flags\": \"workspace:*\",\n \"msw\": \"2.6.4\",\n \"tsup\": \"8.0.1\",\n \"typescript\": \"5.6.3\",\n \"vite\": \"6.0.3\",\n \"vitest\": \"2.1.8\"\n },\n \"peerDependencies\": {\n \"@vercel/edge-config\": \"^1.2.0\",\n \"flags\": \"*\",\n \"@openfeature/server-sdk\": \"1.18.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openfeature/server-sdk\": {\n \"optional\": true\n },\n \"@vercel/edge-config\": {\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 interally 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 ctx?.flags?.reportValue(key, value, {\n sdkVersion: version,\n ...data,\n });\n}\n","// TODO should we store the context schema (entities schema) in Edge Config and validate context?\n// TODO should we make evaluate return the variant ids as well?\nimport type { DataSource } from './data-source/interface';\nimport { evaluate } from './evaluate';\nimport { internalReportValue } from './lib/report-value';\nimport {\n ErrorCode,\n type EvaluationResult,\n type Packed,\n ResolutionReason,\n type Value,\n} from './types';\n\nexport type Source = {\n orgId: string;\n orgSlug: string;\n projectId: string;\n projectSlug: string;\n};\n\nexport type FlagsClient = {\n environment: string;\n dataSource: DataSource;\n evaluate: <T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ) => Promise<EvaluationResult<T>>;\n initialize(): void | Promise<void>;\n shutdown(): void | Promise<void>;\n};\n\n/**\n * Creates a Vercel Flags client\n *\n * @example\n * const edgeConfigClient = createClient('');\n * const flagsClient = createClient({\n * dataSource: new EdgeConfigDataSource({\n * edgeConfigItemKey: 'flags',\n * edgeConfigClient,\n * }),\n * environment: 'production',\n * });\n */\nexport function createClient({\n environment,\n dataSource,\n}: {\n environment: string;\n dataSource: DataSource;\n}): FlagsClient {\n return {\n dataSource,\n environment,\n initialize: () => {\n if (dataSource && typeof dataSource.initialize === 'function') {\n return dataSource.initialize();\n }\n },\n shutdown: () => {\n if (dataSource && typeof dataSource.shutdown === 'function') {\n return dataSource.shutdown();\n }\n },\n async evaluate<T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ): Promise<EvaluationResult<T>> {\n // TODO dataSource.getData should move into \"initialize\" and set up the subscription.\n //\n // From OpenFeature: \"It's recommended to provide non-blocking mechanisms for flag\n // evaluation, particularly in languages or environments wherein there's a\n // single thread of execution.\n const data = await dataSource.getData();\n\n const flagDefinition = data.definitions[flagKey] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n return {\n value: defaultValue,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `Definition not found for flag \"${flagKey}\"`,\n };\n }\n\n const result = evaluate<T>({\n defaultValue,\n definition: flagDefinition,\n environment: this.environment,\n entities: entities ?? {},\n segments: data.segments,\n });\n\n if (dataSource.projectId) {\n internalReportValue(flagKey, result.value, {\n originProjectId: dataSource.projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n\n return result;\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * A store to avoid reading the Edge Config for every flag evaluation,\n * and instead reading it once per request.\n */\nexport const store = new AsyncLocalStorage<WeakKey>();\n","import type { EdgeConfigClient } from '@vercel/edge-config';\nimport { store } from '../store';\nimport type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\n/**\n * Implements the DataSource interface for Edge Config.\n */\nexport class EdgeConfigDataSource implements DataSource {\n connectionString?: string;\n edgeConfigClient: EdgeConfigClient;\n edgeConfigItemKey: string;\n requestCache: WeakMap<WeakKey, Promise<Packed.Data | undefined>>;\n projectId?: string;\n\n constructor(options: {\n edgeConfigItemKey: string;\n edgeConfigClient: EdgeConfigClient;\n projectId?: string;\n }) {\n this.edgeConfigClient = options.edgeConfigClient;\n this.edgeConfigItemKey = options.edgeConfigItemKey;\n this.requestCache = new WeakMap();\n this.projectId = options.projectId;\n }\n\n // This is a temporary solution to avoid reading the Edge Config for every flag,\n // and instead reading it once per request.\n private async getCachedData() {\n const cacheKey = store.getStore();\n if (cacheKey) {\n const cached = this.requestCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n const promise = this.edgeConfigClient.get<Packed.Data>(\n this.edgeConfigItemKey,\n );\n\n if (cacheKey) this.requestCache.set(cacheKey, promise);\n\n return promise;\n }\n\n async getData() {\n const data = await this.getCachedData();\n\n if (!data) {\n throw new Error(\n `No definitions found in Edge Config under key \"${this.edgeConfigItemKey}\"`,\n );\n }\n\n return data;\n }\n}\n","import type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\nexport class InMemoryDataSource implements DataSource {\n private data: Packed.Data;\n public projectId?: string;\n\n constructor(data: Packed.Data, projectId?: string) {\n this.data = data;\n this.projectId = projectId;\n }\n\n async getData() {\n return this.data;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/evaluate.ts","../src/types.ts","../src/utils.ts","../package.json","../src/lib/report-value.ts","../src/client.ts","../src/store.ts","../src/data-source/edge-config-data-source.ts","../src/data-source/in-memory-data-source.ts"],"names":["ResolutionReason","Original","AccessorType","Packed","_a","sum"],"mappings":";AAAA,SAAS,gBAAgB,8BAA8B;;;ACAvD,SAAS,YAAY,iBAAiB;;;AC+F/B,IAAK,mBAAL,kBAAKA,sBAAL;AACL,EAAAA,kBAAA,YAAS;AACT,EAAAA,kBAAA,kBAAe;AACf,EAAAA,kBAAA,gBAAa;AACb,EAAAA,kBAAA,iBAAc;AACd,EAAAA,kBAAA,WAAQ;AALE,SAAAA;AAAA,GAAA;AAsKL,IAAU;AAAA,CAAV,CAAUC,cAAV;AAME,MAAK;AAAL,IAAKC,kBAAL;AACL,IAAAA,cAAA,aAAU;AACV,IAAAA,cAAA,YAAS;AAAA,KAFC,eAAAD,UAAA,iBAAAA,UAAA;AAAA,GANG;AAqLV,IAAU;AAAA,CAAV,CAAUE,YAAV;AAaE,MAAK;AAAL,IAAKD,kBAAL;AACL,IAAAA,cAAA,aAAU;AACV,IAAAA,cAAA,YAAS;AAAA,KAFC,eAAAC,QAAA,iBAAAA,QAAA;AAAA,GAbG;;;ACraV,SAAS,oBAAoB,GAAiB;AACnD,QAAM,IAAI,MAAM,6BAA6B;AAC/C;;;AFVA,SAAS,YAAY,KAAU,WAA2B;AACxD,SAAO,UAAU,OAAO,CAAC,KAAU,QAAyB;AAC1D,QAAI,OAAO,OAAO,KAAK;AACrB,aAAO,IAAI,GAAG;AAAA,IAChB;AACA,WAAO;AAAA,EACT,GAAG,GAAG;AACR;AAQA,SAAS,OAAU,KAAiB,QAAkC;AAEpE,MAAI,MAAM,QAAQ,GAAG;AAAG,WAAO,YAAY,OAAO,UAAU,GAAG;AAI/D,MAAI,QAAQ,OAAO,aAAa;AAC9B,UAAM,IAAI,MAAM,oBAAoB;AAEtC,QAAM,IAAI,MAAM,0BAA0B;AAC5C;AAEA,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,SAAS,OAAiC;AACjD,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,QAAQ,OAAoC;AACnD,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAEA,SAAS,gBACP,SACA,QACS;AACT,aAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,OAAO,GAAG;AACxD,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC5D,YAAM,SAAS,OAAO,CAAC,MAAM,SAAS,GAAG,MAAM;AAC/C,UAAI,SAAS,MAAM,KAAK,OAAO,SAAS,MAAM;AAAG,eAAO;AAAA,IAC1D;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAgB,SAAyB,QAA6B;AAjE/E;AAkEE,MAAI,QAAQ,WAAW,gBAAgB,QAAQ,SAAS,MAAM;AAAG,WAAO;AACxE,MAAI,QAAQ,WAAW,gBAAgB,QAAQ,SAAS,MAAM;AAAG,WAAO;AACxE,MAAI,GAAC,aAAQ,UAAR,mBAAe;AAAQ,WAAO;AAEnC,QAAM,oBAAoB,QAAQ,MAAM;AAAA,IAAK,CAAC,SAC5C,gBAAgB,KAAK,YAAY,MAAM;AAAA,EACzC;AAEA,MAAI,CAAC;AAAmB,WAAO;AAE/B,SAAO,qBAAqB,QAAQ,kBAAkB,OAAO;AAC/D;AAEA,SAAS,sBACP,KACA,KACA,QACA;AAnFF;AAoFE,UAAQ,KAAK;AAAA,IACX,oBAAoB;AAClB,YAAM,WAAU,YAAO,aAAP,mBAAkB;AAClC,UAAI,CAAC;AAAS,eAAO;AACrB,aAAO,aAAgB,SAAS,MAAM;AAAA,IACxC;AAAA,IACA,yBAAwB;AACtB,YAAM,WAAU,YAAO,aAAP,mBAAkB;AAClC,UAAI,CAAC;AAAS,eAAO;AACrB,aAAO,CAAC,aAAgB,SAAS,MAAM;AAAA,IACzC;AAAA,IACA,2BAAwB;AACtB,UAAI,CAAC,QAAQ,GAAG;AAAG,eAAO;AAC1B,YAAM,aAAa;AACnB,aAAO,WAAW,KAAK,CAAC,cAAc;AAlG5C,YAAAC;AAmGQ,cAAM,WAAUA,MAAA,OAAO,aAAP,gBAAAA,IAAkB;AAClC,YAAI,CAAC;AAAS,iBAAO;AACrB,eAAO,aAAgB,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA,gCAA4B;AAC1B,YAAM,aAAa;AACnB,aAAO,WAAW,MAAM,CAAC,cAAc;AA1G7C,YAAAA;AA2GQ,cAAM,WAAUA,MAAA,OAAO,aAAP,gBAAAA,IAAkB;AAClC,YAAI,CAAC;AAAS,iBAAO;AACrB,eAAO,aAAgB,SAAS,MAAM;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,IACA;AACE,YAAM,IAAI,MAAM,cAAc,GAAG,8BAA8B;AAAA,EACnE;AACF;AAEA,SAAS,gBACP,YACA,QACS;AACT,SAAO,WAAW,MAAM,CAAC,cAAc;AACrC,UAAM,CAAC,aAAa,QAAQ,GAAG,IAAI;AAEnC,QAAI,gBAAgB,OAAO,aAAa,SAAS;AAC/C,aAAO,OAAO,sBAAsB,QAAQ,KAAK,MAAM;AAAA,IACzD;AAEA,UAAM,MAAM,OAAO,aAAa,MAAM;AACtC,QAAI;AACF,cAAQ,QAAQ;AAAA,QACd;AACE,iBAAO,QAAQ;AAAA,QACjB;AACE,iBAAO,QAAQ;AAAA,QACjB;AACE,iBAAO,QAAQ,GAAG,KAAK,IAAI,SAAS,GAAG;AAAA,QACzC;AAGE,iBACE,QAAQ,GAAG,KAAK,OAAO,QAAQ,eAAe,CAAC,IAAI,SAAS,GAAG;AAAA,QAEnE,4CAAiC;AAC/B,cAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEvD,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAI3C,cAAI,OAAO,SAAS,IAAI,QAAQ;AAC9B,mBAAO,IAAI,OAAO,QAAQ,EAAE,MAAM,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC;AAAA,UAC9D;AAGA,iBAAO,IAAI,MAAM,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC;AAAA,QAC/C;AAAA,QACA,4CAAiC;AAC/B,cAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEvD,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAC3C,iBAAO,IAAI;AAAA,YACT,OAAO,SAAS,IAAI;AAAA;AAAA,cAEhB,CAAC,SAAS,OAAO,IAAI,IAAI;AAAA;AAAA;AAAA,cAEzB,CAAC,SAAS,IAAI,SAAS,IAAI;AAAA;AAAA,UACjC;AAAA,QACF;AAAA,QACA,8CAAkC;AAEhC,cAAI,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAGhC,cAAI,CAAC,MAAM,QAAQ,GAAG;AAAG,mBAAO;AAEhC,gBAAM,SAAS,IAAI,IAAI,IAAI,OAAO,QAAQ,CAAC;AAC3C,iBAAO,IAAI;AAAA,YACT,OAAO,SAAS,IAAI;AAAA;AAAA,cAEhB,CAAC,SAAS,CAAC,OAAO,IAAI,IAAI;AAAA;AAAA;AAAA,cAE1B,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI;AAAA;AAAA,UAClC;AAAA,QACF;AAAA,QACA;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,IAAI,WAAW,GAAG;AAAA,QAC7D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,CAAC,IAAI,WAAW,GAAG;AAAA,QAC9D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG;AAAA,QAC3D;AACE,iBAAO,SAAS,GAAG,KAAK,SAAS,GAAG,KAAK,CAAC,IAAI,SAAS,GAAG;AAAA,QAC5D;AACE,iBAAO,QAAQ,UAAa,QAAQ;AAAA,QACtC;AACE,iBAAO,QAAQ,UAAa,QAAQ;AAAA,QACtC;AAEE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM;AAAA,QACnD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,OAAO;AAAA,QACpD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM;AAAA,QACnD;AACE,cAAI,QAAQ,QAAQ,QAAQ;AAAW,mBAAO;AAC9C,kBAAQ,SAAS,GAAG,KAAK,SAAS,GAAG,MAAM,OAAO;AAAA,QACpD;AACE,cACE,SAAS,GAAG,KACZ,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,MAClB,2BAAK,UAAS,SACd;AACA,mBAAO,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,KAAK,GAAG;AAAA,UACpD;AACA,iBAAO;AAAA,QAET;AACE,cACE,SAAS,GAAG,KACZ,OAAO,QAAQ,YACf,CAAC,MAAM,QAAQ,GAAG,MAClB,2BAAK,UAAS,SACd;AACA,mBAAO,CAAC,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,EAAE,KAAK,GAAG;AAAA,UACrD;AACA,iBAAO;AAAA,QACT,4BAAwB;AACtB,cAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,GAAG;AAAG,mBAAO;AAC7C,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,gBAAM,IAAI,IAAI,KAAK,GAAG;AAGtB,iBAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,QACjC;AAAA,QACA,0BAAuB;AACrB,cAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,GAAG;AAAG,mBAAO;AAC7C,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,gBAAM,IAAI,IAAI,KAAK,GAAG;AACtB,iBAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,QACjC;AAAA,QACA,SAAS;AACP,gBAAM,KAAY;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,oCAAoC,KAAK;AACvD,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,SAAS,IAAI,MAAgB;AAC3B,SAAO,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAC3C;AAEA,SAAS,qBACP,QACA,SACA;AAEA,MAAI,YAAY;AAAG,WAAO;AAE1B,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,SAAS;AACZ,YAAM,MAAM,OAAO,QAAQ,MAAM,MAAM;AAGvC,UAAI,OAAO,QAAQ;AAAU,eAAO;AAEpC,YAAM,WAAW;AAGjB,UAAI,QAAQ,gBAAgB;AAAG,eAAO;AACtC,UAAI,QAAQ,gBAAgB;AAAU,eAAO;AAE7C,YAAM,QAAQ,UAAU,KAAK,OAAO,WAAW,IAAI,IAAI;AACvD,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,IACA,SAAS;AACP,YAAM,EAAE,KAAK,IAAI;AACjB,0BAAoB,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAAS,cACP,QACA,SAIA;AACA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,MACL,OAAO,OAAO,WAAW,SAAS,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,SAAS;AACZ,YAAM,MAAM,OAAO,QAAQ,MAAM,MAAM;AACvC,YAAM,iBAAiB,OAAO,WAAW,SAAS,QAAQ,cAAc;AAGxE,UAAI,OAAO,QAAQ,UAAU;AAC3B,eAAO,EAAE,OAAO,gBAAqB,iCAA+B;AAAA,MACtE;AAGA,YAAM,WAAW;AAMjB,YAAM,QAAQ,UAAU,KAAK,OAAO,WAAW,IAAI;AACnD,YAAM,eAAe,IAAI,QAAQ,OAAO;AACxC,YAAM,gBAAgB,QAAQ,QAAQ;AAAA,QACpC,CAAC,WAAY,SAAS,eAAgB;AAAA,MACxC;AACA,YAAM,eAAe,kBAAkB,eAAe,OAAO,QAAQ;AACrE,aAAO;AAAA,QACL,OACE,iBAAiB,KACZ,iBACA,OAAO,WAAW,SAAS,YAAY;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AACP,YAAM,EAAE,KAAK,IAAI;AACjB,0BAAoB,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAWO,SAAS,SAId,QACqB;AACrB,QAAM,YAAY,OAAO,WAAW,aAAa,OAAO,WAAW;AAGnE,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO;AAAA,MACL,GAAG,cAAiB,QAAQ,SAAS;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL;AAAA,MACA,cAAc,iCAAiC,OAAO,WAAW;AAAA,MACjE,OAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,WAAW,WAAW;AACxB,UAAM,iBAAiB,OAAO,WAAW,aAAa,UAAU,KAAK;AAErE,QAAI,mBAAmB,QAAW;AAGhC,YAAM,IAAI;AAAA,QACR,iCAAiC,UAAU,KAAK;AAAA,MAClD;AAAA,IACF;AAEA,WAAO,SAAY,EAAE,GAAG,QAAQ,aAAa,UAAU,MAAM,CAAC;AAAA,EAChE;AAEA,MAAI,UAAU,SAAS;AACrB,UAAM,eAAe,UAAU,QAAQ;AAAA,MAAU,CAAC,eAChD,gBAAgB,YAAY,MAAM;AAAA,IACpC;AAEA,QAAI,eAAe,IAAI;AACrB,aAAO;AAAA,QACL,GAAG,cAAiB,QAAQ,YAAY;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,UAAU,QAChC,UAAU,MAAM,KAAK,CAAC,SAAS,gBAAgB,KAAK,YAAY,MAAM,CAAC,IACvE;AAEJ,MAAI,mBAAmB;AACrB,WAAO;AAAA,MACL,GAAG,cAAiB,QAAQ,kBAAkB,OAAO;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG,cAAiB,QAAQ,UAAU,WAAW;AAAA,IACjD;AAAA,EACF;AACF;AAUO,SAAS,kBACd,SACA,OACA,UACQ;AACR,MAAI,QAAQ,KAAK,SAAS;AAAU,WAAO;AAE3C,MAAIC,OAAM;AACV,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,IAAAA,QAAO,QAAQ,CAAC;AAChB,QAAI,QAAQA;AAAK,aAAO;AAAA,EAC1B;AAEA,SAAO;AACT;;;AGvbE,cAAW;;;ACIN,SAAS,oBACd,KACA,OACA,MAMA;AAfF;AAgBE,QAAM,SAAS,OAAO,IAAI,yBAAyB;AACnD,QAAM,OAAM,aAAQ,IAAI,YAAY,MAAM,MAA9B,mBAAiC;AAC7C,mCAAK,UAAL,mBAAY,YAAY,KAAK,OAAO;AAAA,IAClC,YAAY;AAAA,IACZ,GAAG;AAAA,EACL;AACF;;;ACuBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AACF,GAGgB;AACd,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM;AAChB,UAAI,cAAc,OAAO,WAAW,eAAe,YAAY;AAC7D,eAAO,WAAW,WAAW;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,UAAU,MAAM;AACd,UAAI,cAAc,OAAO,WAAW,aAAa,YAAY;AAC3D,eAAO,WAAW,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,MAAM,SACJ,SACA,cACA,UAC8B;AAM9B,YAAM,OAAO,MAAM,WAAW,QAAQ;AAEtC,YAAM,iBAAiB,KAAK,YAAY,OAAO;AAE/C,UAAI,mBAAmB,QAAW;AAChC,eAAO;AAAA,UACL,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,cAAc,kCAAkC,OAAO;AAAA,QACzD;AAAA,MACF;AAEA,YAAM,SAAS,SAAY;AAAA,QACzB;AAAA,QACA,YAAY;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,UAAU,YAAY,CAAC;AAAA,QACvB,UAAU,KAAK;AAAA,MACjB,CAAC;AAED,UAAI,WAAW,WAAW;AACxB,4BAAoB,SAAS,OAAO,OAAO;AAAA,UACzC,iBAAiB,WAAW;AAAA,UAC5B,gBAAgB;AAAA,UAChB,QAAQ,OAAO;AAAA,UACf,aACE,OAAO,iCACH,OAAO,cACP;AAAA,QACR,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/GA,SAAS,yBAAyB;AAM3B,IAAM,QAAQ,IAAI,kBAA2B;;;ACE7C,IAAM,uBAAN,MAAiD;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAIT;AACD,SAAK,mBAAmB,QAAQ;AAChC,SAAK,oBAAoB,QAAQ;AACjC,SAAK,eAAe,oBAAI,QAAQ;AAChC,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIA,MAAc,gBAAgB;AAC5B,UAAM,WAAW,MAAM,SAAS;AAChC,QAAI,UAAU;AACZ,YAAM,SAAS,KAAK,aAAa,IAAI,QAAQ;AAC7C,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,UAAU,KAAK,iBAAiB;AAAA,MACpC,KAAK;AAAA,IACP;AAEA,QAAI;AAAU,WAAK,aAAa,IAAI,UAAU,OAAO;AAErD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU;AACd,UAAM,OAAO,MAAM,KAAK,cAAc;AAEtC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR,kDAAkD,KAAK,iBAAiB;AAAA,MAC1E;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;ACrDO,IAAM,qBAAN,MAA+C;AAAA,EAC5C;AAAA,EACD;AAAA,EAEP,YAAY,MAAmB,WAAoB;AACjD,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,MAAM,UAAU;AACd,WAAO,KAAK;AAAA,EACd;AACF;;;ATEA,IAAI,qBAAyC;AAItC,SAAS,2BACd,kBACmB;AACnB,QAAM,eAAe;AAErB,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB,iBAAiB,MAAM,CAAC,CAAC;AAC5D,UAAM,eAAe,OAAO,IAAI,cAAc;AAC9C,UAAM,kBAAkB,OAAO,IAAI,iBAAiB;AACpD,UAAM,YAAY,OAAO,IAAI,WAAW;AACxC,QAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,WAAW;AACnD,YAAM,IAAI,MAAM,YAAY;AAAA,IAC9B;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,OAAO,IAAI,mBAAmB;AAAA,MACjD,KAAK,OAAO,IAAI,KAAK;AAAA,IACvB;AAAA,EACF,QAAQ;AACN,UAAM,IAAI,MAAM,YAAY;AAAA,EAC9B;AACF;AAKO,SAAS,0BAA0B;AACxC,uBAAqB;AACvB;AAEO,SAAS,iCAAiC,kBAA0B;AACzE,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,QAAM,oBAAoB,2BAA2B,gBAAgB;AACrE,QAAM,oBAAoB,kBAAkB,qBAAqB;AAEjE,MAAI,CAAC,kBAAkB,gBAAgB,CAAC,kBAAkB,iBAAiB;AACzE,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAIA,QAAM,6BAA6B,kCAAkC,kBAAkB,YAAY,UAAU,kBAAkB,eAAe;AAE9I,QAAM,mBAAmB,uBAAuB,0BAA0B;AAE1E,QAAM,aAAa,IAAI,qBAAqB;AAAA,IAC1C;AAAA,IACA;AAAA,IACA,WAAW,kBAAkB;AAAA,EAC/B,CAAC;AAED,QAAM,cAAc,oBAAoB,kBAAkB,GAAG;AAC7D,SAAO,aAAa,EAAE,YAAY,YAAY,CAAC;AACjD;AAaO,SAAS,wBAAwB;AACtC,MAAI;AAAoB,WAAO;AAE/B,MAAI,CAAC,QAAQ,IAAI,OAAO;AACtB,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,uBAAqB,iCAAiC,QAAQ,IAAI,KAAK;AACvE,SAAO;AACT;AASO,SAAS,oBAAoB,sBAAqC;AACvE,MAAI,sBAAsB;AACxB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,CAAC,aAAa,cAAc,eAAe;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,cAAc,cAAc;AAC9B,WAAO;AAAA,EACT;AACA,SAAO;AACT","sourcesContent":["import { createClient as createEdgeConfigClient } from '@vercel/edge-config';\nimport { createClient, type FlagsClient } from './client';\nimport { EdgeConfigDataSource } from './data-source/edge-config-data-source';\nimport { InMemoryDataSource } from './data-source/in-memory-data-source';\nimport type { DataSource } from './data-source/interface';\nimport type { ConnectionOptions } from './types';\n\nexport {\n createClient,\n type FlagsClient,\n} from './client';\nexport { EdgeConfigDataSource, InMemoryDataSource };\nexport { store } from './store';\nexport { type Packed, ResolutionReason as Reason } from './types';\nexport type { DataSource };\nexport { evaluate } from './evaluate';\n\nlet defaultFlagsClient: FlagsClient | null = null;\n\n// TODO this should possibly be a generic parser for the URL, which\n// can be used with sources other than Edge Config at some point\nexport function parseFlagsConnectionString(\n connectionString: string,\n): ConnectionOptions {\n const errorMessage = 'flags: Invalid connection string';\n\n try {\n const params = new URLSearchParams(connectionString.slice(6));\n const edgeConfigId = params.get('edgeConfigId');\n const edgeConfigToken = params.get('edgeConfigToken');\n const projectId = params.get('projectId');\n if (!edgeConfigId || !edgeConfigToken || !projectId) {\n throw new Error(errorMessage);\n }\n\n return {\n edgeConfigId,\n edgeConfigToken,\n projectId,\n edgeConfigItemKey: params.get('edgeConfigItemKey'),\n env: params.get('env'),\n };\n } catch {\n throw new Error(errorMessage);\n }\n}\n\n/**\n * Internal function for testing purposes\n */\nexport function resetDefaultFlagsClient() {\n defaultFlagsClient = null;\n}\n\nexport function createClientFromConnectionString(connectionString: string) {\n if (!connectionString) {\n throw new Error('flags: Missing connection string');\n }\n\n const connectionOptions = parseFlagsConnectionString(connectionString);\n const edgeConfigItemKey = connectionOptions.edgeConfigItemKey || 'flags';\n\n if (!connectionOptions.edgeConfigId || !connectionOptions.edgeConfigToken) {\n throw new Error('flags: Missing edge config connection information');\n }\n\n // TODO use latest connection string format\n // const edgeConfigConnectionString = `edge-config:id=${connectionOptions.edgeConfigId}&token=${connectionOptions.edgeConfigToken}`;\n const edgeConfigConnectionString = `https://edge-config.vercel.com/${connectionOptions.edgeConfigId}?token=${connectionOptions.edgeConfigToken}`;\n\n const edgeConfigClient = createEdgeConfigClient(edgeConfigConnectionString);\n\n const dataSource = new EdgeConfigDataSource({\n edgeConfigClient,\n edgeConfigItemKey,\n projectId: connectionOptions.projectId,\n });\n\n const environment = getFlagsEnvironment(connectionOptions.env);\n return createClient({ dataSource, environment });\n}\n\n/**\n * This function is for internal use only.\n *\n * Produces a default flags client reading from a default edge config.\n *\n * - relies on process.env.FLAGS\n * - does not use process.env.EDGE_CONFIG\n *\n * @param connectionString - usually from process.env.FLAGS\n * @returns - a flags client\n */\nexport function getDefaultFlagsClient() {\n if (defaultFlagsClient) return defaultFlagsClient;\n\n if (!process.env.FLAGS) {\n throw new Error('flags: Missing environment variable FLAGS');\n }\n\n defaultFlagsClient = createClientFromConnectionString(process.env.FLAGS);\n return defaultFlagsClient;\n}\n\n/**\n * Resolve the Flags environment. If connectionOptionsEnv is provided, use it as-is.\n *\n * Fall back to VERCEL_ENV if it is a known Vercel environment (production, preview, development)\n * If VERCEL_ENV is unset, it will resolve 'development' (Vercel provides it in preview and production)\n * If VERCEL_ENV is not one of the known values, it will resolve 'preview'\n */\nexport function getFlagsEnvironment(connectionOptionsEnv: string | null) {\n if (connectionOptionsEnv) {\n return connectionOptionsEnv;\n }\n const vercelEnv = process.env.VERCEL_ENV;\n if (!vercelEnv || vercelEnv === 'development') {\n return 'development';\n }\n if (vercelEnv === 'production') {\n return 'production';\n }\n return 'preview';\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} from './types';\nimport { exhaustivenessCheck } from './utils';\n\ntype PathArray = (string | number)[];\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 matchTargetList<T>(\n targets: Packed.TargetList,\n params: EvaluationParams<T>,\n): boolean {\n for (const [kind, attributes] of Object.entries(targets)) {\n for (const [attribute, values] of Object.entries(attributes)) {\n const entity = access([kind, attribute], params);\n if (isString(entity) && values.includes(entity)) 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, rhs] = condition;\n\n if (lhsAccessor === Packed.AccessorType.SEGMENT) {\n return rhs && matchSegmentCondition(cmpKey, rhs, params);\n }\n\n const lhs = access(lhsAccessor, params);\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.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 typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return new RegExp(rhs.pattern, rhs.flags).test(lhs);\n }\n return false;\n\n case Comparator.NOT_REGEX:\n if (\n isString(lhs) &&\n typeof rhs === 'object' &&\n !Array.isArray(rhs) &&\n rhs?.type === 'regex'\n ) {\n return !new RegExp(rhs.pattern, rhs.flags).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 const maxValue = 100_000;\n\n // bypass hashing for common values and edges\n if (outcome.passPromille <= 0) return false;\n if (outcome.passPromille >= maxValue) return true;\n\n const value = hashInput(lhs, params.definition.seed) % maxValue;\n return value < outcome.passPromille;\n }\n default: {\n const { type } = outcome;\n exhaustivenessCheck(type);\n }\n }\n}\n\nfunction handleOutcome<T>(\n params: EvaluationParams<T>,\n outcome: Packed.Outcome,\n): {\n value: T;\n outcomeType: OutcomeType;\n} {\n if (typeof outcome === 'number') {\n return {\n value: params.definition.variants[outcome] as T,\n outcomeType: OutcomeType.VALUE,\n };\n }\n switch (outcome.type) {\n case 'split': {\n const lhs = access(outcome.base, params);\n const defaultOutcome = params.definition.variants[outcome.defaultVariant];\n\n // serve the default variant if the lhs is not a string\n if (typeof lhs !== 'string') {\n return { value: defaultOutcome as T, outcomeType: OutcomeType.SPLIT };\n }\n\n /** 2^32-1 */\n const maxValue = 4_294_967_295;\n /**\n * (xxHash32): turns the string into a number between 0 and 2^32-1 (max uint32 value)\n * Since we know the range of the hash function, we don't use modulo here. If we change\n * the hash function, or if the range changes, we should add a modulo here and/or adjust maxValue.\n */\n const value = hashInput(lhs, params.definition.seed);\n const sumOfWeights = sum(outcome.weights);\n const scaledWeights = outcome.weights.map(\n (weight) => (weight / sumOfWeights) * maxValue,\n );\n const variantIndex = findWeightedIndex(scaledWeights, value, maxValue);\n return {\n value:\n variantIndex === -1\n ? (defaultOutcome as T)\n : (params.definition.variants[variantIndex] as T),\n outcomeType: OutcomeType.SPLIT,\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): 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 {\n ...handleOutcome<T>(params, envConfig),\n reason: ResolutionReason.PAUSED,\n };\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 };\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 return evaluate<T>({ ...params, environment: envConfig.reuse });\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 {\n ...handleOutcome<T>(params, matchedIndex),\n reason: ResolutionReason.TARGET_MATCH,\n };\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 {\n ...handleOutcome<T>(params, firstMatchingRule.outcome),\n reason: ResolutionReason.RULE_MATCH,\n };\n }\n\n return {\n ...handleOutcome<T>(params, envConfig.fallthrough),\n reason: ResolutionReason.FALLTHROUGH,\n };\n}\n\n/**\n * Find the weighted index that the given value falls into.\n *\n * Takes a set of weights that add up to maxValue, and returns the index\n * that corresponds to the given value.\n *\n * @returns index or -1\n */\nexport function findWeightedIndex(\n weights: number[],\n value: number,\n maxValue: number,\n): number {\n if (value < 0 || value >= maxValue) return -1;\n\n let sum = 0;\n for (let i = 0; i < weights.length; i++) {\n sum += weights[i] as number;\n if (value < sum) return i;\n }\n\n return -1;\n}\n","export interface ConnectionOptions {\n edgeConfigId: string;\n edgeConfigToken: string;\n edgeConfigItemKey: string | null;\n env: string | null;\n projectId: string;\n}\n\n// -----------------------------------------------------------------------------\n// Shared data\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 `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 * Indicates why the flag evaluated to a certain value\n */\n reason: Exclude<ResolutionReason, ResolutionReason.ERROR>;\n errorMessage?: never;\n errorCode?: never;\n }\n | {\n reason: ResolutionReason.ERROR;\n errorMessage: string;\n errorCode?: ErrorCode;\n /**\n * In cases of errors this is the he defaultValue if one was provided\n */\n value?: T;\n };\n\nexport type FlagKey = string;\nexport type VariantId = string;\nexport type EnvironmentKey = string;\nexport type SegmentId = string;\nexport type Value = string | number | boolean;\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}\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 * - deos 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 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 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 };\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 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;\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 Condition =\n | [LHS, Comparator, RHS]\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 * This function is used to check for exhaustiveness in switch statements.\n *\n * @param _ - The value to check.\n *\n * @example\n * Given `type Union = 'a' | 'b' | 'c'`, the following code will not compile:\n * ```ts\n * switch (union) {\n * case 'a':\n * return 'a';\n * case 'b':\n * return 'b';\n * default:\n * exhaustivenessCheck(union); // This will throw an error\n * }\n * ```\n * This is because `value` has been narrowed to `'c'` by the `default` arm,\n * which is not assignable to `never`. If we covered the `'c'` case, the type\n * would narrow to `never`, which is assignable to `never` and would not cause an error.\n */\nexport function exhaustivenessCheck(_: never): never {\n throw new Error('Exhaustiveness check failed');\n}\n","{\n \"name\": \"@vercel/flags-core\",\n \"version\": \"0.1.8\",\n \"description\": \"\",\n \"keywords\": [],\n \"license\": \"MIT\",\n \"author\": \"\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openfeature\": {\n \"import\": \"./dist/openfeature.js\",\n \"require\": \"./dist/openfeature.cjs\"\n }\n },\n \"main\": \"./dist/index.js\",\n \"typesVersions\": {\n \"*\": {\n \".\": [\n \"dist/*.d.ts\",\n \"dist/*.d.cts\"\n ],\n \"./openfeature\": [\n \"dist/openfeature.d.ts\",\n \"dist/openfeature.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 \"jose\": \"5.2.1\",\n \"js-xxhash\": \"4.0.0\",\n \"@vercel/edge-config\": \"^1.4.3\"\n },\n \"devDependencies\": {\n \"@types/node\": \"20.11.17\",\n \"flags\": \"workspace:*\",\n \"msw\": \"2.6.4\",\n \"tsup\": \"8.0.1\",\n \"typescript\": \"5.6.3\",\n \"vite\": \"6.0.3\",\n \"vitest\": \"2.1.8\"\n },\n \"peerDependencies\": {\n \"flags\": \"*\",\n \"@openfeature/server-sdk\": \"1.18.0\"\n },\n \"peerDependenciesMeta\": {\n \"@openfeature/server-sdk\": {\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 interally 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 ctx?.flags?.reportValue(key, value, {\n sdkVersion: version,\n ...data,\n });\n}\n","// TODO should we store the context schema (entities schema) in Edge Config and validate context?\n// TODO should we make evaluate return the variant ids as well?\nimport type { DataSource } from './data-source/interface';\nimport { evaluate } from './evaluate';\nimport { internalReportValue } from './lib/report-value';\nimport {\n ErrorCode,\n type EvaluationResult,\n type Packed,\n ResolutionReason,\n type Value,\n} from './types';\n\nexport type Source = {\n orgId: string;\n orgSlug: string;\n projectId: string;\n projectSlug: string;\n};\n\nexport type FlagsClient = {\n environment: string;\n dataSource: DataSource;\n evaluate: <T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ) => Promise<EvaluationResult<T>>;\n initialize(): void | Promise<void>;\n shutdown(): void | Promise<void>;\n};\n\n/**\n * Creates a Vercel Flags client\n *\n * @example\n * const edgeConfigClient = createClient('');\n * const flagsClient = createClient({\n * dataSource: new EdgeConfigDataSource({\n * edgeConfigItemKey: 'flags',\n * edgeConfigClient,\n * }),\n * environment: 'production',\n * });\n */\nexport function createClient({\n environment,\n dataSource,\n}: {\n environment: string;\n dataSource: DataSource;\n}): FlagsClient {\n return {\n dataSource,\n environment,\n initialize: () => {\n if (dataSource && typeof dataSource.initialize === 'function') {\n return dataSource.initialize();\n }\n },\n shutdown: () => {\n if (dataSource && typeof dataSource.shutdown === 'function') {\n return dataSource.shutdown();\n }\n },\n async evaluate<T = Value, E = Record<string, unknown>>(\n flagKey: string,\n defaultValue?: T,\n entities?: E,\n ): Promise<EvaluationResult<T>> {\n // TODO dataSource.getData should move into \"initialize\" and set up the subscription.\n //\n // From OpenFeature: \"It's recommended to provide non-blocking mechanisms for flag\n // evaluation, particularly in languages or environments wherein there's a\n // single thread of execution.\n const data = await dataSource.getData();\n\n const flagDefinition = data.definitions[flagKey] as Packed.FlagDefinition;\n\n if (flagDefinition === undefined) {\n return {\n value: defaultValue,\n reason: ResolutionReason.ERROR,\n errorCode: ErrorCode.FLAG_NOT_FOUND,\n errorMessage: `Definition not found for flag \"${flagKey}\"`,\n };\n }\n\n const result = evaluate<T>({\n defaultValue,\n definition: flagDefinition,\n environment: this.environment,\n entities: entities ?? {},\n segments: data.segments,\n });\n\n if (dataSource.projectId) {\n internalReportValue(flagKey, result.value, {\n originProjectId: dataSource.projectId,\n originProvider: 'vercel',\n reason: result.reason,\n outcomeType:\n result.reason !== ResolutionReason.ERROR\n ? result.outcomeType\n : undefined,\n });\n }\n\n return result;\n },\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * A store to avoid reading the Edge Config for every flag evaluation,\n * and instead reading it once per request.\n */\nexport const store = new AsyncLocalStorage<WeakKey>();\n","import type { EdgeConfigClient } from '@vercel/edge-config';\nimport { store } from '../store';\nimport type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\n/**\n * Implements the DataSource interface for Edge Config.\n */\nexport class EdgeConfigDataSource implements DataSource {\n connectionString?: string;\n edgeConfigClient: EdgeConfigClient;\n edgeConfigItemKey: string;\n requestCache: WeakMap<WeakKey, Promise<Packed.Data | undefined>>;\n projectId?: string;\n\n constructor(options: {\n edgeConfigItemKey: string;\n edgeConfigClient: EdgeConfigClient;\n projectId?: string;\n }) {\n this.edgeConfigClient = options.edgeConfigClient;\n this.edgeConfigItemKey = options.edgeConfigItemKey;\n this.requestCache = new WeakMap();\n this.projectId = options.projectId;\n }\n\n // This is a temporary solution to avoid reading the Edge Config for every flag,\n // and instead reading it once per request.\n private async getCachedData() {\n const cacheKey = store.getStore();\n if (cacheKey) {\n const cached = this.requestCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n const promise = this.edgeConfigClient.get<Packed.Data>(\n this.edgeConfigItemKey,\n );\n\n if (cacheKey) this.requestCache.set(cacheKey, promise);\n\n return promise;\n }\n\n async getData() {\n const data = await this.getCachedData();\n\n if (!data) {\n throw new Error(\n `No definitions found in Edge Config under key \"${this.edgeConfigItemKey}\"`,\n );\n }\n\n return data;\n }\n}\n","import type { Packed } from '../types';\nimport type { DataSource } from './interface';\n\nexport class InMemoryDataSource implements DataSource {\n private data: Packed.Data;\n public projectId?: string;\n\n constructor(data: Packed.Data, projectId?: string) {\n this.data = data;\n this.projectId = projectId;\n }\n\n async getData() {\n return this.data;\n }\n}\n"]}
|
|
@@ -351,8 +351,6 @@ declare namespace Packed {
|
|
|
351
351
|
exclude?: TargetList;
|
|
352
352
|
};
|
|
353
353
|
type FlagDefinition = {
|
|
354
|
-
/** for backwards compatibility with HappyKit */
|
|
355
|
-
happykitFlagId?: string;
|
|
356
354
|
/** for backwards compatibility with HappyKit */
|
|
357
355
|
variantIds?: string[];
|
|
358
356
|
/** variants, packed down to just their values */
|
|
@@ -351,8 +351,6 @@ declare namespace Packed {
|
|
|
351
351
|
exclude?: TargetList;
|
|
352
352
|
};
|
|
353
353
|
type FlagDefinition = {
|
|
354
|
-
/** for backwards compatibility with HappyKit */
|
|
355
|
-
happykitFlagId?: string;
|
|
356
354
|
/** for backwards compatibility with HappyKit */
|
|
357
355
|
variantIds?: string[];
|
|
358
356
|
/** variants, packed down to just their values */
|
package/dist/index.cjs
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _chunk6ZAELH3Kcjs = require('./chunk-6ZAELH3K.cjs');
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
@@ -23,5 +23,5 @@ var _chunkOWBLBSGOcjs = require('./chunk-OWBLBSGO.cjs');
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
exports.EdgeConfigDataSource =
|
|
26
|
+
exports.EdgeConfigDataSource = _chunk6ZAELH3Kcjs.EdgeConfigDataSource; exports.InMemoryDataSource = _chunk6ZAELH3Kcjs.InMemoryDataSource; exports.Reason = _chunk6ZAELH3Kcjs.ResolutionReason; exports.createClient = _chunk6ZAELH3Kcjs.createClient; exports.createClientFromConnectionString = _chunk6ZAELH3Kcjs.createClientFromConnectionString; exports.evaluate = _chunk6ZAELH3Kcjs.evaluate; exports.getDefaultFlagsClient = _chunk6ZAELH3Kcjs.getDefaultFlagsClient; exports.getFlagsEnvironment = _chunk6ZAELH3Kcjs.getFlagsEnvironment; exports.parseFlagsConnectionString = _chunk6ZAELH3Kcjs.parseFlagsConnectionString; exports.resetDefaultFlagsClient = _chunk6ZAELH3Kcjs.resetDefaultFlagsClient; exports.store = _chunk6ZAELH3Kcjs.store;
|
|
27
27
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DataSource, P as Packed, E as EvaluationParams, a as EvaluationResult, C as ConnectionOptions, F as FlagsClient } from './client-
|
|
2
|
-
export { R as Reason, c as createClient } from './client-
|
|
1
|
+
import { D as DataSource, P as Packed, E as EvaluationParams, a as EvaluationResult, C as ConnectionOptions, F as FlagsClient } from './client-BxFTPk0J.cjs';
|
|
2
|
+
export { R as Reason, c as createClient } from './client-BxFTPk0J.cjs';
|
|
3
3
|
import { EdgeConfigClient } from '@vercel/edge-config';
|
|
4
4
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as DataSource, P as Packed, E as EvaluationParams, a as EvaluationResult, C as ConnectionOptions, F as FlagsClient } from './client-
|
|
2
|
-
export { R as Reason, c as createClient } from './client-
|
|
1
|
+
import { D as DataSource, P as Packed, E as EvaluationParams, a as EvaluationResult, C as ConnectionOptions, F as FlagsClient } from './client-BxFTPk0J.js';
|
|
2
|
+
export { R as Reason, c as createClient } from './client-BxFTPk0J.js';
|
|
3
3
|
import { EdgeConfigClient } from '@vercel/edge-config';
|
|
4
4
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
5
5
|
|
package/dist/index.js
CHANGED
package/dist/openfeature.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); var _class;
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk6ZAELH3Kcjs = require('./chunk-6ZAELH3K.cjs');
|
|
4
4
|
|
|
5
5
|
// src/openfeature.ts
|
|
6
6
|
|
|
@@ -30,7 +30,7 @@ var VercelProvider = (_class = class {
|
|
|
30
30
|
|
|
31
31
|
constructor(clientOrConnectionString) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);
|
|
32
32
|
if (typeof clientOrConnectionString === "string") {
|
|
33
|
-
this.client =
|
|
33
|
+
this.client = _chunk6ZAELH3Kcjs.createClientFromConnectionString.call(void 0, clientOrConnectionString);
|
|
34
34
|
} else {
|
|
35
35
|
this.client = clientOrConnectionString;
|
|
36
36
|
}
|
package/dist/openfeature.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Provider, ProviderMetadata, EvaluationContext, ResolutionDetails, JsonValue } from '@openfeature/server-sdk';
|
|
2
|
-
import { F as FlagsClient } from './client-
|
|
2
|
+
import { F as FlagsClient } from './client-BxFTPk0J.cjs';
|
|
3
3
|
|
|
4
4
|
declare class VercelProvider implements Provider {
|
|
5
5
|
readonly metadata: ProviderMetadata;
|
package/dist/openfeature.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Provider, ProviderMetadata, EvaluationContext, ResolutionDetails, JsonValue } from '@openfeature/server-sdk';
|
|
2
|
-
import { F as FlagsClient } from './client-
|
|
2
|
+
import { F as FlagsClient } from './client-BxFTPk0J.js';
|
|
3
3
|
|
|
4
4
|
declare class VercelProvider implements Provider {
|
|
5
5
|
readonly metadata: ProviderMetadata;
|
package/dist/openfeature.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/flags-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"jose": "5.2.1",
|
|
39
|
-
"js-xxhash": "4.0.0"
|
|
39
|
+
"js-xxhash": "4.0.0",
|
|
40
|
+
"@vercel/edge-config": "^1.4.3"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@types/node": "20.11.17",
|
|
43
|
-
"@vercel/edge-config": "^1.4.3",
|
|
44
44
|
"msw": "2.6.4",
|
|
45
45
|
"tsup": "8.0.1",
|
|
46
46
|
"typescript": "5.6.3",
|
|
@@ -49,16 +49,12 @@
|
|
|
49
49
|
"flags": "4.0.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@vercel/edge-config": "^1.2.0",
|
|
53
52
|
"flags": "*",
|
|
54
53
|
"@openfeature/server-sdk": "1.18.0"
|
|
55
54
|
},
|
|
56
55
|
"peerDependenciesMeta": {
|
|
57
56
|
"@openfeature/server-sdk": {
|
|
58
57
|
"optional": true
|
|
59
|
-
},
|
|
60
|
-
"@vercel/edge-config": {
|
|
61
|
-
"optional": true
|
|
62
58
|
}
|
|
63
59
|
},
|
|
64
60
|
"publishConfig": {
|