@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.
Files changed (92) hide show
  1. package/dist/adapter-utils.cjs +1 -1
  2. package/dist/adapter-utils.d.cts +2 -2
  3. package/dist/adapter-utils.d.ts +2 -2
  4. package/dist/adapter-utils.js +1 -1
  5. package/dist/adapter-utils.js.map +1 -1
  6. package/dist/audit-ledger-Dc6hAXam.d.cts +378 -0
  7. package/dist/audit-ledger-dxvslGi3.d.ts +378 -0
  8. package/dist/chunk-2FF6QGOA.js +2 -0
  9. package/dist/chunk-2FF6QGOA.js.map +1 -0
  10. package/dist/chunk-4MNQDXH7.cjs +3 -0
  11. package/dist/chunk-4MNQDXH7.cjs.map +1 -0
  12. package/dist/chunk-644QZVTT.js +16 -0
  13. package/dist/{chunk-26Z5VNPZ.js.map → chunk-644QZVTT.js.map} +1 -1
  14. package/dist/chunk-ENZEHIL7.cjs +3 -0
  15. package/dist/chunk-ENZEHIL7.cjs.map +1 -0
  16. package/dist/chunk-I722BZA5.js +7 -0
  17. package/dist/chunk-I722BZA5.js.map +1 -0
  18. package/dist/chunk-IXRS4LM4.cjs +2 -0
  19. package/dist/chunk-IXRS4LM4.cjs.map +1 -0
  20. package/dist/chunk-NPX5EKPP.cjs +16 -0
  21. package/dist/{chunk-EX3XG667.cjs.map → chunk-NPX5EKPP.cjs.map} +1 -1
  22. package/dist/chunk-PA6VC32N.js +2 -0
  23. package/dist/chunk-PA6VC32N.js.map +1 -0
  24. package/dist/chunk-PXRV64PA.js +3 -0
  25. package/dist/chunk-PXRV64PA.js.map +1 -0
  26. package/dist/chunk-R2GHSCTR.js +3 -0
  27. package/dist/chunk-R2GHSCTR.js.map +1 -0
  28. package/dist/chunk-T4TRJEJN.cjs +2 -0
  29. package/dist/chunk-T4TRJEJN.cjs.map +1 -0
  30. package/dist/chunk-X7G7UBXU.cjs +7 -0
  31. package/dist/chunk-X7G7UBXU.cjs.map +1 -0
  32. package/dist/index.cjs +2 -2
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +214 -391
  35. package/dist/index.d.ts +214 -391
  36. package/dist/index.js +2 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/internals.cjs +1 -1
  39. package/dist/internals.d.cts +5 -5
  40. package/dist/internals.d.ts +5 -5
  41. package/dist/internals.js +1 -1
  42. package/dist/plugins/index.cjs +2 -2
  43. package/dist/plugins/index.cjs.map +1 -1
  44. package/dist/plugins/index.d.cts +2 -2
  45. package/dist/plugins/index.d.ts +2 -2
  46. package/dist/plugins/index.js +1 -1
  47. package/dist/plugins/index.js.map +1 -1
  48. package/dist/{plugins-Ykl_sAPE.d.ts → plugins-BIzXaYbg.d.cts} +15 -1
  49. package/dist/{plugins-Ykl_sAPE.d.cts → plugins-BIzXaYbg.d.ts} +15 -1
  50. package/dist/predicate-Bnx3LN7P.d.cts +655 -0
  51. package/dist/predicate-BxQVf0ug.d.ts +655 -0
  52. package/dist/system-A6VYKLVF.js +2 -0
  53. package/dist/{system-VZWB6WXX.js.map → system-A6VYKLVF.js.map} +1 -1
  54. package/dist/system-CDJMD5O5.cjs +2 -0
  55. package/dist/{system-GK3NSFQH.cjs.map → system-CDJMD5O5.cjs.map} +1 -1
  56. package/dist/testing.cjs +1 -1
  57. package/dist/testing.cjs.map +1 -1
  58. package/dist/testing.d.cts +1 -1
  59. package/dist/testing.d.ts +1 -1
  60. package/dist/testing.js +1 -1
  61. package/dist/testing.js.map +1 -1
  62. package/dist/{utils-BnQajqPu.d.cts → utils-Mg55IerF.d.cts} +27 -1
  63. package/dist/{utils-BnQajqPu.d.ts → utils-Mg55IerF.d.ts} +27 -1
  64. package/dist/worker.cjs +1 -1
  65. package/dist/worker.d.cts +1 -1
  66. package/dist/worker.d.ts +1 -1
  67. package/dist/worker.js +1 -1
  68. package/package.json +1 -1
  69. package/dist/audit-ledger-9IElAHH9.d.ts +0 -205
  70. package/dist/audit-ledger-qMjEBqiP.d.cts +0 -205
  71. package/dist/chunk-26Z5VNPZ.js +0 -16
  72. package/dist/chunk-4VZOZWXM.cjs +0 -2
  73. package/dist/chunk-4VZOZWXM.cjs.map +0 -1
  74. package/dist/chunk-7NMXRATK.cjs +0 -3
  75. package/dist/chunk-7NMXRATK.cjs.map +0 -1
  76. package/dist/chunk-7TSYQEN3.js +0 -2
  77. package/dist/chunk-7TSYQEN3.js.map +0 -1
  78. package/dist/chunk-EOLY64E6.cjs +0 -3
  79. package/dist/chunk-EOLY64E6.cjs.map +0 -1
  80. package/dist/chunk-EX3XG667.cjs +0 -16
  81. package/dist/chunk-N4KTCKOI.cjs +0 -7
  82. package/dist/chunk-N4KTCKOI.cjs.map +0 -1
  83. package/dist/chunk-T6IJUWYR.js +0 -3
  84. package/dist/chunk-T6IJUWYR.js.map +0 -1
  85. package/dist/chunk-TPOKS4RY.js +0 -3
  86. package/dist/chunk-TPOKS4RY.js.map +0 -1
  87. package/dist/chunk-TZHC4E6S.js +0 -7
  88. package/dist/chunk-TZHC4E6S.js.map +0 -1
  89. package/dist/helpers-D2pfb6vT.d.ts +0 -235
  90. package/dist/helpers-hh6UanB1.d.cts +0 -235
  91. package/dist/system-GK3NSFQH.cjs +0 -2
  92. package/dist/system-VZWB6WXX.js +0 -2
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunk4MNQDXH7_cjs=require('./chunk-4MNQDXH7.cjs');var g=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Q=new Set(["$all","$any","$not"]);var T=new Set(["number","string","boolean","bigint","date","unknown"]);function P(e){if(!e)return {kind:"unknown"};let n=/^Branded<(.+)>$/.exec(e);return n?{kind:"branded",inner:P(n[1])}:e.endsWith(" | null")||e.endsWith(" | undefined")?{...P(e.replace(/ \| (null|undefined)$/,"")),nullable:true}:T.has(e)?{kind:e}:/^(email|uuid|url|cuid|datetime|iso\b)/i.test(e)?{kind:"string"}:e.includes(" | ")?{kind:"union",members:e.split(" | ").map(P)}:e==="array"?{kind:"array",element:{kind:"unknown"}}:e==="object"?{kind:"object",shape:{}}:e==="record"?{kind:"record",value:{kind:"unknown"}}:e==="tuple"?{kind:"tuple",elements:[]}:e==="union"?{kind:"union",members:[]}:{kind:"unknown"}}function z(e){if(e==null)return {kind:"unknown"};if(typeof e=="function")return chunk4MNQDXH7_cjs.a&&console.warn("[Directive] getKind: received a function \u2014 did you forget () on a t.* builder? Example: write `t.number()`, not `t.number`."),{kind:"unknown"};if(typeof e!="object")return {kind:"unknown"};let n=e,r;try{r=n._kind;}catch{return {kind:"unknown"}}if(r)return r;let i;try{i=n._typeName;}catch{return {kind:"unknown"}}return P(i)}function H(e){let n=new Map;if(!e||typeof e!="object")return n;let r=e,t="facts"in r&&r.facts&&typeof r.facts=="object"?r.facts:r;for(let[a,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let o;try{o=z(s);}catch{continue}if(n.set(a,o),o.kind==="object")for(let[c,l]of Object.entries(o.shape))n.set(`${a}.${c}`,l);}return n.size===0&&chunk4MNQDXH7_cjs.a&&console.warn("[Directive] getSchemaFieldKinds: schema appears empty (no introspectable keys). Did you pass the module instead of its schema? Pass `myModule.schema`, not `myModule`."),n}var k=["$eq","$ne","$in","$nin","$exists"],D=["$gt","$gte","$lt","$lte","$between"],W=["$matches","$startsWith","$endsWith","$contains"];function w(e){switch(e.kind){case "number":case "bigint":case "date":return [...k,...D];case "string":return [...k,...D,...W];case "boolean":case "unknown":return k;case "array":return [...k,"$contains"];case "object":case "record":case "tuple":return k;case "literal":case "enum":return w(e.primitive==="number"?{kind:"number"}:e.primitive==="boolean"?{kind:"boolean"}:e.primitive==="null"?{kind:"unknown"}:{kind:"string"});case "branded":return w(e.inner);case "union":{if(e.members.length===0)return k;let n=e.members.map(t=>new Set(w(t))),r=n[0],i=[];for(let t of r)n.every(a=>a.has(t))&&i.push(t);return i}default:{return k}}}function X(){return Array.from(g)}var O=64;function u(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function x(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let n=Object.getPrototypeOf(e);return n===Object.prototype||n===null}function E(e){if(!u(e))return false;let n=0,r=false;for(let i of Object.keys(e)){if(i.startsWith("$"))r=true,g.has(i)||f(`predicate: unknown operator "${i}" \u2014 looks like a typo. Known operators: ${[...g].join(", ")}`);else if(r||n===0)return false;n++;}return r?n>0:false}function re(e){return e===null?false:Array.isArray(e)?e.every(n=>x(n)&&"fact"in n&&"op"in n):x(e)}function h(e,n,r="",i=new WeakSet,t=0){if(t>O){chunk4MNQDXH7_cjs.a&&console.warn(`[Directive] predicate depth limit (${O}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),n.bail?.("depth");return}if(Array.isArray(e)){e.forEach((s,o)=>{if(!u(s))return;let c=s;if(typeof c.fact=="string"&&typeof c.op=="string"){let l=r?`${r}[${o}]`:`[${o}]`;n.operator?.(r?`${r}.${c.fact}`:c.fact,c.op,c.value,`${l}.value`);}});return}if(!u(e))return;if(i.has(e)){chunk4MNQDXH7_cjs.a&&console.warn("[Directive] walkPredicate: cyclic predicate spec"),n.bail?.("cycle");return}i.add(e);let a=e;for(let s of ["$all","$any","$not"])if(s in a){if(n.combinator?.(s)===false)return;let c=s==="$not"?[a.$not]:a[s]??[];for(let l of c)h(l,n,r,i,t+1);return}for(let s of Object.keys(a)){let o=r?`${r}.${s}`:s;if(s.startsWith("$")){n.strayOperatorKey?.(s,o);continue}let c=a[s];if(E(c)){let l=c;for(let p of Object.keys(l))n.operator?.(o,p,l[p],`${o}.${p}`);continue}if(x(c)){if(n.nested?.(s)===false)continue;h(c,n,o,i,t+1);continue}n.literal?.(o,c);}}function ie(e){if(!x(e))return false;let n=false;return h(e,{operator(){n=true;},literal(){n=true;},combinator(){n=true;},strayOperatorKey(){n=true;},bail(){n=true;}}),!n}function I(e){return u(e)&&Object.hasOwn(e,"$template")&&typeof e.$template=="string"}function oe(e,n=""){function r(t,a,s,o){if(typeof t=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${a}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(t instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${a}" is not JSON-serializable (serializes to {} and loses all members).`);if(t instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${a}" is not JSON-serializable (serializes to {} and loses all entries).`);if(t instanceof RegExp)throw new Error(`[Directive] validatePredicate: RegExp operand at "${a}" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`);if(!(t===null||typeof t!="object")&&!(o>O)&&!s.has(t)){if(s.add(t),Array.isArray(t)){t.forEach((c,l)=>{r(c,`${a}[${l}]`,s,o+1);});return}for(let c of Object.keys(t))r(t[c],a?`${a}.${c}`:c,s,o+1);}}function i(t,a,s){if(typeof t=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${s}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(t instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${s}" is not JSON-serializable (serializes to {} and loses all members).`);if(t instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${s}" is not JSON-serializable (serializes to {} and loses all entries).`);if(a==="$matches"&&!(t instanceof RegExp))throw new Error(`[Directive] validatePredicate: $matches operand at "${s}" must be a RegExp; got ${t===null?"null":typeof t}. A regex lost to JSON.parse becomes {} \u2014 reify with new RegExp(pattern, flags) before installing.`);if(Array.isArray(t))t.forEach((o,c)=>{r(o,`${s}[${c}]`,new WeakSet,1);});else if(x(t))for(let o of Object.keys(t))r(t[o],`${s}.${o}`,new WeakSet,1);}if(e instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand${n?` at "${n}"`:""} is not JSON-serializable (serializes to {} and loses all members).`);if(e instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand${n?` at "${n}"`:""} is not JSON-serializable (serializes to {} and loses all entries).`);h(e,{operator(t,a,s,o){i(s,a,n?`${n}.${o}`:o);},literal(t,a){i(a,"",n?`${n}.${t}`:t);}});}function M(e){return typeof e!="string"||e.length===0?false:!!(/\)(?:[+*]\??|\{\d+,?\d*\})\s*[+*?]\s*[+*]/.test(e)||/\(([^()]*?[+*]|[^()]*?\{\d+,?\d*\})[^()]*\)\s*[+*]/.test(e)||/\(\??:?([^()|]+)\|\1\)\s*[+*]/.test(e))}function se(e,n,r={}){let i=[],t=0,a=r.maxOperatorCount,s=r.maxArrayOperandLength;return h(e,{operator(o,c,l,p){if(t++,a!==void 0&&t>a){i.some($=>$.reason.includes("maxOperatorCount"))||i.push({path:o,op:c,reason:`Predicate exceeds maxOperatorCount=${a} \u2014 too many clauses (DoS guard).`});return}if(s!==void 0&&(c==="$in"||c==="$nin")&&Array.isArray(l)&&l.length>s){i.push({path:o,op:c,reason:`Operator ${c} operand exceeds maxArrayOperandLength=${s} (got ${l.length}) \u2014 too large for a query planner.`});return}if(c==="$matches"){let $;if(l instanceof RegExp?$=l.source:typeof l=="string"&&($=l),$!==void 0&&M($)){i.push({path:o,op:c,reason:`Operator $matches operand at "${o}" contains nested quantifiers (ReDoS risk: ${JSON.stringify($)}). Reject untrusted regex or rewrite without nested + / *.`});return}}let m=n.get(o);if(!m){i.push({path:o,op:c,reason:`Unknown fact "${o}" \u2014 not in schema. Known facts: ${n.size===0?"(empty schema)":Array.from(n.keys()).join(", ")}`});return}let y=w(m);y.includes(c)||i.push({path:o,op:c,kind:m,allowedOps:y,reason:`Operator "${c}" is not allowed on fact "${o}" of kind "${m.kind}". Allowed operators for this kind: ${y.join(", ")}.`});},literal(o,c){t++,n.has(o)||i.push({path:o,op:"$eq",reason:`Unknown fact "${o}" \u2014 not in schema.`});},strayOperatorKey(o,c){i.push({path:c,op:o,reason:`Stray operator key "${o}" at "${c}" \u2014 operators must live inside a fact's operator object, not at the predicate top level.`});}}),i.length===0?{ok:true,operatorCount:t}:{ok:false,errors:i,operatorCount:t}}function _(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function v(e,n){let r=e.ids.get(n);return r===void 0&&(r=e.next.v++,e.ids.set(n,r)),r}function d(e,n,r){if(Object.is(e,n))return true;if(e instanceof Date&&n instanceof Date)return e.getTime()===n.getTime();if(typeof e!="object"||typeof n!="object"||e===null||n===null)return false;let i=r??_(),t=`${v(i,e)}:${v(i,n)}`;if(i.pairs.has(t))return true;if(i.pairs.add(t),Array.isArray(e)||Array.isArray(n))return !Array.isArray(e)||!Array.isArray(n)||e.length!==n.length?false:e.every((o,c)=>d(o,n[c],i));if(e instanceof Set||n instanceof Set){if(!(e instanceof Set)||!(n instanceof Set)||e.size!==n.size)return false;let o=[...n];return [...e].every(c=>o.some(l=>d(c,l,i)))}if(e instanceof Map||n instanceof Map){if(!(e instanceof Map)||!(n instanceof Map)||e.size!==n.size)return false;let o=[...n.entries()],c=new Array(o.length).fill(false);for(let[l,p]of e){let m=false;for(let y=0;y<o.length;y++){if(c[y])continue;let[$,N]=o[y];if(d(l,$,i)&&d(p,N,i)){c[y]=true,m=true;break}}if(!m)return false}return true}let a=Object.keys(e),s=Object.keys(n);return a.length!==s.length?false:a.every(o=>Object.hasOwn(n,o)&&d(e[o],n[o],i))}function j(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function A(e,n,r){let i=j(n),t=j(r);if(i===void 0||t===void 0||typeof i!=typeof t)return false;switch(e){case "$gt":return i>t;case "$gte":return i>=t;case "$lt":return i<t;case "$lte":return i<=t;default:return false}}function R(e,n,r,i){switch(e){case "$eq":return d(n,r);case "$ne":return !d(n,r);case "$in":return Array.isArray(r)&&r.some(t=>d(n,t));case "$nin":return Array.isArray(r)&&!r.some(t=>d(n,t));case "$exists":return r===(n!==void 0);case "$changed":return !d(n,i);case "$gt":case "$gte":case "$lt":case "$lte":return A(e,n,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let t=j(r[0]),a=j(r[1]);return t!==void 0&&a!==void 0&&typeof t==typeof a&&t>a?(f("$between: reversed pair \u2014 [min, max] required"),false):A("$gte",n,r[0])&&A("$lte",n,r[1])}case "$matches":{if(!(r instanceof RegExp))throw new Error("[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).");return typeof n!="string"?false:r.test(n)}case "$startsWith":return typeof n!="string"?false:n.startsWith(String(r));case "$endsWith":return typeof n!="string"?false:n.endsWith(String(r));case "$contains":return typeof n=="string"?n.includes(String(r)):Array.isArray(n)?n.some(t=>d(t,r)):n instanceof Set?n.has(r):false;default:return false}}function f(e){chunk4MNQDXH7_cjs.a&&console.warn(`[Directive] ${e}`);}function q(e,n,r,i){if(E(e)){let t=Object.keys(e);t.length>1&&f(`predicate: operator object has ${t.length} operators (${t.join(", ")}) \u2014 write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`);for(let a of t)if(!R(a,n,e[a],r))return false;return true}return u(e)?S(e,u(n)?n:Object.create(null),u(r)?r:void 0,i+1):d(n,e)}function S(e,n,r,i=0){if(i>O)return f(`predicate depth limit (${O}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),false;if(Array.isArray(e))return e.every(t=>{if(!u(t))return false;let{fact:a,op:s,value:o}=t;return R(s,n?.[a],o,r?.[a])});if(!u(e))return !!e;if("$all"in e)return e.$all.every(t=>S(t,n,r,i+1));if("$any"in e)return e.$any.some(t=>S(t,n,r,i+1));if("$not"in e)return !S(e.$not,n,r,i+1);for(let t of Object.keys(e)){if(g.has(t))return f(`predicate: operator "${t}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!q(e[t],n?.[t],r?.[t],i))return false}return true}function V(e,n,r,i=""){let t=[];if(Array.isArray(e)){for(let a of e){if(!u(a))continue;let{fact:s,op:o,value:c}=a,l=n?.[s];t.push({path:i+s,op:o,expected:c,actual:l,pass:R(o,l,c,r?.[s])});}return t}if(!u(e))return t;for(let a of ["$all","$any","$not"])if(a in e){let s=a==="$not"?[e.$not]:e[a],o=[];for(let p of s)o.push(...V(p,n,r,i));let c=o.filter(p=>p.pass).length,l;return a==="$all"?l=o.length===0||c===o.length:a==="$any"?l=o.length>0&&c>0:l=!o.every(p=>p.pass),t.push({path:i||a,op:a,expected:s.length,actual:c,pass:l,children:o}),t}for(let a of Object.keys(e)){if(g.has(a))continue;let s=e[a],o=n?.[a],c=i+a;if(E(s))for(let l of Object.keys(s))t.push({path:c,op:l,expected:s[l],actual:o,pass:R(l,o,s[l],r?.[a])});else u(s)?t.push(...V(s,u(o)?o:Object.create(null),u(r?.[a])?r?.[a]:void 0,`${c}.`)):t.push({path:c,op:"$eq",expected:s,actual:o,pass:d(o,s)});}return t}var F=new WeakMap;function ce(e){if(e===null||typeof e!="object")throw new Error(`[Directive] memoizePredicate: predicate must be a plain object or array; got ${typeof e}`);let n=F.get(e);if(n)return n;let r=(i,t)=>S(e,i,t);return F.set(e,r),r}function le(e,n=""){let r=new Set;return h(e,{operator(i){r.add(n+i);},literal(i){r.add(n+i);},strayOperatorKey(i){g.has(i)||f(`extractDeps: unknown operator "${i}" \u2014 skipping. Known operators: ${[...g].join(", ")}`);}}),r}var C=/^[A-Za-z_][A-Za-z0-9_]*$/;function J(e){return typeof e=="symbol"||e==null?"":String(e)}function B(e,n){return typeof e=="symbol"?(f("template: cannot interpolate a symbol value \u2014 using empty string"),""):e===void 0?(f(`template: ${n?`key "${n}" is `:""}undefined \u2014 using empty string`),""):e===null?(f(`template: ${n?`key "${n}" is `:""}null \u2014 using empty string`),""):String(e)}function L(e,n){let r=e.$template,i="",t=0;for(;t<r.length;){if(r[t]==="$"&&r[t+1]==="$"&&r[t+2]==="{"){i+="${",t+=3;continue}if(r[t]==="$"&&r[t+1]==="{"){let a=r.indexOf("}",t+2);if(a===-1){f(`template: unterminated "\${" in ${JSON.stringify(r)}`),i+=r.slice(t);break}let s=r.slice(t+2,a);if(!C.test(s))f(`template: invalid placeholder "\${${s}}" \u2014 not an identifier`);else {let o=n!=null&&Object.hasOwn(n,s),c=o?n[s]:void 0;o?i+=B(c,s):(f(`template: unknown key "${s}"`),i+=J(c));}t=a+1;continue}i+=r[t],t++;}return i}function ue(e){let n=new Set,r=e.$template,i=0;for(;i<r.length;){if(r[i]==="$"&&r[i+1]==="$"&&r[i+2]==="{"){i+=3;continue}if(r[i]==="$"&&r[i+1]==="{"){let t=r.indexOf("}",i+2);if(t===-1)break;let a=r.slice(i+2,t);C.test(a)&&n.add(a),i=t+1;continue}i++;}return n}function de(e,n){return e.map(r=>chunk4MNQDXH7_cjs.e(n?.[r])).join("|")}function fe(e,n,r){let i=e.$set,t=r??{};for(let a of Object.keys(i)){let s=i[a];if(I(s))n[a]=L(s,t);else if(u(s)&&Object.hasOwn(s,"$ref")&&typeof s.$ref=="string"){let o=s.$ref;Object.hasOwn(t,o)||f(`applyPatch: $ref "${o}" is missing from event payload \u2014 assigning undefined to fact "${a}"`),n[a]=t[o];}else n[a]=s;}}exports.a=g;exports.b=Q;exports.c=z;exports.d=H;exports.e=w;exports.f=X;exports.g=O;exports.h=re;exports.i=h;exports.j=ie;exports.k=I;exports.l=oe;exports.m=M;exports.n=se;exports.o=S;exports.p=V;exports.q=ce;exports.r=le;exports.s=L;exports.t=ue;exports.u=de;exports.v=fe;//# sourceMappingURL=chunk-T4TRJEJN.cjs.map
2
+ //# sourceMappingURL=chunk-T4TRJEJN.cjs.map
@@ -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-T4TRJEJN.cjs","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,7 @@
1
+ 'use strict';function a(e,t,r){e[t]=r;}function c(e,t){return e[t]}function u(e,t){return {name:e,onRequirementCreated:t.onRequirementCreated?r=>t.onRequirementCreated(r.requirement):void 0,onRequirementMet:t.onRequirementResolved?r=>t.onRequirementResolved(r.requirement):void 0,onError:t.onError}}function d(e){return t=>t.type===e}function p(e){let t=new Set(e);return r=>t.has(r.type)}var n=[];function m(){let e=n.length;return e===0?null:n[e-1]}function l(){return n.length>0}function R(e){let t=new Set;n.push(t);try{return {value:e(),deps:t}}finally{n.pop();}}function S(e){let t=n.splice(0,n.length);try{return e()}finally{for(let r of t)n.push(r);}}function g(e){let t=n.length;t!==0&&n[t-1].add(e);}var q=Object.freeze(new Set(["__proto__","constructor","prototype"]));function x(e){if(e===null||typeof e!="object")return null;if(e instanceof Date)return "Date";if(e instanceof Set)return "Set";if(e instanceof Map)return "Map";if(typeof File<"u"&&e instanceof File)return "File";if(Array.isArray(e))return null;let t=Object.getPrototypeOf(e);return t!==null&&t!==Object.prototype?"ClassInstance":null}var o=new Set,s={Date:".getTime() for timestamps",Set:"[...set] for arrays",Map:"Object.fromEntries(map) for plain objects",File:"{ name, size, type, lastModified } for metadata",ClassInstance:"a plain-object snapshot"};function y(e,t){let r=`${e}|${t}`;if(o.has(r))return;o.add(r);let i=s[t]??"a JSON-roundtrippable value";console.warn(`[Directive] Fact "${e}" assigned a ${t} instance.
2
+ Facts must be JSON-roundtrippable for reactivity to work correctly.
3
+ ${t} mutations are not tracked.
4
+ Use ${i} instead.
5
+ See: https://directive.run/docs/facts#json-rule`);}
6
+ exports.a=a;exports.b=c;exports.c=u;exports.d=d;exports.e=p;exports.f=m;exports.g=l;exports.h=R;exports.i=S;exports.j=g;exports.k=q;exports.l=x;exports.m=y;//# sourceMappingURL=chunk-X7G7UBXU.cjs.map
7
+ //# sourceMappingURL=chunk-X7G7UBXU.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/types/adapter-utils.ts","../src/core/tracking.ts"],"names":["setBridgeFact","facts","key","value","getBridgeFact","createCallbackPlugin","name","callbacks","req","requirementGuard","type","requirementGuardMultiple","types","typeSet","depStack","getCurrentDeps","len","isTracking","withTracking","fn","deps","withoutTracking","saved","ctx","trackAccess","BLOCKED_PROPS","detectNonJsonValueType","proto","nonJsonWarningCache","nonJsonHints","warnNonJsonFactAssignment","factPath","valueType","cacheKey","hint"],"mappings":"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","file":"chunk-X7G7UBXU.cjs","sourcesContent":["/**\n * Adapter Type Utilities - Shared types and helpers for framework adapters\n *\n * These utilities reduce type assertions in adapters by providing:\n * - Schema composition types\n * - Constraint/resolver converters\n * - Plugin factory helpers\n */\n\nimport type { Facts } from \"./facts.js\";\nimport type { Plugin } from \"./plugins.js\";\nimport type { ConstraintDef, Requirement } from \"./requirements.js\";\nimport type { ResolverContext, ResolverDef } from \"./resolvers.js\";\nimport type { InferSchema, Schema } from \"./schema.js\";\n\n// ============================================================================\n// Schema Composition Types\n// ============================================================================\n\n/**\n * Merge two schemas into one.\n * Useful for adapters that add bridge-specific facts to user schemas.\n *\n * @example\n * ```typescript\n * type BridgeFields = { __state: SchemaType<Record<string, unknown>> };\n * type Combined = MergedSchema<UserSchema, BridgeFields>;\n * ```\n */\nexport type MergedSchema<Base extends Schema, Extra extends Schema> = Base &\n Extra;\n\n/**\n * Create a schema type from a fields definition.\n * Helper for defining adapter bridge schemas.\n *\n * @example\n * ```typescript\n * type AdapterBridgeSchema = BridgeSchema<{\n * __adapterState: SchemaType<Record<string, unknown>>;\n * }>;\n * ```\n */\nexport type BridgeSchema<Fields extends Schema> = Fields;\n\n// ============================================================================\n// Bridge Schema Helper\n// ============================================================================\n\n/**\n * Create a bridge schema definition for adapters.\n * Returns a schema object compatible with createModule().\n *\n * @example\n * ```typescript\n * const bridgeSchema = createBridgeSchema({\n * __state: t.object<Record<string, unknown>>(),\n * });\n * ```\n */\nexport function createBridgeSchema<S extends Schema>(schema: S): S {\n return schema;\n}\n\n// ============================================================================\n// Type-Safe Fact Mutation\n// ============================================================================\n\n/**\n * Type-safe fact setter for known schema keys.\n * Use when you have a typed schema and want to set a specific fact.\n *\n * @example\n * ```typescript\n * setFact(facts, \"count\", 10); // Type-checked\n * ```\n */\nexport function setFact<S extends Schema, K extends keyof InferSchema<S>>(\n facts: Facts<S>,\n key: K,\n value: InferSchema<S>[K],\n): void {\n (facts as Record<string, unknown>)[key as string] = value;\n}\n\n/**\n * Set a bridge fact without strict typing.\n * Use for adapter-internal bridge fields like `__adapterState`.\n *\n * @example\n * ```typescript\n * setBridgeFact(facts, \"__adapterState\", currentState);\n * ```\n */\nexport function setBridgeFact<V>(\n facts: Facts<Schema>,\n key: string,\n value: V,\n): void {\n (facts as Record<string, unknown>)[key] = value;\n}\n\n/**\n * Get a bridge fact without strict typing.\n * Use for adapter-internal bridge fields.\n *\n * @example\n * ```typescript\n * const state = getBridgeFact<MyState>(facts, \"__adapterState\");\n * ```\n */\nexport function getBridgeFact<V>(facts: Facts<Schema>, key: string): V {\n return (facts as Record<string, unknown>)[key] as V;\n}\n\n// ============================================================================\n// Constraint Converters\n// ============================================================================\n\n/**\n * Adapter constraint definition (generic form used by adapters).\n */\nexport interface AdapterConstraint<TState> {\n when: (state: TState) => boolean | Promise<boolean>;\n require: Requirement | ((state: TState) => Requirement | null);\n priority?: number;\n}\n\n/**\n * Convert adapter-style constraints to Directive format.\n * Maps adapter constraints that work with external state (TState) to\n * Directive constraints that work with Facts<Schema>.\n *\n * @param constraints - Adapter constraints keyed by name\n * @param extractState - Function to extract adapter state from facts\n *\n * @example\n * ```typescript\n * const directiveConstraints = convertConstraints<MyState, BridgeSchema>(\n * adapterConstraints,\n * (facts) => getBridgeFact<MyState>(facts, \"__state\"),\n * );\n * ```\n */\nexport function convertConstraints<TState, S extends Schema>(\n constraints: Record<string, AdapterConstraint<TState>>,\n extractState: (facts: Facts<S>) => TState,\n): Record<string, ConstraintDef<S, Requirement>> {\n const result: Record<string, ConstraintDef<S, Requirement>> = {};\n\n for (const [id, constraint] of Object.entries(constraints)) {\n result[id] = {\n priority: constraint.priority ?? 0,\n when: (facts) => constraint.when(extractState(facts)),\n require: (facts) => {\n const req =\n typeof constraint.require === \"function\"\n ? constraint.require(extractState(facts))\n : constraint.require;\n return req;\n },\n };\n }\n\n return result;\n}\n\n// ============================================================================\n// Resolver Converters\n// ============================================================================\n\n/**\n * Adapter resolver context (generic form used by adapters).\n */\nexport interface AdapterResolverContext<TContext> {\n context: TContext;\n signal: AbortSignal;\n}\n\n/**\n * Adapter resolver definition (generic form used by adapters).\n */\nexport interface AdapterResolver<\n TContext,\n R extends Requirement = Requirement,\n> {\n requirement: (req: Requirement) => req is R;\n key?: (req: R) => string;\n resolve: (\n req: R,\n ctx: AdapterResolverContext<TContext>,\n ) => void | Promise<void>;\n}\n\n/**\n * Convert adapter-style resolvers to Directive format.\n * Maps adapter resolvers that work with external context (TContext) to\n * Directive resolvers that work with ResolverContext<Schema>.\n *\n * @param resolvers - Adapter resolvers keyed by name\n * @param createContext - Function to create adapter context from Directive context\n *\n * @example\n * ```typescript\n * const directiveResolvers = convertResolvers<MyContext, BridgeSchema>(\n * adapterResolvers,\n * (ctx) => ({\n * getState: () => getBridgeFact<MyState>(ctx.facts, \"__state\"),\n * setState: (update) => setBridgeFact(ctx.facts, \"__state\", update),\n * signal: ctx.signal,\n * }),\n * );\n * ```\n */\nexport function convertResolvers<TContext, S extends Schema>(\n resolvers: Record<string, AdapterResolver<TContext, Requirement>>,\n createContext: (ctx: ResolverContext<S>) => TContext,\n): Record<string, ResolverDef<S, Requirement>> {\n const result: Record<string, ResolverDef<S, Requirement>> = {};\n\n for (const [id, resolver] of Object.entries(resolvers)) {\n result[id] = {\n requirement: resolver.requirement,\n key: resolver.key,\n resolve: async (req, ctx) => {\n const adapterCtx = createContext(ctx);\n await resolver.resolve(req, {\n context: adapterCtx,\n signal: ctx.signal,\n });\n },\n };\n }\n\n return result;\n}\n\n// ============================================================================\n// Plugin Factory\n// ============================================================================\n\n/**\n * Callback definitions for adapter plugins.\n */\nexport interface AdapterCallbacks {\n onRequirementCreated?: (req: Requirement) => void;\n onRequirementResolved?: (req: Requirement) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Create a callback plugin for adapter events.\n * Wraps adapter callbacks in a Directive plugin.\n *\n * @param name - Plugin name (for debugging)\n * @param callbacks - Callback functions to invoke\n *\n * @example\n * ```typescript\n * const callbackPlugin = createCallbackPlugin(\"adapter-callbacks\", {\n * onRequirementCreated: (req) => console.log(\"Created:\", req),\n * onRequirementResolved: (req) => console.log(\"Resolved:\", req),\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: Plugins work with any schema type\nexport function createCallbackPlugin(\n name: string,\n callbacks: AdapterCallbacks,\n): Plugin<any> {\n return {\n name,\n onRequirementCreated: callbacks.onRequirementCreated\n ? (req) => callbacks.onRequirementCreated!(req.requirement)\n : undefined,\n onRequirementMet: callbacks.onRequirementResolved\n ? (req) => callbacks.onRequirementResolved!(req.requirement)\n : undefined,\n onError: callbacks.onError,\n };\n}\n\n// ============================================================================\n// Module Config Helpers\n// ============================================================================\n\n/**\n * Cast constraints to the correct type for createModule.\n * Use this when TypeScript can't infer the constraint types correctly.\n */\nexport function asConstraints<S extends Schema>(\n constraints: Record<string, ConstraintDef<S, Requirement>>,\n): Record<string, ConstraintDef<S, Requirement>> {\n return constraints;\n}\n\n/**\n * Cast resolvers to the correct type for createModule.\n * Use this when TypeScript can't infer the resolver types correctly.\n */\nexport function asResolvers<S extends Schema>(\n resolvers: Record<string, ResolverDef<S, Requirement>>,\n): Record<string, ResolverDef<S, Requirement>> {\n return resolvers;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Create a type guard for a specific requirement type.\n * Simplifies the common pattern of checking req.type.\n *\n * @example\n * ```typescript\n * const isResetReq = requirementGuard<ResetReq>(\"RESET\");\n * // Use in resolver:\n * { requirement: isResetReq, resolve: ... }\n * ```\n */\nexport function requirementGuard<R extends Requirement>(\n type: R[\"type\"],\n): (req: Requirement) => req is R {\n return (req): req is R => req.type === type;\n}\n\n/**\n * Create a type guard that matches multiple requirement types.\n *\n * @example\n * ```typescript\n * const isDataReq = requirementGuardMultiple<FetchReq | RefreshReq>([\"FETCH\", \"REFRESH\"]);\n * ```\n */\nexport function requirementGuardMultiple<R extends Requirement>(\n types: Array<R[\"type\"]>,\n): (req: Requirement) => req is R {\n const typeSet = new Set(types);\n return (req): req is R => typeSet.has(req.type);\n}\n","/**\n * Dependency tracking context for auto-tracking derivations\n *\n * Uses a stack-based approach to handle nested derivation computations.\n * When a derivation accesses a fact, the tracking context records it.\n */\n\n/** Stack of active dependency sets (bare Sets for zero-allocation hot path) */\nconst depStack: Set<string>[] = [];\n\n/**\n * Get the current dependency set, or null if not tracking.\n *\n * @returns The active dependency Set, or `null` if no tracking is active.\n *\n * @internal\n */\nexport function getCurrentDeps(): Set<string> | null {\n const len = depStack.length;\n return len === 0 ? null : depStack[len - 1]!;\n}\n\n/**\n * Check if dependency tracking is currently active.\n *\n * @returns `true` if inside a {@link withTracking} call, `false` otherwise.\n *\n * @internal\n */\nexport function isTracking(): boolean {\n return depStack.length > 0;\n}\n\n/**\n * Run a function with dependency tracking.\n *\n * @remarks\n * Pushes a fresh Set onto the stack, executes `fn`, then pops it.\n * Any fact reads inside `fn` are recorded as dependencies.\n * Nesting is supported — inner calls get their own independent Set.\n *\n * @param fn - The function to execute under tracking.\n * @returns An object with the computed `value` and a `deps` Set of accessed\n * fact keys.\n *\n * @internal\n */\nexport function withTracking<T>(fn: () => T): { value: T; deps: Set<string> } {\n const deps = new Set<string>();\n depStack.push(deps);\n\n try {\n const value = fn();\n return { value, deps };\n } finally {\n depStack.pop();\n }\n}\n\n/**\n * Run a function without tracking.\n *\n * @remarks\n * Temporarily clears the tracking stack so that fact reads inside `fn` do\n * not register as dependencies. The stack is restored after `fn` returns\n * (even on error). Useful for side-effect reads that should not trigger\n * derivation invalidation.\n *\n * @param fn - The function to execute without tracking.\n * @returns The return value of `fn`.\n *\n * @internal\n */\nexport function withoutTracking<T>(fn: () => T): T {\n const saved = depStack.splice(0, depStack.length);\n\n try {\n return fn();\n } finally {\n for (const ctx of saved) {\n depStack.push(ctx);\n }\n }\n}\n\n/**\n * Track a specific key in the current context.\n *\n * @remarks\n * No-op if no tracking context is active.\n *\n * @param key - The fact key to record as a dependency.\n *\n * @internal\n */\nexport function trackAccess(key: string): void {\n const len = depStack.length;\n if (len === 0) {\n return;\n }\n depStack[len - 1]!.add(key);\n}\n\n/**\n * Prototype pollution guard — shared across all proxy handlers.\n *\n * @remarks\n * Contains `__proto__`, `constructor`, and `prototype`. Every proxy `get`\n * and `has` trap checks this set and returns `undefined` / `false` for\n * matching keys, preventing prototype pollution via proxy-based objects.\n *\n * @internal\n */\nexport const BLOCKED_PROPS: ReadonlySet<string> = Object.freeze(\n new Set([\"__proto__\", \"constructor\", \"prototype\"]),\n);\n\n// ============================================================================\n// Non-JSON value-type detection (MIGRATION_FEEDBACK item 20)\n// ============================================================================\n\n/**\n * Detect whether `value` is a non-JSON-roundtrippable type whose mutations\n * the facts proxy cannot track for reactivity.\n *\n * Returns the kind label (`\"Date\"`, `\"Set\"`, `\"Map\"`, `\"File\"`, or\n * `\"ClassInstance\"`) when one is detected, or `null` for plain objects,\n * arrays, primitives, and `null`/`undefined`.\n *\n * The `File` check is SSR-safe: if the runtime has no `File` global the\n * branch is skipped without throwing.\n *\n * The `ClassInstance` check fires for any object whose prototype is not\n * `Object.prototype` and which is not an array — e.g. instances of user\n * classes whose mutations bypass reactivity.\n *\n * @internal\n */\nexport function detectNonJsonValueType(value: unknown): string | null {\n if (value === null || typeof value !== \"object\") {\n return null;\n }\n if (value instanceof Date) {\n return \"Date\";\n }\n if (value instanceof Set) {\n return \"Set\";\n }\n if (value instanceof Map) {\n return \"Map\";\n }\n if (typeof File !== \"undefined\" && value instanceof File) {\n return \"File\";\n }\n // Plain objects and arrays are JSON-friendly.\n if (Array.isArray(value)) {\n return null;\n }\n // Class instances: prototype is not Object.prototype.\n // Plain `{}` literals have prototype `Object.prototype`; objects created\n // via `Object.create(null)` have a `null` prototype which we treat as\n // \"plain\" (it's still JSON-roundtrippable).\n const proto = Object.getPrototypeOf(value);\n if (proto !== null && proto !== Object.prototype) {\n return \"ClassInstance\";\n }\n\n return null;\n}\n\n/**\n * Per-(path, valueType) dedupe cache — once a warning fires for a given\n * combo we never re-emit. Keeps the dev console quiet under loops that\n * assign the same Date 100 times in a row.\n *\n * @internal\n */\nconst nonJsonWarningCache = new Set<string>();\n\nconst nonJsonHints: Record<string, string> = {\n Date: \".getTime() for timestamps\",\n Set: \"[...set] for arrays\",\n Map: \"Object.fromEntries(map) for plain objects\",\n File: \"{ name, size, type, lastModified } for metadata\",\n ClassInstance: \"a plain-object snapshot\",\n};\n\n/**\n * Emit a one-time dev-mode warning when a non-JSON value is assigned to a\n * fact. Called from the proxy `set` traps in both `createFactsProxy`\n * (single-module / standalone facts) and `createModuleFactsProxy`\n * (system-namespaced facts). No-ops in production builds — the call sites\n * are gated on `isDevelopment` so this entire helper is tree-shakable.\n *\n * @param factPath - Display path for the warning (e.g. `auth.token` or\n * bare `token` for non-namespaced stores).\n * @param valueType - The label returned from {@link detectNonJsonValueType}.\n *\n * @internal\n */\nexport function warnNonJsonFactAssignment(\n factPath: string,\n valueType: string,\n): void {\n const cacheKey = `${factPath}|${valueType}`;\n if (nonJsonWarningCache.has(cacheKey)) {\n return;\n }\n nonJsonWarningCache.add(cacheKey);\n\n const hint = nonJsonHints[valueType] ?? \"a JSON-roundtrippable value\";\n console.warn(\n `[Directive] Fact \"${factPath}\" assigned a ${valueType} instance.\\n` +\n `Facts must be JSON-roundtrippable for reactivity to work correctly.\\n` +\n `${valueType} mutations are not tracked.\\n` +\n `Use ${hint} instead.\\n` +\n `See: https://directive.run/docs/facts#json-rule`,\n );\n}\n\n/**\n * Reset the warning dedupe cache. Test-only — exported via internals for\n * vitest spec setup. Not part of the public API.\n *\n * @internal\n */\nexport function _resetNonJsonWarningCache(): void {\n nonJsonWarningCache.clear();\n}\n"]}