@envflags/js-sdk 0.1.0 → 0.1.1
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/dist/shared.js +11 -7
- package/dist/shared.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/dist/shared.js
CHANGED
|
@@ -83,6 +83,15 @@ function matchesStrings(attribute, values, predicate) {
|
|
|
83
83
|
if (typeof attribute !== "string") return false;
|
|
84
84
|
return values.some((value) => typeof value === "string" && predicate(attribute, value));
|
|
85
85
|
}
|
|
86
|
+
function matchesRegex(attribute, values, flags = "") {
|
|
87
|
+
return matchesStrings(attribute, values, (left, right) => {
|
|
88
|
+
try {
|
|
89
|
+
return new RegExp(right, flags).test(left);
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
86
95
|
function matchesNumbers(attribute, values, predicate) {
|
|
87
96
|
if (typeof attribute !== "number" || !Number.isFinite(attribute)) return false;
|
|
88
97
|
return values.some((value) => typeof value === "number" && Number.isFinite(value) && predicate(attribute, value));
|
|
@@ -128,13 +137,8 @@ function matchesClause(clause, context, payload, visiting) {
|
|
|
128
137
|
case "startsWith": return matchesStrings(attribute, clause.values, (left, right) => left.startsWith(right));
|
|
129
138
|
case "endsWith": return matchesStrings(attribute, clause.values, (left, right) => left.endsWith(right));
|
|
130
139
|
case "contains": return matchesStrings(attribute, clause.values, (left, right) => left.includes(right));
|
|
131
|
-
case "matches": return
|
|
132
|
-
|
|
133
|
-
return new RegExp(right).test(left);
|
|
134
|
-
} catch {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
140
|
+
case "matches": return matchesRegex(attribute, clause.values);
|
|
141
|
+
case "matchesIgnoreCase": return matchesRegex(attribute, clause.values, "i");
|
|
138
142
|
case "lessThan": return matchesNumbers(attribute, clause.values, (left, right) => left < right);
|
|
139
143
|
case "greaterThan": return matchesNumbers(attribute, clause.values, (left, right) => left > right);
|
|
140
144
|
case "before": return matchesDates(attribute, clause.values, (left, right) => left < right);
|
package/dist/shared.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","names":["#baseUrl","#fetch","#onError","#pollIntervalMs","#sdkKey","#payload","#revision","#subscribers","#startPolling","#refreshPromise","#performRefresh","#timer","#context","#etag","#prepared","#cacheRevision","#validationCache"],"sources":["../src/sha1.ts","../src/evaluate.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["function rotateLeft(value: number, bits: number) {\n return ((value << bits) | (value >>> (32 - bits))) >>> 0\n}\n\nfunction add(...values: number[]) {\n return values.reduce((sum, value) => (sum + value) >>> 0, 0)\n}\n\n/** A small synchronous SHA-1 implementation so flag evaluation stays sync. */\nexport function sha1(value: string) {\n const input = new TextEncoder().encode(value)\n const paddedLength = Math.ceil((input.length + 9) / 64) * 64\n const bytes = new Uint8Array(paddedLength)\n bytes.set(input)\n bytes[input.length] = 0x80\n\n const bitLength = BigInt(input.length) * 8n\n const view = new DataView(bytes.buffer)\n view.setUint32(paddedLength - 8, Number(bitLength >> 32n), false)\n view.setUint32(paddedLength - 4, Number(bitLength & 0xffffffffn), false)\n\n let h0 = 0x67452301\n let h1 = 0xefcdab89\n let h2 = 0x98badcfe\n let h3 = 0x10325476\n let h4 = 0xc3d2e1f0\n const words = new Uint32Array(80)\n\n for (let offset = 0; offset < paddedLength; offset += 64) {\n for (let index = 0; index < 16; index += 1) {\n words[index] = view.getUint32(offset + index * 4, false)\n }\n for (let index = 16; index < 80; index += 1) {\n words[index] = rotateLeft(\n words[index - 3]! ^\n words[index - 8]! ^\n words[index - 14]! ^\n words[index - 16]!,\n 1,\n )\n }\n\n let a = h0\n let b = h1\n let c = h2\n let d = h3\n let e = h4\n\n for (let index = 0; index < 80; index += 1) {\n let f: number\n let k: number\n\n if (index < 20) {\n f = (b & c) | (~b & d)\n k = 0x5a827999\n } else if (index < 40) {\n f = b ^ c ^ d\n k = 0x6ed9eba1\n } else if (index < 60) {\n f = (b & c) | (b & d) | (c & d)\n k = 0x8f1bbcdc\n } else {\n f = b ^ c ^ d\n k = 0xca62c1d6\n }\n\n const temporary = add(rotateLeft(a, 5), f, e, k, words[index]!)\n e = d\n d = c\n c = rotateLeft(b, 30)\n b = a\n a = temporary\n }\n\n h0 = add(h0, a)\n h1 = add(h1, b)\n h2 = add(h2, c)\n h3 = add(h3, d)\n h4 = add(h4, e)\n }\n\n return [h0, h1, h2, h3, h4]\n .map(word => word.toString(16).padStart(8, '0'))\n .join('')\n}\n","import { sha1 } from './sha1'\nimport type {\n Clause,\n EvaluationContext,\n EvaluationPayload,\n JsonValue,\n Segment,\n VariationSelector,\n} from './types'\n\nconst BUCKET_DENOMINATOR = Number(0x0fff_ffff_ffff_ffffn)\n\nfunction hasAttribute(context: EvaluationContext, attribute: string) {\n return Object.prototype.hasOwnProperty.call(context, attribute)\n}\n\nfunction scalarEquals(left: unknown, right: JsonValue) {\n return (\n (left === null ||\n typeof left === 'boolean' ||\n typeof left === 'number' ||\n typeof left === 'string') &&\n left === right\n )\n}\n\nfunction matchesIn(attribute: unknown, values: JsonValue[]) {\n const attributes = Array.isArray(attribute) ? attribute : [attribute]\n return attributes.some(item =>\n values.some(value => scalarEquals(item, value)),\n )\n}\n\nfunction matchesStrings(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: string, value: string) => boolean,\n) {\n if (typeof attribute !== 'string') return false\n return values.some(\n value => typeof value === 'string' && predicate(attribute, value),\n )\n}\n\nfunction matchesNumbers(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: number, value: number) => boolean,\n) {\n if (typeof attribute !== 'number' || !Number.isFinite(attribute)) return false\n return values.some(\n value =>\n typeof value === 'number' &&\n Number.isFinite(value) &&\n predicate(attribute, value),\n )\n}\n\nfunction instant(value: unknown) {\n if (typeof value === 'number')\n return Number.isFinite(value) ? value : undefined\n if (\n typeof value !== 'string' ||\n !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(\n value,\n )\n ) {\n return undefined\n }\n\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction matchesDates(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: number, value: number) => boolean,\n) {\n const attributeInstant = instant(attribute)\n if (attributeInstant === undefined) return false\n\n return values.some(value => {\n const valueInstant = instant(value)\n return (\n valueInstant !== undefined && predicate(attributeInstant, valueInstant)\n )\n })\n}\n\nfunction matchesSegment(\n segment: Segment,\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n) {\n const key = context.key\n if (typeof key === 'string' && key.length > 0) {\n if (segment.excluded?.includes(key)) return false\n if (segment.included?.includes(key)) return true\n }\n\n return (segment.rules ?? []).some(rule =>\n rule.clauses.every(clause =>\n matchesClause(clause, context, payload, visiting),\n ),\n )\n}\n\nfunction matchesSegments(\n values: JsonValue[],\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n) {\n return values.some(value => {\n if (typeof value !== 'string' || visiting.has(value)) return false\n const segment = payload.segments[value]\n if (!segment) return false\n\n const nestedVisiting = new Set(visiting)\n nestedVisiting.add(value)\n return matchesSegment(segment, context, payload, nestedVisiting)\n })\n}\n\nfunction matchesClause(\n clause: Clause,\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n): boolean {\n if (!hasAttribute(context, clause.attribute)) return false\n const attribute = context[clause.attribute]\n\n switch (clause.op) {\n case 'in':\n return matchesIn(attribute, clause.values)\n case 'notIn':\n return !matchesIn(attribute, clause.values)\n case 'startsWith':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.startsWith(right),\n )\n case 'endsWith':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.endsWith(right),\n )\n case 'contains':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.includes(right),\n )\n case 'matches':\n return matchesStrings(attribute, clause.values, (left, right) => {\n try {\n return new RegExp(right).test(left)\n } catch {\n return false\n }\n })\n case 'lessThan':\n return matchesNumbers(\n attribute,\n clause.values,\n (left, right) => left < right,\n )\n case 'greaterThan':\n return matchesNumbers(\n attribute,\n clause.values,\n (left, right) => left > right,\n )\n case 'before':\n return matchesDates(\n attribute,\n clause.values,\n (left, right) => left < right,\n )\n case 'after':\n return matchesDates(\n attribute,\n clause.values,\n (left, right) => left > right,\n )\n case 'segmentMatch':\n return matchesSegments(clause.values, context, payload, visiting)\n }\n}\n\nexport function bucket(flagKey: string, salt: string, bucketBy: string) {\n const digest = sha1(`${flagKey}.${salt}.${bucketBy}`)\n const integer = BigInt(`0x${digest.slice(0, 15)}`)\n return Number(integer) / BUCKET_DENOMINATOR\n}\n\nfunction selectVariation(\n selector: VariationSelector,\n flagKey: string,\n context: EvaluationContext,\n payload: EvaluationPayload,\n) {\n if ('variation' in selector && selector.variation !== undefined) {\n return selector.variation\n }\n\n const rollout = selector.rollout\n if (!rollout?.length) return undefined\n\n const bucketAttribute = selector.bucketBy ?? 'key'\n if (!hasAttribute(context, bucketAttribute)) {\n return rollout.at(-1)?.variation\n }\n\n const bucketBy = String(context[bucketAttribute])\n const contextBucket = bucket(flagKey, payload.salt, bucketBy)\n let accumulatedWeight = 0\n\n for (const entry of rollout) {\n accumulatedWeight += entry.weight / 100_000\n if (contextBucket < accumulatedWeight) return entry.variation\n }\n\n return rollout.at(-1)?.variation\n}\n\nexport function evaluate<T extends JsonValue>(\n payload: EvaluationPayload,\n flagKey: string,\n context: EvaluationContext | undefined,\n defaultValue: T,\n): JsonValue {\n const flag = payload.flags[flagKey]\n if (!flag) return defaultValue\n\n const resolved = context ?? {}\n const key = resolved.key\n\n let variation: number | undefined\n\n if (!flag.on) {\n variation = flag.offVariation\n } else {\n variation = flag.targets.find(\n target =>\n typeof key === 'string' &&\n key.length > 0 &&\n target.values.includes(key),\n )?.variation\n\n if (variation === undefined) {\n const rule = flag.rules.find(candidate =>\n candidate.clauses.every(clause =>\n matchesClause(clause, resolved, payload, new Set()),\n ),\n )\n if (rule) variation = selectVariation(rule, flagKey, resolved, payload)\n }\n\n variation ??= selectVariation(flag.fallthrough, flagKey, resolved, payload)\n }\n\n return variation === undefined || !(variation in flag.variations)\n ? defaultValue\n : flag.variations[variation]!\n}\n","import { evaluate } from './evaluate'\nimport type { EvaluationContext, EvaluationPayload, JsonValue } from './types'\n\nconst DEFAULT_BASE_URL = 'https://envflags.com'\nconst DEFAULT_POLL_INTERVAL_MS = 30_000\n\ntype Fetch = typeof globalThis.fetch\n\nexport type EnvflagsClientOptions = {\n baseUrl?: string\n bootstrap?: EvaluationPayload\n fetch?: Fetch\n onError?: (error: Error) => void\n pollIntervalMs?: number | false\n}\n\ntype PollResponse = {\n envId: string\n version: number\n etag: string\n payloadUrl: string\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parsePollResponse(value: unknown): PollResponse {\n if (\n !isRecord(value) ||\n typeof value.envId !== 'string' ||\n !Number.isSafeInteger(value.version) ||\n (value.version as number) < 0 ||\n typeof value.etag !== 'string' ||\n typeof value.payloadUrl !== 'string'\n ) {\n throw new Error('The envflags poll response is invalid')\n }\n\n return value as PollResponse\n}\n\nfunction parsePayload(value: unknown): EvaluationPayload {\n if (\n !isRecord(value) ||\n typeof value.envId !== 'string' ||\n !Number.isSafeInteger(value.version) ||\n (value.version as number) < 0 ||\n typeof value.salt !== 'string' ||\n !isRecord(value.flags) ||\n !isRecord(value.segments)\n ) {\n throw new Error('The envflags payload is invalid')\n }\n\n return value as EvaluationPayload\n}\n\nfunction responseError(action: string, response: Response) {\n return new Error(\n `Unable to ${action}: envflags returned ${response.status} ${response.statusText}`,\n )\n}\n\nexport class EnvflagsClient {\n readonly #baseUrl: URL\n readonly #fetch: Fetch\n readonly #onError: (error: Error) => void\n readonly #pollIntervalMs: number | false\n readonly #sdkKey: string\n #context?: EvaluationContext\n #etag?: string\n #payload?: EvaluationPayload\n #revision = 0\n #refreshPromise?: Promise<boolean>\n #subscribers = new Set<() => void>()\n #timer?: ReturnType<typeof setInterval>\n\n constructor(sdkKey: string, options: EnvflagsClientOptions = {}) {\n const normalizedSdkKey = sdkKey.trim()\n if (!normalizedSdkKey) throw new Error('An envflags SDK key is required')\n if (\n options.pollIntervalMs !== undefined &&\n options.pollIntervalMs !== false &&\n (!Number.isFinite(options.pollIntervalMs) || options.pollIntervalMs < 0)\n ) {\n throw new Error('pollIntervalMs must be a non-negative finite number')\n }\n\n this.#sdkKey = normalizedSdkKey\n this.#baseUrl = new URL(options.baseUrl ?? DEFAULT_BASE_URL)\n this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis)\n this.#onError = options.onError ?? (() => undefined)\n this.#pollIntervalMs =\n options.pollIntervalMs === undefined\n ? DEFAULT_POLL_INTERVAL_MS\n : options.pollIntervalMs\n if (options.bootstrap) {\n this.#payload = parsePayload(options.bootstrap)\n this.#revision = 1\n }\n }\n\n get initialized() {\n return this.#payload !== undefined\n }\n\n get version() {\n return this.#payload?.version\n }\n\n /** Subscribe to payload changes. Intended for UI framework bindings. */\n subscribe = (listener: () => void) => {\n this.#subscribers.add(listener)\n return () => {\n this.#subscribers.delete(listener)\n }\n }\n\n /** Return a stable value suitable for React's useSyncExternalStore. */\n getSnapshot = () => this.#revision\n\n protected reportError(error: Error) {\n this.#onError(error)\n }\n\n async initialize() {\n try {\n await this.refresh()\n } catch (cause) {\n const error =\n cause instanceof Error\n ? cause\n : new Error('Unable to initialize envflags')\n this.reportError(error)\n if (!this.#payload) throw error\n }\n\n this.#startPolling()\n return this\n }\n\n refresh() {\n if (!this.#refreshPromise) {\n this.#refreshPromise = this.#performRefresh().finally(() => {\n this.#refreshPromise = undefined\n })\n }\n\n return this.#refreshPromise\n }\n\n close() {\n if (this.#timer !== undefined) clearInterval(this.#timer)\n this.#timer = undefined\n }\n\n setContext(context: EvaluationContext) {\n this.#context = context\n return this\n }\n\n variation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context?: EvaluationContext,\n ): T {\n if (!this.#payload) return defaultValue\n return evaluate(\n this.#payload,\n flagKey,\n context ?? this.#context,\n defaultValue,\n ) as T\n }\n\n boolVariation(\n flagKey: string,\n defaultValue: boolean,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'boolean' ? value : defaultValue\n }\n\n stringVariation(\n flagKey: string,\n defaultValue: string,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'string' ? value : defaultValue\n }\n\n numberVariation(\n flagKey: string,\n defaultValue: number,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : defaultValue\n }\n\n jsonVariation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context?: EvaluationContext,\n ) {\n return this.variation(flagKey, defaultValue, context)\n }\n\n async #performRefresh() {\n const headers = new Headers({\n accept: 'application/json',\n authorization: `Bearer ${this.#sdkKey}`,\n })\n if (this.#etag) headers.set('if-none-match', this.#etag)\n\n const pollUrl = new URL('/sdk/poll', this.#baseUrl)\n const pollResponse = await this.#fetch(pollUrl, { headers })\n if (pollResponse.status === 304) return false\n if (!pollResponse.ok)\n throw responseError('poll for flag updates', pollResponse)\n\n const pointer = parsePollResponse(await pollResponse.json())\n if (\n this.#payload?.envId === pointer.envId &&\n this.#payload.version === pointer.version\n ) {\n this.#etag = pointer.etag\n return false\n }\n\n const payloadUrl = new URL(pointer.payloadUrl, this.#baseUrl)\n const payloadResponse = await this.#fetch(payloadUrl, {\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${this.#sdkKey}`,\n },\n })\n if (!payloadResponse.ok) {\n throw responseError('fetch the flag payload', payloadResponse)\n }\n\n const payload = parsePayload(await payloadResponse.json())\n if (\n payload.envId !== pointer.envId ||\n payload.version !== pointer.version\n ) {\n throw new Error('The envflags payload does not match its version pointer')\n }\n\n this.#payload = payload\n this.#etag = pointer.etag\n this.#revision += 1\n for (const subscriber of this.#subscribers) subscriber()\n return true\n }\n\n #startPolling() {\n if (\n this.#timer !== undefined ||\n this.#pollIntervalMs === false ||\n this.#pollIntervalMs <= 0\n ) {\n return\n }\n\n this.#timer = setInterval(() => {\n void this.refresh().catch(cause => {\n this.reportError(\n cause instanceof Error\n ? cause\n : new Error('Unable to refresh envflags'),\n )\n })\n }, this.#pollIntervalMs)\n }\n}\n\nexport function createClient(\n sdkKey: string,\n options: EnvflagsClientOptions = {},\n) {\n return new EnvflagsClient(sdkKey, options)\n}\n","import { EnvflagsClient, type EnvflagsClientOptions } from './client'\nimport type { EvaluationContext, JsonValue } from './types'\n\n/** The library-neutral Standard Schema v1 validation contract. */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n readonly '~standard': StandardSchemaProps<Input, Output>\n}\n\nexport interface StandardSchemaProps<Input = unknown, Output = Input> {\n readonly version: 1\n readonly vendor: string\n readonly validate: (\n value: unknown,\n options?: StandardSchemaOptions,\n ) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>\n readonly types?: StandardSchemaTypes<Input, Output>\n}\n\nexport interface StandardSchemaOptions {\n readonly libraryOptions?: Record<string, unknown>\n}\n\nexport interface StandardSchemaTypes<Input = unknown, Output = Input> {\n readonly input: Input\n readonly output: Output\n}\n\nexport type StandardSchemaIssue = {\n readonly message: string\n readonly path?: ReadonlyArray<PropertyKey | StandardSchemaPathSegment>\n}\n\nexport type StandardSchemaPathSegment = {\n readonly key: PropertyKey\n}\n\nexport type StandardSchemaResult<Output> =\n | { readonly value: Output; readonly issues?: undefined }\n | { readonly issues: ReadonlyArray<StandardSchemaIssue> }\n\nexport type StandardSchemaOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n>['output']\n\nexport type FlagDefinition<Schema extends StandardSchemaV1 = StandardSchemaV1> =\n {\n readonly schema: Schema\n readonly defaultValue: StandardSchemaOutput<Schema>\n }\n\nexport type FlagDefinitions = Record<string, FlagDefinition>\n\ntype FlagKey<Definitions extends FlagDefinitions> = Extract<\n keyof Definitions,\n string\n>\n\nexport type FlagValue<\n Definitions extends FlagDefinitions,\n Key extends FlagKey<Definitions>,\n> = StandardSchemaOutput<Definitions[Key]['schema']>\n\ntype ValidationResult =\n { ok: true; value: JsonValue } | { ok: false; message: string }\n\ntype PreparedDefinition = {\n schema: StandardSchemaV1<unknown, JsonValue>\n defaultValue: JsonValue\n}\n\nexport type PreparedFlagDefinitions<Definitions extends FlagDefinitions> = {\n readonly definitions: Readonly<\n Record<FlagKey<Definitions>, PreparedDefinition>\n >\n}\n\n/** Define one flag's runtime schema and offline/invalid-value fallback. */\nexport function flag<Schema extends StandardSchemaV1>(\n schema: Schema,\n defaultValue: StandardSchemaOutput<Schema>,\n): FlagDefinition<Schema> {\n return { schema, defaultValue }\n}\n\nfunction isPromise<T>(value: unknown): value is Promise<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n}\n\nfunction isJsonValue(\n value: unknown,\n ancestors = new Set<object>(),\n): value is JsonValue {\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'string'\n ) {\n return true\n }\n if (typeof value === 'number') return Number.isFinite(value)\n if (typeof value !== 'object') return false\n if (ancestors.has(value)) return false\n\n const nestedAncestors = new Set(ancestors)\n nestedAncestors.add(value)\n if (Array.isArray(value)) {\n return value.every(item => isJsonValue(item, nestedAncestors))\n }\n\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) return false\n return Object.values(value).every(item => isJsonValue(item, nestedAncestors))\n}\n\nfunction jsonEquals(left: JsonValue, right: JsonValue): boolean {\n if (left === right) return true\n if (Array.isArray(left) || Array.isArray(right)) {\n return (\n Array.isArray(left) &&\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((value, index) => jsonEquals(value, right[index]!))\n )\n }\n if (left === null || right === null) return false\n if (typeof left !== 'object' || typeof right !== 'object') return false\n\n const leftKeys = Object.keys(left)\n const rightKeys = Object.keys(right)\n return (\n leftKeys.length === rightKeys.length &&\n leftKeys.every(key => key in right && jsonEquals(left[key]!, right[key]!))\n )\n}\n\nfunction formatIssues(issues: ReadonlyArray<StandardSchemaIssue>) {\n return issues.map(issue => issue.message).join('; ') || 'validation failed'\n}\n\nfunction validate(\n flagKey: string,\n schema: StandardSchemaV1<unknown, JsonValue>,\n value: unknown,\n): ValidationResult {\n let result:\n StandardSchemaResult<JsonValue> | Promise<StandardSchemaResult<JsonValue>>\n try {\n result = schema['~standard'].validate(value)\n } catch (cause) {\n return {\n ok: false,\n message: cause instanceof Error ? cause.message : 'validation threw',\n }\n }\n\n if (isPromise(result)) {\n return {\n ok: false,\n message: `Flag \"${flagKey}\" uses an asynchronous schema; flag schemas must validate synchronously`,\n }\n }\n if (result.issues) {\n return { ok: false, message: formatIssues(result.issues) }\n }\n if (!isJsonValue(result.value)) {\n return {\n ok: false,\n message: `Flag \"${flagKey}\" schema produced a non-JSON value`,\n }\n }\n\n return { ok: true, value: result.value }\n}\n\nexport function prepareFlagDefinitions<Definitions extends FlagDefinitions>(\n definitions: Definitions,\n): PreparedFlagDefinitions<Definitions> {\n const prepared: Record<string, PreparedDefinition> = {}\n\n for (const [flagKey, definition] of Object.entries(definitions)) {\n const schema = definition.schema as StandardSchemaV1<unknown, JsonValue>\n if (schema?.['~standard']?.version !== 1) {\n throw new Error(`Flag \"${flagKey}\" must use a Standard Schema v1 schema`)\n }\n\n const result = validate(flagKey, schema, definition.defaultValue)\n if (!result.ok) {\n throw new Error(\n `Invalid default for flag \"${flagKey}\": ${result.message}`,\n )\n }\n\n const repeated = validate(flagKey, schema, result.value)\n if (!repeated.ok || !jsonEquals(result.value, repeated.value)) {\n throw new Error(\n `Invalid default for flag \"${flagKey}\": schema output must remain stable when validated again`,\n )\n }\n\n prepared[flagKey] = { schema, defaultValue: result.value }\n }\n\n return {\n definitions: Object.freeze(prepared) as Record<\n FlagKey<Definitions>,\n PreparedDefinition\n >,\n }\n}\n\nexport class DefinedEnvflagsClient<\n Definitions extends FlagDefinitions,\n> extends EnvflagsClient {\n readonly #prepared: PreparedFlagDefinitions<Definitions>\n #cacheRevision = -1\n #validationCache = new Map<string, Map<JsonValue, ValidationResult>>()\n\n constructor(\n sdkKey: string,\n options: EnvflagsClientOptions,\n prepared: PreparedFlagDefinitions<Definitions>,\n ) {\n super(sdkKey, options)\n this.#prepared = prepared\n }\n\n flag<Key extends FlagKey<Definitions>>(\n flagKey: Key,\n context?: EvaluationContext,\n ): FlagValue<Definitions, Key> {\n const definition = this.#prepared.definitions[flagKey]\n const candidate = this.variation(flagKey, definition.defaultValue, context)\n\n if (this.#cacheRevision !== this.getSnapshot()) {\n this.#cacheRevision = this.getSnapshot()\n this.#validationCache.clear()\n }\n\n let flagCache = this.#validationCache.get(flagKey)\n if (!flagCache) {\n flagCache = new Map()\n this.#validationCache.set(flagKey, flagCache)\n }\n\n let result = flagCache.get(candidate)\n if (!result) {\n result = validate(flagKey, definition.schema, candidate)\n flagCache.set(candidate, result)\n if (!result.ok) {\n this.reportError(\n new Error(\n `Invalid value for flag \"${flagKey}\": ${result.message}; using its default`,\n ),\n )\n }\n }\n\n return (result.ok ? result.value : definition.defaultValue) as FlagValue<\n Definitions,\n Key\n >\n }\n}\n\nexport function createDefinedClient<Definitions extends FlagDefinitions>(\n prepared: PreparedFlagDefinitions<Definitions>,\n sdkKey: string,\n options: EnvflagsClientOptions = {},\n) {\n return new DefinedEnvflagsClient(sdkKey, options, prepared)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shared.js","names":["#baseUrl","#fetch","#onError","#pollIntervalMs","#sdkKey","#payload","#revision","#subscribers","#startPolling","#refreshPromise","#performRefresh","#timer","#context","#etag","#prepared","#cacheRevision","#validationCache"],"sources":["../src/sha1.ts","../src/evaluate.ts","../src/client.ts","../src/schema.ts"],"sourcesContent":["function rotateLeft(value: number, bits: number) {\n return ((value << bits) | (value >>> (32 - bits))) >>> 0\n}\n\nfunction add(...values: number[]) {\n return values.reduce((sum, value) => (sum + value) >>> 0, 0)\n}\n\n/** A small synchronous SHA-1 implementation so flag evaluation stays sync. */\nexport function sha1(value: string) {\n const input = new TextEncoder().encode(value)\n const paddedLength = Math.ceil((input.length + 9) / 64) * 64\n const bytes = new Uint8Array(paddedLength)\n bytes.set(input)\n bytes[input.length] = 0x80\n\n const bitLength = BigInt(input.length) * 8n\n const view = new DataView(bytes.buffer)\n view.setUint32(paddedLength - 8, Number(bitLength >> 32n), false)\n view.setUint32(paddedLength - 4, Number(bitLength & 0xffffffffn), false)\n\n let h0 = 0x67452301\n let h1 = 0xefcdab89\n let h2 = 0x98badcfe\n let h3 = 0x10325476\n let h4 = 0xc3d2e1f0\n const words = new Uint32Array(80)\n\n for (let offset = 0; offset < paddedLength; offset += 64) {\n for (let index = 0; index < 16; index += 1) {\n words[index] = view.getUint32(offset + index * 4, false)\n }\n for (let index = 16; index < 80; index += 1) {\n words[index] = rotateLeft(\n words[index - 3]! ^\n words[index - 8]! ^\n words[index - 14]! ^\n words[index - 16]!,\n 1,\n )\n }\n\n let a = h0\n let b = h1\n let c = h2\n let d = h3\n let e = h4\n\n for (let index = 0; index < 80; index += 1) {\n let f: number\n let k: number\n\n if (index < 20) {\n f = (b & c) | (~b & d)\n k = 0x5a827999\n } else if (index < 40) {\n f = b ^ c ^ d\n k = 0x6ed9eba1\n } else if (index < 60) {\n f = (b & c) | (b & d) | (c & d)\n k = 0x8f1bbcdc\n } else {\n f = b ^ c ^ d\n k = 0xca62c1d6\n }\n\n const temporary = add(rotateLeft(a, 5), f, e, k, words[index]!)\n e = d\n d = c\n c = rotateLeft(b, 30)\n b = a\n a = temporary\n }\n\n h0 = add(h0, a)\n h1 = add(h1, b)\n h2 = add(h2, c)\n h3 = add(h3, d)\n h4 = add(h4, e)\n }\n\n return [h0, h1, h2, h3, h4]\n .map(word => word.toString(16).padStart(8, '0'))\n .join('')\n}\n","import { sha1 } from './sha1'\nimport type {\n Clause,\n EvaluationContext,\n EvaluationPayload,\n JsonValue,\n Segment,\n VariationSelector,\n} from './types'\n\nconst BUCKET_DENOMINATOR = Number(0x0fff_ffff_ffff_ffffn)\n\nfunction hasAttribute(context: EvaluationContext, attribute: string) {\n return Object.prototype.hasOwnProperty.call(context, attribute)\n}\n\nfunction scalarEquals(left: unknown, right: JsonValue) {\n return (\n (left === null ||\n typeof left === 'boolean' ||\n typeof left === 'number' ||\n typeof left === 'string') &&\n left === right\n )\n}\n\nfunction matchesIn(attribute: unknown, values: JsonValue[]) {\n const attributes = Array.isArray(attribute) ? attribute : [attribute]\n return attributes.some(item =>\n values.some(value => scalarEquals(item, value)),\n )\n}\n\nfunction matchesStrings(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: string, value: string) => boolean,\n) {\n if (typeof attribute !== 'string') return false\n return values.some(\n value => typeof value === 'string' && predicate(attribute, value),\n )\n}\n\nfunction matchesRegex(attribute: unknown, values: JsonValue[], flags = '') {\n return matchesStrings(attribute, values, (left, right) => {\n try {\n return new RegExp(right, flags).test(left)\n } catch {\n return false\n }\n })\n}\n\nfunction matchesNumbers(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: number, value: number) => boolean,\n) {\n if (typeof attribute !== 'number' || !Number.isFinite(attribute)) return false\n return values.some(\n value =>\n typeof value === 'number' &&\n Number.isFinite(value) &&\n predicate(attribute, value),\n )\n}\n\nfunction instant(value: unknown) {\n if (typeof value === 'number')\n return Number.isFinite(value) ? value : undefined\n if (\n typeof value !== 'string' ||\n !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/.test(\n value,\n )\n ) {\n return undefined\n }\n\n const parsed = Date.parse(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction matchesDates(\n attribute: unknown,\n values: JsonValue[],\n predicate: (attribute: number, value: number) => boolean,\n) {\n const attributeInstant = instant(attribute)\n if (attributeInstant === undefined) return false\n\n return values.some(value => {\n const valueInstant = instant(value)\n return (\n valueInstant !== undefined && predicate(attributeInstant, valueInstant)\n )\n })\n}\n\nfunction matchesSegment(\n segment: Segment,\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n) {\n const key = context.key\n if (typeof key === 'string' && key.length > 0) {\n if (segment.excluded?.includes(key)) return false\n if (segment.included?.includes(key)) return true\n }\n\n return (segment.rules ?? []).some(rule =>\n rule.clauses.every(clause =>\n matchesClause(clause, context, payload, visiting),\n ),\n )\n}\n\nfunction matchesSegments(\n values: JsonValue[],\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n) {\n return values.some(value => {\n if (typeof value !== 'string' || visiting.has(value)) return false\n const segment = payload.segments[value]\n if (!segment) return false\n\n const nestedVisiting = new Set(visiting)\n nestedVisiting.add(value)\n return matchesSegment(segment, context, payload, nestedVisiting)\n })\n}\n\nfunction matchesClause(\n clause: Clause,\n context: EvaluationContext,\n payload: EvaluationPayload,\n visiting: Set<string>,\n): boolean {\n if (!hasAttribute(context, clause.attribute)) return false\n const attribute = context[clause.attribute]\n\n switch (clause.op) {\n case 'in':\n return matchesIn(attribute, clause.values)\n case 'notIn':\n return !matchesIn(attribute, clause.values)\n case 'startsWith':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.startsWith(right),\n )\n case 'endsWith':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.endsWith(right),\n )\n case 'contains':\n return matchesStrings(attribute, clause.values, (left, right) =>\n left.includes(right),\n )\n case 'matches':\n return matchesRegex(attribute, clause.values)\n case 'matchesIgnoreCase':\n return matchesRegex(attribute, clause.values, 'i')\n case 'lessThan':\n return matchesNumbers(\n attribute,\n clause.values,\n (left, right) => left < right,\n )\n case 'greaterThan':\n return matchesNumbers(\n attribute,\n clause.values,\n (left, right) => left > right,\n )\n case 'before':\n return matchesDates(\n attribute,\n clause.values,\n (left, right) => left < right,\n )\n case 'after':\n return matchesDates(\n attribute,\n clause.values,\n (left, right) => left > right,\n )\n case 'segmentMatch':\n return matchesSegments(clause.values, context, payload, visiting)\n }\n}\n\nexport function bucket(flagKey: string, salt: string, bucketBy: string) {\n const digest = sha1(`${flagKey}.${salt}.${bucketBy}`)\n const integer = BigInt(`0x${digest.slice(0, 15)}`)\n return Number(integer) / BUCKET_DENOMINATOR\n}\n\nfunction selectVariation(\n selector: VariationSelector,\n flagKey: string,\n context: EvaluationContext,\n payload: EvaluationPayload,\n) {\n if ('variation' in selector && selector.variation !== undefined) {\n return selector.variation\n }\n\n const rollout = selector.rollout\n if (!rollout?.length) return undefined\n\n const bucketAttribute = selector.bucketBy ?? 'key'\n if (!hasAttribute(context, bucketAttribute)) {\n return rollout.at(-1)?.variation\n }\n\n const bucketBy = String(context[bucketAttribute])\n const contextBucket = bucket(flagKey, payload.salt, bucketBy)\n let accumulatedWeight = 0\n\n for (const entry of rollout) {\n accumulatedWeight += entry.weight / 100_000\n if (contextBucket < accumulatedWeight) return entry.variation\n }\n\n return rollout.at(-1)?.variation\n}\n\nexport function evaluate<T extends JsonValue>(\n payload: EvaluationPayload,\n flagKey: string,\n context: EvaluationContext | undefined,\n defaultValue: T,\n): JsonValue {\n const flag = payload.flags[flagKey]\n if (!flag) return defaultValue\n\n const resolved = context ?? {}\n const key = resolved.key\n\n let variation: number | undefined\n\n if (!flag.on) {\n variation = flag.offVariation\n } else {\n variation = flag.targets.find(\n target =>\n typeof key === 'string' &&\n key.length > 0 &&\n target.values.includes(key),\n )?.variation\n\n if (variation === undefined) {\n const rule = flag.rules.find(candidate =>\n candidate.clauses.every(clause =>\n matchesClause(clause, resolved, payload, new Set()),\n ),\n )\n if (rule) variation = selectVariation(rule, flagKey, resolved, payload)\n }\n\n variation ??= selectVariation(flag.fallthrough, flagKey, resolved, payload)\n }\n\n return variation === undefined || !(variation in flag.variations)\n ? defaultValue\n : flag.variations[variation]!\n}\n","import { evaluate } from './evaluate'\nimport type { EvaluationContext, EvaluationPayload, JsonValue } from './types'\n\nconst DEFAULT_BASE_URL = 'https://envflags.com'\nconst DEFAULT_POLL_INTERVAL_MS = 30_000\n\ntype Fetch = typeof globalThis.fetch\n\nexport type EnvflagsClientOptions = {\n baseUrl?: string\n bootstrap?: EvaluationPayload\n fetch?: Fetch\n onError?: (error: Error) => void\n pollIntervalMs?: number | false\n}\n\ntype PollResponse = {\n envId: string\n version: number\n etag: string\n payloadUrl: string\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parsePollResponse(value: unknown): PollResponse {\n if (\n !isRecord(value) ||\n typeof value.envId !== 'string' ||\n !Number.isSafeInteger(value.version) ||\n (value.version as number) < 0 ||\n typeof value.etag !== 'string' ||\n typeof value.payloadUrl !== 'string'\n ) {\n throw new Error('The envflags poll response is invalid')\n }\n\n return value as PollResponse\n}\n\nfunction parsePayload(value: unknown): EvaluationPayload {\n if (\n !isRecord(value) ||\n typeof value.envId !== 'string' ||\n !Number.isSafeInteger(value.version) ||\n (value.version as number) < 0 ||\n typeof value.salt !== 'string' ||\n !isRecord(value.flags) ||\n !isRecord(value.segments)\n ) {\n throw new Error('The envflags payload is invalid')\n }\n\n return value as EvaluationPayload\n}\n\nfunction responseError(action: string, response: Response) {\n return new Error(\n `Unable to ${action}: envflags returned ${response.status} ${response.statusText}`,\n )\n}\n\nexport class EnvflagsClient {\n readonly #baseUrl: URL\n readonly #fetch: Fetch\n readonly #onError: (error: Error) => void\n readonly #pollIntervalMs: number | false\n readonly #sdkKey: string\n #context?: EvaluationContext\n #etag?: string\n #payload?: EvaluationPayload\n #revision = 0\n #refreshPromise?: Promise<boolean>\n #subscribers = new Set<() => void>()\n #timer?: ReturnType<typeof setInterval>\n\n constructor(sdkKey: string, options: EnvflagsClientOptions = {}) {\n const normalizedSdkKey = sdkKey.trim()\n if (!normalizedSdkKey) throw new Error('An envflags SDK key is required')\n if (\n options.pollIntervalMs !== undefined &&\n options.pollIntervalMs !== false &&\n (!Number.isFinite(options.pollIntervalMs) || options.pollIntervalMs < 0)\n ) {\n throw new Error('pollIntervalMs must be a non-negative finite number')\n }\n\n this.#sdkKey = normalizedSdkKey\n this.#baseUrl = new URL(options.baseUrl ?? DEFAULT_BASE_URL)\n this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis)\n this.#onError = options.onError ?? (() => undefined)\n this.#pollIntervalMs =\n options.pollIntervalMs === undefined\n ? DEFAULT_POLL_INTERVAL_MS\n : options.pollIntervalMs\n if (options.bootstrap) {\n this.#payload = parsePayload(options.bootstrap)\n this.#revision = 1\n }\n }\n\n get initialized() {\n return this.#payload !== undefined\n }\n\n get version() {\n return this.#payload?.version\n }\n\n /** Subscribe to payload changes. Intended for UI framework bindings. */\n subscribe = (listener: () => void) => {\n this.#subscribers.add(listener)\n return () => {\n this.#subscribers.delete(listener)\n }\n }\n\n /** Return a stable value suitable for React's useSyncExternalStore. */\n getSnapshot = () => this.#revision\n\n protected reportError(error: Error) {\n this.#onError(error)\n }\n\n async initialize() {\n try {\n await this.refresh()\n } catch (cause) {\n const error =\n cause instanceof Error\n ? cause\n : new Error('Unable to initialize envflags')\n this.reportError(error)\n if (!this.#payload) throw error\n }\n\n this.#startPolling()\n return this\n }\n\n refresh() {\n if (!this.#refreshPromise) {\n this.#refreshPromise = this.#performRefresh().finally(() => {\n this.#refreshPromise = undefined\n })\n }\n\n return this.#refreshPromise\n }\n\n close() {\n if (this.#timer !== undefined) clearInterval(this.#timer)\n this.#timer = undefined\n }\n\n setContext(context: EvaluationContext) {\n this.#context = context\n return this\n }\n\n variation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context?: EvaluationContext,\n ): T {\n if (!this.#payload) return defaultValue\n return evaluate(\n this.#payload,\n flagKey,\n context ?? this.#context,\n defaultValue,\n ) as T\n }\n\n boolVariation(\n flagKey: string,\n defaultValue: boolean,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'boolean' ? value : defaultValue\n }\n\n stringVariation(\n flagKey: string,\n defaultValue: string,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'string' ? value : defaultValue\n }\n\n numberVariation(\n flagKey: string,\n defaultValue: number,\n context?: EvaluationContext,\n ) {\n const value = this.variation(flagKey, defaultValue, context)\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : defaultValue\n }\n\n jsonVariation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n context?: EvaluationContext,\n ) {\n return this.variation(flagKey, defaultValue, context)\n }\n\n async #performRefresh() {\n const headers = new Headers({\n accept: 'application/json',\n authorization: `Bearer ${this.#sdkKey}`,\n })\n if (this.#etag) headers.set('if-none-match', this.#etag)\n\n const pollUrl = new URL('/sdk/poll', this.#baseUrl)\n const pollResponse = await this.#fetch(pollUrl, { headers })\n if (pollResponse.status === 304) return false\n if (!pollResponse.ok)\n throw responseError('poll for flag updates', pollResponse)\n\n const pointer = parsePollResponse(await pollResponse.json())\n if (\n this.#payload?.envId === pointer.envId &&\n this.#payload.version === pointer.version\n ) {\n this.#etag = pointer.etag\n return false\n }\n\n const payloadUrl = new URL(pointer.payloadUrl, this.#baseUrl)\n const payloadResponse = await this.#fetch(payloadUrl, {\n headers: {\n accept: 'application/json',\n authorization: `Bearer ${this.#sdkKey}`,\n },\n })\n if (!payloadResponse.ok) {\n throw responseError('fetch the flag payload', payloadResponse)\n }\n\n const payload = parsePayload(await payloadResponse.json())\n if (\n payload.envId !== pointer.envId ||\n payload.version !== pointer.version\n ) {\n throw new Error('The envflags payload does not match its version pointer')\n }\n\n this.#payload = payload\n this.#etag = pointer.etag\n this.#revision += 1\n for (const subscriber of this.#subscribers) subscriber()\n return true\n }\n\n #startPolling() {\n if (\n this.#timer !== undefined ||\n this.#pollIntervalMs === false ||\n this.#pollIntervalMs <= 0\n ) {\n return\n }\n\n this.#timer = setInterval(() => {\n void this.refresh().catch(cause => {\n this.reportError(\n cause instanceof Error\n ? cause\n : new Error('Unable to refresh envflags'),\n )\n })\n }, this.#pollIntervalMs)\n }\n}\n\nexport function createClient(\n sdkKey: string,\n options: EnvflagsClientOptions = {},\n) {\n return new EnvflagsClient(sdkKey, options)\n}\n","import { EnvflagsClient, type EnvflagsClientOptions } from './client'\nimport type { EvaluationContext, JsonValue } from './types'\n\n/** The library-neutral Standard Schema v1 validation contract. */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n readonly '~standard': StandardSchemaProps<Input, Output>\n}\n\nexport interface StandardSchemaProps<Input = unknown, Output = Input> {\n readonly version: 1\n readonly vendor: string\n readonly validate: (\n value: unknown,\n options?: StandardSchemaOptions,\n ) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>\n readonly types?: StandardSchemaTypes<Input, Output>\n}\n\nexport interface StandardSchemaOptions {\n readonly libraryOptions?: Record<string, unknown>\n}\n\nexport interface StandardSchemaTypes<Input = unknown, Output = Input> {\n readonly input: Input\n readonly output: Output\n}\n\nexport type StandardSchemaIssue = {\n readonly message: string\n readonly path?: ReadonlyArray<PropertyKey | StandardSchemaPathSegment>\n}\n\nexport type StandardSchemaPathSegment = {\n readonly key: PropertyKey\n}\n\nexport type StandardSchemaResult<Output> =\n | { readonly value: Output; readonly issues?: undefined }\n | { readonly issues: ReadonlyArray<StandardSchemaIssue> }\n\nexport type StandardSchemaOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema['~standard']['types']\n>['output']\n\nexport type FlagDefinition<Schema extends StandardSchemaV1 = StandardSchemaV1> =\n {\n readonly schema: Schema\n readonly defaultValue: StandardSchemaOutput<Schema>\n }\n\nexport type FlagDefinitions = Record<string, FlagDefinition>\n\ntype FlagKey<Definitions extends FlagDefinitions> = Extract<\n keyof Definitions,\n string\n>\n\nexport type FlagValue<\n Definitions extends FlagDefinitions,\n Key extends FlagKey<Definitions>,\n> = StandardSchemaOutput<Definitions[Key]['schema']>\n\ntype ValidationResult =\n { ok: true; value: JsonValue } | { ok: false; message: string }\n\ntype PreparedDefinition = {\n schema: StandardSchemaV1<unknown, JsonValue>\n defaultValue: JsonValue\n}\n\nexport type PreparedFlagDefinitions<Definitions extends FlagDefinitions> = {\n readonly definitions: Readonly<\n Record<FlagKey<Definitions>, PreparedDefinition>\n >\n}\n\n/** Define one flag's runtime schema and offline/invalid-value fallback. */\nexport function flag<Schema extends StandardSchemaV1>(\n schema: Schema,\n defaultValue: StandardSchemaOutput<Schema>,\n): FlagDefinition<Schema> {\n return { schema, defaultValue }\n}\n\nfunction isPromise<T>(value: unknown): value is Promise<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n}\n\nfunction isJsonValue(\n value: unknown,\n ancestors = new Set<object>(),\n): value is JsonValue {\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'string'\n ) {\n return true\n }\n if (typeof value === 'number') return Number.isFinite(value)\n if (typeof value !== 'object') return false\n if (ancestors.has(value)) return false\n\n const nestedAncestors = new Set(ancestors)\n nestedAncestors.add(value)\n if (Array.isArray(value)) {\n return value.every(item => isJsonValue(item, nestedAncestors))\n }\n\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) return false\n return Object.values(value).every(item => isJsonValue(item, nestedAncestors))\n}\n\nfunction jsonEquals(left: JsonValue, right: JsonValue): boolean {\n if (left === right) return true\n if (Array.isArray(left) || Array.isArray(right)) {\n return (\n Array.isArray(left) &&\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((value, index) => jsonEquals(value, right[index]!))\n )\n }\n if (left === null || right === null) return false\n if (typeof left !== 'object' || typeof right !== 'object') return false\n\n const leftKeys = Object.keys(left)\n const rightKeys = Object.keys(right)\n return (\n leftKeys.length === rightKeys.length &&\n leftKeys.every(key => key in right && jsonEquals(left[key]!, right[key]!))\n )\n}\n\nfunction formatIssues(issues: ReadonlyArray<StandardSchemaIssue>) {\n return issues.map(issue => issue.message).join('; ') || 'validation failed'\n}\n\nfunction validate(\n flagKey: string,\n schema: StandardSchemaV1<unknown, JsonValue>,\n value: unknown,\n): ValidationResult {\n let result:\n StandardSchemaResult<JsonValue> | Promise<StandardSchemaResult<JsonValue>>\n try {\n result = schema['~standard'].validate(value)\n } catch (cause) {\n return {\n ok: false,\n message: cause instanceof Error ? cause.message : 'validation threw',\n }\n }\n\n if (isPromise(result)) {\n return {\n ok: false,\n message: `Flag \"${flagKey}\" uses an asynchronous schema; flag schemas must validate synchronously`,\n }\n }\n if (result.issues) {\n return { ok: false, message: formatIssues(result.issues) }\n }\n if (!isJsonValue(result.value)) {\n return {\n ok: false,\n message: `Flag \"${flagKey}\" schema produced a non-JSON value`,\n }\n }\n\n return { ok: true, value: result.value }\n}\n\nexport function prepareFlagDefinitions<Definitions extends FlagDefinitions>(\n definitions: Definitions,\n): PreparedFlagDefinitions<Definitions> {\n const prepared: Record<string, PreparedDefinition> = {}\n\n for (const [flagKey, definition] of Object.entries(definitions)) {\n const schema = definition.schema as StandardSchemaV1<unknown, JsonValue>\n if (schema?.['~standard']?.version !== 1) {\n throw new Error(`Flag \"${flagKey}\" must use a Standard Schema v1 schema`)\n }\n\n const result = validate(flagKey, schema, definition.defaultValue)\n if (!result.ok) {\n throw new Error(\n `Invalid default for flag \"${flagKey}\": ${result.message}`,\n )\n }\n\n const repeated = validate(flagKey, schema, result.value)\n if (!repeated.ok || !jsonEquals(result.value, repeated.value)) {\n throw new Error(\n `Invalid default for flag \"${flagKey}\": schema output must remain stable when validated again`,\n )\n }\n\n prepared[flagKey] = { schema, defaultValue: result.value }\n }\n\n return {\n definitions: Object.freeze(prepared) as Record<\n FlagKey<Definitions>,\n PreparedDefinition\n >,\n }\n}\n\nexport class DefinedEnvflagsClient<\n Definitions extends FlagDefinitions,\n> extends EnvflagsClient {\n readonly #prepared: PreparedFlagDefinitions<Definitions>\n #cacheRevision = -1\n #validationCache = new Map<string, Map<JsonValue, ValidationResult>>()\n\n constructor(\n sdkKey: string,\n options: EnvflagsClientOptions,\n prepared: PreparedFlagDefinitions<Definitions>,\n ) {\n super(sdkKey, options)\n this.#prepared = prepared\n }\n\n flag<Key extends FlagKey<Definitions>>(\n flagKey: Key,\n context?: EvaluationContext,\n ): FlagValue<Definitions, Key> {\n const definition = this.#prepared.definitions[flagKey]\n const candidate = this.variation(flagKey, definition.defaultValue, context)\n\n if (this.#cacheRevision !== this.getSnapshot()) {\n this.#cacheRevision = this.getSnapshot()\n this.#validationCache.clear()\n }\n\n let flagCache = this.#validationCache.get(flagKey)\n if (!flagCache) {\n flagCache = new Map()\n this.#validationCache.set(flagKey, flagCache)\n }\n\n let result = flagCache.get(candidate)\n if (!result) {\n result = validate(flagKey, definition.schema, candidate)\n flagCache.set(candidate, result)\n if (!result.ok) {\n this.reportError(\n new Error(\n `Invalid value for flag \"${flagKey}\": ${result.message}; using its default`,\n ),\n )\n }\n }\n\n return (result.ok ? result.value : definition.defaultValue) as FlagValue<\n Definitions,\n Key\n >\n }\n}\n\nexport function createDefinedClient<Definitions extends FlagDefinitions>(\n prepared: PreparedFlagDefinitions<Definitions>,\n sdkKey: string,\n options: EnvflagsClientOptions = {},\n) {\n return new DefinedEnvflagsClient(sdkKey, options, prepared)\n}\n"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type EvaluationContext = {
|
|
|
7
7
|
key?: string;
|
|
8
8
|
[attribute: string]: unknown;
|
|
9
9
|
};
|
|
10
|
-
export type ClauseOperator = 'after' | 'before' | 'contains' | 'endsWith' | 'greaterThan' | 'in' | 'lessThan' | 'matches' | 'notIn' | 'segmentMatch' | 'startsWith';
|
|
10
|
+
export type ClauseOperator = 'after' | 'before' | 'contains' | 'endsWith' | 'greaterThan' | 'in' | 'lessThan' | 'matches' | 'matchesIgnoreCase' | 'notIn' | 'segmentMatch' | 'startsWith';
|
|
11
11
|
export type Clause = {
|
|
12
12
|
attribute: string;
|
|
13
13
|
op: ClauseOperator;
|