@directive-run/core 1.11.0 → 1.13.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/dist/adapter-utils.cjs +1 -1
- package/dist/adapter-utils.d.cts +2 -2
- package/dist/adapter-utils.d.ts +2 -2
- package/dist/adapter-utils.js +1 -1
- package/dist/adapter-utils.js.map +1 -1
- package/dist/audit-ledger-Dc6hAXam.d.cts +378 -0
- package/dist/audit-ledger-dxvslGi3.d.ts +378 -0
- package/dist/chunk-2FF6QGOA.js +2 -0
- package/dist/chunk-2FF6QGOA.js.map +1 -0
- package/dist/chunk-4MNQDXH7.cjs +3 -0
- package/dist/chunk-4MNQDXH7.cjs.map +1 -0
- package/dist/chunk-644QZVTT.js +16 -0
- package/dist/{chunk-26Z5VNPZ.js.map → chunk-644QZVTT.js.map} +1 -1
- package/dist/chunk-ENZEHIL7.cjs +3 -0
- package/dist/chunk-ENZEHIL7.cjs.map +1 -0
- package/dist/chunk-I722BZA5.js +7 -0
- package/dist/chunk-I722BZA5.js.map +1 -0
- package/dist/chunk-IXRS4LM4.cjs +2 -0
- package/dist/chunk-IXRS4LM4.cjs.map +1 -0
- package/dist/chunk-NPX5EKPP.cjs +16 -0
- package/dist/{chunk-EX3XG667.cjs.map → chunk-NPX5EKPP.cjs.map} +1 -1
- package/dist/chunk-PA6VC32N.js +2 -0
- package/dist/chunk-PA6VC32N.js.map +1 -0
- package/dist/chunk-PXRV64PA.js +3 -0
- package/dist/chunk-PXRV64PA.js.map +1 -0
- package/dist/chunk-R2GHSCTR.js +3 -0
- package/dist/chunk-R2GHSCTR.js.map +1 -0
- package/dist/chunk-T4TRJEJN.cjs +2 -0
- package/dist/chunk-T4TRJEJN.cjs.map +1 -0
- package/dist/chunk-X7G7UBXU.cjs +7 -0
- package/dist/chunk-X7G7UBXU.cjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +214 -391
- package/dist/index.d.ts +214 -391
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +1 -1
- package/dist/internals.d.cts +5 -5
- package/dist/internals.d.ts +5 -5
- package/dist/internals.js +1 -1
- package/dist/plugins/index.cjs +2 -2
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.d.cts +2 -2
- package/dist/plugins/index.d.ts +2 -2
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/{plugins-Ykl_sAPE.d.ts → plugins-BIzXaYbg.d.cts} +15 -1
- package/dist/{plugins-Ykl_sAPE.d.cts → plugins-BIzXaYbg.d.ts} +15 -1
- package/dist/predicate-Bnx3LN7P.d.cts +655 -0
- package/dist/predicate-BxQVf0ug.d.ts +655 -0
- package/dist/system-A6VYKLVF.js +2 -0
- package/dist/{system-VZWB6WXX.js.map → system-A6VYKLVF.js.map} +1 -1
- package/dist/system-CDJMD5O5.cjs +2 -0
- package/dist/{system-GK3NSFQH.cjs.map → system-CDJMD5O5.cjs.map} +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/{utils-BnQajqPu.d.cts → utils-Mg55IerF.d.cts} +27 -1
- package/dist/{utils-BnQajqPu.d.ts → utils-Mg55IerF.d.ts} +27 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/audit-ledger-9IElAHH9.d.ts +0 -205
- package/dist/audit-ledger-qMjEBqiP.d.cts +0 -205
- package/dist/chunk-26Z5VNPZ.js +0 -16
- package/dist/chunk-4VZOZWXM.cjs +0 -2
- package/dist/chunk-4VZOZWXM.cjs.map +0 -1
- package/dist/chunk-7NMXRATK.cjs +0 -3
- package/dist/chunk-7NMXRATK.cjs.map +0 -1
- package/dist/chunk-7TSYQEN3.js +0 -2
- package/dist/chunk-7TSYQEN3.js.map +0 -1
- package/dist/chunk-EOLY64E6.cjs +0 -3
- package/dist/chunk-EOLY64E6.cjs.map +0 -1
- package/dist/chunk-EX3XG667.cjs +0 -16
- package/dist/chunk-N4KTCKOI.cjs +0 -7
- package/dist/chunk-N4KTCKOI.cjs.map +0 -1
- package/dist/chunk-T6IJUWYR.js +0 -3
- package/dist/chunk-T6IJUWYR.js.map +0 -1
- package/dist/chunk-TPOKS4RY.js +0 -3
- package/dist/chunk-TPOKS4RY.js.map +0 -1
- package/dist/chunk-TZHC4E6S.js +0 -7
- package/dist/chunk-TZHC4E6S.js.map +0 -1
- package/dist/helpers-D2pfb6vT.d.ts +0 -235
- package/dist/helpers-hh6UanB1.d.cts +0 -235
- package/dist/system-GK3NSFQH.cjs +0 -2
- package/dist/system-VZWB6WXX.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/types/predicate.ts","../src/core/schema-introspection.ts","../src/core/predicate.ts"],"names":["PREDICATE_OPERATORS","PREDICATE_COMBINATORS","PRIMITIVE_KINDS","parseTypeName","typeName","branded","getKind","schema","dev_true_default","s","kindNode","getSchemaFieldKinds","out","root","facts","key","builder","node","innerKey","innerNode","COMMON_OPS","ORDERABLE_OPS","STRING_OPS","getOperatorsForKind","sets","m","first","intersection","op","listAllPredicateOperators","MAX_PREDICATE_DEPTH","isPlainObject","v","isPlainObjectStrict","proto","isOperatorObject","count","hasDollarKey","k","devWarn","isPredicate","c","walkPredicate","spec","visitor","path","seen","depth","clause","i","clausePath","obj","kind","children","child","childPath","value","opObj","isEmptyOrConfigPredicate","isPredicateBody","isTemplate","validatePredicate","checkValueJsonSafe","at","el","checkOperand","_factPath","operand","operandPath","factPath","dangerousRegex","source","validatePredicateAgainstSchema","kindMap","opts","errors","operatorCount","maxOperatorCount","maxArrayOperandLength","_operandPath","e","regexSource","allowedOps","_value","deepEqualSeen","pairId","id","deepEqual","a","b","guard","bArr","w","bEntries","used","ka","va","found","kb","vb","ak","bk","toComparable","relational","actual","applyOperator","prevValue","lo","hi","message","evalField","prev","keys","evaluatePredicate","fact","p","evaluatePredicateExplained","pathPrefix","childSpecs","passCount","pass","memoizedCache","memoizePredicate","predicate","cached","fn","extractDeps","prefix","deps","IDENTIFIER","stringifyValueQuiet","stringifyValue","evaluateTemplate","scope","tpl","end","present","extractTemplateKeys","evaluateKeySelector","selector","field","stableStringify","applyPatch","payload","set","safePayload","refKey"],"mappings":"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","file":"chunk-2FF6QGOA.js","sourcesContent":["/**\n * Data-configuration predicates and templates.\n *\n * A {@link FactPredicate} is a declarative, serializable boolean spec over a\n * module's fact namespace — the data form of a constraint `when`, an effect\n * `on`, or a boolean derivation. A {@link FactTemplate} is the value-producing\n * counterpart: a fact-interpolating string.\n *\n * Convention: `$` marks an operator/expression node inside a predicate or\n * template body (`$eq`, `$gte`, `$all`, `$template`, `$set`, `$ref`).\n * Definition arms (`compute`, `handler`, `patch`) stay sigil-free.\n *\n * Operators are `$`-prefixed so they can never collide with a fact key —\n * schema keys starting with `$` are rejected at registration.\n */\n\n// ============================================================================\n// Operators\n// ============================================================================\n\n/** Comparison operator names — the `$`-prefixed keys inside an operator object. */\nexport type PredicateOp =\n | \"$eq\"\n | \"$ne\"\n | \"$in\"\n | \"$nin\"\n | \"$exists\"\n | \"$gt\"\n | \"$gte\"\n | \"$lt\"\n | \"$lte\"\n | \"$between\"\n | \"$matches\"\n | \"$startsWith\"\n | \"$endsWith\"\n | \"$contains\"\n | \"$changed\";\n\n/** Combinator node keys. */\nexport type PredicateCombinatorKey = \"$all\" | \"$any\" | \"$not\";\n\n/**\n * Every reserved `$`-key recognized inside a predicate body.\n *\n * @internal\n */\nexport const PREDICATE_OPERATORS: ReadonlySet<string> = new Set<string>([\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n \"$changed\",\n]);\n\n/**\n * Combinator keys, as a runtime set.\n *\n * @internal\n */\nexport const PREDICATE_COMBINATORS: ReadonlySet<string> = new Set<string>([\n \"$all\",\n \"$any\",\n \"$not\",\n]);\n\n// ============================================================================\n// Operator object\n// ============================================================================\n\n/**\n * `true` when `V` supports relational operators (`$gt` … `$between`).\n * `[V]` tuple-wrapping suppresses distribution over union-typed facts.\n */\ntype IsOrderable<V> = [V] extends [number | bigint | Date]\n ? true\n : [V] extends [string]\n ? true\n : false;\n\n/**\n * The operator object permitted for a fact of type `V`. Built as a\n * **per-operator union** (one operator per member) rather than an\n * intersection — a typo'd operator (`$eqq`) then matches no member and is a\n * compile error, and a relational operator on a non-orderable fact resolves\n * to `never`.\n *\n * One operator per object — for two operators on the same fact, write the\n * array form or `$all`. This is by design (the type is the source of truth).\n *\n * `$matches` requires `RegExp`. The runtime throws on string operands.\n *\n * @example\n * ```ts\n * const op1: OperatorObject<number> = { $gte: 30 };\n * const op2: OperatorObject<string> = { $matches: /^J/i };\n * const op3: OperatorObject<string> = { $in: [\"red\", \"yellow\"] };\n * const op4: OperatorObject<string> = { $startsWith: \"Ada\" };\n * const op5: OperatorObject<string> = { $endsWith: \".com\" };\n * ```\n */\nexport type OperatorObject<V> =\n | { $eq: V }\n | { $ne: V }\n | { $in: readonly V[] }\n | { $nin: readonly V[] }\n | { $exists: boolean }\n | { $changed: true }\n | (IsOrderable<V> extends true\n ?\n | { $gt: V }\n | { $gte: V }\n | { $lt: V }\n | { $lte: V }\n | { $between: readonly [V, V] }\n : never)\n | ([V] extends [string]\n ?\n | { $matches: RegExp }\n | { $contains: string }\n | { $startsWith: string }\n | { $endsWith: string }\n : never)\n | ([V] extends [readonly (infer E)[]] ? { $contains: E } : never);\n\n/**\n * The spec for a single fact key: a bare value (equality), an operator\n * object, or — for an object-typed fact — a nested predicate (partial match).\n */\ntype PredicateField<V> =\n | V\n | OperatorObject<V>\n | ([V] extends [readonly unknown[]]\n ? never\n : [V] extends [object]\n ? PredicateObject<V>\n : never);\n\n// ============================================================================\n// FactPredicate\n// ============================================================================\n\n/**\n * Object form — every key is a fact name, every value a\n * {@link PredicateField}. Multiple keys are AND-ed. A nested object value\n * recurses (partial match), which is how cross-module namespaced predicates\n * (`{ self: { phase: \"red\" }, auth: { token: { $exists: true } } }`) work.\n */\nexport type PredicateObject<F> = {\n [K in keyof F]?: PredicateField<F[K]>;\n};\n\n/** Array form — explicit clauses, AND-ed. The codegen/devtools-friendly form. */\nexport type PredicateClause<F> = {\n [K in keyof F]: {\n readonly fact: K;\n readonly op: PredicateOp;\n readonly value: unknown;\n };\n}[keyof F];\n\n/** Combinator node — exactly one of `$all` / `$any` / `$not`. */\nexport type PredicateCombinator<F> =\n | { $all: readonly FactPredicate<F>[]; $any?: never; $not?: never }\n | { $any: readonly FactPredicate<F>[]; $all?: never; $not?: never }\n | { $not: FactPredicate<F>; $all?: never; $any?: never };\n\n/**\n * A declarative boolean spec over a fact namespace `F`. The data form of a\n * constraint `when`, an effect `on`, or a boolean derivation. Accepts an\n * object form, an array-of-clauses form, or a combinator node.\n *\n * Keys are **fact names only** — derivations are not addressable from inside\n * a predicate. To gate on a derivation, either reference the underlying fact\n * the derivation reads, or fall back to the function form of `when` / `on`.\n *\n * @example\n * ```ts\n * // Object form (the common case)\n * const p1: FactPredicate<{ phase: string; elapsed: number }> = {\n * phase: \"red\",\n * elapsed: { $gte: 30 },\n * };\n *\n * // Combinator form\n * const p2: FactPredicate<{ phase: string }> = {\n * $any: [{ phase: \"red\" }, { phase: \"yellow\" }],\n * };\n * ```\n */\nexport type FactPredicate<F> =\n | PredicateObject<F>\n | readonly PredicateClause<F>[]\n | PredicateCombinator<F>;\n\n// ============================================================================\n// FactTemplate\n// ============================================================================\n\n/**\n * A fact-interpolating string expression. `${key}` placeholders are replaced\n * with the named fact's value; `$${` emits a literal `${`. The value-producing\n * counterpart to {@link FactPredicate} — usable as a string derivation, a\n * constraint `require` field value, or an event `patch` value.\n *\n * @example { $template: \"Phase ${phase} for ${elapsed}s\" }\n */\nexport interface FactTemplate {\n readonly $template: string;\n}\n\n// ============================================================================\n// Selectors (resolver key, event patch)\n// ============================================================================\n\n/**\n * *Note: despite the \"Selector\" name, this does not select from facts — it\n * projects fields of the requirement payload for stable-stringification.*\n *\n * A resolver dedup key written as data: an ordered list of requirement-payload\n * field names. `key: [\"type\", \"to\"]` dedupes requirements by those fields.\n *\n * @example\n * ```ts\n * resolvers: {\n * fetch: {\n * requirement: \"FETCH\",\n * key: [\"url\", \"method\"] satisfies KeySelector<{ url: string; method: string }>,\n * resolve: doFetch,\n * },\n * }\n * ```\n */\nexport type KeySelector<R> = readonly (keyof R & string)[];\n\n/**\n * *Note: Directive's `$ref` is **not** a JSON Pointer or JSON Schema `$ref`.\n * It is a payload field copy — equivalent to `event.payload[key]`. Renaming\n * to `$from` is tracked as a possible v1.6+ additive alias.*\n *\n * A typed single-field copy from an event payload. Lives in the patch-spec\n * namespace — used inside a {@link PatchSpec} `$set` value.\n *\n * @example\n * ```ts\n * patch: { $set: { userId: { $ref: \"id\" } satisfies PayloadRef<{ id: string }> } }\n * ```\n */\nexport interface PayloadRef<P> {\n readonly $ref: keyof P & string;\n}\n\n/**\n * A patch value: a literal, a typed payload copy, or (for string facts) a\n * template. Lives in the patch-spec namespace — used inside a {@link PatchSpec}\n * `$set` block.\n *\n * @example\n * ```ts\n * const v1: PatchValue<boolean, { active: boolean }> = true;\n * const v2: PatchValue<string, { name: string }> = { $ref: \"name\" };\n * const v3: PatchValue<string, { name: string }> = { $template: \"user ${name}\" };\n * ```\n */\nexport type PatchValue<V, P> =\n | V\n | PayloadRef<P>\n | ([V] extends [string] ? FactTemplate : never);\n\n/**\n * An event handler written as data: assigns facts from literals, payload\n * fields (`$ref`), or interpolated strings (`$template`).\n *\n * @example\n * ```ts\n * const spec: PatchSpec<{ status: string; label: string }, { name: string }> = {\n * $set: {\n * status: \"active\",\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * ```\n */\nexport interface PatchSpec<F, P> {\n readonly $set: { [K in keyof F]?: PatchValue<F[K], P> };\n}\n\n// ============================================================================\n// Explain\n// ============================================================================\n\n/**\n * The per-clause result of an explained predicate evaluation. One entry per\n * leaf operator (`$eq`, `$gte`, …); combinator nodes (`$all`, `$any`, `$not`)\n * may also appear as headers when the runtime emits them — hence the union\n * over {@link PredicateCombinatorKey}.\n *\n * @example\n * ```ts\n * const result: ClauseResult = {\n * path: \"elapsed\",\n * op: \"$gte\",\n * expected: 30,\n * actual: 20,\n * pass: false,\n * };\n * ```\n */\nexport interface ClauseResult {\n /** Dotted path to the fact (`elapsed`, `auth.token`). */\n readonly path: string;\n /** The operator applied (`$gte`, `$eq`, …) — `$eq` for a bare value. */\n readonly op: PredicateOp | PredicateCombinatorKey;\n /**\n * The value the predicate expected. For combinator clauses (`$all`,\n * `$any`, `$not`) this is the child count.\n */\n readonly expected: unknown;\n /**\n * The actual fact value at evaluation time. For combinator clauses this\n * is the number of child clauses that passed.\n */\n readonly actual: unknown;\n /** Whether this clause passed. */\n readonly pass: boolean;\n /**\n * Children of a combinator clause (`$all`, `$any`, `$not`). Preserves the\n * tree shape of the original predicate so renderers (devtools,\n * `system.explain()`) can indent nested clauses.\n */\n readonly children?: ClauseResult[];\n}\n","/**\n * Schema Introspection\n *\n * A runtime discriminant for every `t.*()` builder result, so downstream\n * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`)\n * can ask \"what kind is this fact?\" without grepping the source.\n *\n * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`.\n * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.)\n * preserve / decorate it. When `_kind` is absent (legacy or third-party\n * builder), the parser falls back to reading the freeform `_typeName`\n * string. When even that fails: `{ kind: \"unknown\" }` — graceful close.\n *\n * This module has zero hot-path cost; it is only invoked when an\n * introspecting caller asks for it.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { PREDICATE_OPERATORS, type PredicateOp } from \"./types/predicate.js\";\n\n/**\n * Minimal structural shape for a schema-builder result that\n * introspection cares about. Avoids the contravariance trap on\n * `ExtendedSchemaType<T>` when `T = unknown` (which makes\n * `ChainableString` un-assignable to `ExtendedSchemaType<unknown>`\n * via the `_refinements` field). Any builder result is structurally\n * compatible with this shape.\n */\nexport interface IntrospectableSchema {\n readonly _kind?: SchemaKindNode;\n readonly _typeName?: string;\n}\n\n// ============================================================================\n// SchemaKindNode tree\n// ============================================================================\n\n/**\n * The closed set of kinds a Directive schema field can be.\n *\n * Drives operator availability via {@link getOperatorsForKind}: e.g.\n * `\"number\"` gets the orderable operators (`$gte`, `$lte`); `\"boolean\"`\n * does not.\n */\nexport type SchemaKind =\n | \"number\"\n | \"string\"\n | \"boolean\"\n | \"bigint\"\n | \"date\"\n | \"array\"\n | \"object\"\n | \"record\"\n | \"tuple\"\n | \"enum\"\n | \"literal\"\n | \"union\"\n | \"branded\"\n | \"unknown\";\n\n/**\n * A tree-shaped discriminator for a schema field. Composite kinds\n * (array, object, tuple, etc.) carry their element / shape information\n * so an LLM-prompt builder can show \"cartTotal is a number\" AND\n * \"items is an array of { sku: string, qty: number }\".\n *\n * `nullable` / `hasDefault` flags appear on the inner node (NOT a\n * wrapping kind) so operator-lookup on `t.number().nullable()` returns\n * the number's operators unchanged — `$gte` works on the non-null arm.\n */\nexport type SchemaKindNode =\n | (\n | { kind: \"number\" | \"string\" | \"boolean\" | \"bigint\" | \"date\" | \"unknown\" }\n | { kind: \"literal\"; value: string | number | boolean | null; primitive: \"string\" | \"number\" | \"boolean\" | \"null\" }\n | { kind: \"enum\"; values: readonly (string | number)[]; primitive: \"string\" | \"number\" }\n | { kind: \"array\"; element: SchemaKindNode }\n | { kind: \"tuple\"; elements: readonly SchemaKindNode[] }\n | { kind: \"object\"; shape: Record<string, SchemaKindNode> }\n | { kind: \"record\"; value: SchemaKindNode }\n | { kind: \"union\"; members: readonly SchemaKindNode[] }\n | { kind: \"branded\"; inner: SchemaKindNode }\n ) & {\n /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */\n nullable?: boolean;\n /** True if the schema has a `.default()`. */\n hasDefault?: boolean;\n };\n\n// ============================================================================\n// Parse `_typeName` → SchemaKindNode (fallback for legacy / third-party)\n// ============================================================================\n\nconst PRIMITIVE_KINDS = new Set<SchemaKind>([\n \"number\",\n \"string\",\n \"boolean\",\n \"bigint\",\n \"date\",\n \"unknown\",\n]);\n\n/**\n * Best-effort parse of a freeform `_typeName` string into a structured\n * kind node. Used only when `_kind` is absent. Always falls back to\n * `{ kind: \"unknown\" }`; never throws.\n */\nfunction parseTypeName(typeName: string | undefined): SchemaKindNode {\n if (!typeName) return { kind: \"unknown\" };\n\n // \"Branded<inner>\" — recurse.\n const branded = /^Branded<(.+)>$/.exec(typeName);\n if (branded) {\n return { kind: \"branded\", inner: parseTypeName(branded[1]) };\n }\n\n // \"X | null\" / \"X | undefined\" — nullable wrapper.\n if (typeName.endsWith(\" | null\") || typeName.endsWith(\" | undefined\")) {\n const inner = parseTypeName(\n typeName.replace(/ \\| (null|undefined)$/, \"\"),\n );\n\n return { ...inner, nullable: true };\n }\n\n // Bare primitive.\n if (PRIMITIVE_KINDS.has(typeName as SchemaKind)) {\n return { kind: typeName as SchemaKind } as SchemaKindNode;\n }\n\n // String-flavored named types (email, uuid, url, etc.) all map to \"string\"\n // for operator purposes.\n if (/^(email|uuid|url|cuid|datetime|iso\\b)/i.test(typeName)) {\n return { kind: \"string\" };\n }\n\n // Generic union \"X | Y | Z\" → union of parsed members (used by t.union()).\n if (typeName.includes(\" | \")) {\n const members = typeName.split(\" | \").map(parseTypeName);\n\n return { kind: \"union\", members };\n }\n\n // Bare names we recognize as composite without elements.\n if (typeName === \"array\") return { kind: \"array\", element: { kind: \"unknown\" } };\n if (typeName === \"object\") return { kind: \"object\", shape: {} };\n if (typeName === \"record\") return { kind: \"record\", value: { kind: \"unknown\" } };\n if (typeName === \"tuple\") return { kind: \"tuple\", elements: [] };\n if (typeName === \"union\") return { kind: \"union\", members: [] };\n\n return { kind: \"unknown\" };\n}\n\n// ============================================================================\n// Get the kind node for a single schema field\n// ============================================================================\n\n/**\n * Return the {@link SchemaKindNode} for a schema field. Prefers the\n * explicit `_kind` discriminant set by the builder; falls back to\n * parsing the freeform `_typeName` string for legacy / third-party\n * builders that don't set `_kind`.\n *\n * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder\n * that throws on property access returns `{ kind: \"unknown\" }` instead of\n * propagating the throw to introspecting callers.\n *\n * In dev mode, a function input (`typeof schema === \"function\"`) emits a\n * warning — common foot-gun where the caller forgot to invoke a builder\n * factory (e.g. wrote `t.number` instead of `t.number()`).\n *\n * @example\n * ```ts\n * getKind(t.number()) // → { kind: \"number\" }\n * getKind(t.string().nullable()) // → { kind: \"string\", nullable: true }\n * getKind(t.array(t.number())) // → { kind: \"array\", element: { kind: \"number\" } }\n * ```\n */\nexport function getKind(schema: unknown): SchemaKindNode {\n if (schema === null || schema === undefined) return { kind: \"unknown\" };\n if (typeof schema === \"function\") {\n if (isDevelopment) {\n console.warn(\n \"[Directive] getKind: received a function — did you forget () on a t.* builder? Example: write `t.number()`, not `t.number`.\",\n );\n }\n\n return { kind: \"unknown\" };\n }\n if (typeof schema !== \"object\") return { kind: \"unknown\" };\n const s = schema as IntrospectableSchema;\n\n // Hostile-getter guard: a third-party builder that throws on `_kind` /\n // `_typeName` reads must not crash an introspecting caller.\n let kindNode: SchemaKindNode | undefined;\n try {\n kindNode = s._kind;\n } catch {\n return { kind: \"unknown\" };\n }\n if (kindNode) return kindNode;\n\n let typeName: string | undefined;\n try {\n typeName = s._typeName;\n } catch {\n return { kind: \"unknown\" };\n }\n\n return parseTypeName(typeName);\n}\n\n// ============================================================================\n// Walk a module schema → Map<dotted-path, SchemaKindNode>\n// ============================================================================\n\n/**\n * Walk the `facts` block of a module schema and emit a flat map from\n * dotted path → kind node. Nested `t.object()` shapes flatten using\n * `.` as the separator, matching the convention used by\n * `OperatorObject<V>`'s nested-path support.\n *\n * Passing a top-level schema directly (without the `facts:` wrapper)\n * also works — anything iterable as `Record<string, ExtendedSchemaType>`\n * is acceptable.\n *\n * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is\n * silently skipped (treated as `{ kind: \"unknown\" }` for that field)\n * rather than aborting the whole walk.\n *\n * In dev mode, a top-level schema that yields an empty map (no\n * introspectable keys) emits a warning — common foot-gun where the\n * caller passed `myModule` instead of `myModule.schema`.\n */\nexport function getSchemaFieldKinds(\n schema: unknown,\n): Map<string, SchemaKindNode> {\n const out = new Map<string, SchemaKindNode>();\n if (!schema || typeof schema !== \"object\") return out;\n const root = schema as Record<string, unknown>;\n const factsCandidate =\n \"facts\" in root && root.facts && typeof root.facts === \"object\"\n ? root.facts\n : root;\n const facts = factsCandidate as Record<string, unknown>;\n\n for (const [key, builder] of Object.entries(facts)) {\n if (!builder || typeof builder !== \"object\") continue;\n let node: SchemaKindNode;\n try {\n node = getKind(builder);\n } catch {\n // A pathological builder whose getter throws past getKind's own\n // guards — skip the field but keep walking the rest.\n continue;\n }\n out.set(key, node);\n\n // Flatten nested object shapes one level — matches OperatorObject<V>'s\n // dotted-path support.\n if (node.kind === \"object\") {\n for (const [innerKey, innerNode] of Object.entries(node.shape)) {\n out.set(`${key}.${innerKey}`, innerNode);\n }\n }\n }\n\n if (out.size === 0 && isDevelopment) {\n console.warn(\n \"[Directive] getSchemaFieldKinds: schema appears empty (no introspectable keys). Did you pass the module instead of its schema? Pass `myModule.schema`, not `myModule`.\",\n );\n }\n\n return out;\n}\n\n// ============================================================================\n// Operator allowlist per kind\n// ============================================================================\n\nconst COMMON_OPS: readonly PredicateOp[] = [\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n];\n\nconst ORDERABLE_OPS: readonly PredicateOp[] = [\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n];\n\nconst STRING_OPS: readonly PredicateOp[] = [\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n];\n\n/**\n * Return the set of `PredicateOp` strings that are valid against a\n * given {@link SchemaKindNode}.\n *\n * Mirrors the type-level matrix encoded in `OperatorObject<V>` in\n * `types/predicate.ts` — drift between the two is enforced by the\n * compile-time conformance test\n * (`schema-introspection-conformance.test-d.ts`).\n *\n * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists`\n * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`,\n * `$lt`, `$lte`, `$between`\n * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains`\n * - **Array:** + `$contains` (over the element type)\n * - **Union:** *intersection* across members (the operand must be valid\n * for every branch).\n * - **Branded:** delegates to the inner kind.\n * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in`\n * operand restricted at the LLM-prompt layer (not enforced here).\n *\n * `nullable` does not change operator availability — `$gte` on a\n * nullable number is fine on the non-null arm; `$exists` handles null.\n */\nexport function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[] {\n switch (node.kind) {\n case \"number\":\n case \"bigint\":\n case \"date\":\n return [...COMMON_OPS, ...ORDERABLE_OPS];\n case \"string\":\n return [...COMMON_OPS, ...ORDERABLE_OPS, ...STRING_OPS];\n case \"boolean\":\n case \"unknown\":\n return COMMON_OPS;\n case \"array\":\n return [...COMMON_OPS, \"$contains\"];\n case \"object\":\n case \"record\":\n case \"tuple\":\n return COMMON_OPS;\n case \"literal\":\n case \"enum\":\n // Operators allowed by the underlying primitive.\n return getOperatorsForKind(\n node.primitive === \"number\"\n ? { kind: \"number\" }\n : node.primitive === \"boolean\"\n ? { kind: \"boolean\" }\n : node.primitive === \"null\"\n ? { kind: \"unknown\" }\n : { kind: \"string\" },\n );\n case \"branded\":\n return getOperatorsForKind(node.inner);\n case \"union\": {\n // Intersection of operators valid on every member.\n if (node.members.length === 0) return COMMON_OPS;\n const sets = node.members.map((m) => new Set(getOperatorsForKind(m)));\n const first = sets[0]!;\n const intersection: PredicateOp[] = [];\n for (const op of first) {\n if (sets.every((s) => s.has(op))) intersection.push(op);\n }\n\n return intersection;\n }\n default: {\n // Exhaustiveness check — TS will flag if a new kind is added without\n // a switch arm.\n const _exhaustive: never = node;\n void _exhaustive;\n\n return COMMON_OPS;\n }\n }\n}\n\n/**\n * Return all known predicate operators — convenience for prompt builders\n * that need to show the LLM the full set.\n */\nexport function listAllPredicateOperators(): readonly PredicateOp[] {\n return Array.from(PREDICATE_OPERATORS) as readonly PredicateOp[];\n}\n","/**\n * Runtime for data-configuration predicates and templates.\n *\n * Pure module — imports only its own types. Reads facts through whatever\n * object it is handed (the reactive `Facts` proxy in production, a plain\n * snapshot in tests), so it never depends on the engine, store, or tracking.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { stableStringify } from \"../utils/utils.js\";\nimport {\n type ClauseResult,\n type FactTemplate,\n PREDICATE_OPERATORS,\n type PatchSpec,\n type PredicateOp,\n} from \"./types/predicate.js\";\n\n// ============================================================================\n// Recursion bound\n// ============================================================================\n\n/**\n * Maximum predicate-AST recursion depth. Legitimate cross-module predicates\n * nest fewer than ~15 levels; 64 is generous but bounded — past it the runtime\n * dev-warns and bails rather than risking a stack overflow on a cyclic or\n * pathologically deep spec. Shared by every structural predicate walker\n * ({@link walkPredicate}, {@link evaluatePredicate}) so the cap lives in one\n * place.\n */\nexport const MAX_PREDICATE_DEPTH = 64;\n\n// ============================================================================\n// Discriminators\n// ============================================================================\n\n/** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */\ntype Scope = Record<string, unknown>;\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n\n return !(v instanceof Date) && !(v instanceof RegExp);\n}\n\n/**\n * True when `v` is a plain `{}` literal (its prototype is `Object.prototype`\n * or `null`). Excludes class instances, Date, RegExp, Map, Set, Promise, etc.\n */\nfunction isPlainObjectStrict(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n const proto = Object.getPrototypeOf(v);\n\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * True when every own key of `v` is a recognized `$`-operator (and there is ≥1).\n * If any key starts with `$` but is not a known operator, dev-warn (typo) and\n * still treat the value as an operator object so the typo is not masked as a\n * literal — `applyOperator` will return false for the unknown op.\n */\nfunction isOperatorObject(v: unknown): v is Record<string, unknown> {\n if (!isPlainObject(v)) {\n return false;\n }\n\n let count = 0;\n let hasDollarKey = false;\n for (const k of Object.keys(v)) {\n if (k.startsWith(\"$\")) {\n hasDollarKey = true;\n if (!PREDICATE_OPERATORS.has(k)) {\n devWarn(\n `predicate: unknown operator \"${k}\" — looks like a typo. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n } else if (hasDollarKey || count === 0) {\n // Mixed $/non-$ keys aren't an operator object; let the caller treat\n // it as a literal/recursive predicate. The non-$ key check happens\n // below by short-circuiting when a non-$ key appears.\n return false;\n }\n count++;\n }\n\n if (!hasDollarKey) {\n return false;\n }\n\n // All keys are `$`-prefixed: this is an operator object, even if some keys\n // are typos. An unknown op makes applyOperator() return false.\n return count > 0;\n}\n\n/**\n * True when `v` is a data-form spec (predicate object/array) rather than a\n * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.)\n * — only plain `{}` literals and arrays of plain clause shapes qualify.\n *\n * @example\n * ```ts\n * isPredicate({ phase: \"red\" }); // true\n * isPredicate((f) => f.phase === \"red\"); // false\n * isPredicate([{ fact: \"phase\", op: \"$eq\", value: \"red\" }]); // true\n * ```\n */\nexport function isPredicate(v: unknown): boolean {\n if (v === null) {\n return false;\n }\n if (Array.isArray(v)) {\n return v.every(\n (c) =>\n isPlainObjectStrict(c) &&\n \"fact\" in (c as object) &&\n \"op\" in (c as object),\n );\n }\n\n return isPlainObjectStrict(v);\n}\n\n// ============================================================================\n// Structural traversal\n// ============================================================================\n\n/**\n * Visitor passed to {@link walkPredicate}. Every callback is optional; a\n * walker implements only the arms it cares about.\n */\nexport interface PredicateVisitor {\n /**\n * A leaf operator clause: a fact + a `$`-operator + its operand. Fires once\n * per operator in a multi-operator object.\n *\n * @param factPath - Dotted path to the fact (`elapsed`, `auth.token`).\n * @param op - The operator key (`$gte`, `$matches`, …).\n * @param operand - The operator's operand value.\n * @param operandPath - Dotted path to the operand for diagnostics\n * (`elapsed.$gte`, `value` / `[0].value` for the array-clause form).\n */\n operator?(\n factPath: string,\n op: string,\n operand: unknown,\n operandPath: string,\n ): void;\n /**\n * A bare-value (equality) clause — a fact mapped to a non-object literal,\n * an array, or a non-plain class instance (Date, RegExp, Set, …).\n *\n * @param factPath - Dotted path to the fact.\n * @param value - The equality operand.\n */\n literal?(factPath: string, value: unknown): void;\n /**\n * A combinator node (`$all` / `$any` / `$not`), called before descending.\n * Return `false` to skip its children.\n */\n combinator?(kind: \"$all\" | \"$any\" | \"$not\"): boolean | void;\n /**\n * A nested-object (cross-module pivot) key, called before descending.\n * Return `false` to skip its children.\n */\n nested?(key: string): boolean | void;\n /**\n * A `$`-prefixed key appearing where a fact key was expected — either an\n * unknown/typo operator, or an operator mixed with fact keys at predicate\n * top level.\n *\n * @param key - The stray `$`-key.\n * @param factPath - Dotted path to the stray key.\n */\n strayOperatorKey?(key: string, factPath: string): void;\n /**\n * Called when traversal bails out early — a cycle was re-encountered or\n * the depth cap was hit. The subtree below the bail point is NOT visited.\n */\n bail?(reason: \"cycle\" | \"depth\"): void;\n}\n\n/**\n * Single depth-guarded, cycle-guarded structural traversal of a predicate\n * AST. The pure structural walkers — dependency extraction, `$changed`\n * detection, empty/config detection, serialization validation — share this\n * so a new operator or combinator is threaded through one place.\n *\n * Handles the object form, the array-clause form, combinator nodes, nested\n * cross-module objects, operator objects, and bare-value literals. It does\n * **not** evaluate — see {@link evaluatePredicate} for that.\n *\n * @internal\n */\nexport function walkPredicate(\n spec: unknown,\n visitor: PredicateVisitor,\n path = \"\",\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): void {\n if (depth > MAX_PREDICATE_DEPTH) {\n if (isDevelopment) {\n console.warn(\n `[Directive] predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n }\n visitor.bail?.(\"depth\");\n\n return;\n }\n\n // Array-clause form — each `{ fact, op, value }` clause is a leaf operator.\n if (Array.isArray(spec)) {\n spec.forEach((clause, i) => {\n if (!isPlainObject(clause)) {\n return;\n }\n const c = clause as Record<string, unknown>;\n if (typeof c.fact === \"string\" && typeof c.op === \"string\") {\n const clausePath = path ? `${path}[${i}]` : `[${i}]`;\n visitor.operator?.(\n path ? `${path}.${c.fact}` : c.fact,\n c.op,\n c.value,\n `${clausePath}.value`,\n );\n }\n });\n\n return;\n }\n\n if (!isPlainObject(spec)) {\n return;\n }\n if (seen.has(spec)) {\n if (isDevelopment) {\n console.warn(\"[Directive] walkPredicate: cyclic predicate spec\");\n }\n visitor.bail?.(\"cycle\");\n\n return;\n }\n seen.add(spec);\n\n const obj = spec as Record<string, unknown>;\n\n // Combinator node — descend into children unless the visitor opts out.\n for (const kind of [\"$all\", \"$any\", \"$not\"] as const) {\n if (kind in obj) {\n const descend = visitor.combinator?.(kind);\n if (descend === false) {\n return;\n }\n const children =\n kind === \"$not\" ? [obj.$not] : ((obj[kind] as unknown[]) ?? []);\n for (const child of children) {\n walkPredicate(child, visitor, path, seen, depth + 1);\n }\n\n return;\n }\n }\n\n // Object form — one entry per key.\n for (const key of Object.keys(obj)) {\n const childPath = path ? `${path}.${key}` : key;\n\n if (key.startsWith(\"$\")) {\n // A `$`-key at fact position — typo operator or top-level operator\n // mixed with fact keys. Surface it; do not descend.\n visitor.strayOperatorKey?.(key, childPath);\n continue;\n }\n\n const value = obj[key];\n\n if (isOperatorObject(value)) {\n const opObj = value as Record<string, unknown>;\n for (const op of Object.keys(opObj)) {\n visitor.operator?.(childPath, op, opObj[op], `${childPath}.${op}`);\n }\n continue;\n }\n\n // Only a strict plain object (`{}` / `Object.create(null)`) recurses as\n // a nested cross-module predicate. A Set, Map, or class instance is a\n // bare-value leaf — surfacing it as `literal` lets a walker inspect its\n // runtime class (e.g. validatePredicate's JSON-serializability check).\n if (isPlainObjectStrict(value)) {\n const descend = visitor.nested?.(key);\n if (descend === false) {\n continue;\n }\n walkPredicate(value, visitor, childPath, seen, depth + 1);\n continue;\n }\n\n // Bare value — equality leaf (also array / Set / Map / class instances).\n visitor.literal?.(childPath, value);\n }\n}\n\n/**\n * True when `v` structurally passes {@link isPredicate} but contains no\n * operators, no combinators, and no fact-clause entries that resolve to a\n * primitive/operator leaf — i.e. an empty `{}` or a deeply-nested object\n * tree that never bottoms out in a leaf value. Used by the dynamic\n * `register()` / `assign()` paths to dev-warn when a config object is\n * passed where a predicate (or function) was expected.\n *\n * Returns `false` for arrays — array-form predicates with `fact`+`op`\n * clauses are handled by the structural `isPredicate` check upstream.\n *\n * @example\n * ```ts\n * isEmptyOrConfigPredicate({}); // true (empty — config-object misuse)\n * isEmptyOrConfigPredicate({ phase: \"red\" }); // false (real fact clause)\n * isEmptyOrConfigPredicate({ $eq: 5 }); // false (operator)\n * isEmptyOrConfigPredicate({ count: { $gt: 5 } }); // false (operator clause)\n * ```\n *\n * @internal\n */\nexport function isEmptyOrConfigPredicate(v: unknown): boolean {\n // Arrays and non-plain-object specs are never \"empty config objects\".\n if (!isPlainObjectStrict(v)) {\n return false;\n }\n\n // A spec is a config tree only when walkPredicate fires NONE of the\n // predicate-semantic callbacks — no operator, no combinator, no literal\n // leaf, no stray `$`-key. Nested plain objects are descended; an empty\n // `{}` or a tree of empty `{}` fires nothing and stays \"config\". A cycle\n // or depth-cap bail is treated as \"not a config object\" (can't determine\n // — fail safe so the dev-warn is not spuriously emitted).\n let isPredicateBody = false;\n walkPredicate(v, {\n operator() {\n isPredicateBody = true;\n },\n literal() {\n isPredicateBody = true;\n },\n combinator() {\n isPredicateBody = true;\n },\n strayOperatorKey() {\n isPredicateBody = true;\n },\n bail() {\n isPredicateBody = true;\n },\n });\n\n return !isPredicateBody;\n}\n\n/**\n * True when `v` is a {@link FactTemplate} (`{ $template: string }`).\n *\n * @example\n * ```ts\n * isTemplate({ $template: \"Hi ${name}\" }); // true\n * isTemplate({ $set: { name: \"x\" } }); // false\n * ```\n */\nexport function isTemplate(v: unknown): v is FactTemplate {\n return (\n isPlainObject(v) &&\n Object.hasOwn(v, \"$template\") &&\n typeof (v as { $template: unknown }).$template === \"string\"\n );\n}\n\n// ============================================================================\n// Load-time validation\n// ============================================================================\n\n/**\n * Throw when a predicate spec contains an operand that cannot survive a\n * JSON round-trip — i.e. that would silently mis-evaluate if the spec was\n * loaded from `JSON.parse`.\n *\n * Three failure classes are detected:\n *\n * - **Lost `RegExp` operand.** A `$matches` operand that is not a\n * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as\n * `{}`, so a `$matches` clause with an empty-object operand is the\n * signature of a regex that did not survive serialization. Reify it\n * with `new RegExp(pattern, flags)` before installing the predicate.\n * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a\n * `bigint` operand cannot have been produced by a JSON pipeline and\n * cannot be persisted by one either.\n * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all\n * members; a predicate carrying one is not JSON-safe.\n *\n * This is an opt-in helper — the engine does not call it automatically.\n * Users who load predicates from JSON should call it after `JSON.parse`\n * to fail loud rather than silently mis-evaluate. See the\n * \"Serialization\" section of RFC-0004.\n *\n * @example\n * ```ts\n * validatePredicate({ phase: { $matches: {} } });\n * // throws — empty object where a RegExp is required\n *\n * validatePredicate({ phase: \"red\", elapsed: { $gte: 30 } });\n * // ok — JSON-clean operands\n * ```\n */\nexport function validatePredicate(spec: unknown, path = \"\"): void {\n /**\n * Recursively walk an operand's object/array structure, throwing on any\n * value that cannot survive a JSON round-trip — `bigint`, `Set`, `Map`, or\n * a nested `RegExp`. Depth- and cycle-guarded. A top-level operand is\n * inspected by the operator-specific {@link checkOperand} (which permits a\n * `RegExp` as the direct `$matches` operand); this helper handles values\n * nested *inside* a plain-object or array operand, where a `RegExp` is just\n * as JSON-unsafe as a `Set`.\n */\n function checkValueJsonSafe(\n value: unknown,\n at: string,\n seen: WeakSet<object>,\n depth: number,\n ): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (value instanceof RegExp) {\n throw new Error(\n `[Directive] validatePredicate: RegExp operand at \"${at}\" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`,\n );\n }\n if (value === null || typeof value !== \"object\") {\n return;\n }\n if (depth > MAX_PREDICATE_DEPTH) {\n return;\n }\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, seen, depth + 1);\n });\n\n return;\n }\n\n for (const k of Object.keys(value as Record<string, unknown>)) {\n checkValueJsonSafe(\n (value as Record<string, unknown>)[k],\n at ? `${at}.${k}` : k,\n seen,\n depth + 1,\n );\n }\n }\n\n /** Throw on a JSON-unrehydratable operand value. */\n function checkOperand(value: unknown, op: string, at: string): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (op === \"$matches\" && !(value instanceof RegExp)) {\n throw new Error(\n `[Directive] validatePredicate: $matches operand at \"${at}\" must be a RegExp; got ${value === null ? \"null\" : typeof value}. A regex lost to JSON.parse becomes {} — reify with new RegExp(pattern, flags) before installing.`,\n );\n }\n // A plain-object / array operand (e.g. `$eq: { ... }`, `$in: [ ... ]`)\n // can carry a `bigint`, `Set`, `Map`, or nested `RegExp` arbitrarily deep\n // — `checkOperand` only sees the operand's top type, so recurse into its\n // structure. The direct `$matches` RegExp is handled above and never\n // reaches this branch (a RegExp is not a plain object / array).\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, new WeakSet(), 1);\n });\n } else if (isPlainObjectStrict(value)) {\n for (const k of Object.keys(value)) {\n checkValueJsonSafe(value[k], `${at}.${k}`, new WeakSet(), 1);\n }\n }\n }\n\n // Top-level Set / Map node — a regex / set / map handed in directly as the\n // whole spec. walkPredicate would treat it as an empty object, so check\n // the entry node here.\n if (spec instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (spec instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n\n // Single structural traversal — every operator clause and equality leaf is\n // checked for a JSON-unrehydratable operand. The walker threads the dotted\n // operand path so error messages point at the offending clause.\n walkPredicate(spec, {\n operator(_factPath, op, operand, operandPath) {\n checkOperand(operand, op, path ? `${path}.${operandPath}` : operandPath);\n },\n literal(factPath, value) {\n checkOperand(value, \"\", path ? `${path}.${factPath}` : factPath);\n },\n });\n}\n\n// ============================================================================\n// Schema-aware validation (semantic — operator on kind, operator-count cap)\n// ============================================================================\n\nimport {\n getOperatorsForKind,\n type SchemaKindNode,\n} from \"./schema-introspection.js\";\n\nexport interface SchemaValidationError {\n /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */\n readonly path: string;\n /** The operator that failed (or the literal-equality marker `$eq`). */\n readonly op: string;\n /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */\n readonly kind?: SchemaKindNode;\n /** The operators that ARE allowed for this fact's kind. */\n readonly allowedOps?: readonly string[];\n /** Human-readable failure reason (suitable for feeding back to an LLM). */\n readonly reason: string;\n}\n\nexport interface SchemaValidationOptions {\n /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */\n readonly maxOperatorCount?: number;\n /**\n * Reject `$in` / `$nin` operands that contain more than this many elements\n * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000\n * — beyond that, a downstream query compiler may degrade quadratically.\n */\n readonly maxArrayOperandLength?: number;\n}\n\n/**\n * Heuristic: flag a regex source string that has obvious nested quantifiers\n * (e.g. `(.+)+`, `(.*)*`, `(\\w+)+`, `(a|a)+`) — the classic ReDoS shapes.\n * Not a full ReDoS prover; intentionally conservative so a string-rehydrated\n * `$matches` operand can be rejected before it ever reaches `RegExp.test`.\n *\n * Callers MUST NOT treat a `false` result as \"safe\" — a determined adversary\n * can craft patterns this heuristic misses. The right answer for untrusted\n * regex is \"don't accept untrusted regex\"; this helper exists to catch the\n * obvious foot-guns.\n *\n * @example\n * ```ts\n * dangerousRegex(\"(a+)+\"); // → true\n * dangerousRegex(\"(.*)*\"); // → true\n * dangerousRegex(\"(\\\\w+)+\"); // → true\n * dangerousRegex(\"^[a-z]+$\"); // → false\n * ```\n */\nexport function dangerousRegex(source: string): boolean {\n if (typeof source !== \"string\" || source.length === 0) {\n return false;\n }\n // Nested quantifiers — a group ending in `*` or `+` (or `{n,}`) immediately\n // followed by another `*` / `+` / `{n,}` quantifier. Allow `?` between\n // (lazy) since `(...)?+` is still pathological. Also catch `{n,m}` upper\n // bounds when they wrap a quantified group.\n //\n // Patterns flagged:\n // (.+)+ (.*)* (.+)* (.*)+\n // (\\w+)+ (\\d*)+ ([abc]+)+\n // (a|a)+ (a|b|c)* ((x))+ (?:x+)+\n //\n // The check looks for a closing `)` preceded by a quantifier-bearing token\n // (`+`, `*`, `}` from `{n,m}`, or `+?` / `*?` lazy) and followed by another\n // quantifier (`+`, `*`, or `{n,`).\n const nestedQuantifier = /\\)(?:[+*]\\??|\\{\\d+,?\\d*\\})\\s*[+*?]\\s*[+*]/;\n if (nestedQuantifier.test(source)) {\n return true;\n }\n // Group whose inner content already has a `+` / `*` / `{n,}` quantifier on\n // a character class or token, and the group is then itself quantified.\n // E.g. `(a+)+`, `(\\w+)+`, `(.*)*`, `([abc]+)*`.\n const groupedQuantified =\n /\\(([^()]*?[+*]|[^()]*?\\{\\d+,?\\d*\\})[^()]*\\)\\s*[+*]/;\n if (groupedQuantified.test(source)) {\n return true;\n }\n // Alternation of identical branches: `(a|a)+`, `(foo|foo)*`.\n const sameBranchAlt = /\\(\\??:?([^()|]+)\\|\\1\\)\\s*[+*]/;\n if (sameBranchAlt.test(source)) {\n return true;\n }\n\n return false;\n}\n\nexport type SchemaValidationResult =\n | { ok: true; operatorCount: number }\n | { ok: false; errors: readonly SchemaValidationError[]; operatorCount: number };\n\n/**\n * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate\n * against a schema's runtime kind map. Catches errors that\n * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a\n * boolean fact), unknown fact paths, and (optionally) operator-count\n * exhaustion DoS attempts.\n *\n * Pair with {@link validatePredicate} (structural / JSON safety) for full\n * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a\n * module schema.\n *\n * Designed for the LLM-emit retry loop: returns a list of errors with\n * structured `{path, op, kind, allowedOps, reason}` rather than throwing,\n * so the caller can feed the errors back to the model.\n *\n * @example\n * ```ts\n * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } });\n * const result = validatePredicateAgainstSchema(\n * { cartTotal: { $gte: 50 }, active: { $gte: true } },\n * kindMap,\n * );\n * // → { ok: false, errors: [{ path: \"active\", op: \"$gte\", reason: \"...\" }], operatorCount: 2 }\n * ```\n */\nexport function validatePredicateAgainstSchema(\n spec: unknown,\n kindMap: Map<string, SchemaKindNode>,\n opts: SchemaValidationOptions = {},\n): SchemaValidationResult {\n const errors: SchemaValidationError[] = [];\n let operatorCount = 0;\n const maxOperatorCount = opts.maxOperatorCount;\n const maxArrayOperandLength = opts.maxArrayOperandLength;\n\n walkPredicate(spec, {\n operator(factPath, op, operand, _operandPath) {\n operatorCount++;\n if (\n maxOperatorCount !== undefined &&\n operatorCount > maxOperatorCount\n ) {\n // Don't pile up identical errors past the cap; one is enough.\n if (\n !errors.some((e) => e.reason.includes(\"maxOperatorCount\"))\n ) {\n errors.push({\n path: factPath,\n op,\n reason: `Predicate exceeds maxOperatorCount=${maxOperatorCount} — too many clauses (DoS guard).`,\n });\n }\n\n return;\n }\n\n // M1: $in / $nin operand length cap — too-large array operands choke\n // downstream query planners and OR-tree compilers.\n if (\n maxArrayOperandLength !== undefined &&\n (op === \"$in\" || op === \"$nin\") &&\n Array.isArray(operand) &&\n operand.length > maxArrayOperandLength\n ) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator ${op} operand exceeds maxArrayOperandLength=${maxArrayOperandLength} (got ${operand.length}) — too large for a query planner.`,\n });\n\n return;\n }\n\n // M2: $matches operand ReDoS heuristic — flag obvious nested\n // quantifiers in either a RegExp or a string-form pattern. String-form\n // patterns are rejected at evaluation time (see applyOperator), but\n // a static check here catches them before they ever load.\n //\n // WARNING: don't rehydrate LLM-emitted string-form regex without your\n // own complexity audit; `dangerousRegex()` is a foot-gun catcher, not\n // a ReDoS prover.\n if (op === \"$matches\") {\n let regexSource: string | undefined;\n if (operand instanceof RegExp) {\n regexSource = operand.source;\n } else if (typeof operand === \"string\") {\n regexSource = operand;\n }\n if (regexSource !== undefined && dangerousRegex(regexSource)) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator $matches operand at \"${factPath}\" contains nested quantifiers (ReDoS risk: ${JSON.stringify(regexSource)}). Reject untrusted regex or rewrite without nested + / *.`,\n });\n\n return;\n }\n }\n\n const kind = kindMap.get(factPath);\n if (!kind) {\n errors.push({\n path: factPath,\n op,\n reason: `Unknown fact \"${factPath}\" — not in schema. Known facts: ${\n kindMap.size === 0\n ? \"(empty schema)\"\n : Array.from(kindMap.keys()).join(\", \")\n }`,\n });\n\n return;\n }\n\n const allowedOps = getOperatorsForKind(kind);\n if (!allowedOps.includes(op as never)) {\n errors.push({\n path: factPath,\n op,\n kind,\n allowedOps,\n reason: `Operator \"${op}\" is not allowed on fact \"${factPath}\" of kind \"${kind.kind}\". Allowed operators for this kind: ${allowedOps.join(\", \")}.`,\n });\n }\n },\n literal(factPath, _value) {\n operatorCount++;\n // Bare-value (equality) — always permitted as long as fact exists.\n if (!kindMap.has(factPath)) {\n errors.push({\n path: factPath,\n op: \"$eq\",\n reason: `Unknown fact \"${factPath}\" — not in schema.`,\n });\n }\n },\n strayOperatorKey(key, factPath) {\n errors.push({\n path: factPath,\n op: key,\n reason: `Stray operator key \"${key}\" at \"${factPath}\" — operators must live inside a fact's operator object, not at the predicate top level.`,\n });\n },\n });\n\n if (errors.length === 0) return { ok: true, operatorCount };\n\n return { ok: false, errors, operatorCount };\n}\n\n// ============================================================================\n// Equality\n// ============================================================================\n\n/**\n * Pairwise cycle-guard state shared across a single `deepEqual` traversal.\n *\n * Asymmetric cycles (only one side cyclic) must not short-circuit; we only\n * treat a pair as equal when the same `(a, b)` pair is re-encountered.\n */\ninterface DeepEqualSeen {\n ids: WeakMap<object, number>;\n next: { v: number };\n pairs: Set<string>;\n}\n\nfunction deepEqualSeen(): DeepEqualSeen {\n return { ids: new WeakMap(), next: { v: 1 }, pairs: new Set() };\n}\n\nfunction pairId(seen: DeepEqualSeen, obj: object): number {\n let id = seen.ids.get(obj);\n if (id === undefined) {\n id = seen.next.v++;\n seen.ids.set(obj, id);\n }\n\n return id;\n}\n\n/** Structural equality with NaN/Date handling and a pairwise cycle guard. */\nfunction deepEqual(a: unknown, b: unknown, seen?: DeepEqualSeen): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (\n typeof a !== \"object\" ||\n typeof b !== \"object\" ||\n a === null ||\n b === null\n ) {\n return false;\n }\n\n const guard = seen ?? deepEqualSeen();\n const key = `${pairId(guard, a)}:${pairId(guard, b)}`;\n if (guard.pairs.has(key)) {\n return true; // same (a, b) pair re-encountered — treat as equal\n }\n guard.pairs.add(key);\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n\n return a.every((v, i) => deepEqual(v, b[i], guard));\n }\n\n // Set equality — same size, every element of `a` has a structurally-equal\n // counterpart in `b`. Must precede the `Object.keys` fallback below because\n // `Object.keys(new Set(...))` is always `[]`, which would otherwise let\n // any two Sets (or any two Maps) compare equal regardless of contents.\n if (a instanceof Set || b instanceof Set) {\n if (!(a instanceof Set) || !(b instanceof Set) || a.size !== b.size) {\n return false;\n }\n const bArr = [...b];\n\n return [...a].every((v) => bArr.some((w) => deepEqual(v, w, guard)));\n }\n\n // Map equality — same size, every key in `a` matches a key in `b` with a\n // structurally-equal value. Greedy match with a used-flag to handle\n // structural (non-reference) key equality correctly.\n if (a instanceof Map || b instanceof Map) {\n if (!(a instanceof Map) || !(b instanceof Map) || a.size !== b.size) {\n return false;\n }\n const bEntries = [...b.entries()];\n const used = new Array<boolean>(bEntries.length).fill(false);\n for (const [ka, va] of a) {\n let found = false;\n for (let i = 0; i < bEntries.length; i++) {\n if (used[i]) {\n continue;\n }\n const [kb, vb] = bEntries[i]!;\n if (deepEqual(ka, kb, guard) && deepEqual(va, vb, guard)) {\n used[i] = true;\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n\n return true;\n }\n\n const ak = Object.keys(a as object);\n const bk = Object.keys(b as object);\n if (ak.length !== bk.length) {\n return false;\n }\n\n return ak.every(\n (k) =>\n Object.hasOwn(b as object, k) &&\n deepEqual(\n (a as Record<string, unknown>)[k],\n (b as Record<string, unknown>)[k],\n guard,\n ),\n );\n}\n\n// ============================================================================\n// Operators\n// ============================================================================\n\nfunction toComparable(v: unknown): number | bigint | string | undefined {\n if (v instanceof Date) {\n return v.getTime();\n }\n if (typeof v === \"number\" || typeof v === \"bigint\" || typeof v === \"string\") {\n return v;\n }\n\n return undefined;\n}\n\nfunction relational(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n): boolean {\n const a = toComparable(actual);\n const b = toComparable(operand);\n if (a === undefined || b === undefined || typeof a !== typeof b) {\n return false;\n }\n\n switch (op) {\n case \"$gt\":\n return a > b;\n case \"$gte\":\n return a >= b;\n case \"$lt\":\n return a < b;\n case \"$lte\":\n return a <= b;\n default:\n return false;\n }\n}\n\n/** Apply one operator. `prevValue` is supplied only for `$changed`. */\nfunction applyOperator(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n prevValue: unknown,\n): boolean {\n switch (op) {\n case \"$eq\":\n return deepEqual(actual, operand);\n case \"$ne\":\n return !deepEqual(actual, operand);\n case \"$in\":\n return (\n Array.isArray(operand) && operand.some((v) => deepEqual(actual, v))\n );\n case \"$nin\":\n return (\n Array.isArray(operand) && !operand.some((v) => deepEqual(actual, v))\n );\n case \"$exists\":\n return operand === (actual !== undefined);\n case \"$changed\":\n return !deepEqual(actual, prevValue);\n case \"$gt\":\n case \"$gte\":\n case \"$lt\":\n case \"$lte\":\n return relational(op, actual, operand);\n case \"$between\": {\n if (!Array.isArray(operand) || operand.length !== 2) {\n return false;\n }\n const lo = toComparable(operand[0]);\n const hi = toComparable(operand[1]);\n if (\n lo !== undefined &&\n hi !== undefined &&\n typeof lo === typeof hi &&\n lo > hi\n ) {\n devWarn(\"$between: reversed pair — [min, max] required\");\n\n return false;\n }\n\n return (\n relational(\"$gte\", actual, operand[0]) &&\n relational(\"$lte\", actual, operand[1])\n );\n }\n case \"$matches\": {\n if (!(operand instanceof RegExp)) {\n // String operands are not accepted — a string cannot carry flags\n // (case-insensitivity, dotall, multiline) and would also enable a\n // ReDoS surface for data-loaded predicates. Throw immediately so\n // the bug surfaces at the point of use.\n throw new Error(\n \"[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).\",\n );\n }\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return operand.test(actual);\n }\n case \"$startsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.startsWith(String(operand));\n case \"$endsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.endsWith(String(operand));\n case \"$contains\":\n if (typeof actual === \"string\") {\n return actual.includes(String(operand));\n }\n if (Array.isArray(actual)) {\n return actual.some((v) => deepEqual(v, operand));\n }\n // Set membership — uses `.has()` which is reference-equality for\n // objects (matches native Set semantics) and value-equality for\n // primitives. Map `$contains` is deferred to v2; users who need it\n // today can fall back to a function-form predicate.\n if (actual instanceof Set) {\n return actual.has(operand);\n }\n\n return false;\n default:\n return false;\n }\n}\n\n// ============================================================================\n// Evaluation\n// ============================================================================\n\nfunction devWarn(message: string): void {\n if (isDevelopment) {\n console.warn(`[Directive] ${message}`);\n }\n}\n\nfunction evalField(\n value: unknown,\n actual: unknown,\n prev: unknown,\n depth: number,\n): boolean {\n if (isOperatorObject(value)) {\n const keys = Object.keys(value);\n // Type rejects multi-operator objects; the runtime ANDs them on a\n // best-effort basis but dev-warns so the author knows to switch to the\n // array form or `$all`.\n if (keys.length > 1) {\n devWarn(\n `predicate: operator object has ${keys.length} operators (${keys.join(\", \")}) — write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`,\n );\n }\n for (const op of keys) {\n if (!applyOperator(op as PredicateOp, actual, value[op], prev)) {\n return false;\n }\n }\n\n return true;\n }\n\n // A plain (non-operator) object recurses — nested / namespaced predicate.\n if (isPlainObject(value)) {\n return evaluatePredicate(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev) ? prev : undefined,\n depth + 1,\n );\n }\n\n // Bare value → equality.\n return deepEqual(actual, value);\n}\n\n/**\n * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous\n * snapshot) is consulted only by the `$changed` operator.\n *\n * @example\n * ```ts\n * evaluatePredicate({ phase: \"red\", elapsed: { $gte: 30 } }, { phase: \"red\", elapsed: 45 });\n * // → true\n * evaluatePredicate({ $any: [{ phase: \"red\" }, { phase: \"yellow\" }] }, { phase: \"green\" });\n * // → false\n * ```\n */\nexport function evaluatePredicate(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n depth = 0,\n): boolean {\n // `freezeSpec` permits cycles (it uses a WeakSet seen-guard), so a\n // registered spec can be self-referential. Cap recursion to defend the\n // reconcile loop against a stack overflow at evaluation time.\n if (depth > MAX_PREDICATE_DEPTH) {\n devWarn(\n `predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n\n return false;\n }\n // Array form — clauses AND-ed.\n if (Array.isArray(spec)) {\n return spec.every((clause) => {\n if (!isPlainObject(clause)) {\n return false;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n\n return applyOperator(op, facts?.[fact], value, prev?.[fact]);\n });\n }\n\n if (!isPlainObject(spec)) {\n return Boolean(spec);\n }\n\n // Combinator node.\n if (\"$all\" in spec) {\n return (spec.$all as unknown[]).every((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$any\" in spec) {\n return (spec.$any as unknown[]).some((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$not\" in spec) {\n return !evaluatePredicate(spec.$not, facts, prev, depth + 1);\n }\n\n // Object form — every key AND-ed.\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `predicate: operator \"${key}\" mixed with fact keys — wrap operators in a per-fact object`,\n );\n\n return false;\n }\n if (!evalField(spec[key], facts?.[key], prev?.[key], depth)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Evaluate a predicate and return a per-clause breakdown — the data feed for\n * devtools, `system.explain()`, and `directive explain`.\n *\n * @example\n * ```ts\n * evaluatePredicateExplained(\n * { phase: \"red\", elapsed: { $gte: 30 } },\n * { phase: \"red\", elapsed: 20 },\n * );\n * // → [\n * // { path: \"phase\", op: \"$eq\", expected: \"red\", actual: \"red\", pass: true },\n * // { path: \"elapsed\", op: \"$gte\", expected: 30, actual: 20, pass: false },\n * // ]\n * ```\n */\nexport function evaluatePredicateExplained(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n pathPrefix = \"\",\n): ClauseResult[] {\n const out: ClauseResult[] = [];\n\n if (Array.isArray(spec)) {\n for (const clause of spec) {\n if (!isPlainObject(clause)) {\n continue;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n const actual = facts?.[fact];\n out.push({\n path: pathPrefix + fact,\n op,\n expected: value,\n actual,\n pass: applyOperator(op, actual, value, prev?.[fact]),\n });\n }\n\n return out;\n }\n\n if (!isPlainObject(spec)) {\n return out;\n }\n\n for (const key of [\"$all\", \"$any\", \"$not\"] as const) {\n if (key in spec) {\n const childSpecs =\n key === \"$not\" ? [spec.$not] : (spec[key] as unknown[]);\n const children: ClauseResult[] = [];\n for (const child of childSpecs) {\n children.push(\n ...evaluatePredicateExplained(child, facts, prev, pathPrefix),\n );\n }\n const passCount = children.filter((c) => c.pass).length;\n let pass: boolean;\n if (key === \"$all\") {\n pass = children.length === 0 || passCount === children.length;\n } else if (key === \"$any\") {\n pass = children.length > 0 && passCount > 0;\n } else {\n // $not — single child wrapped above\n pass = !children.every((c) => c.pass);\n }\n out.push({\n path: pathPrefix || key,\n op: key,\n expected: childSpecs.length,\n actual: passCount,\n pass,\n children,\n });\n\n return out;\n }\n }\n\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n continue;\n }\n const value = spec[key];\n const actual = facts?.[key];\n const path = pathPrefix + key;\n\n if (isOperatorObject(value)) {\n for (const op of Object.keys(value)) {\n out.push({\n path,\n op: op as PredicateOp,\n expected: value[op],\n actual,\n pass: applyOperator(\n op as PredicateOp,\n actual,\n value[op],\n prev?.[key],\n ),\n });\n }\n } else if (isPlainObject(value)) {\n out.push(\n ...evaluatePredicateExplained(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev?.[key]) ? (prev?.[key] as Scope) : undefined,\n `${path}.`,\n ),\n );\n } else {\n out.push({\n path,\n op: \"$eq\",\n expected: value,\n actual,\n pass: deepEqual(actual, value),\n });\n }\n }\n\n return out;\n}\n\nconst memoizedCache = new WeakMap<\n object,\n (facts: Scope, prev?: Scope) => boolean\n>();\n\n/**\n * Memoize a predicate as a reusable evaluation closure.\n *\n * The returned function accepts any `facts` scope (the reactive proxy in\n * production, a plain object in tests) plus an optional `prev` snapshot for\n * `$changed`. The closure is cached **by predicate identity** in a\n * `WeakMap`, so passing the same `predicate` reference repeatedly is\n * allocation-free; cleanup is automatic once the predicate is no longer\n * reachable.\n *\n * Note: no actual compilation happens — the returned closure re-walks the\n * spec on every call via `evaluatePredicate`. The name reflects what the\n * function does (closure memoization keyed by predicate identity), not a\n * bytecode/AST compile step.\n *\n * Intended for advanced users who want a stable function reference per\n * predicate (custom devtools, batched analyses). Regular module code does\n * not need to call this — the engine wraps data-form `when` / `on` specs\n * automatically at registration.\n *\n * @example\n * ```ts\n * const predicate = { phase: \"red\", elapsed: { $gte: 30 } };\n * const check = memoizePredicate(predicate);\n * check({ phase: \"red\", elapsed: 45 }); // → true\n * check({ phase: \"red\", elapsed: 5 }); // → false\n * ```\n */\nexport function memoizePredicate(\n predicate: object,\n): (facts: Scope, prev?: Scope) => boolean {\n if (predicate === null || typeof predicate !== \"object\") {\n throw new Error(\n `[Directive] memoizePredicate: predicate must be a plain object or array; got ${typeof predicate}`,\n );\n }\n const cached = memoizedCache.get(predicate);\n if (cached) {\n return cached;\n }\n\n const fn = (facts: Scope, prev?: Scope): boolean =>\n evaluatePredicate(predicate, facts, prev);\n memoizedCache.set(predicate, fn);\n\n return fn;\n}\n\n// ============================================================================\n// Dependency extraction\n// ============================================================================\n\n/**\n * Collect the fact keys a predicate references. Used for static analysis,\n * devtools, and effect `on` dependency wiring. Nested predicates contribute\n * dotted keys (`auth.token`).\n *\n * @example\n * ```ts\n * extractDeps({ phase: \"red\", elapsed: { $gte: 30 } });\n * // → Set { \"phase\", \"elapsed\" }\n * extractDeps({ self: { phase: \"red\" }, auth: { token: { $exists: true } } });\n * // → Set { \"self.phase\", \"auth.token\" }\n * ```\n */\nexport function extractDeps(spec: unknown, prefix = \"\"): Set<string> {\n const deps = new Set<string>();\n\n // Single structural traversal — every operator clause and equality leaf\n // contributes its dotted fact path. Combinators and nested objects are\n // descended automatically; stray `$`-keys never synthesize phantom deps.\n walkPredicate(spec, {\n operator(factPath) {\n deps.add(prefix + factPath);\n },\n literal(factPath) {\n deps.add(prefix + factPath);\n },\n strayOperatorKey(key) {\n // A `$`-key at fact position never synthesizes a phantom dep. A typo'd\n // operator (e.g. `$eqq`) additionally dev-warns; a known operator\n // mixed with fact keys is skipped silently (evaluatePredicate warns).\n if (!PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `extractDeps: unknown operator \"${key}\" — skipping. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n },\n });\n\n return deps;\n}\n\n// ============================================================================\n// Templates\n// ============================================================================\n\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** Stringify a value without dev-warns for null/undefined — used when the\n * caller has already emitted a higher-level diagnostic (e.g. \"unknown key\"). */\nfunction stringifyValueQuiet(v: unknown): string {\n if (typeof v === \"symbol\") {\n return \"\";\n }\n if (v === undefined || v === null) {\n return \"\";\n }\n\n return String(v);\n}\n\nfunction stringifyValue(v: unknown, key?: string): string {\n if (typeof v === \"symbol\") {\n devWarn(\"template: cannot interpolate a symbol value — using empty string\");\n\n return \"\";\n }\n if (v === undefined) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}undefined — using empty string`,\n );\n\n return \"\";\n }\n if (v === null) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}null — using empty string`,\n );\n\n return \"\";\n }\n\n return String(v);\n}\n\n/**\n * Interpolate a {@link FactTemplate} against a scope. Single-pass character\n * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal\n * `${`; unknown keys dev-warn and yield an empty string.\n *\n * @example\n * ```ts\n * evaluateTemplate({ $template: \"Hi ${name}!\" }, { name: \"Ada\" });\n * // → \"Hi Ada!\"\n * evaluateTemplate({ $template: \"$${price}\" }, {});\n * // → \"${price}\"\n * ```\n */\nexport function evaluateTemplate(spec: FactTemplate, scope: Scope): string {\n const tpl = spec.$template;\n let out = \"\";\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n out += \"${\";\n i += 3;\n continue;\n }\n\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n devWarn(`template: unterminated \"\\${\" in ${JSON.stringify(tpl)}`);\n out += tpl.slice(i);\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (!IDENTIFIER.test(key)) {\n devWarn(\n `template: invalid placeholder \"\\${${key}}\" — not an identifier`,\n );\n } else {\n // `stringifyValue` dev-warns separately for null vs undefined; here\n // we only warn when the key itself is missing from the scope (vs\n // present-but-null), so users see distinct diagnostics. Use\n // Object.hasOwn rather than `in` so prototype-chain keys (e.g.\n // `toString`, `constructor`) are never interpolated.\n const present = scope != null && Object.hasOwn(scope, key);\n const value = present ? scope[key] : undefined;\n if (!present) {\n devWarn(`template: unknown key \"${key}\"`);\n out += stringifyValueQuiet(value);\n } else {\n out += stringifyValue(value, key);\n }\n }\n i = end + 1;\n continue;\n }\n\n out += tpl[i];\n i++;\n }\n\n return out;\n}\n\n/**\n * Collect the placeholder keys referenced by a template. The static-analysis\n * counterpart to {@link extractDeps} — useful for devtools, codegen, and\n * \"which facts does this template read\" inspections. Only valid identifier\n * placeholders are collected; malformed ones are ignored.\n *\n * @example\n * ```ts\n * extractTemplateKeys({ $template: \"${firstName} ${lastName}\" });\n * // → Set { \"firstName\", \"lastName\" }\n * extractTemplateKeys({ $template: \"$${literal}\" });\n * // → Set {} (escaped — not a placeholder)\n * ```\n */\nexport function extractTemplateKeys(spec: FactTemplate): Set<string> {\n const keys = new Set<string>();\n const tpl = spec.$template;\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n i += 3;\n continue;\n }\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (IDENTIFIER.test(key)) {\n keys.add(key);\n }\n i = end + 1;\n continue;\n }\n i++;\n }\n\n return keys;\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\n/**\n * Build a stable dedup key by selecting fields from a requirement payload.\n * Order-as-declared; values are stable-stringified (keys sorted recursively)\n * so two payloads with the same fields in different orders dedupe to the\n * same key.\n *\n * @example\n * ```ts\n * evaluateKeySelector([\"url\", \"method\"], { url: \"/a\", method: \"GET\" });\n * // → '\"/a\"|\"GET\"'\n * evaluateKeySelector([\"id\"], { id: 42 });\n * // → '42'\n * ```\n */\nexport function evaluateKeySelector(\n selector: readonly string[],\n source: Record<string, unknown>,\n): string {\n return selector.map((field) => stableStringify(source?.[field])).join(\"|\");\n}\n\n// ============================================================================\n// Patch\n// ============================================================================\n\n/**\n * Apply a {@link PatchSpec} — assign facts from literals, payload copies\n * (`$ref`), or interpolated strings (`$template`). Mutates through the passed\n * `facts` proxy so change-tracking and downstream invalidation fire.\n *\n * @example\n * ```ts\n * const spec = {\n * $set: {\n * active: true,\n * userId: { $ref: \"id\" },\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * applyPatch(spec, facts, { id: \"u_1\", name: \"Ada\" });\n * // facts.active = true; facts.userId = \"u_1\"; facts.label = \"user Ada\"\n * ```\n */\nexport function applyPatch(\n spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>,\n facts: Record<string, unknown>,\n payload: Record<string, unknown>,\n): void {\n const set = spec.$set;\n const safePayload = payload ?? {};\n for (const key of Object.keys(set)) {\n const value = (set as Record<string, unknown>)[key];\n\n if (isTemplate(value)) {\n facts[key] = evaluateTemplate(value, safePayload);\n } else if (\n isPlainObject(value) &&\n Object.hasOwn(value, \"$ref\") &&\n typeof value.$ref === \"string\"\n ) {\n const refKey = value.$ref;\n // Use Object.hasOwn rather than `in` — tightens defense against\n // prototype-chain lookups so a payload `__proto__` shape can't smuggle\n // an inherited property into the fact assignment. The proxy already\n // blocks writes to dangerous keys, but this keeps the read symmetric.\n if (!Object.hasOwn(safePayload, refKey)) {\n devWarn(\n `applyPatch: $ref \"${refKey}\" is missing from event payload — assigning undefined to fact \"${key}\"`,\n );\n }\n facts[key] = safePayload[refKey];\n } else {\n facts[key] = value;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';var b=typeof process<"u"&&process.env?.NODE_ENV!=="production";function m(n,o=new WeakSet){if(n===null||typeof n!="object")return n;let r=n;if(o.has(r)||Object.isFrozen(r))return n;if(o.add(r),Array.isArray(r))for(let s of r)m(s,o);else for(let s of Object.keys(r))m(r[s],o);return Object.freeze(r),n}function A(n){return m(n)}function x(n,o,r){return (...s)=>{try{return r(...s)}catch(u){throw u instanceof Error&&u.message.startsWith("[Directive] ")?new Error(`[Directive] ${n} '${o}': ${u.message.slice(12)}`,{cause:u}):u}}}async function T(n,o,r){let s,u=new Promise((g,d)=>{s=setTimeout(()=>d(new Error(r)),o);});try{return await Promise.race([n,u])}finally{clearTimeout(s);}}function l(n,o=50){let r=new WeakSet;function s(t){if(t===null)return "null";if(t===void 0)return "undefined";let e=typeof t;if(e==="string")return JSON.stringify(t);if(e==="number"||e==="boolean")return String(t);if(e==="function")return '"[function]"';if(e==="symbol")return '"[symbol]"'}function u(t,e){if(r.has(t))return '"[circular]"';r.add(t);let i=e();return r.delete(t),i}function g(t,e){return u(t,()=>`[${t.map(i=>c(i,e+1)).join(",")}]`)}function d(t,e){return u(t,()=>`{${Object.keys(t).sort().map(f=>`${JSON.stringify(f)}:${c(t[f],e+1)}`).join(",")}}`)}function c(t,e){if(e>o)return '"[max depth exceeded]"';if(typeof t=="bigint")return `${t.toString()}n`;let i=s(t);if(i!==void 0)return i;if(t instanceof Date)return `D:${t.toISOString()}`;if(t instanceof RegExp)return `R:${t.source}:${t.flags}`;if(t instanceof Map){let a=[...t.entries()].sort();return `M:${c(a,e+1)}`}if(t instanceof Set){let a=[...t].sort();return `S:${c(a,e+1)}`}return Array.isArray(t)?g(t,e):typeof t=="object"?d(t,e):'"[unknown]"'}return c(n,0)}function D(n,o=50){let r=new Set(["__proto__","constructor","prototype"]),s=new WeakSet;function u(t,e){if(s.has(t))return true;s.add(t);let i=e();return s.delete(t),i}function g(t,e){for(let i of t)if(!c(i,e+1))return false;return true}function d(t,e){for(let i of Object.keys(t))if(r.has(i)||!c(t[i],e+1))return false;return true}function c(t,e){if(e>o)return false;if(t==null||typeof t!="object")return true;let i=t;return Array.isArray(i)?u(i,()=>g(i,e)):u(i,()=>d(i,e))}return c(n,0)}function E(n,o){if(n===o)return true;if(!n||!o)return false;let r=Object.keys(n),s=Object.keys(o);if(r.length!==s.length)return false;for(let u of r)if(n[u]!==o[u])return false;return true}function $(n){let o=l(n),r=5381;for(let s=0;s<o.length;s++)r=(r<<5)+r^o.charCodeAt(s);return (r>>>0).toString(16)}function h(n,o=Date.now()){return n.expiresAt!==void 0&&o>n.expiresAt}function R(n,o=Date.now()){if(!n||typeof n!="object")throw new Error("[Directive] Invalid snapshot: expected an object with 'data' and 'createdAt' properties.");if(!("data"in n))throw new Error("[Directive] Invalid snapshot: missing required 'data' property.");if(!("createdAt"in n)||typeof n.createdAt!="number")throw new Error("[Directive] Invalid snapshot: missing or invalid 'createdAt' property (expected number).");if(h(n,o)){let r=new Date(n.expiresAt).toISOString();throw new Error(`[Directive] Snapshot expired at ${r}. Obtain a fresh snapshot from the source.`)}return n.data}function P(n,o){let r=[];function s(e,i,a,f){r.push({path:e,oldValue:i,newValue:a,type:f});}function u(e,i,a){return e==null?(i!=null&&s(a,e,i,"added"),true):i==null?(s(a,e,i,"removed"),true):false}function g(e,i,a){if(e.length!==i.length){s(a,e,i,"changed");return}for(let f=0;f<e.length;f++)c(e[f],i[f],`${a}[${f}]`);}function d(e,i,a){let f=new Set([...Object.keys(e),...Object.keys(i)]);for(let y of f){let p=a?`${a}.${y}`:y;y in e?y in i?c(e[y],i[y],p):s(p,e[y],void 0,"removed"):s(p,void 0,i[y],"added");}}function c(e,i,a){if(!u(e,i,a)){if(typeof e!="object"||typeof i!="object"){Object.is(e,i)||s(a,e,i,"changed");return}if(Array.isArray(e)&&Array.isArray(i)){g(e,i,a);return}d(e,i,a);}}c(n.data,o.data,"");let t=n.version!==o.version&&(n.version!==void 0||o.version!==void 0);return {identical:r.length===0,changes:r,versionChanged:t,oldVersion:n.version,newVersion:o.version}}function C(n){return "signature"in n&&typeof n.signature=="string"}async function v(n,o){let r=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),s=await k(r,o);return {...n,signature:s,algorithm:"hmac-sha256"}}async function I(n,o){if(!n.signature||n.algorithm!=="hmac-sha256")return false;let r=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),s=await k(r,o);return w(n.signature,s)}async function k(n,o){let r=typeof o=="string"?new TextEncoder().encode(o):o,s={name:"HMAC",hash:{name:"SHA-256"}},u=await crypto.subtle.importKey("raw",r,s,false,["sign"]),g=new TextEncoder().encode(n),d=await crypto.subtle.sign("HMAC",u,g);return Array.from(new Uint8Array(d)).map(c=>c.toString(16).padStart(2,"0")).join("")}function w(n,o){if(n.length!==o.length)return false;let r=0;for(let s=0;s<n.length;s++)r|=n.charCodeAt(s)^o.charCodeAt(s);return r===0}function L(n,o=500){try{let r=JSON.stringify(n,(s,u)=>typeof u=="bigint"?`${u}n`:u,2);return r?r.length<=o?r:`${r.slice(0,o)}
|
|
2
|
+
... (truncated, ${r.length} chars total)`:"[undefined]"}catch{return "[unserializable]"}}exports.a=b;exports.b=A;exports.c=x;exports.d=T;exports.e=l;exports.f=D;exports.g=E;exports.h=$;exports.i=h;exports.j=R;exports.k=P;exports.l=C;exports.m=v;exports.n=I;exports.o=L;//# sourceMappingURL=chunk-4MNQDXH7.cjs.map
|
|
3
|
+
//# sourceMappingURL=chunk-4MNQDXH7.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dev-true.ts","../src/utils/utils.ts"],"names":["dev_true_default","deepFreeze","value","seen","obj","item","key","freezeSpec","spec","attributeError","category","id","fn","args","e","withTimeout","promise","ms","errorMessage","timeoutId","timeoutPromise","_","reject","stableStringify","maxDepth","stringifyPrimitive","val","type","withCircularGuard","result","stringifyArray","depth","v","stringify","stringifyObject","k","primitive","entries","items","isPrototypeSafe","dangerousKeys","objVal","checkArray","arr","check","checkObject","shallowEqual","a","b","keysA","keysB","hashObject","str","hash","i","isSnapshotExpired","snapshot","now","validateSnapshot","expiredAt","diffSnapshots","oldSnapshot","newSnapshot","changes","pushChange","path","oldValue","newValue","compareNullish","oldObj","newObj","compareArrays","oldArr","newArr","compare","compareObjects","oldRecord","newRecord","allKeys","childPath","versionChanged","isSignedSnapshot","signSnapshot","secret","payload","signature","hmacSha256","verifySnapshotSignature","signedSnapshot","expectedSignature","timingSafeEqual","message","secretBytes","algorithm","messageBytes","safeStringify","data","maxLen","_key"],"mappings":"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","file":"chunk-4MNQDXH7.cjs","sourcesContent":["// Runtime check that bundlers (webpack, esbuild, turbopack, rollup) inline\n// based on the consumer's NODE_ENV. Without this, the published bundle bakes\n// in `true` and dev-mode validation runs in every consumer's production\n// build — a real footgun the v1.5/v1.6 release hit.\nexport default typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n","/**\n * Shared utilities for Directive\n */\n\n// ============================================================================\n// Deep freeze\n// ============================================================================\n\n/**\n * Recursively `Object.freeze` an object including nested objects, arrays, and\n * array elements. Uses a `WeakSet` to handle cycles. Skips primitives and\n * already-frozen values to avoid wasted work.\n *\n * Used at definition-registration sites (constraints, derivations, effects,\n * events, prefixed specs) so post-registration mutation of a nested operand\n * cannot silently change the compiled closure's behavior. Prefer\n * {@link freezeSpec} at registration sites — it documents the convention.\n */\nexport function deepFreeze<T>(\n value: T,\n seen: WeakSet<object> = new WeakSet(),\n): T {\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n const obj = value as unknown as object;\n if (seen.has(obj) || Object.isFrozen(obj)) {\n return value;\n }\n seen.add(obj);\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n deepFreeze(item, seen);\n }\n } else {\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key], seen);\n }\n }\n\n Object.freeze(obj);\n return value;\n}\n\n/**\n * Freeze a definition spec at registration. Centralizes the deepFreeze\n * convention so a new definition arm cannot forget it — every constraint,\n * derivation, effect, event, and prefixed-spec registration funnels through\n * this single helper.\n *\n * @param spec - The definition spec to freeze (mutated in place, returned)\n * @returns The same `spec` value, now deeply frozen\n *\n * @example\n * ```ts\n * // At registration time, freeze user-supplied specs so post-registration\n * // mutation cannot silently change the compiled closure's behavior.\n * const spec = freezeSpec(userPredicate);\n * memoizePredicate(spec);\n * ```\n */\nexport function freezeSpec<T>(spec: T): T {\n return deepFreeze(spec);\n}\n\n/**\n * Wrap a synthesized definition function so a `[Directive]`-prefixed error\n * thrown from inside it is re-thrown with the owning definition's category +\n * id injected, and the original error preserved as `cause`. Non-`[Directive]`\n * errors (user code, native) pass through untouched.\n *\n * Centralizes the owner-attribution wrap shared by the data-form `when`\n * (constraints), `on` (effects), and `compute` (derivations) closures — a\n * `[Directive]`-prefixed throw (e.g. `$matches: string`) is re-pointed at the\n * owning definition so the stack trace blames user config, not the runtime.\n *\n * @param category - The owning definition kind, used in the re-thrown message.\n * @param id - The owning definition's id.\n * @param fn - The synthesized function to wrap.\n * @returns A function with identical signature that re-attributes Directive errors.\n */\nexport function attributeError<A extends unknown[], R>(\n category: \"constraint\" | \"effect\" | \"derivation\",\n id: string,\n fn: (...args: A) => R,\n): (...args: A) => R {\n // Synchronous by design: the wrapped definition functions (memoized\n // predicate `when`/`on` closures, template closures) always return\n // synchronously. A `try/catch` only re-attributes a synchronous throw — an\n // async-returning fn's rejected promise would escape un-re-attributed.\n return (...args: A): R => {\n try {\n return fn(...args);\n } catch (e) {\n if (e instanceof Error && e.message.startsWith(\"[Directive] \")) {\n throw new Error(\n `[Directive] ${category} '${id}': ${e.message.slice(\"[Directive] \".length)}`,\n { cause: e },\n );\n }\n throw e;\n }\n };\n}\n\n/**\n * Execute a promise with a timeout, properly cleaning up the timer.\n * Used by both constraints and resolvers for timeout handling.\n *\n * @param promise - The promise to wrap with a timeout\n * @param ms - Timeout duration in milliseconds\n * @param errorMessage - Error message if timeout occurs\n * @returns The promise result\n * @throws Error if timeout is exceeded\n */\nexport async function withTimeout<T>(\n promise: Promise<T>,\n ms: number,\n errorMessage: string,\n): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout>;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(errorMessage)), ms);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId!);\n }\n}\n\n/**\n * Normalize an error to an Error instance.\n * Ensures consistent error handling throughout the library.\n *\n * @param error - The error to normalize (can be anything)\n * @returns An Error instance\n */\nexport function normalizeError(error: unknown): Error {\n if (error instanceof Error) {\n return error;\n }\n return new Error(String(error));\n}\n\n/**\n * Create a stable JSON string with sorted keys.\n * Handles circular references and deeply nested objects safely.\n *\n * @param value - The value to stringify\n * @param maxDepth - Maximum nesting depth (default: 50)\n * @returns A stable JSON string\n */\nexport function stableStringify(value: unknown, maxDepth = 50): string {\n const seen = new WeakSet();\n\n /** Stringify a primitive value (null, undefined, string, number, boolean, function, symbol). */\n function stringifyPrimitive(val: unknown): string | undefined {\n if (val === null) return \"null\";\n if (val === undefined) return \"undefined\";\n\n const type = typeof val;\n if (type === \"string\") return JSON.stringify(val);\n if (type === \"number\" || type === \"boolean\") return String(val);\n if (type === \"function\") return '\"[function]\"';\n if (type === \"symbol\") return '\"[symbol]\"';\n\n return undefined;\n }\n\n /** Guard against circular references using a seen-set, then delegate to fn. */\n function withCircularGuard(obj: object, fn: () => string): string {\n if (seen.has(obj)) {\n return '\"[circular]\"';\n }\n seen.add(obj);\n const result = fn();\n seen.delete(obj);\n\n return result;\n }\n\n /** Stringify an array with circular reference protection. */\n function stringifyArray(val: unknown[], depth: number): string {\n return withCircularGuard(\n val,\n () => `[${val.map((v) => stringify(v, depth + 1)).join(\",\")}]`,\n );\n }\n\n /** Stringify an object with sorted keys and circular reference protection. */\n function stringifyObject(\n obj: Record<string, unknown>,\n depth: number,\n ): string {\n return withCircularGuard(obj, () => {\n const keys = Object.keys(obj).sort();\n const pairs = keys.map(\n (k) => `${JSON.stringify(k)}:${stringify(obj[k], depth + 1)}`,\n );\n\n return `{${pairs.join(\",\")}}`;\n });\n }\n\n /** Recursively stringify a value with depth limit and circular detection. */\n function stringify(val: unknown, depth: number): string {\n if (depth > maxDepth) {\n return '\"[max depth exceeded]\"';\n }\n\n // BigInt is not JSON-serializable; encode with a trailing 'n' to remain\n // distinct from numeric strings.\n if (typeof val === \"bigint\") {\n return `${val.toString()}n`;\n }\n\n const primitive = stringifyPrimitive(val);\n if (primitive !== undefined) {\n return primitive;\n }\n\n // Typed-value branches: each prefix is bare (no outer quotes) so it can\n // never collide with a JSON-encoded string. `JSON.stringify(\"D:...\")`\n // emits `\"D:...\"` (the wrapping quotes ARE part of the output string),\n // whereas the Date branch emits `D:...` (no quotes). Distinct outputs.\n if (val instanceof Date) {\n return `D:${val.toISOString()}`;\n }\n if (val instanceof RegExp) {\n return `R:${val.source}:${val.flags}`;\n }\n if (val instanceof Map) {\n const entries = [...val.entries()].sort();\n return `M:${stringify(entries, depth + 1)}`;\n }\n if (val instanceof Set) {\n const items = [...val].sort();\n return `S:${stringify(items, depth + 1)}`;\n }\n\n if (Array.isArray(val)) {\n return stringifyArray(val, depth);\n }\n\n if (typeof val === \"object\") {\n return stringifyObject(val as Record<string, unknown>, depth);\n }\n\n return '\"[unknown]\"';\n }\n\n return stringify(value, 0);\n}\n\n/**\n * Check for prototype pollution in an object, including nested objects.\n * Returns true if the object is safe, false if dangerous keys are found.\n *\n * @param obj - The object to check\n * @param maxDepth - Maximum nesting depth to check (default: 50)\n * @returns True if safe, false if dangerous keys found\n */\nexport function isPrototypeSafe(obj: unknown, maxDepth = 50): boolean {\n const dangerousKeys = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n const seen = new WeakSet();\n\n /** Guard against circular references using a seen-set, then delegate to fn. */\n function withCircularGuard(objVal: object, fn: () => boolean): boolean {\n if (seen.has(objVal)) return true;\n seen.add(objVal);\n const result = fn();\n seen.delete(objVal);\n\n return result;\n }\n\n /** Check array elements for prototype pollution keys. */\n function checkArray(arr: unknown[], depth: number): boolean {\n for (const item of arr) {\n if (!check(item, depth + 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /** Check object keys and values for prototype pollution. */\n function checkObject(\n objVal: Record<string, unknown>,\n depth: number,\n ): boolean {\n for (const key of Object.keys(objVal)) {\n if (dangerousKeys.has(key)) {\n return false;\n }\n if (!check(objVal[key], depth + 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /** Recursively check a value tree for dangerous prototype keys. */\n function check(val: unknown, depth: number): boolean {\n if (depth > maxDepth) return false; // Fail safe at max depth - don't assume safety\n if (val === null || val === undefined) return true;\n if (typeof val !== \"object\") return true;\n\n const objVal = val as Record<string, unknown>;\n\n if (Array.isArray(objVal)) {\n return withCircularGuard(objVal, () => checkArray(objVal, depth));\n }\n\n return withCircularGuard(objVal, () => checkObject(objVal, depth));\n }\n\n return check(obj, 0);\n}\n\n/**\n * Shallow equality comparison for objects.\n * Used by React hooks to avoid unnecessary re-renders.\n *\n * @param a - First object\n * @param b - Second object\n * @returns True if objects are shallowly equal\n */\nexport function shallowEqual<T extends Record<string, unknown>>(\n a: T,\n b: T,\n): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n\n return true;\n}\n\n/**\n * Generate a simple hash string from an object.\n * Uses djb2 algorithm on the stable stringified value.\n *\n * **Limitations:**\n * - 32-bit hash output means collision probability increases with data set size\n * (birthday paradox: ~50% collision chance at ~77,000 distinct values)\n * - Suitable for: cache invalidation, change detection, deduplication of small sets\n * - NOT suitable for: cryptographic use, security-sensitive operations, large-scale deduplication\n *\n * For security-sensitive use cases requiring stronger collision resistance,\n * consider using a cryptographic hash like SHA-256.\n *\n * @param value - The value to hash\n * @returns A hex hash string (8 characters, 32 bits)\n */\nexport function hashObject(value: unknown): string {\n const str = stableStringify(value);\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash) ^ str.charCodeAt(i);\n }\n // Convert to unsigned 32-bit and then to hex\n return (hash >>> 0).toString(16);\n}\n\n// ============================================================================\n// Distributable Snapshot Utilities\n// ============================================================================\n\n/**\n * Distributable snapshot type for type-safe helper functions.\n */\nexport interface DistributableSnapshotLike<T = Record<string, unknown>> {\n data: T;\n createdAt: number;\n expiresAt?: number;\n version?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Check if a distributable snapshot has expired.\n * Returns false if the snapshot has no expiresAt field.\n *\n * @example\n * ```typescript\n * const snapshot = system.getDistributableSnapshot({ ttlSeconds: 3600 });\n * // ... later ...\n * if (isSnapshotExpired(snapshot)) {\n * // Refresh the snapshot\n * }\n * ```\n *\n * @param snapshot - The snapshot to check\n * @param now - Optional current timestamp (defaults to Date.now())\n * @returns True if the snapshot has expired, false otherwise\n */\nexport function isSnapshotExpired<T>(\n snapshot: DistributableSnapshotLike<T>,\n now: number = Date.now(),\n): boolean {\n return snapshot.expiresAt !== undefined && now > snapshot.expiresAt;\n}\n\n/**\n * Validate a distributable snapshot and return its data.\n * Throws if the snapshot is malformed or has expired.\n *\n * @example\n * ```typescript\n * const cached = JSON.parse(await redis.get(`entitlements:${userId}`));\n * try {\n * const data = validateSnapshot(cached);\n * // Use data.canUseFeature, etc.\n * } catch (e) {\n * // Snapshot invalid or expired, refresh it\n * }\n * ```\n *\n * @example Using custom timestamp for testing\n * ```typescript\n * const snapshot = { data: { test: true }, createdAt: 1000, expiresAt: 2000 };\n * validateSnapshot(snapshot, 1500); // Returns { test: true }\n * validateSnapshot(snapshot, 2500); // Throws: Snapshot expired\n * ```\n *\n * @param snapshot - The snapshot to validate\n * @param now - Optional current timestamp (defaults to Date.now())\n * @returns The snapshot data if valid\n * @throws Error if the snapshot is malformed or has expired\n */\nexport function validateSnapshot<T>(\n snapshot: DistributableSnapshotLike<T>,\n now: number = Date.now(),\n): T {\n // Structural validation\n if (!snapshot || typeof snapshot !== \"object\") {\n throw new Error(\n \"[Directive] Invalid snapshot: expected an object with 'data' and 'createdAt' properties.\",\n );\n }\n if (!(\"data\" in snapshot)) {\n throw new Error(\n \"[Directive] Invalid snapshot: missing required 'data' property.\",\n );\n }\n if (!(\"createdAt\" in snapshot) || typeof snapshot.createdAt !== \"number\") {\n throw new Error(\n \"[Directive] Invalid snapshot: missing or invalid 'createdAt' property (expected number).\",\n );\n }\n\n // Expiration validation\n if (isSnapshotExpired(snapshot, now)) {\n const expiredAt = new Date(snapshot.expiresAt!).toISOString();\n throw new Error(\n `[Directive] Snapshot expired at ${expiredAt}. Obtain a fresh snapshot from the source.`,\n );\n }\n return snapshot.data;\n}\n\n/**\n * Diff result for a single changed value.\n */\nexport interface SnapshotDiffEntry {\n /** The key path that changed (e.g., \"canUseApi\" or \"limits.apiCalls\") */\n path: string;\n /** The value in the old snapshot */\n oldValue: unknown;\n /** The value in the new snapshot */\n newValue: unknown;\n /** Type of change: \"added\", \"removed\", or \"changed\" */\n type: \"added\" | \"removed\" | \"changed\";\n}\n\n/**\n * Result of diffing two snapshots.\n */\nexport interface SnapshotDiff {\n /** Whether the snapshots are identical */\n identical: boolean;\n /** List of changes between snapshots */\n changes: SnapshotDiffEntry[];\n /** Whether the version changed (if both have versions) */\n versionChanged: boolean;\n /** Old version (if available) */\n oldVersion?: string;\n /** New version (if available) */\n newVersion?: string;\n}\n\n/**\n * Compare two distributable snapshots and return the differences.\n * Useful for debugging, audit logs, and webhook payloads.\n *\n * @example\n * ```typescript\n * const oldSnapshot = system.getDistributableSnapshot({ includeVersion: true });\n * system.dispatch({ type: \"upgradePlan\", plan: \"pro\" });\n * const newSnapshot = system.getDistributableSnapshot({ includeVersion: true });\n *\n * const diff = diffSnapshots(oldSnapshot, newSnapshot);\n * if (!diff.identical) {\n * console.log(\"Changes:\", diff.changes);\n * // [{ path: \"canUseApi\", oldValue: false, newValue: true, type: \"changed\" }]\n * }\n * ```\n *\n * @param oldSnapshot - The previous snapshot\n * @param newSnapshot - The new snapshot\n * @returns A diff result with all changes\n */\nexport function diffSnapshots<T = Record<string, unknown>>(\n oldSnapshot: DistributableSnapshotLike<T>,\n newSnapshot: DistributableSnapshotLike<T>,\n): SnapshotDiff {\n const changes: SnapshotDiffEntry[] = [];\n\n /** Push a change entry to the diff results. */\n function pushChange(\n path: string,\n oldValue: unknown,\n newValue: unknown,\n type: SnapshotDiffEntry[\"type\"],\n ): void {\n changes.push({ path, oldValue, newValue, type });\n }\n\n /** Handle null/undefined comparison cases. Returns true if fully handled. */\n function compareNullish(\n oldObj: unknown,\n newObj: unknown,\n path: string,\n ): boolean {\n if (oldObj === null || oldObj === undefined) {\n if (newObj !== null && newObj !== undefined) {\n pushChange(path, oldObj, newObj, \"added\");\n }\n\n return true;\n }\n if (newObj === null || newObj === undefined) {\n pushChange(path, oldObj, newObj, \"removed\");\n\n return true;\n }\n\n return false;\n }\n\n /** Compare two arrays element by element, recursing into each. */\n function compareArrays(\n oldArr: unknown[],\n newArr: unknown[],\n path: string,\n ): void {\n if (oldArr.length !== newArr.length) {\n pushChange(path, oldArr, newArr, \"changed\");\n\n return;\n }\n for (let i = 0; i < oldArr.length; i++) {\n compare(oldArr[i], newArr[i], `${path}[${i}]`);\n }\n }\n\n /** Compare two objects by key union, detecting added/removed/changed. */\n function compareObjects(\n oldRecord: Record<string, unknown>,\n newRecord: Record<string, unknown>,\n path: string,\n ): void {\n const allKeys = new Set([\n ...Object.keys(oldRecord),\n ...Object.keys(newRecord),\n ]);\n\n for (const key of allKeys) {\n const childPath = path ? `${path}.${key}` : key;\n if (!(key in oldRecord)) {\n pushChange(childPath, undefined, newRecord[key], \"added\");\n } else if (!(key in newRecord)) {\n pushChange(childPath, oldRecord[key], undefined, \"removed\");\n } else {\n compare(oldRecord[key], newRecord[key], childPath);\n }\n }\n }\n\n /** Recursively compare two values and record differences. */\n function compare(oldObj: unknown, newObj: unknown, path: string): void {\n if (compareNullish(oldObj, newObj, path)) {\n return;\n }\n\n // Handle primitives\n if (typeof oldObj !== \"object\" || typeof newObj !== \"object\") {\n if (!Object.is(oldObj, newObj)) {\n pushChange(path, oldObj, newObj, \"changed\");\n }\n\n return;\n }\n\n // Handle arrays\n if (Array.isArray(oldObj) && Array.isArray(newObj)) {\n compareArrays(oldObj, newObj, path);\n\n return;\n }\n\n // Handle objects\n compareObjects(\n oldObj as Record<string, unknown>,\n newObj as Record<string, unknown>,\n path,\n );\n }\n\n // Compare data\n compare(oldSnapshot.data, newSnapshot.data, \"\");\n\n // Check version change\n const versionChanged =\n oldSnapshot.version !== newSnapshot.version &&\n (oldSnapshot.version !== undefined || newSnapshot.version !== undefined);\n\n return {\n identical: changes.length === 0,\n changes,\n versionChanged,\n oldVersion: oldSnapshot.version,\n newVersion: newSnapshot.version,\n };\n}\n\n// ============================================================================\n// Snapshot Signing (HMAC)\n// ============================================================================\n\n/**\n * A signed distributable snapshot.\n * Contains the original snapshot plus a cryptographic signature.\n */\nexport interface SignedSnapshot<T = Record<string, unknown>>\n extends DistributableSnapshotLike<T> {\n /** HMAC-SHA256 signature in hex format */\n signature: string;\n /** Signing algorithm used */\n algorithm: \"hmac-sha256\";\n}\n\n/**\n * Check if a snapshot is signed.\n *\n * @param snapshot - The snapshot to check\n * @returns True if the snapshot has a signature\n */\nexport function isSignedSnapshot<T>(\n snapshot: DistributableSnapshotLike<T> | SignedSnapshot<T>,\n): snapshot is SignedSnapshot<T> {\n return \"signature\" in snapshot && typeof snapshot.signature === \"string\";\n}\n\n/**\n * Sign a distributable snapshot using HMAC-SHA256.\n * Creates a tamper-proof signature that can be verified later.\n *\n * **Security Notes:**\n * - Use a cryptographically random secret of at least 32 bytes\n * - Store the secret securely (environment variable, secrets manager)\n * - Never expose the secret to clients\n * - The signature covers all snapshot fields for integrity\n *\n * @example\n * ```typescript\n * const snapshot = system.getDistributableSnapshot({\n * includeDerivations: ['canUseFeature', 'limits'],\n * ttlSeconds: 3600,\n * });\n *\n * // Sign the snapshot (server-side only)\n * const signed = await signSnapshot(snapshot, process.env.SNAPSHOT_SECRET);\n *\n * // Store in JWT, Redis, or send to client\n * const jwt = createJWT({ snapshot: signed });\n *\n * // Later, verify the signature\n * const isValid = await verifySnapshotSignature(signed, process.env.SNAPSHOT_SECRET);\n * if (!isValid) {\n * throw new Error('Snapshot has been tampered with');\n * }\n * ```\n *\n * @param snapshot - The snapshot to sign\n * @param secret - The HMAC secret (string or Uint8Array)\n * @returns A signed snapshot with the signature attached\n */\nexport async function signSnapshot<T>(\n snapshot: DistributableSnapshotLike<T>,\n secret: string | Uint8Array,\n): Promise<SignedSnapshot<T>> {\n // Create a canonical representation for signing\n const payload = stableStringify({\n data: snapshot.data,\n createdAt: snapshot.createdAt,\n expiresAt: snapshot.expiresAt,\n version: snapshot.version,\n metadata: snapshot.metadata,\n });\n\n const signature = await hmacSha256(payload, secret);\n\n return {\n ...snapshot,\n signature,\n algorithm: \"hmac-sha256\",\n };\n}\n\n/**\n * Verify the signature of a signed snapshot.\n * Returns true if the signature is valid, false otherwise.\n *\n * **Important:** Always verify signatures before trusting snapshot data,\n * especially if the snapshot was received from an untrusted source (client, cache).\n *\n * @example\n * ```typescript\n * // Receive signed snapshot from client or cache\n * const snapshot = JSON.parse(cachedData);\n *\n * // Verify before using\n * const isValid = await verifySnapshotSignature(snapshot, process.env.SNAPSHOT_SECRET);\n * if (!isValid) {\n * throw new Error('Invalid snapshot signature - possible tampering');\n * }\n *\n * // Now safe to use snapshot.data\n * if (snapshot.data.canUseFeature.api) {\n * // Grant access\n * }\n * ```\n *\n * @param signedSnapshot - The signed snapshot to verify\n * @param secret - The HMAC secret (must match the signing secret)\n * @returns True if signature is valid, false otherwise\n */\nexport async function verifySnapshotSignature<T>(\n signedSnapshot: SignedSnapshot<T>,\n secret: string | Uint8Array,\n): Promise<boolean> {\n if (!signedSnapshot.signature || signedSnapshot.algorithm !== \"hmac-sha256\") {\n return false;\n }\n\n // Recreate the canonical payload (same as signing)\n const payload = stableStringify({\n data: signedSnapshot.data,\n createdAt: signedSnapshot.createdAt,\n expiresAt: signedSnapshot.expiresAt,\n version: signedSnapshot.version,\n metadata: signedSnapshot.metadata,\n });\n\n const expectedSignature = await hmacSha256(payload, secret);\n\n // Use timing-safe comparison\n return timingSafeEqual(signedSnapshot.signature, expectedSignature);\n}\n\n/**\n * Create HMAC-SHA256 signature of a message.\n * Uses Web Crypto API for cross-platform support (Node.js, browsers, Deno, Bun).\n */\nasync function hmacSha256(\n message: string,\n secret: string | Uint8Array,\n): Promise<string> {\n // Convert secret to Uint8Array if string\n const secretBytes: Uint8Array =\n typeof secret === \"string\" ? new TextEncoder().encode(secret) : secret;\n\n // Import key for HMAC\n const algorithm: HmacImportParams = {\n name: \"HMAC\",\n hash: { name: \"SHA-256\" },\n };\n const key = await crypto.subtle.importKey(\n \"raw\",\n secretBytes as unknown as ArrayBuffer,\n algorithm,\n false,\n [\"sign\"],\n );\n\n // Sign the message\n const messageBytes = new TextEncoder().encode(message);\n const signature = await crypto.subtle.sign(\"HMAC\", key, messageBytes);\n\n // Convert to hex string\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n/**\n * Timing-safe string comparison to prevent timing attacks.\n * Both strings should be the same length (hex signatures from same algorithm).\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n\n/**\n * Safely stringify any value for display. Handles circular references,\n * BigInt, throwing toJSON, and optional truncation.\n *\n * This is the canonical implementation – all packages should import this\n * instead of maintaining local copies.\n */\nexport function safeStringify(data: unknown, maxLen = 500): string {\n try {\n const str = JSON.stringify(\n data,\n (_key, value) => {\n if (typeof value === \"bigint\") {\n return `${value}n`;\n }\n\n return value;\n },\n 2,\n );\n if (!str) {\n return \"[undefined]\";\n }\n if (str.length <= maxLen) {\n return str;\n }\n\n return `${str.slice(0, maxLen)}\\n... (truncated, ${str.length} chars total)`;\n } catch {\n return \"[unserializable]\";\n }\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {z,a as a$1}from'./chunk-R2GHSCTR.js';import {k as k$1,h,q,s,v}from'./chunk-2FF6QGOA.js';import {k,l,m as m$1}from'./chunk-I722BZA5.js';import {a,f,b as b$1}from'./chunk-PXRV64PA.js';var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function D(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!k.has(t))return e.get(t)},set(n,t,s){return typeof t=="symbol"||k.has(t)?false:e.set?e.set(t,s):false},has(n,t){return typeof t=="symbol"||k.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||k.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function $(e,n){let t=Z.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,Z.set(e,t);let s=D({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n}${m}${r}`],set:(r,u)=>{if(a){let i=l(u);i&&m$1(`${n}.${r}`,i);}return e[`${n}${m}${r}`]=u,true},has:r=>`${n}${m}${r}`in e,delete:r=>(delete e[`${n}${m}${r}`],true)});return t.set(n,s),s}function re(e,n,t){let s=Q.get(e);if(s)return s;let r=D({get:u=>{if(Object.hasOwn(n,u))return $(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let s=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(s);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),i=["self",...t],c=D({get:o=>{if(o==="self")return $(e,n);if(u.has(o))return $(e,o);a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>i});return r.set(s,c),c}function B(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let s=D({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,s),s}function se(e,n,t){let s=X.get(e);if(s)return s;let r=D({get:u=>{if(Object.hasOwn(n,u))return B(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let s=te.get(e);return s||(s=new Map,te.set(e,s)),D({get:r=>{if(!Object.hasOwn(n,r))return;let u=s.get(r);if(u)return u;let i=D({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return s.set(r,i),i},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function R(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function H(e){let n={};for(let[t,s]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),i=t.slice(r+m.length);n[u]||(n[u]={}),n[u][i]=s;}else n._root||(n._root={}),n._root[t]=s;}return n}function P(e,n,t,s){return t?oe(e,n,s):$(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let i=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return b$1(i),i}if(!e||typeof e!="object")return e;let s=e;if("$all"in s||"$any"in s){let i="$all"in s?"$all":"$any",c=s[i],o={[i]:c.map(f=>E(f,n,t))};return b$1(o),o}if("$not"in s){let i={$not:E(s.$not,n,t)};return b$1(i),i}function r(i,c){return E(i,c,ce)}let u={};for(let i of Object.keys(s)){if(i.startsWith("$")||ae(i)){u[i]=s[i];continue}if(i==="self"){let c=s[i];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(i)){let c=s[i];if(c&&typeof c=="object"){let o=r(c,i);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,i)]=s[i];}return b$1(u),u}var ce=new Set;function me(e,n){let t=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,s$1=e.constraints;if(s$1){let c=false,o={};for(let[f,l]of Object.entries(s$1)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t)},c=true;continue}o[f]=l;}c&&(s$1=o);}let r=e.derive;if(r){let c=false,o={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o[f]=l;continue}let g=d.compute;if(typeof g=="function"){o[f]=l;continue}if(k$1(g)){b$1(g);let k=w=>s(g,w);o[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(h(g)){b$1(g);let k=q(g),w=j=>k(j);o[f]=d.meta?{compute:w,meta:d.meta}:w,c=true;continue}o[f]=l;}c&&(r=o);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),g=Object.hasOwn(l,"patch");if(d&&g&&a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),g&&!d){let k=l;b$1(k.patch);let w=(j,O)=>v(k.patch,j,O??{});o[f]=k.meta?{handler:w,meta:k.meta}:w,c=true;continue}}o[f]=l;}c&&(u=o);}let i=e.effects;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.on!==void 0&&h(d.on)){o[f]={...d,on:E(d.on,n,t)},c=true;continue}o[f]=l;}c&&(i=o);}return s$1===e.constraints&&r===e.derive&&u===e.events&&i===e.effects?e:{...e,constraints:s$1,derive:r,events:u,effects:i}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[s,r]of Object.entries(e.schema.facts))t[b(n,s)]=r;return t}function pe(e,n){if(e.init)return t=>{let s=$(t,n);e.init(s);}}function ve(e,n,t,s){if(!e.derive)return;let r={};for(let[u,i]of Object.entries(e.derive)){let c=a$1(i),o=c?i.compute:i,f=c?i.meta:void 0,l=(d,g)=>{let k=P(d,n,t,s),w=B(g,n);return o(k,w)};r[b(n,u)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[s,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),i=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=$(f,n);i(d,l);};t[b(n,s)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,s){if(!e.constraints)return;let r={};for(let[u,i]of Object.entries(e.constraints)){let c=i,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),owns:c.owns?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=P(f,n,t,s);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=P(f,n,t,s);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,s){if(!e.resolvers)return;let r={};for(let[i,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:P(l.facts,n,t,s),signal:l.signal}};let o=c;r[b(n,i)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,s){if(!e.effects)return;let r={};for(let[u,i]of Object.entries(e.effects)){let c=i;r[b(n,u)]={...c,run:(o,f)=>{let l=P(o,n,t,s),d=f?P(f,n,t,s):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(s=>b(n,s))}}function I(e){let{mod:n,namespace:t,snapshotModulesSet:s}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),i=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,i),events:be(r,t),effects:Se(r,t,u,i),constraints:Me(r,t,u,i),resolvers:Re(r,t,u,i),hooks:r.hooks,meta:r.meta,history:Oe(r,t,s)}}function xe(e){let n=Object.keys(e),t=new Set(n),s=new Set,r=new Set,u=[],i=[];function c(o){if(s.has(o))return;if(r.has(o)){let l=i.indexOf(o),d=[...i.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),i.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);i.pop(),r.delete(o),s.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let s of Object.keys(n.schema.facts))t.push(`${e}${m}${s}`);if(n.schema.derivations)for(let s of Object.keys(n.schema.derivations))t.push(`${e}${m}${s}`);return t}function ze(e){if("module"in e){if(!e.module)throw new Error("[Directive] createSystem requires a module. Got: "+typeof e.module);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array.
|
|
2
|
+
|
|
3
|
+
Instead of:
|
|
4
|
+
createSystem({ modules: [authModule, dataModule] })
|
|
5
|
+
|
|
6
|
+
Use:
|
|
7
|
+
createSystem({ modules: { auth: authModule, data: dataModule } })
|
|
8
|
+
|
|
9
|
+
Or for a single module:
|
|
10
|
+
createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead:
|
|
11
|
+
|
|
12
|
+
createSystem({ module: myModule })
|
|
13
|
+
|
|
14
|
+
For multiple modules, wrap in an object:
|
|
15
|
+
createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e){let n=e.modules,t=new Set(Object.keys(n)),s=typeof e.history=="object"?e.history:null,r=s?.snapshotModules?new Set(s.snapshotModules):null;if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let h of Object.keys(y.crossModuleDeps))h===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(h)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${h}, but no module with namespace "${h}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(a&&s?.snapshotModules)for(let a of s.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,i=e.initOrder??"auto";if(Array.isArray(i)){let a=i,y=Object.keys(n).filter(h=>!a.includes(h));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else i==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f$1}=de(e);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let h of Object.keys(y.schema.facts))if(h.includes(m))throw new Error(`[Directive] Schema key "${h}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l={names:null};function d(){return l.names===null&&(l.names=Object.keys(n)),l.names}let g=u.map(a=>{let y=n[a];return y?I({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);a&&e.tickMs&&e.tickMs>0&&(g.some(y=>y.events&&Object.keys(y.events).some(h=>h.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but no module defines a "tick" event handler.`));let k$1=null,w=null;function j(a$1){for(let[y,h]of Object.entries(a$1)){if(k.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(h&&typeof h=="object"&&!f(h))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,x]of Object.entries(h))k.has(M)||(w.facts[`${y}${m}${M}`]=x);}}w=z({modules:g,plugins:e.plugins,history:c,trace:o,errorBoundary:f$1,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{e.initialFacts&&j(e.initialFacts),k$1&&(j(k$1),k$1=null);}});let O=new Map;for(let a of Object.keys(n)){let y=n[a];y&&O.set(a,ue(a,y));}let q=re(w.facts,n,d),ye=se(w.derive,n,d),ge=ie(w,n,d),A=null,F=e.tickMs,_={_mode:"namespaced",facts:q,history:w.history,derive:ye,events:ge,constraints:w.constraints,effects:w.effects,resolvers:w.resolvers,async hydrate(a){if(w.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k$1=y);},initialize(){w.initialize();},start(){if(w.start(),F&&F>0){let a;for(let y of g)if(y?.events&&(a=Object.keys(y.events).find(h=>h.endsWith(`${m}tick`)),a))break;if(a){let y=a;A=setInterval(()=>{w.dispatch({type:y});},F);}}},stop(){A&&(clearInterval(A),A=null),w.stop();},destroy(){this.stop(),w.destroy();},dispatch(a){w.dispatch(a);},read(a){return w.read(R(a))},subscribe(a$1,y){let h=[];for(let M of a$1)if(M.endsWith(".*")){let x=M.slice(0,-2),W=O.get(x);W?h.push(...W):a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${x}" not found.`);}else h.push(R(M));return w.subscribe(h,y)},subscribeModule(a$1,y){let h=O.get(a$1);return !h||h.length===0?(a&&console.warn(`[Directive] subscribeModule("${a$1}") \u2014 namespace not found. Available: ${[...O.keys()].join(", ")}`),()=>{}):w.subscribe(h,y)},watch(a,y,h){return w.watch(R(a),y,h)},when(a,y){return w.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(R),excludeDerivations:a?.excludeDerivations?.map(R),includeFacts:a?.includeFacts?.map(R)},h=w.getDistributableSnapshot(y);return {...h,data:H(h.data)}},watchDistributableSnapshot(a,y){let h={...a,includeDerivations:a?.includeDerivations?.map(R),excludeDerivations:a?.excludeDerivations?.map(R),includeFacts:a?.includeFacts?.map(R)};return w.watchDistributableSnapshot(h,M=>{y({...M,data:H(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(k.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let x of Object.keys(y.schema.facts))if(x.includes(m))throw new Error(`[Directive] Schema key "${x}" in module "${a}" contains the reserved separator "${m}".`);let h=y,M=I({mod:h,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=h,l.names=null,O.set(a,ue(a,h)),w.registerModule(M);}};return le(_,w),fe(_),_}function de(e){let n=e.history,t=e.trace,s=e.errorBoundary;return e.zeroConfig&&(n=n??a,s={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:s}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let s of t)s in e||(e[s]=n[s].bind(n));}function fe(e){a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e){let n=e.module;if(!n)throw new Error("[Directive] createSystem requires a module. Got: "+typeof n);if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e.initialFacts&&!f(e.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e.tickMs&&e.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but module has no "tick" event handler.`)),(typeof e.history=="object"?e.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:s,errorBoundary:r}=de(e),u=null,i=null;i=z({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e.plugins,history:t,trace:s,errorBoundary:r,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{if(e.initialFacts)for(let[d,g]of Object.entries(e.initialFacts))k.has(d)||(i.facts[d]=g);if(u){if(!f(u))a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,g]of Object.entries(u))k.has(d)||(i.facts[d]=g);u=null;}}});let c=new Proxy({},{get(d,g){if(typeof g!="symbol"&&!k.has(g))return k=>{i.dispatch({type:g,...k});}},has(d,g){return typeof g=="symbol"||k.has(g)?false:n.events?g in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,g){if(typeof g!="symbol"&&!k.has(g)&&n.events&&g in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f$1=e.tickMs,l={_mode:"single",facts:i.facts,history:i.history,derive:i.derive,events:c,constraints:i.constraints,effects:i.effects,resolvers:i.resolvers,async hydrate(d){if(i.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let g=await d();g&&typeof g=="object"&&(u=g);},initialize(){i.initialize();},start(){i.start(),f$1&&f$1>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{i.dispatch({type:"tick"});},f$1));},stop(){o&&(clearInterval(o),o=null),i.stop();},destroy(){this.stop(),i.destroy();},registerModule(d){i.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l,i),fe(l),l}export{ze as a};//# sourceMappingURL=chunk-644QZVTT.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-644QZVTT.js.map
|