@variantlab/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/_size/config.cjs +634 -0
- package/dist/_size/config.cjs.map +1 -0
- package/dist/_size/config.d.cts +2 -0
- package/dist/_size/config.d.ts +2 -0
- package/dist/_size/config.js +631 -0
- package/dist/_size/config.js.map +1 -0
- package/dist/_size/engine.cjs +1178 -0
- package/dist/_size/engine.cjs.map +1 -0
- package/dist/_size/engine.d.cts +2 -0
- package/dist/_size/engine.d.ts +2 -0
- package/dist/_size/engine.js +1175 -0
- package/dist/_size/engine.js.map +1 -0
- package/dist/_size/targeting.cjs +332 -0
- package/dist/_size/targeting.cjs.map +1 -0
- package/dist/_size/targeting.d.cts +97 -0
- package/dist/_size/targeting.d.ts +97 -0
- package/dist/_size/targeting.js +325 -0
- package/dist/_size/targeting.js.map +1 -0
- package/dist/config-B3DTOt1J.d.ts +46 -0
- package/dist/config-U0cqXPTa.d.cts +46 -0
- package/dist/engine-BEuGiH3G.d.cts +173 -0
- package/dist/engine-BoNBfZBL.d.ts +173 -0
- package/dist/index.cjs +1352 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +223 -0
- package/dist/index.d.ts +223 -0
- package/dist/index.js +1324 -0
- package/dist/index.js.map +1 -0
- package/dist/types-BkXPpEyg.d.cts +82 -0
- package/dist/types-BkXPpEyg.d.ts +82 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/engine/crash-counter.ts","../../src/targeting/glob.ts","../../src/targeting/semver.ts","../../src/config/errors.ts","../../src/config/freeze.ts","../../src/config/validator.ts","../../src/assignment/hash.ts","../../src/assignment/default.ts","../../src/assignment/sticky-hash.ts","../../src/assignment/random.ts","../../src/assignment/weighted.ts","../../src/assignment/mutex.ts","../../src/assignment/index.ts","../../src/history/ring-buffer.ts","../../src/targeting/operators/app-version.ts","../../src/targeting/operators/attributes.ts","../../src/targeting/operators/locale.ts","../../src/targeting/operators/platform.ts","../../src/targeting/operators/routes.ts","../../src/targeting/operators/screen-size.ts","../../src/targeting/operators/user-id.ts","../../src/targeting/evaluator.ts","../../src/engine/kill-switch.ts","../../src/engine/subscribe.ts","../../src/engine/time-gate.ts","../../src/engine/engine.ts","../../src/engine/create.ts"],"names":["v"],"mappings":"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","file":"engine.js","sourcesContent":["/**\n * In-memory crash counter for crash-rollback.\n *\n * For each experiment, we maintain a sliding window of crash\n * timestamps. `record()` appends, `countWithin()` drops expired\n * entries and returns the current count. Persistence across\n * process restarts is phase 4 (`rollback.persistent`) — the phase 1\n * MVP only protects users within a single session.\n */\nexport class CrashCounter {\n private readonly crashes = new Map<string, number[]>();\n\n /** Record a crash; returns the new in-window count (post-prune). */\n record(experimentId: string, now: number, window: number): number {\n const list = this.crashes.get(experimentId) ?? [];\n list.push(now);\n this.crashes.set(experimentId, list);\n return this.countWithin(experimentId, now, window);\n }\n\n countWithin(experimentId: string, now: number, window: number): number {\n const list = this.crashes.get(experimentId);\n if (list === undefined) return 0;\n const cutoff = now - window;\n let i = 0;\n while (i < list.length && (list[i] ?? 0) < cutoff) i++;\n if (i > 0) list.splice(0, i);\n return list.length;\n }\n\n clear(experimentId?: string): void {\n if (experimentId === undefined) this.crashes.clear();\n else this.crashes.delete(experimentId);\n }\n}\n","/**\n * Hand-rolled route glob subset. Linear-time matcher, no regex, no\n * backtracking, no character classes. Supports the surface in\n * `docs/design/targeting-dsl.md`:\n *\n * - Exact: `/about`\n * - Wildcard segment: `/blog/*`\n * - Wildcard deep: `/docs/**` (only allowed as the last segment)\n * - Parameter: `/user/:id` (treated as a single-segment wildcard)\n * - Trailing slash insensitive\n * - Whole-path forms: `*` (single-segment) and `**` (any number of segments)\n *\n * Rejects: character classes, braces, negation, `***`, mixed\n * literal+wildcard in a single segment (e.g. `/foo*bar`).\n */\n\nexport type Segment =\n | { readonly kind: \"literal\"; readonly value: string }\n | { readonly kind: \"param\" }\n | { readonly kind: \"rest\" };\n\n/**\n * Compile a glob pattern into a segment list. Returns `null` for\n * unsupported / malformed patterns. Compiled patterns can be reused\n * and are the hot-path form.\n */\nexport function compileGlob(pattern: string): Segment[] | null {\n if (pattern.length === 0) return null;\n\n // Whole-path shortcuts. `*` and `**` have no leading slash.\n if (pattern === \"*\") return [{ kind: \"param\" }];\n if (pattern === \"**\") return [{ kind: \"rest\" }];\n\n if (pattern[0] !== \"/\") return null;\n\n // Reject `***` anywhere outright.\n if (pattern.indexOf(\"***\") >= 0) return null;\n\n // Strip a trailing slash (except for the root `/` itself).\n const normalized = pattern.length > 1 && pattern.endsWith(\"/\") ? pattern.slice(0, -1) : pattern;\n\n // Root: single empty segment list means \"match `/` exactly\".\n if (normalized === \"/\") return [];\n\n const raw = normalized.slice(1).split(\"/\");\n const segs: Segment[] = [];\n for (let i = 0; i < raw.length; i++) {\n const part = raw[i] as string;\n if (part.length === 0) return null; // e.g. `//` or trailing empty\n if (part === \"**\") {\n // `**` must be the last segment.\n if (i !== raw.length - 1) return null;\n segs.push({ kind: \"rest\" });\n continue;\n }\n if (part === \"*\") {\n segs.push({ kind: \"param\" });\n continue;\n }\n if (part[0] === \":\") {\n // `:id` — single-segment wildcard. Disallow empty name `:` alone.\n if (part.length < 2) return null;\n segs.push({ kind: \"param\" });\n continue;\n }\n // Literal segment. Reject any wildcard chars or colons inside.\n // Compile-time regex (not hot path); linear, no backtracking.\n if (/[*:?[\\]{}!]/.test(part)) return null;\n segs.push({ kind: \"literal\", value: part });\n }\n return segs;\n}\n\n/**\n * Match a compiled glob against a path. O(n + m) linear, no\n * backtracking because `**` is only ever the final segment.\n */\nexport function matchCompiledRoute(segs: readonly Segment[], path: string): boolean {\n if (path.length === 0) return false;\n if (path[0] !== \"/\") return false;\n\n // Strip a trailing slash (except for the root `/`).\n const normalized = path.length > 1 && path.endsWith(\"/\") ? path.slice(0, -1) : path;\n\n // Root `/` case: empty segment list matches exactly `/`.\n if (segs.length === 0) return normalized === \"/\";\n\n const parts = normalized === \"/\" ? [] : normalized.slice(1).split(\"/\");\n\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i] as Segment;\n if (seg.kind === \"rest\") {\n // `**` tail — matches zero or more remaining parts.\n return true;\n }\n if (i >= parts.length) return false;\n const part = parts[i] as string;\n if (part.length === 0) return false;\n if (seg.kind === \"literal\") {\n if (seg.value !== part) return false;\n }\n // `param` always matches a non-empty part.\n }\n return parts.length === segs.length;\n}\n\n/** Convenience: compile and match. Returns false on compile error. */\nexport function matchRoute(pattern: string, path: string): boolean {\n const segs = compileGlob(pattern);\n if (segs === null) return false;\n return matchCompiledRoute(segs, path);\n}\n","/**\n * Hand-rolled semver subset. No dependencies, no regex on the hot path,\n * no backtracking. Supports the surface documented in\n * `docs/design/targeting-dsl.md`:\n *\n * - Comparators: `=`, `<`, `<=`, `>`, `>=`, and a bare version (treated as `=`)\n * - Caret: `^X.Y.Z` → `[>=X.Y.Z, <(X+1).0.0]`\n * - Tilde: `~X.Y.Z` → `[>=X.Y.Z, <X.(Y+1).0]`\n * - Hyphen range: `X.Y.Z - A.B.C` → `[>=X.Y.Z, <=A.B.C]`\n * - Compound (AND): space-separated comparators, e.g. `>=1.0.0 <2.0.0`\n * - OR: `||`-separated clauses\n *\n * Explicitly rejects prereleases (`1.0.0-beta`), build metadata\n * (`1.0.0+sha`), and `x` wildcards (`1.2.x`).\n */\n\nexport type Version = readonly [number, number, number];\nexport type Op = \"=\" | \"<\" | \"<=\" | \">\" | \">=\";\nexport interface Comparator {\n readonly op: Op;\n readonly v: Version;\n}\nexport type Clause = readonly Comparator[];\nexport type Range = readonly Clause[];\n\n/**\n * Pure character scanner. No regex. Returns `[major, minor, patch]`\n * or `null` if the string is not exactly three dot-separated\n * non-negative integers.\n */\nexport function parseVersion(s: string): Version | null {\n if (s.length === 0) return null;\n const parts: number[] = [0, 0, 0];\n let idx = 0;\n let part = 0;\n let seen = false;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c === 46 /* . */) {\n if (!seen) return null;\n parts[idx++] = part;\n if (idx > 2) return null;\n part = 0;\n seen = false;\n } else if (c >= 48 && c <= 57) {\n part = part * 10 + (c - 48);\n seen = true;\n } else return null;\n }\n if (!seen || idx !== 2) return null;\n parts[2] = part;\n return [parts[0] as number, parts[1] as number, parts[2] as number];\n}\n\n/** Numeric comparison, field by field. */\nexport function cmpVersion(a: Version, b: Version): number {\n return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];\n}\n\n/**\n * Parse a semver range string. Returns a `Range` on success or `null`\n * on any syntactic or structural error.\n */\nexport function parseSemver(s: string): Range | null {\n if (s.length === 0) return null;\n const clauses: Clause[] = [];\n for (const part of s.split(\"||\")) {\n const c = parseClause(part.trim());\n if (c === null) return null;\n clauses.push(c);\n }\n return clauses;\n}\n\nfunction parseClause(s: string): Clause | null {\n if (s.length === 0) return null;\n\n // Hyphen range: `X.Y.Z - A.B.C`. Whitespace-sensitive separator.\n const hy = s.indexOf(\" - \");\n if (hy >= 0) {\n const lo = parseVersion(s.slice(0, hy).trim());\n const hi = parseVersion(s.slice(hy + 3).trim());\n if (lo === null || hi === null) return null;\n return [\n { op: \">=\", v: lo },\n { op: \"<=\", v: hi },\n ];\n }\n\n // Compound: whitespace-separated comparators, all ANDed.\n const cmps: Comparator[] = [];\n for (const tok of s.split(/\\s+/)) {\n if (tok.length === 0) continue;\n const parsed = parseComparator(tok);\n if (parsed === null) return null;\n for (const c of parsed) cmps.push(c);\n }\n return cmps.length > 0 ? cmps : null;\n}\n\n/**\n * Parse a single comparator like `>=1.2.3`, `^1.2.3`, `~1.2.3`, or a\n * bare version. Returns an array so that caret/tilde can expand to\n * two comparators.\n */\nfunction parseComparator(s: string): Comparator[] | null {\n const c0 = s[0];\n if (c0 === \"^\" || c0 === \"~\") {\n const v = parseVersion(s.slice(1));\n if (v === null) return null;\n const upper: Version = c0 === \"^\" ? [v[0] + 1, 0, 0] : [v[0], v[1] + 1, 0];\n return [\n { op: \">=\", v },\n { op: \"<\", v: upper },\n ];\n }\n\n let op: Op = \"=\";\n let rest = s;\n if (c0 === \">\" || c0 === \"<\") {\n if (s[1] === \"=\") {\n op = `${c0}=` as Op;\n rest = s.slice(2);\n } else {\n op = c0;\n rest = s.slice(1);\n }\n } else if (c0 === \"=\") {\n rest = s.slice(1);\n }\n\n const v = parseVersion(rest);\n return v === null ? null : [{ op, v }];\n}\n\n/** Match a parsed range against a parsed version. */\nexport function matchCompiled(range: Range, version: Version): boolean {\n for (const clause of range) if (matchClause(clause, version)) return true;\n return false;\n}\n\nfunction matchClause(clause: Clause, version: Version): boolean {\n for (const c of clause) {\n const d = cmpVersion(version, c.v);\n const op = c.op;\n const fail =\n op === \"=\"\n ? d !== 0\n : op === \"<\"\n ? d >= 0\n : op === \"<=\"\n ? d > 0\n : op === \">\"\n ? d <= 0\n : d < 0;\n if (fail) return false;\n }\n return true;\n}\n\n/** Convenience: parse both sides and compare. Returns false on parse error. */\nexport function matchSemver(range: string, version: string): boolean {\n const r = parseSemver(range);\n if (r === null) return false;\n const v = parseVersion(version);\n return v !== null && matchCompiled(r, v);\n}\n","import type { IssueCode } from \"./codes.js\";\n\n/**\n * A single config-validation issue.\n *\n * `path` is an RFC 6901 JSON Pointer into the source config\n * (`\"\"` for root, `\"/experiments/0/variants/2/id\"` for nested).\n * `code` is a narrow union of strings for programmatic handling.\n * `message` is a human-readable sentence safe for CLI output.\n */\nexport interface ConfigIssue {\n readonly path: string;\n readonly code: IssueCode;\n readonly message: string;\n}\n\n/**\n * Thrown by `validateConfig` when one or more rules fail.\n *\n * `issues` is always non-empty and frozen. The validator collects\n * every issue it finds and throws once at the end — it does not\n * fail fast — so a single throw can surface many independent\n * problems in one pass.\n */\nexport class ConfigValidationError extends Error {\n readonly issues: readonly ConfigIssue[];\n\n constructor(issues: readonly ConfigIssue[]) {\n super(`Config validation failed with ${issues.length} issue(s)`);\n this.name = \"ConfigValidationError\";\n this.issues = Object.freeze(issues.slice());\n }\n}\n","/**\n * Recursively freeze a plain-JSON-shaped value.\n *\n * - Primitives (including `null`/`undefined`) are returned as-is.\n * - Arrays and plain objects are frozen in-place with `Object.freeze`.\n * - Already-frozen subtrees are skipped (short-circuit) so this is\n * cheap to call on shared references and idempotent.\n *\n * Sanitized config trees are tree-shaped (no cycles, no class\n * instances) so no cycle detection is required.\n */\nexport function deepFreeze<T>(value: T): T {\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n if (Object.isFrozen(value)) {\n return value;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n deepFreeze(value[i]);\n }\n return Object.freeze(value);\n }\n // Plain object (may be null-proto after sanitize).\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n deepFreeze(obj[keys[i] as string]);\n }\n return Object.freeze(value);\n}\n","import { compileGlob } from \"../targeting/glob.js\";\nimport { parseSemver } from \"../targeting/semver.js\";\nimport type { IssueCode } from \"./codes.js\";\nimport { type ConfigIssue, ConfigValidationError } from \"./errors.js\";\nimport { deepFreeze } from \"./freeze.js\";\nimport type { ExperimentsConfig } from \"./types.js\";\n\n/* Limits (see docs/design/config-format.md). */\nconst MAX_BYTES = 1_048_576;\nconst MAX_EXP = 1000;\nconst MAX_VAR = 100;\nconst MIN_VAR = 2;\nconst MAX_ROUTES = 100;\nconst MAX_DEPTH = 10;\nconst MAX_NAME = 128;\nconst MAX_DESC = 512;\n\nconst ID_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;\nconst RESERVED = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\nconst ASSIGNS = new Set([\"default\", \"random\", \"sticky-hash\", \"weighted\"]);\nconst STATUSES = new Set([\"draft\", \"active\", \"archived\"]);\nconst TYPES = new Set([\"render\", \"value\"]);\nconst PLATFORMS = new Set([\"ios\", \"android\", \"web\", \"node\"]);\nconst SIZES = new Set([\"small\", \"medium\", \"large\"]);\n\n// `TextEncoder` is standardized in Node 18+, browsers, Deno, Bun, and\n// Edge runtimes — the only platform global `@variantlab/core` uses.\ndeclare class TextEncoder {\n encode(input?: string): Uint8Array;\n}\n\n/**\n * Parse, sanitize, validate, and deep-freeze an experiments config.\n * Collects every issue before throwing (fail-slow, not fail-fast).\n */\nexport function validateConfig(input: unknown): ExperimentsConfig {\n const issues: ConfigIssue[] = [];\n\n if (measureBytes(input) > MAX_BYTES) {\n push(issues, \"\", \"config-too-large\");\n throw new ConfigValidationError(issues);\n }\n\n let parsed: unknown = input;\n if (typeof input === \"string\") {\n try {\n parsed = JSON.parse(input);\n } catch (err) {\n push(issues, \"\", \"invalid-json\", (err as Error).message);\n throw new ConfigValidationError(issues);\n }\n }\n\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n push(issues, \"\", \"not-an-object\");\n throw new ConfigValidationError(issues);\n }\n\n const sanitized = sanitize(parsed, issues, \"\");\n validateRoot(sanitized as Record<string, unknown>, issues);\n\n if (issues.length > 0) {\n throw new ConfigValidationError(issues);\n }\n return deepFreeze(sanitized as ExperimentsConfig);\n}\n\n/* Raw-bytes measurement. Strings: exact UTF-8. Objects: approximate\n * via JSON.stringify then UTF-8 length. The goal is to cap untrusted\n * input memory, so approximate is fine. */\nconst encoder = new TextEncoder();\nfunction measureBytes(input: unknown): number {\n if (typeof input === \"string\") return encoder.encode(input).length;\n try {\n const s = JSON.stringify(input);\n if (typeof s !== \"string\") return 0;\n return encoder.encode(s).length;\n } catch {\n return 0;\n }\n}\n\n/* Sanitize: rebuild every object with Object.create(null) and copy\n * only own, non-reserved keys. Produces a null-proto tree. */\nfunction sanitize(value: unknown, issues: ConfigIssue[], ptr: string): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) {\n const out: unknown[] = [];\n for (let i = 0; i < value.length; i++) {\n out.push(sanitize(value[i], issues, `${ptr}/${i}`));\n }\n return out;\n }\n const src = value as Record<string, unknown>;\n const dst: Record<string, unknown> = Object.create(null);\n const keys = Object.keys(src);\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i] as string;\n if (RESERVED.has(k)) {\n push(issues, jp(ptr, k), \"reserved-key\", k);\n continue;\n }\n dst[k] = sanitize(src[k], issues, jp(ptr, k));\n }\n return dst;\n}\n\nfunction validateRoot(root: Record<string, unknown>, issues: ConfigIssue[]): void {\n const version = root[\"version\"];\n if (version === undefined) {\n push(issues, \"/version\", \"version/missing\");\n } else if (version !== 1) {\n push(issues, \"/version\", \"version/invalid\");\n }\n\n const enabled = root[\"enabled\"];\n if (enabled !== undefined && typeof enabled !== \"boolean\") {\n push(issues, \"/enabled\", \"enabled/invalid\");\n }\n\n const signature = root[\"signature\"];\n if (signature !== undefined && (typeof signature !== \"string\" || signature.length === 0)) {\n push(issues, \"/signature\", \"signature/invalid\");\n }\n\n const experiments = root[\"experiments\"];\n if (experiments === undefined) {\n push(issues, \"/experiments\", \"experiments/missing\");\n return;\n }\n if (!Array.isArray(experiments)) {\n push(issues, \"/experiments\", \"experiments/not-an-array\");\n return;\n }\n if (experiments.length > MAX_EXP) {\n push(issues, \"/experiments\", \"experiments/too-many\");\n }\n\n const seen = new Set<string>();\n for (let i = 0; i < experiments.length; i++) {\n validateExperiment(experiments[i], `/experiments/${i}`, seen, issues);\n }\n}\n\nfunction validateExperiment(\n exp: unknown,\n p: string,\n seen: Set<string>,\n issues: ConfigIssue[],\n): void {\n if (exp === null || typeof exp !== \"object\" || Array.isArray(exp)) {\n push(issues, p, \"experiment/not-an-object\");\n return;\n }\n const e = exp as Record<string, unknown>;\n\n const id = e[\"id\"];\n if (id === undefined) {\n push(issues, `${p}/id`, \"experiment/missing-required\", \"id\");\n } else if (typeof id !== \"string\" || !ID_RE.test(id)) {\n push(issues, `${p}/id`, \"experiment/id/invalid\");\n } else if (seen.has(id)) {\n push(issues, `${p}/id`, \"experiment/id/duplicate\", id);\n } else {\n seen.add(id);\n }\n\n const name = e[\"name\"];\n if (name === undefined) {\n push(issues, `${p}/name`, \"experiment/missing-required\", \"name\");\n } else if (typeof name !== \"string\" || name.length === 0 || name.length > MAX_NAME) {\n push(issues, `${p}/name`, \"experiment/name/invalid\");\n }\n\n checkOptString(\n e[\"description\"],\n `${p}/description`,\n MAX_DESC,\n \"experiment/description/invalid\",\n issues,\n );\n checkEnum(e[\"type\"], `${p}/type`, TYPES, \"experiment/type/invalid\", issues);\n checkEnum(e[\"status\"], `${p}/status`, STATUSES, \"experiment/status/invalid\", issues);\n checkOptString(e[\"mutex\"], `${p}/mutex`, MAX_NAME, \"experiment/mutex/invalid\", issues);\n checkOptString(e[\"owner\"], `${p}/owner`, MAX_NAME, \"experiment/owner/invalid\", issues);\n checkOptBool(e[\"overridable\"], `${p}/overridable`, \"experiment/overridable/invalid\", issues);\n\n const variantIds = validateVariants(e[\"variants\"], p, issues);\n validateDefault(e[\"default\"], variantIds, p, issues);\n validateAssignment(e[\"assignment\"], e[\"split\"], variantIds, p, issues);\n validateRoutes(e[\"routes\"], p, issues);\n validateTargeting(e[\"targeting\"], p, issues);\n validateDates(e[\"startDate\"], e[\"endDate\"], p, issues);\n validateRollback(e[\"rollback\"], p, issues);\n}\n\nfunction validateVariants(field: unknown, p: string, issues: ConfigIssue[]): Set<string> {\n const ids = new Set<string>();\n const vp = `${p}/variants`;\n if (field === undefined) {\n push(issues, vp, \"experiment/variants/missing\");\n return ids;\n }\n if (!Array.isArray(field)) {\n push(issues, vp, \"experiment/variants/missing\");\n return ids;\n }\n if (field.length < MIN_VAR) {\n push(issues, vp, \"experiment/variants/too-few\");\n }\n if (field.length > MAX_VAR) {\n push(issues, vp, \"experiment/variants/too-many\");\n }\n for (let i = 0; i < field.length; i++) {\n const v = field[i];\n const vip = `${vp}/${i}`;\n if (v === null || typeof v !== \"object\" || Array.isArray(v)) {\n push(issues, vip, \"variant/not-an-object\");\n continue;\n }\n const vo = v as Record<string, unknown>;\n const vid = vo[\"id\"];\n if (vid === undefined) {\n push(issues, `${vip}/id`, \"experiment/missing-required\", \"variant.id\");\n } else if (typeof vid !== \"string\" || !ID_RE.test(vid)) {\n push(issues, `${vip}/id`, \"variant/id/invalid\");\n } else if (ids.has(vid)) {\n push(issues, `${vip}/id`, \"variant/id/duplicate\", vid);\n } else {\n ids.add(vid);\n }\n checkOptString(vo[\"label\"], `${vip}/label`, MAX_NAME, \"variant/label/invalid\", issues);\n checkOptString(\n vo[\"description\"],\n `${vip}/description`,\n MAX_DESC,\n \"variant/description/invalid\",\n issues,\n );\n }\n return ids;\n}\n\nfunction validateDefault(field: unknown, ids: Set<string>, p: string, issues: ConfigIssue[]): void {\n const dp = `${p}/default`;\n if (field === undefined) {\n push(issues, dp, \"experiment/default/missing\");\n return;\n }\n if (typeof field !== \"string\") {\n push(issues, dp, \"experiment/default/unknown-variant\");\n return;\n }\n if (ids.size > 0 && !ids.has(field)) {\n push(issues, dp, \"experiment/default/unknown-variant\", field);\n }\n}\n\nfunction validateAssignment(\n aField: unknown,\n sField: unknown,\n ids: Set<string>,\n p: string,\n issues: ConfigIssue[],\n): void {\n let strategy = \"default\";\n if (aField !== undefined) {\n if (typeof aField !== \"string\" || !ASSIGNS.has(aField)) {\n push(issues, `${p}/assignment`, \"experiment/assignment/invalid\");\n } else {\n strategy = aField;\n }\n }\n\n const sp = `${p}/split`;\n if (strategy === \"weighted\" && sField === undefined) {\n push(issues, sp, \"split/missing\");\n return;\n }\n if (sField === undefined) return;\n if (sField === null || typeof sField !== \"object\" || Array.isArray(sField)) {\n push(issues, sp, \"split/not-an-object\");\n return;\n }\n const split = sField as Record<string, unknown>;\n const keys = Object.keys(split);\n let sum = 0;\n let bad = false;\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i] as string;\n if (ids.size > 0 && !ids.has(k)) {\n push(issues, `${sp}/${esc(k)}`, \"split/unknown-variant\", k);\n bad = true;\n continue;\n }\n const v = split[k];\n if (typeof v !== \"number\" || !Number.isInteger(v) || v < 0 || v > 100) {\n push(issues, `${sp}/${esc(k)}`, \"split/value-invalid\");\n bad = true;\n continue;\n }\n sum += v;\n }\n if (!bad && sum !== 100) {\n push(issues, sp, \"split/sum-invalid\", String(sum));\n }\n}\n\nfunction validateRoutes(field: unknown, p: string, issues: ConfigIssue[]): void {\n if (field === undefined) return;\n const rp = `${p}/routes`;\n if (!Array.isArray(field)) {\n push(issues, rp, \"experiment/routes/invalid\");\n return;\n }\n if (field.length > MAX_ROUTES) {\n push(issues, rp, \"experiment/routes/invalid\");\n }\n for (let i = 0; i < field.length; i++) {\n const r = field[i];\n if (typeof r !== \"string\" || compileGlob(r) === null) {\n push(issues, `${rp}/${i}`, \"route/glob/invalid\");\n }\n }\n}\n\nfunction validateTargeting(field: unknown, p: string, issues: ConfigIssue[]): void {\n if (field === undefined) return;\n const tp = `${p}/targeting`;\n if (field === null || typeof field !== \"object\" || Array.isArray(field)) {\n push(issues, tp, \"targeting/not-an-object\");\n return;\n }\n if (depthOf(field, 0) > MAX_DEPTH) {\n push(issues, tp, \"targeting/depth-exceeded\");\n }\n const t = field as Record<string, unknown>;\n\n if (t[\"platform\"] !== undefined) {\n checkEnumArray(\n t[\"platform\"],\n `${tp}/platform`,\n PLATFORMS,\n \"targeting/platform/invalid\",\n issues,\n );\n }\n if (t[\"appVersion\"] !== undefined) {\n const v = t[\"appVersion\"];\n if (typeof v !== \"string\" || parseSemver(v) === null) {\n push(issues, `${tp}/appVersion`, \"targeting/appversion/invalid\");\n }\n }\n if (t[\"locale\"] !== undefined) {\n checkStringArray(t[\"locale\"], `${tp}/locale`, \"targeting/locale/invalid\", issues);\n }\n if (t[\"screenSize\"] !== undefined) {\n checkEnumArray(\n t[\"screenSize\"],\n `${tp}/screenSize`,\n SIZES,\n \"targeting/screensize/invalid\",\n issues,\n );\n }\n if (t[\"routes\"] !== undefined) {\n const r = t[\"routes\"];\n if (!Array.isArray(r) || r.length === 0) {\n push(issues, `${tp}/routes`, \"targeting/routes/invalid\");\n } else {\n for (let i = 0; i < r.length; i++) {\n const v = r[i];\n if (typeof v !== \"string\" || compileGlob(v) === null) {\n push(issues, `${tp}/routes/${i}`, \"targeting/routes/invalid\");\n }\n }\n }\n }\n if (t[\"userId\"] !== undefined) {\n validateUserId(t[\"userId\"], `${tp}/userId`, issues);\n }\n if (t[\"attributes\"] !== undefined) {\n const a = t[\"attributes\"];\n if (a === null || typeof a !== \"object\" || Array.isArray(a)) {\n push(issues, `${tp}/attributes`, \"targeting/attributes/invalid\");\n }\n }\n}\n\nfunction validateUserId(u: unknown, p: string, issues: ConfigIssue[]): void {\n const code: IssueCode = \"targeting/userid/invalid\";\n if (Array.isArray(u)) {\n if (u.length === 0) {\n push(issues, p, code);\n return;\n }\n for (let i = 0; i < u.length; i++) {\n const v = u[i];\n if (typeof v !== \"string\" || v.length === 0) {\n push(issues, `${p}/${i}`, code);\n }\n }\n return;\n }\n if (u !== null && typeof u === \"object\") {\n const o = u as Record<string, unknown>;\n const h = o[\"hash\"];\n const m = o[\"mod\"];\n if (typeof h !== \"string\" || h.length === 0) {\n push(issues, `${p}/hash`, code);\n }\n if (typeof m !== \"number\" || !Number.isInteger(m) || m < 0 || m > 100) {\n push(issues, `${p}/mod`, code);\n }\n return;\n }\n push(issues, p, code);\n}\n\nfunction validateDates(sField: unknown, eField: unknown, p: string, issues: ConfigIssue[]): void {\n let s: number | undefined;\n let e: number | undefined;\n if (sField !== undefined) {\n if (typeof sField !== \"string\" || !isValidIsoDate(sField)) {\n push(issues, `${p}/startDate`, \"experiment/startdate/invalid\");\n } else {\n s = Date.parse(sField);\n }\n }\n if (eField !== undefined) {\n if (typeof eField !== \"string\" || !isValidIsoDate(eField)) {\n push(issues, `${p}/endDate`, \"experiment/enddate/invalid\");\n } else {\n e = Date.parse(eField);\n }\n }\n if (s !== undefined && e !== undefined && !(e > s)) {\n push(issues, `${p}/endDate`, \"experiment/date-range/invalid\");\n }\n}\n\nfunction validateRollback(field: unknown, p: string, issues: ConfigIssue[]): void {\n if (field === undefined) return;\n const rp = `${p}/rollback`;\n if (field === null || typeof field !== \"object\" || Array.isArray(field)) {\n push(issues, rp, \"rollback/not-an-object\");\n return;\n }\n const r = field as Record<string, unknown>;\n const thr = r[\"threshold\"];\n if (thr === undefined) {\n push(issues, `${rp}/threshold`, \"rollback/threshold/invalid\");\n } else if (typeof thr !== \"number\" || !Number.isInteger(thr) || thr < 1 || thr > 100) {\n push(issues, `${rp}/threshold`, \"rollback/threshold/invalid\");\n }\n const win = r[\"window\"];\n if (win === undefined) {\n push(issues, `${rp}/window`, \"rollback/window/invalid\");\n } else if (typeof win !== \"number\" || !Number.isInteger(win) || win < 1000 || win > 3_600_000) {\n push(issues, `${rp}/window`, \"rollback/window/invalid\");\n }\n const persistent = r[\"persistent\"];\n if (persistent !== undefined && typeof persistent !== \"boolean\") {\n push(issues, `${rp}/persistent`, \"rollback/persistent/invalid\");\n }\n}\n\n/* Small shared helpers. */\n\nfunction checkOptString(\n v: unknown,\n p: string,\n max: number,\n code: IssueCode,\n issues: ConfigIssue[],\n): void {\n if (v === undefined) return;\n if (typeof v !== \"string\" || v.length === 0 || v.length > max) {\n push(issues, p, code);\n }\n}\n\nfunction checkOptBool(v: unknown, p: string, code: IssueCode, issues: ConfigIssue[]): void {\n if (v === undefined) return;\n if (typeof v !== \"boolean\") {\n push(issues, p, code);\n }\n}\n\nfunction checkEnum(\n v: unknown,\n p: string,\n set: Set<string>,\n code: IssueCode,\n issues: ConfigIssue[],\n): void {\n if (v === undefined) return;\n if (typeof v !== \"string\" || !set.has(v)) {\n push(issues, p, code);\n }\n}\n\nfunction checkEnumArray(\n v: unknown,\n p: string,\n set: Set<string>,\n code: IssueCode,\n issues: ConfigIssue[],\n): void {\n if (!Array.isArray(v) || v.length === 0) {\n push(issues, p, code);\n return;\n }\n for (let i = 0; i < v.length; i++) {\n const x = v[i];\n if (typeof x !== \"string\" || !set.has(x)) {\n push(issues, `${p}/${i}`, code);\n }\n }\n}\n\nfunction checkStringArray(v: unknown, p: string, code: IssueCode, issues: ConfigIssue[]): void {\n if (!Array.isArray(v) || v.length === 0) {\n push(issues, p, code);\n return;\n }\n for (let i = 0; i < v.length; i++) {\n const x = v[i];\n if (typeof x !== \"string\" || x.length === 0) {\n push(issues, `${p}/${i}`, code);\n }\n }\n}\n\n/* ISO 8601 date: Date.parse must accept and the string must contain\n * T + Z-or-offset, to reject bare dates like \"2026-01-01\". */\nconst ISO_TAIL_RE = /T.*(?:Z|[+-]\\d{2}:?\\d{2})$/;\nfunction isValidIsoDate(s: string): boolean {\n if (s.length < 10) return false;\n if (Number.isNaN(Date.parse(s))) return false;\n return ISO_TAIL_RE.test(s);\n}\n\n/* Depth of a value inside the targeting subtree (root = 0). */\nfunction depthOf(value: unknown, current: number): number {\n if (value === null || typeof value !== \"object\") return current;\n let m = current;\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const d = depthOf(value[i], current + 1);\n if (d > m) m = d;\n }\n return m;\n }\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n const d = depthOf(obj[keys[i] as string], current + 1);\n if (d > m) m = d;\n }\n return m;\n}\n\n/* RFC 6901 encoders. */\nfunction jp(parent: string, key: string): string {\n return `${parent}/${esc(key)}`;\n}\nfunction esc(s: string): string {\n return s.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/**\n * Append an issue. The `message` defaults to the code itself — issue\n * messages are intentionally terse so that bundle size stays under\n * budget. Consumers that want pretty messages should switch on `code`.\n */\nfunction push(issues: ConfigIssue[], path: string, code: IssueCode, message?: string): void {\n issues.push({ path, code, message: message ?? code });\n}\n","/**\n * Synchronous 32-bit string hash for deterministic assignment.\n *\n * `getVariant` is required to be synchronous and O(1) (see\n * `ARCHITECTURE.md` runtime data flow and the design principle\n * of cheap, render-safe reads). Web Crypto's `subtle.digest` is\n * always async, so we hand-roll a tiny hash here:\n *\n * - FNV-1a (32-bit) core for fast streaming.\n * - Murmur3 finalizer for avalanche (uniform bit distribution).\n *\n * Total: ~150 bytes gzipped. Deterministic across every runtime we\n * target (Node 18+, browsers, RN, Deno, Bun, Edge) because every\n * step is a 32-bit integer operation with defined overflow semantics\n * via `Math.imul` and `>>> 0`.\n *\n * This is **not** cryptographic — do not use for signing. The async\n * sha256 path in `../targeting/hash.ts` remains available for\n * advanced use cases. The phase-0 \"which hash algorithm\" open\n * question in `docs/phases/phase-0-foundation.md` resolves here.\n */\n\n/** FNV-1a 32-bit hash + Murmur3 finalizer. Returns a uint32. */\nexport function hash32(input: string): number {\n let h = 2166136261; // FNV offset basis\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 16777619); // FNV prime\n }\n // Murmur3 fmix32 avalanche\n h ^= h >>> 16;\n h = Math.imul(h, 0x85ebca6b);\n h ^= h >>> 13;\n h = Math.imul(h, 0xc2b2ae35);\n h ^= h >>> 16;\n return h >>> 0;\n}\n\n/** Map a userId to a [0, 100) bucket. Used by user-id hash-mod targeting. */\nexport function bucketUserId(userId: string): number {\n return hash32(userId) % 100;\n}\n","/**\n * Default assignment: always returns the experiment's `default`\n * variant. Used when no strategy is configured, when the user is\n * not yet bucketable (no `userId`), or as the fallback in\n * fail-open error paths.\n */\nimport type { Experiment } from \"../config/types.js\";\n\nexport function assignDefault(experiment: Experiment): string {\n return experiment.default;\n}\n","/**\n * Sticky-hash assignment.\n *\n * Deterministic from `(userId, experimentId)`: hash the pair with\n * the sync 32-bit hash and map the result modulo the sorted variant\n * count. Sort order is lexicographic on `variant.id` so that the\n * mapping is stable across processes, devices, and restarts.\n *\n * Adding a new variant renumbers existing users (the classic\n * hash-mod trade-off). This is acceptable for phase 1 — the\n * config-format doc calls out that variant additions are effectively\n * a new experiment. Rendezvous hashing would fix this but costs\n * ~300 bytes we don't want to spend before someone asks for it.\n */\nimport type { Experiment } from \"../config/types.js\";\nimport { hash32 } from \"./hash.js\";\n\nexport function assignStickyHash(experiment: Experiment, userId: string): string {\n const ids = experiment.variants.map((v) => v.id).sort();\n const bucket = hash32(`${userId}:${experiment.id}`) % ids.length;\n return ids[bucket] ?? experiment.default;\n}\n","/**\n * \"Random\" assignment.\n *\n * In phase 1 MVP this is behaviorally identical to `sticky-hash`:\n * a deterministic function of `(userId, experimentId)`. The two\n * strategies exist as distinct config values because the contract\n * differs:\n *\n * - `sticky-hash` — promised to be stable across devices for the\n * same `userId`, zero storage needed.\n * - `random` — the engine is allowed to bucket the user\n * however it likes as long as each user sees a consistent\n * answer. Future phases may back this with storage-cached\n * uniform-random assignments.\n *\n * The non-negotiable rule (design-principles.md §performance &\n * ARCHITECTURE.md §core invariants): **no `Math.random` in the hot\n * path**. Delegating to `assignStickyHash` keeps us honest and\n * collapses both paths to the same tree-shaken code.\n */\nimport type { Experiment } from \"../config/types.js\";\nimport { assignStickyHash } from \"./sticky-hash.js\";\n\nexport function assignRandom(experiment: Experiment, userId: string): string {\n return assignStickyHash(experiment, userId);\n}\n","/**\n * Weighted assignment.\n *\n * Maps `(userId, experimentId)` to a `[0, 10000)` bucket via the\n * sync hash, then walks the split's cumulative boundaries in\n * sorted-key order. `split` is validated at config-load time to\n * sum to exactly 100, so we multiply by 100 internally to get an\n * integer 10000-unit range without floating point.\n *\n * Determinism: same user, same experiment, same split → same\n * variant forever. Changing the split re-buckets everyone, which\n * is the documented behavior in `config-format.md`.\n */\nimport type { Experiment } from \"../config/types.js\";\nimport { hash32 } from \"./hash.js\";\n\nexport function assignWeighted(experiment: Experiment, userId: string): string {\n const split = experiment.split;\n if (split === undefined) return experiment.default;\n const ids = Object.keys(split).sort();\n if (ids.length === 0) return experiment.default;\n const bucket = hash32(`${userId}:${experiment.id}`) % 10000;\n let cumulative = 0;\n for (const id of ids) {\n cumulative += (split[id] ?? 0) * 100;\n if (bucket < cumulative) return id;\n }\n // Unreachable when the validator enforces sum === 100.\n return experiment.default;\n}\n","/**\n * Mutex group resolution.\n *\n * When a user is eligible for multiple experiments sharing the\n * same `mutex` group, the engine deterministically picks ONE\n * winner and excludes the rest (they fall back to their default\n * variant).\n *\n * Winner selection: `hash32(userId:mutex)` mod `candidates.length`\n * against the lexicographically sorted candidate list. Same user,\n * same group, same candidates → same winner, forever.\n *\n * The engine filters candidates to *eligible* experiments (passed\n * targeting + time gates) before calling this, so mutex resolution\n * never picks a non-targeted winner.\n */\nimport { hash32 } from \"./hash.js\";\n\nexport function resolveMutex(\n userId: string,\n mutexGroup: string,\n candidateIds: readonly string[],\n): string | undefined {\n if (candidateIds.length === 0) return undefined;\n const sorted = candidateIds.slice().sort();\n const bucket = hash32(`${userId}:${mutexGroup}`) % sorted.length;\n return sorted[bucket];\n}\n","/**\n * Assignment barrel.\n *\n * `assignVariant` is the single entry point used by the engine hot\n * path. It dispatches on `experiment.assignment` and falls back to\n * the default variant whenever the user isn't bucketable (missing\n * `userId`) — every non-`default` strategy depends on a stable\n * identity to be deterministic.\n */\nimport type { Experiment } from \"../config/types.js\";\nimport { assignDefault } from \"./default.js\";\nimport { assignRandom } from \"./random.js\";\nimport { assignStickyHash } from \"./sticky-hash.js\";\nimport { assignWeighted } from \"./weighted.js\";\n\nexport { assignDefault } from \"./default.js\";\nexport { bucketUserId, hash32 } from \"./hash.js\";\nexport { resolveMutex } from \"./mutex.js\";\nexport { assignRandom } from \"./random.js\";\nexport { assignStickyHash } from \"./sticky-hash.js\";\nexport { assignWeighted } from \"./weighted.js\";\n\nexport function assignVariant(experiment: Experiment, userId: string | undefined): string {\n const strategy = experiment.assignment ?? \"default\";\n if (strategy === \"default\") return assignDefault(experiment);\n if (userId === undefined || userId === \"\") return assignDefault(experiment);\n if (strategy === \"random\") return assignRandom(experiment, userId);\n if (strategy === \"sticky-hash\") return assignStickyHash(experiment, userId);\n if (strategy === \"weighted\") return assignWeighted(experiment, userId);\n return assignDefault(experiment);\n}\n","/**\n * Fixed-size ring buffer for engine event history.\n *\n * Overwrites the oldest entry when full. `toArray()` returns the\n * stored entries in chronological order (oldest → newest) which is\n * the order the debug overlay and time-travel replayer expect.\n *\n * Default capacity is 500 — at ~200 bytes per event this caps\n * in-memory history at ~100 KB per engine, which is negligible\n * compared to any other memory cost the app already pays.\n */\nexport class RingBuffer<T> {\n readonly capacity: number;\n private buffer: (T | undefined)[];\n private head = 0;\n private count = 0;\n\n constructor(capacity = 500) {\n if (!Number.isInteger(capacity) || capacity < 1) {\n throw new Error(\"RingBuffer capacity must be a positive integer\");\n }\n this.capacity = capacity;\n this.buffer = new Array<T | undefined>(capacity);\n }\n\n push(item: T): void {\n this.buffer[this.head] = item;\n this.head = (this.head + 1) % this.capacity;\n if (this.count < this.capacity) this.count++;\n }\n\n toArray(): T[] {\n const out: T[] = [];\n const start = this.count < this.capacity ? 0 : this.head;\n for (let i = 0; i < this.count; i++) {\n const item = this.buffer[(start + i) % this.capacity];\n if (item !== undefined) out.push(item);\n }\n return out;\n }\n\n clear(): void {\n this.buffer = new Array<T | undefined>(this.capacity);\n this.head = 0;\n this.count = 0;\n }\n\n get size(): number {\n return this.count;\n }\n}\n","/**\n * App version operator. Wraps the semver matcher. Fail-closed if the\n * context version is missing or unparseable.\n */\n\nimport { matchSemver } from \"../semver.js\";\n\nexport function matchAppVersion(range: string, ctxVersion: string | undefined): boolean {\n if (ctxVersion === undefined) return false;\n return matchSemver(range, ctxVersion);\n}\n","/**\n * Attributes operator. For each specified key, strict-equality\n * against `context.attributes[key]`. An empty targeting object\n * trivially matches (no constraints).\n */\n\nexport function matchAttributes(\n target: { readonly [key: string]: unknown },\n ctxAttrs: { readonly [key: string]: unknown } | undefined,\n): boolean {\n for (const k of Object.keys(target)) {\n if (ctxAttrs === undefined || ctxAttrs[k] !== target[k]) return false;\n }\n return true;\n}\n","/**\n * Locale operator. For each target in the array, matches if the\n * context locale equals the target OR starts with `target + \"-\"`.\n *\n * Targeting `\"en\"` matches `\"en\"`, `\"en-US\"`, `\"en-GB\"`.\n * Targeting `\"en-US\"` matches `\"en-US\"`, `\"en-US-POSIX\"` but not\n * `\"en\"` or `\"en-GB\"`.\n *\n * Case-sensitive — config authors are expected to normalize.\n */\n\nexport function matchLocale(target: ReadonlyArray<string>, ctxLocale: string | undefined): boolean {\n if (ctxLocale === undefined) return false;\n for (const t of target) {\n if (ctxLocale === t || ctxLocale.startsWith(`${t}-`)) return true;\n }\n return false;\n}\n","/**\n * Platform operator. Set membership; fails if the context's platform\n * is undefined. Linear scan is cheap — at most 4 elements per the\n * config allow-list.\n */\n\nexport function matchPlatform(\n target: ReadonlyArray<string>,\n ctxPlatform: string | undefined,\n): boolean {\n return ctxPlatform !== undefined && target.includes(ctxPlatform);\n}\n","/**\n * Routes operator. Iterates patterns and returns true on the first\n * match. Each pattern is parsed per call in this session; Session 4's\n * engine will pre-compile at config load.\n */\n\nimport { matchRoute } from \"../glob.js\";\n\nexport function matchRoutes(target: ReadonlyArray<string>, ctxRoute: string | undefined): boolean {\n if (ctxRoute === undefined) return false;\n for (let i = 0; i < target.length; i++) {\n if (matchRoute(target[i] as string, ctxRoute)) return true;\n }\n return false;\n}\n","/**\n * Screen size operator. Set membership on pre-bucketed sizes. The\n * adapter (or the engine's context updater) is responsible for\n * deriving the bucket from actual pixel dimensions.\n */\n\nexport function matchScreenSize(\n target: ReadonlyArray<string>,\n ctxSize: string | undefined,\n): boolean {\n return ctxSize !== undefined && target.includes(ctxSize);\n}\n","/**\n * User ID operator. Two modes:\n *\n * 1. List: match if `context.userId` is in the explicit string list.\n * 2. Hash bucket: match if the precomputed `userIdBucket` (0..99)\n * is strictly less than `mod`. The evaluator is synchronous and\n * cannot compute sha256 inline; the engine precomputes this on\n * every `updateContext` call and stashes the result on the eval\n * context. If the bucket is missing, the operator fails closed.\n */\n\nimport type { EvalContext, Targeting } from \"../types.js\";\n\ntype Target = NonNullable<Targeting[\"userId\"]>;\n\nexport function matchUserId(target: Target, context: EvalContext): boolean {\n // `\"mod\" in target` narrows the discriminated union reliably — unlike\n // `Array.isArray()`, which does not narrow `ReadonlyArray<T>`.\n if (\"mod\" in target) {\n const bucket = context.userIdBucket;\n return typeof bucket === \"number\" && bucket < target.mod;\n }\n return context.userId !== undefined && target.includes(context.userId);\n}\n","/**\n * Synchronous targeting evaluator. Walks the operators in the order\n * documented in `docs/design/targeting-dsl.md` and short-circuits on\n * the first failure.\n *\n * Order: platform → screenSize → locale → appVersion → routes →\n * attributes → userId → predicate\n *\n * The `enabled` kill switch and `startDate`/`endDate` are experiment-\n * level and live in `explain()` + Session 4's engine — they're not\n * part of `evaluate()`.\n */\n\nimport { matchAppVersion } from \"./operators/app-version.js\";\nimport { matchAttributes } from \"./operators/attributes.js\";\nimport { matchLocale } from \"./operators/locale.js\";\nimport { matchPlatform } from \"./operators/platform.js\";\nimport { matchRoutes } from \"./operators/routes.js\";\nimport { matchScreenSize } from \"./operators/screen-size.js\";\nimport { matchUserId } from \"./operators/user-id.js\";\nimport type { EvalContext, EvaluableTargeting, TargetingResult, VariantContext } from \"./types.js\";\n\nexport function evaluate(\n targeting: EvaluableTargeting,\n context: VariantContext | EvalContext,\n): TargetingResult {\n const c = context as EvalContext;\n if (targeting.platform !== undefined && !matchPlatform(targeting.platform, c.platform))\n return { matched: false, reason: \"platform\" };\n if (targeting.screenSize !== undefined && !matchScreenSize(targeting.screenSize, c.screenSize))\n return { matched: false, reason: \"screenSize\" };\n if (targeting.locale !== undefined && !matchLocale(targeting.locale, c.locale))\n return { matched: false, reason: \"locale\" };\n if (targeting.appVersion !== undefined && !matchAppVersion(targeting.appVersion, c.appVersion))\n return { matched: false, reason: \"appVersion\" };\n if (targeting.routes !== undefined && !matchRoutes(targeting.routes, c.route))\n return { matched: false, reason: \"routes\" };\n if (targeting.attributes !== undefined && !matchAttributes(targeting.attributes, c.attributes))\n return { matched: false, reason: \"attributes\" };\n if (targeting.userId !== undefined && !matchUserId(targeting.userId, c))\n return { matched: false, reason: \"userId\" };\n if (targeting.predicate !== undefined && !targeting.predicate(c))\n return { matched: false, reason: \"predicate\" };\n return { matched: true };\n}\n\n/** Thin convenience wrapper — matches the `API.md` surface. */\nexport function matchTargeting(\n targeting: EvaluableTargeting,\n context: VariantContext | EvalContext,\n): boolean {\n return evaluate(targeting, context).matched;\n}\n","/**\n * Kill-switch logic.\n *\n * Returns `true` when an experiment should short-circuit to its\n * default variant for a reason that isn't context-specific:\n *\n * - Global `config.enabled === false` — admin kill switch for\n * fast incident response.\n * - `status === \"archived\"` — the experiment is over, keep the\n * config around for history but never evaluate it.\n * - `status === \"draft\"` — the experiment is being authored; in\n * production this behaves the same as archived (returns the\n * default), the debug overlay shows it with a badge so devs\n * can still preview it.\n */\nimport type { Experiment, ExperimentsConfig } from \"../config/types.js\";\n\nexport function isKilled(config: ExperimentsConfig, experiment: Experiment): boolean {\n if (config.enabled === false) return true;\n if (experiment.status === \"archived\") return true;\n if (experiment.status === \"draft\") return true;\n return false;\n}\n","/**\n * Listener set for engine events.\n *\n * Iteration copies the underlying Set so that a listener that\n * unsubscribes itself (or another listener) during emission doesn't\n * skip the next listener. Errors thrown inside a listener are\n * swallowed — one bad subscriber must not break the engine for\n * everyone else.\n */\nimport type { EngineEvent } from \"../history/events.js\";\n\nexport type Listener = (event: EngineEvent) => void;\n\nexport class ListenerSet {\n private readonly listeners = new Set<Listener>();\n\n add(listener: Listener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n emit(event: EngineEvent): void {\n for (const listener of Array.from(this.listeners)) {\n try {\n listener(event);\n } catch {\n // Intentional: see file header.\n }\n }\n }\n\n clear(): void {\n this.listeners.clear();\n }\n\n get size(): number {\n return this.listeners.size;\n }\n}\n","/**\n * Start/end date gate.\n *\n * `startDate` is inclusive, `endDate` is exclusive. Matches the\n * semantics documented in `config-format.md` §`startDate / endDate`.\n *\n * `now` is injected (not read via `Date.now()` here) so that the\n * engine can snapshot time at a single point per resolution and\n * so that tests can pin time without mocking globals. The engine\n * calls `Date.now()` once per `getVariant` call at the outer\n * boundary.\n *\n * Malformed ISO strings fail-closed (the gate returns `true` to\n * keep the experiment inactive) — a broken date is a config\n * mistake the validator catches at load time, but defending in\n * depth here is ~10 bytes we're happy to spend.\n */\nimport type { Experiment } from \"../config/types.js\";\n\nexport function isTimeGated(experiment: Experiment, now: number): boolean {\n if (experiment.startDate !== undefined) {\n const t = Date.parse(experiment.startDate);\n if (!Number.isFinite(t) || now < t) return true;\n }\n if (experiment.endDate !== undefined) {\n const t = Date.parse(experiment.endDate);\n if (!Number.isFinite(t) || now >= t) return true;\n }\n return false;\n}\n","/**\n * The `VariantEngine`.\n *\n * Framework-agnostic runtime for `experiments.json`. Mirrors the\n * surface in `API.md` §`VariantEngine` and preserves the\n * non-negotiables from `ARCHITECTURE.md`:\n *\n * - `getVariant` is synchronous and O(1) after warmup.\n * - No `Math.random` anywhere in the hot path.\n * - `Date.now()` called once per resolution at the outer boundary.\n * - Fail-open by default; fail-closed throws.\n * - The loaded config is deeply frozen — no runtime mutation.\n *\n * Resolution order for `getVariant(id)`:\n *\n * 1. `dispose`d? → error path\n * 2. in-memory override? → return override\n * 3. cache hit? → return cached\n * 4. experiment exists? → no → error path\n * 5. rolled back? → return default\n * 6. kill-switched? → return default\n * 7. time-gated? → return default\n * 8. targeting matches? → no → return default\n * 9. mutex winner? → no → return default\n * 10. assign → cache, emit, return\n */\n\nimport { bucketUserId } from \"../assignment/hash.js\";\nimport { assignVariant } from \"../assignment/index.js\";\nimport { resolveMutex } from \"../assignment/mutex.js\";\nimport type { Experiment, ExperimentsConfig, VariantContext } from \"../config/types.js\";\nimport { validateConfig } from \"../config/validator.js\";\nimport type { EngineEvent } from \"../history/events.js\";\nimport { RingBuffer } from \"../history/ring-buffer.js\";\nimport { evaluate } from \"../targeting/evaluator.js\";\nimport { matchRoute } from \"../targeting/glob.js\";\nimport type { EvalContext, EvaluableTargeting } from \"../targeting/types.js\";\nimport { CrashCounter } from \"./crash-counter.js\";\nimport { isKilled } from \"./kill-switch.js\";\nimport { type Listener, ListenerSet } from \"./subscribe.js\";\nimport { isTimeGated } from \"./time-gate.js\";\n\nexport type FailMode = \"fail-open\" | \"fail-closed\";\n\nexport type VariantChangeSource = \"user\" | \"system\" | \"deeplink\" | \"qr\";\n\nexport interface EngineOptions {\n readonly context?: VariantContext;\n readonly failMode?: FailMode;\n readonly historySize?: number;\n /**\n * Pre-resolved assignments to seed the engine cache with at construction.\n *\n * Used by SSR adapters (e.g. `@variantlab/next`) to hydrate a client-side\n * engine with the exact variants the server already rendered, so the first\n * `getVariant` call short-circuits on a cache hit instead of re-evaluating\n * targeting/assignment and risking hydration mismatches.\n *\n * Entries whose experiment id is not in the config, or whose variant id is\n * not in the experiment's variants, are silently ignored. Seeding does NOT\n * emit an `assignment` event — events fire on the first real `getVariant`\n * call. `updateContext`/`loadConfig` still clear the cache.\n */\n readonly initialAssignments?: Readonly<Record<string, string>>;\n}\n\n/** Thrown in fail-closed mode when an experiment id isn't in the config. */\nexport class UnknownExperimentError extends Error {\n readonly experimentId: string;\n constructor(experimentId: string) {\n super(`Unknown experiment: ${experimentId}`);\n this.name = \"UnknownExperimentError\";\n this.experimentId = experimentId;\n }\n}\n\nexport class VariantEngine {\n private config: ExperimentsConfig;\n private experimentIndex: Map<string, Experiment>;\n private context: VariantContext;\n private evalContext: EvalContext;\n private readonly failMode: FailMode;\n private readonly history: RingBuffer<EngineEvent>;\n private readonly listeners = new ListenerSet();\n private readonly overrides = new Map<string, string>();\n private readonly cache = new Map<string, string>();\n private readonly rolledBack = new Set<string>();\n private readonly crashCounter = new CrashCounter();\n private disposed = false;\n\n constructor(config: ExperimentsConfig, options: EngineOptions = {}) {\n this.config = config;\n this.experimentIndex = indexExperiments(config);\n this.context = options.context ?? {};\n this.evalContext = buildEvalContext(this.context);\n this.failMode = options.failMode ?? \"fail-open\";\n this.history = new RingBuffer<EngineEvent>(options.historySize ?? 500);\n this.seedInitialAssignments(options.initialAssignments);\n this.emit({ type: \"ready\", config });\n }\n\n /**\n * Copy caller-supplied `{ experimentId: variantId }` pairs into the\n * in-memory cache so the next `getVariant` call returns them without\n * re-evaluating targeting. Invalid pairs are silently dropped — seeding\n * is best-effort hydration, never a hard error.\n */\n private seedInitialAssignments(seed: Readonly<Record<string, string>> | undefined): void {\n if (seed === undefined) return;\n for (const experimentId of Object.keys(seed)) {\n const variantId = seed[experimentId];\n if (typeof variantId !== \"string\" || variantId.length === 0) continue;\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) continue;\n if (!experiment.variants.some((v) => v.id === variantId)) continue;\n this.cache.set(experimentId, variantId);\n }\n }\n\n // ---------- resolution ---------------------------------------------------\n\n getVariant(experimentId: string): string {\n if (this.disposed) {\n return this.handleError(new Error(\"VariantEngine is disposed\"), experimentId);\n }\n try {\n const override = this.overrides.get(experimentId);\n if (override !== undefined) return override;\n\n const cached = this.cache.get(experimentId);\n if (cached !== undefined) return cached;\n\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) {\n if (this.failMode === \"fail-closed\") {\n throw new UnknownExperimentError(experimentId);\n }\n return this.handleError(new UnknownExperimentError(experimentId), experimentId);\n }\n\n if (this.rolledBack.has(experimentId)) return experiment.default;\n if (isKilled(this.config, experiment)) return experiment.default;\n if (isTimeGated(experiment, Date.now())) return experiment.default;\n\n if (!this.isTargeted(experiment)) return experiment.default;\n\n if (experiment.mutex !== undefined) {\n const winner = this.resolveMutexWinner(experiment.mutex);\n if (winner !== experimentId) return experiment.default;\n }\n\n const variantId = assignVariant(experiment, this.context.userId);\n this.cache.set(experimentId, variantId);\n this.emit({ type: \"assignment\", experimentId, variantId, context: this.context });\n return variantId;\n } catch (err) {\n if (this.failMode === \"fail-closed\") throw err;\n return this.handleError(err as Error, experimentId);\n }\n }\n\n getVariantValue<T = unknown>(experimentId: string): T {\n const variantId = this.getVariant(experimentId);\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) return undefined as T;\n const variant = experiment.variants.find((v) => v.id === variantId);\n return (variant?.value as T) ?? (undefined as T);\n }\n\n // ---------- overrides ---------------------------------------------------\n\n setVariant(experimentId: string, variantId: string, source: VariantChangeSource = \"user\"): void {\n if (this.disposed) return;\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) return;\n if (!experiment.variants.some((v) => v.id === variantId)) return;\n this.overrides.set(experimentId, variantId);\n this.emit({ type: \"variantChanged\", experimentId, variantId, source });\n }\n\n clearVariant(experimentId: string): void {\n if (this.disposed) return;\n if (!this.overrides.delete(experimentId)) return;\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) return;\n const next = this.getVariant(experimentId);\n this.emit({ type: \"variantChanged\", experimentId, variantId: next, source: \"system\" });\n }\n\n resetAll(): void {\n if (this.disposed) return;\n this.overrides.clear();\n this.cache.clear();\n this.rolledBack.clear();\n for (const experiment of this.config.experiments) {\n this.emit({\n type: \"variantChanged\",\n experimentId: experiment.id,\n variantId: this.getVariant(experiment.id),\n source: \"system\",\n });\n }\n }\n\n // ---------- lookup ------------------------------------------------------\n\n /**\n * Returns the currently loaded, deeply-frozen {@link ExperimentsConfig}.\n *\n * Exposed read-only so debug surfaces (e.g. `<VariantDebugOverlay />`)\n * can display the raw config without reaching into private fields.\n * Mutating this value has no effect on the engine.\n */\n getConfig(): ExperimentsConfig {\n return this.config;\n }\n\n /**\n * Returns a shallow copy of the current {@link VariantContext}.\n *\n * A copy is returned rather than the live object so callers can't\n * accidentally mutate engine state. Use {@link updateContext} to\n * change it.\n */\n getContext(): VariantContext {\n return { ...this.context };\n }\n\n getExperiments(route?: string): readonly Experiment[] {\n if (route === undefined) return this.config.experiments;\n return this.config.experiments.filter((exp) => {\n if (exp.routes === undefined) return true;\n return exp.routes.some((pattern) => matchRoute(pattern, route));\n });\n }\n\n // ---------- subscriptions ----------------------------------------------\n\n subscribe(listener: Listener): () => void {\n return this.listeners.add(listener);\n }\n\n // ---------- mutation ----------------------------------------------------\n\n updateContext(patch: Partial<VariantContext>): void {\n if (this.disposed) return;\n const merged: VariantContext = { ...this.context, ...patch };\n this.context = merged;\n this.evalContext = buildEvalContext(merged);\n this.cache.clear();\n this.emit({ type: \"contextUpdated\", context: merged });\n }\n\n async loadConfig(next: unknown): Promise<void> {\n if (this.disposed) return;\n const validated = validateConfig(next);\n this.config = validated;\n this.experimentIndex = indexExperiments(validated);\n this.cache.clear();\n this.rolledBack.clear();\n this.crashCounter.clear();\n this.emit({ type: \"configLoaded\", config: validated });\n }\n\n // ---------- crash rollback ---------------------------------------------\n\n reportCrash(experimentId: string, _error: Error): void {\n if (this.disposed) return;\n const experiment = this.experimentIndex.get(experimentId);\n if (experiment === undefined) return;\n const rollback = experiment.rollback;\n if (rollback === undefined) return;\n const now = Date.now();\n const count = this.crashCounter.record(experimentId, now, rollback.window);\n if (count >= rollback.threshold) {\n this.rolledBack.add(experimentId);\n this.cache.delete(experimentId);\n this.overrides.delete(experimentId);\n this.emit({\n type: \"rollback\",\n experimentId,\n variantId: experiment.default,\n reason: `threshold ${rollback.threshold} crashes in ${rollback.window}ms`,\n });\n }\n }\n\n // ---------- history -----------------------------------------------------\n\n getHistory(): readonly EngineEvent[] {\n return this.history.toArray();\n }\n\n // ---------- lifecycle ---------------------------------------------------\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.listeners.clear();\n this.overrides.clear();\n this.cache.clear();\n this.rolledBack.clear();\n this.crashCounter.clear();\n }\n\n // ---------- internals ---------------------------------------------------\n\n private isTargeted(experiment: Experiment): boolean {\n if (experiment.targeting === undefined) return true;\n return evaluate(experiment.targeting as EvaluableTargeting, this.evalContext).matched;\n }\n\n private resolveMutexWinner(group: string): string | undefined {\n const userId = this.context.userId;\n if (userId === undefined || userId === \"\") return undefined;\n const candidates: string[] = [];\n const now = Date.now();\n for (const exp of this.config.experiments) {\n if (exp.mutex !== group) continue;\n if (this.rolledBack.has(exp.id)) continue;\n if (isKilled(this.config, exp)) continue;\n if (isTimeGated(exp, now)) continue;\n if (!this.isTargeted(exp)) continue;\n candidates.push(exp.id);\n }\n return resolveMutex(userId, group, candidates);\n }\n\n private emit(event: EngineEvent): void {\n this.history.push(event);\n this.listeners.emit(event);\n }\n\n private handleError(error: Error, experimentId: string): string {\n const experiment = this.experimentIndex.get(experimentId);\n this.emit({ type: \"error\", error });\n return experiment?.default ?? \"\";\n }\n}\n\nfunction buildEvalContext(ctx: VariantContext): EvalContext {\n if (ctx.userId === undefined) return ctx;\n return { ...ctx, userIdBucket: bucketUserId(ctx.userId) };\n}\n\nfunction indexExperiments(config: ExperimentsConfig): Map<string, Experiment> {\n const map = new Map<string, Experiment>();\n for (const exp of config.experiments) map.set(exp.id, exp);\n return map;\n}\n","/**\n * `createEngine` — preferred factory over `new VariantEngine()`.\n *\n * The factory validates + deep-freezes the config before instantiation\n * so that callers don't have to remember the two-step dance. The\n * options bag is passed through untouched.\n */\nimport { validateConfig } from \"../config/validator.js\";\nimport { type EngineOptions, VariantEngine } from \"./engine.js\";\n\nexport function createEngine(config: unknown, options: EngineOptions = {}): VariantEngine {\n return new VariantEngine(validateConfig(config), options);\n}\n"]}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/targeting/semver.ts
|
|
4
|
+
function parseVersion(s) {
|
|
5
|
+
if (s.length === 0) return null;
|
|
6
|
+
const parts = [0, 0, 0];
|
|
7
|
+
let idx = 0;
|
|
8
|
+
let part = 0;
|
|
9
|
+
let seen = false;
|
|
10
|
+
for (let i = 0; i < s.length; i++) {
|
|
11
|
+
const c = s.charCodeAt(i);
|
|
12
|
+
if (c === 46) {
|
|
13
|
+
if (!seen) return null;
|
|
14
|
+
parts[idx++] = part;
|
|
15
|
+
if (idx > 2) return null;
|
|
16
|
+
part = 0;
|
|
17
|
+
seen = false;
|
|
18
|
+
} else if (c >= 48 && c <= 57) {
|
|
19
|
+
part = part * 10 + (c - 48);
|
|
20
|
+
seen = true;
|
|
21
|
+
} else return null;
|
|
22
|
+
}
|
|
23
|
+
if (!seen || idx !== 2) return null;
|
|
24
|
+
parts[2] = part;
|
|
25
|
+
return [parts[0], parts[1], parts[2]];
|
|
26
|
+
}
|
|
27
|
+
function cmpVersion(a, b) {
|
|
28
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
29
|
+
}
|
|
30
|
+
function parseSemver(s) {
|
|
31
|
+
if (s.length === 0) return null;
|
|
32
|
+
const clauses = [];
|
|
33
|
+
for (const part of s.split("||")) {
|
|
34
|
+
const c = parseClause(part.trim());
|
|
35
|
+
if (c === null) return null;
|
|
36
|
+
clauses.push(c);
|
|
37
|
+
}
|
|
38
|
+
return clauses;
|
|
39
|
+
}
|
|
40
|
+
function parseClause(s) {
|
|
41
|
+
if (s.length === 0) return null;
|
|
42
|
+
const hy = s.indexOf(" - ");
|
|
43
|
+
if (hy >= 0) {
|
|
44
|
+
const lo = parseVersion(s.slice(0, hy).trim());
|
|
45
|
+
const hi = parseVersion(s.slice(hy + 3).trim());
|
|
46
|
+
if (lo === null || hi === null) return null;
|
|
47
|
+
return [
|
|
48
|
+
{ op: ">=", v: lo },
|
|
49
|
+
{ op: "<=", v: hi }
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
const cmps = [];
|
|
53
|
+
for (const tok of s.split(/\s+/)) {
|
|
54
|
+
if (tok.length === 0) continue;
|
|
55
|
+
const parsed = parseComparator(tok);
|
|
56
|
+
if (parsed === null) return null;
|
|
57
|
+
for (const c of parsed) cmps.push(c);
|
|
58
|
+
}
|
|
59
|
+
return cmps.length > 0 ? cmps : null;
|
|
60
|
+
}
|
|
61
|
+
function parseComparator(s) {
|
|
62
|
+
const c0 = s[0];
|
|
63
|
+
if (c0 === "^" || c0 === "~") {
|
|
64
|
+
const v2 = parseVersion(s.slice(1));
|
|
65
|
+
if (v2 === null) return null;
|
|
66
|
+
const upper = c0 === "^" ? [v2[0] + 1, 0, 0] : [v2[0], v2[1] + 1, 0];
|
|
67
|
+
return [
|
|
68
|
+
{ op: ">=", v: v2 },
|
|
69
|
+
{ op: "<", v: upper }
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
let op = "=";
|
|
73
|
+
let rest = s;
|
|
74
|
+
if (c0 === ">" || c0 === "<") {
|
|
75
|
+
if (s[1] === "=") {
|
|
76
|
+
op = `${c0}=`;
|
|
77
|
+
rest = s.slice(2);
|
|
78
|
+
} else {
|
|
79
|
+
op = c0;
|
|
80
|
+
rest = s.slice(1);
|
|
81
|
+
}
|
|
82
|
+
} else if (c0 === "=") {
|
|
83
|
+
rest = s.slice(1);
|
|
84
|
+
}
|
|
85
|
+
const v = parseVersion(rest);
|
|
86
|
+
return v === null ? null : [{ op, v }];
|
|
87
|
+
}
|
|
88
|
+
function matchCompiled(range, version) {
|
|
89
|
+
for (const clause of range) if (matchClause(clause, version)) return true;
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
function matchClause(clause, version) {
|
|
93
|
+
for (const c of clause) {
|
|
94
|
+
const d = cmpVersion(version, c.v);
|
|
95
|
+
const op = c.op;
|
|
96
|
+
const fail = op === "=" ? d !== 0 : op === "<" ? d >= 0 : op === "<=" ? d > 0 : op === ">" ? d <= 0 : d < 0;
|
|
97
|
+
if (fail) return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
function matchSemver(range, version) {
|
|
102
|
+
const r = parseSemver(range);
|
|
103
|
+
if (r === null) return false;
|
|
104
|
+
const v = parseVersion(version);
|
|
105
|
+
return v !== null && matchCompiled(r, v);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/targeting/operators/app-version.ts
|
|
109
|
+
function matchAppVersion(range, ctxVersion) {
|
|
110
|
+
if (ctxVersion === void 0) return false;
|
|
111
|
+
return matchSemver(range, ctxVersion);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/targeting/operators/attributes.ts
|
|
115
|
+
function matchAttributes(target, ctxAttrs) {
|
|
116
|
+
for (const k of Object.keys(target)) {
|
|
117
|
+
if (ctxAttrs === void 0 || ctxAttrs[k] !== target[k]) return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/targeting/operators/locale.ts
|
|
123
|
+
function matchLocale(target, ctxLocale) {
|
|
124
|
+
if (ctxLocale === void 0) return false;
|
|
125
|
+
for (const t of target) {
|
|
126
|
+
if (ctxLocale === t || ctxLocale.startsWith(`${t}-`)) return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/targeting/operators/platform.ts
|
|
132
|
+
function matchPlatform(target, ctxPlatform) {
|
|
133
|
+
return ctxPlatform !== void 0 && target.includes(ctxPlatform);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/targeting/glob.ts
|
|
137
|
+
function compileGlob(pattern) {
|
|
138
|
+
if (pattern.length === 0) return null;
|
|
139
|
+
if (pattern === "*") return [{ kind: "param" }];
|
|
140
|
+
if (pattern === "**") return [{ kind: "rest" }];
|
|
141
|
+
if (pattern[0] !== "/") return null;
|
|
142
|
+
if (pattern.indexOf("***") >= 0) return null;
|
|
143
|
+
const normalized = pattern.length > 1 && pattern.endsWith("/") ? pattern.slice(0, -1) : pattern;
|
|
144
|
+
if (normalized === "/") return [];
|
|
145
|
+
const raw = normalized.slice(1).split("/");
|
|
146
|
+
const segs = [];
|
|
147
|
+
for (let i = 0; i < raw.length; i++) {
|
|
148
|
+
const part = raw[i];
|
|
149
|
+
if (part.length === 0) return null;
|
|
150
|
+
if (part === "**") {
|
|
151
|
+
if (i !== raw.length - 1) return null;
|
|
152
|
+
segs.push({ kind: "rest" });
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (part === "*") {
|
|
156
|
+
segs.push({ kind: "param" });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (part[0] === ":") {
|
|
160
|
+
if (part.length < 2) return null;
|
|
161
|
+
segs.push({ kind: "param" });
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (/[*:?[\]{}!]/.test(part)) return null;
|
|
165
|
+
segs.push({ kind: "literal", value: part });
|
|
166
|
+
}
|
|
167
|
+
return segs;
|
|
168
|
+
}
|
|
169
|
+
function matchCompiledRoute(segs, path) {
|
|
170
|
+
if (path.length === 0) return false;
|
|
171
|
+
if (path[0] !== "/") return false;
|
|
172
|
+
const normalized = path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
173
|
+
if (segs.length === 0) return normalized === "/";
|
|
174
|
+
const parts = normalized === "/" ? [] : normalized.slice(1).split("/");
|
|
175
|
+
for (let i = 0; i < segs.length; i++) {
|
|
176
|
+
const seg = segs[i];
|
|
177
|
+
if (seg.kind === "rest") {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
if (i >= parts.length) return false;
|
|
181
|
+
const part = parts[i];
|
|
182
|
+
if (part.length === 0) return false;
|
|
183
|
+
if (seg.kind === "literal") {
|
|
184
|
+
if (seg.value !== part) return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return parts.length === segs.length;
|
|
188
|
+
}
|
|
189
|
+
function matchRoute(pattern, path) {
|
|
190
|
+
const segs = compileGlob(pattern);
|
|
191
|
+
if (segs === null) return false;
|
|
192
|
+
return matchCompiledRoute(segs, path);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/targeting/operators/routes.ts
|
|
196
|
+
function matchRoutes(target, ctxRoute) {
|
|
197
|
+
if (ctxRoute === void 0) return false;
|
|
198
|
+
for (let i = 0; i < target.length; i++) {
|
|
199
|
+
if (matchRoute(target[i], ctxRoute)) return true;
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/targeting/operators/screen-size.ts
|
|
205
|
+
function matchScreenSize(target, ctxSize) {
|
|
206
|
+
return ctxSize !== void 0 && target.includes(ctxSize);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/targeting/operators/user-id.ts
|
|
210
|
+
function matchUserId(target, context) {
|
|
211
|
+
if ("mod" in target) {
|
|
212
|
+
const bucket = context.userIdBucket;
|
|
213
|
+
return typeof bucket === "number" && bucket < target.mod;
|
|
214
|
+
}
|
|
215
|
+
return context.userId !== void 0 && target.includes(context.userId);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/targeting/evaluator.ts
|
|
219
|
+
function evaluate(targeting, context) {
|
|
220
|
+
const c = context;
|
|
221
|
+
if (targeting.platform !== void 0 && !matchPlatform(targeting.platform, c.platform))
|
|
222
|
+
return { matched: false, reason: "platform" };
|
|
223
|
+
if (targeting.screenSize !== void 0 && !matchScreenSize(targeting.screenSize, c.screenSize))
|
|
224
|
+
return { matched: false, reason: "screenSize" };
|
|
225
|
+
if (targeting.locale !== void 0 && !matchLocale(targeting.locale, c.locale))
|
|
226
|
+
return { matched: false, reason: "locale" };
|
|
227
|
+
if (targeting.appVersion !== void 0 && !matchAppVersion(targeting.appVersion, c.appVersion))
|
|
228
|
+
return { matched: false, reason: "appVersion" };
|
|
229
|
+
if (targeting.routes !== void 0 && !matchRoutes(targeting.routes, c.route))
|
|
230
|
+
return { matched: false, reason: "routes" };
|
|
231
|
+
if (targeting.attributes !== void 0 && !matchAttributes(targeting.attributes, c.attributes))
|
|
232
|
+
return { matched: false, reason: "attributes" };
|
|
233
|
+
if (targeting.userId !== void 0 && !matchUserId(targeting.userId, c))
|
|
234
|
+
return { matched: false, reason: "userId" };
|
|
235
|
+
if (targeting.predicate !== void 0 && !targeting.predicate(c))
|
|
236
|
+
return { matched: false, reason: "predicate" };
|
|
237
|
+
return { matched: true };
|
|
238
|
+
}
|
|
239
|
+
function matchTargeting(targeting, context) {
|
|
240
|
+
return evaluate(targeting, context).matched;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/targeting/explain.ts
|
|
244
|
+
function explain(experiment, context) {
|
|
245
|
+
const steps = [];
|
|
246
|
+
const record = (field, ok, detail) => {
|
|
247
|
+
steps.push(ok ? { field, matched: true } : { field, matched: false, detail });
|
|
248
|
+
return ok ? null : { matched: false, reason: field, steps };
|
|
249
|
+
};
|
|
250
|
+
if (experiment.startDate !== void 0) {
|
|
251
|
+
const t = Date.parse(experiment.startDate);
|
|
252
|
+
const r = record(
|
|
253
|
+
"startDate",
|
|
254
|
+
Number.isFinite(t) && Date.now() >= t,
|
|
255
|
+
`now<${experiment.startDate}`
|
|
256
|
+
);
|
|
257
|
+
if (r) return r;
|
|
258
|
+
}
|
|
259
|
+
if (experiment.endDate !== void 0) {
|
|
260
|
+
const t = Date.parse(experiment.endDate);
|
|
261
|
+
const r = record("endDate", Number.isFinite(t) && Date.now() < t, `now>=${experiment.endDate}`);
|
|
262
|
+
if (r) return r;
|
|
263
|
+
}
|
|
264
|
+
const tg = experiment.targeting;
|
|
265
|
+
if (tg === void 0) return { matched: true, steps };
|
|
266
|
+
const ctx = context;
|
|
267
|
+
if (tg.platform !== void 0) {
|
|
268
|
+
const r = record(
|
|
269
|
+
"platform",
|
|
270
|
+
matchPlatform(tg.platform, ctx.platform),
|
|
271
|
+
`${ctx.platform} vs ${tg.platform}`
|
|
272
|
+
);
|
|
273
|
+
if (r) return r;
|
|
274
|
+
}
|
|
275
|
+
if (tg.screenSize !== void 0) {
|
|
276
|
+
const r = record(
|
|
277
|
+
"screenSize",
|
|
278
|
+
matchScreenSize(tg.screenSize, ctx.screenSize),
|
|
279
|
+
`${ctx.screenSize} vs ${tg.screenSize}`
|
|
280
|
+
);
|
|
281
|
+
if (r) return r;
|
|
282
|
+
}
|
|
283
|
+
if (tg.locale !== void 0) {
|
|
284
|
+
const r = record("locale", matchLocale(tg.locale, ctx.locale), `${ctx.locale} vs ${tg.locale}`);
|
|
285
|
+
if (r) return r;
|
|
286
|
+
}
|
|
287
|
+
if (tg.appVersion !== void 0) {
|
|
288
|
+
const r = record(
|
|
289
|
+
"appVersion",
|
|
290
|
+
matchAppVersion(tg.appVersion, ctx.appVersion),
|
|
291
|
+
`${ctx.appVersion} vs ${tg.appVersion}`
|
|
292
|
+
);
|
|
293
|
+
if (r) return r;
|
|
294
|
+
}
|
|
295
|
+
if (tg.routes !== void 0) {
|
|
296
|
+
const r = record("routes", matchRoutes(tg.routes, ctx.route), `${ctx.route} vs ${tg.routes}`);
|
|
297
|
+
if (r) return r;
|
|
298
|
+
}
|
|
299
|
+
if (tg.attributes !== void 0) {
|
|
300
|
+
const r = record("attributes", matchAttributes(tg.attributes, ctx.attributes), "mismatch");
|
|
301
|
+
if (r) return r;
|
|
302
|
+
}
|
|
303
|
+
if (tg.userId !== void 0) {
|
|
304
|
+
const r = record("userId", matchUserId(tg.userId, ctx), "mismatch");
|
|
305
|
+
if (r) return r;
|
|
306
|
+
}
|
|
307
|
+
if (tg.predicate !== void 0) {
|
|
308
|
+
const r = record("predicate", tg.predicate(ctx), "false");
|
|
309
|
+
if (r) return r;
|
|
310
|
+
}
|
|
311
|
+
return { matched: true, steps };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/targeting/hash.ts
|
|
315
|
+
var encoder = new TextEncoder();
|
|
316
|
+
async function hashUserId(userId) {
|
|
317
|
+
const bytes = encoder.encode(userId);
|
|
318
|
+
const g = globalThis;
|
|
319
|
+
const buf = await g.crypto.subtle.digest("SHA-256", bytes);
|
|
320
|
+
const view = new DataView(buf);
|
|
321
|
+
const uint32 = view.getUint32(0, false);
|
|
322
|
+
return uint32 % 100;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
exports.evaluate = evaluate;
|
|
326
|
+
exports.explain = explain;
|
|
327
|
+
exports.hashUserId = hashUserId;
|
|
328
|
+
exports.matchRoute = matchRoute;
|
|
329
|
+
exports.matchSemver = matchSemver;
|
|
330
|
+
exports.matchTargeting = matchTargeting;
|
|
331
|
+
//# sourceMappingURL=targeting.cjs.map
|
|
332
|
+
//# sourceMappingURL=targeting.cjs.map
|