@directive-run/core
Advanced tools
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| 'use strict';var chunkQTY2FXZY_cjs=require('./chunk-QTY2FXZY.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function $(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!chunkGKMJ7NMP_cjs.k.has(t))return e.get(t)},set(n,t,i){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.set?e.set(t,i):false},has(n,t){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function j(e,n){let t=Z.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,Z.set(e,t);let i=$({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n}${m}${r}`],set:(r,u)=>{if(chunkGBCWXTXW_cjs.a){let s=chunkGKMJ7NMP_cjs.l(u);s&&chunkGKMJ7NMP_cjs.m(`${n}.${r}`,s);}return e[`${n}${m}${r}`]=u,true},has:r=>`${n}${m}${r}`in e,delete:r=>(delete e[`${n}${m}${r}`],true)});return t.set(n,i),i}function re(e,n,t){let i=Q.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return j(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let i=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(i);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),s=["self",...t],c=$({get:o=>{if(o==="self")return j(e,n);if(u.has(o))return j(e,o);chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>s});return r.set(i,c),c}function K(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let i=$({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,i),i}function se(e,n,t){let i=X.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return K(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let i=te.get(e);return i||(i=new Map,te.set(e,i)),$({get:r=>{if(!Object.hasOwn(n,r))return;let u=i.get(r);if(u)return u;let s=$({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return i.set(r,s),s},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function S(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function B(e){let n={};for(let[t,i]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),s=t.slice(r+m.length);n[u]||(n[u]={}),n[u][s]=i;}else n._root||(n._root={}),n._root[t]=i;}return n}function A(e,n,t,i){return t?oe(e,n,i):j(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let s=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return chunkGBCWXTXW_cjs.b(s),s}if(!e||typeof e!="object")return e;let i=e;if("$all"in i||"$any"in i){let s="$all"in i?"$all":"$any",c=i[s],o={[s]:c.map(f=>E(f,n,t))};return chunkGBCWXTXW_cjs.b(o),o}if("$not"in i){let s={$not:E(i.$not,n,t)};return chunkGBCWXTXW_cjs.b(s),s}function r(s,c){return E(s,c,ce)}let u={};for(let s of Object.keys(i)){if(s.startsWith("$")||ae(s)){u[s]=i[s];continue}if(s==="self"){let c=i[s];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(s)){let c=i[s];if(c&&typeof c=="object"){let o=r(c,s);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,s)]=i[s];}return chunkGBCWXTXW_cjs.b(u),u}var ce=new Set;function me(e,n){let t=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,i=e.constraints;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t)},c=true;continue}o[f]=l;}c&&(i=o);}let r=e.derive;if(r){let c=false,o={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o[f]=l;continue}let h=d.compute;if(typeof h=="function"){o[f]=l;continue}if(chunkGACC2DMS_cjs.k(h)){chunkGBCWXTXW_cjs.b(h);let k=g=>chunkGACC2DMS_cjs.s(h,g);o[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(chunkGACC2DMS_cjs.h(h)){chunkGBCWXTXW_cjs.b(h);let k=chunkGACC2DMS_cjs.q(h),g=P=>k(P);o[f]=d.meta?{compute:g,meta:d.meta}:g,c=true;continue}o[f]=l;}c&&(r=o);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),h=Object.hasOwn(l,"patch");if(d&&h&&chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),h&&!d){let k=l;chunkGBCWXTXW_cjs.b(k.patch);let g=(P,x)=>chunkGACC2DMS_cjs.v(k.patch,P,x??{});o[f]=k.meta?{handler:g,meta:k.meta}:g,c=true;continue}}o[f]=l;}c&&(u=o);}let s=e.effects;if(s){let c=false,o={};for(let[f,l]of Object.entries(s)){let d=l;if(d.on!==void 0&&chunkGACC2DMS_cjs.h(d.on)){o[f]={...d,on:E(d.on,n,t)},c=true;continue}o[f]=l;}c&&(s=o);}return i===e.constraints&&r===e.derive&&u===e.events&&s===e.effects?e:{...e,constraints:i,derive:r,events:u,effects:s}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[i,r]of Object.entries(e.schema.facts))t[b(n,i)]=r;return t}function pe(e,n){if(e.init)return t=>{let i=j(t,n);e.init(i);}}function ve(e,n,t,i){if(!e.derive)return;let r={};for(let[u,s]of Object.entries(e.derive)){let c=chunkQTY2FXZY_cjs.a(s),o=c?s.compute:s,f=c?s.meta:void 0,l=(d,h)=>{let k=A(d,n,t,i),g=K(h,n);return o(k,g)};r[b(n,u)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[i,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),s=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=j(f,n);s(d,l);};t[b(n,i)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,i){if(!e.constraints)return;let r={};for(let[u,s]of Object.entries(e.constraints)){let c=s,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),abortOn:c.abortOn?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=A(f,n,t,i);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=A(f,n,t,i);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,i){if(!e.resolvers)return;let r={};for(let[s,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:A(l.facts,n,t,i),signal:l.signal}};let o=c;r[b(n,s)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,i){if(!e.effects)return;let r={};for(let[u,s]of Object.entries(e.effects)){let c=s;r[b(n,u)]={...c,run:(o,f)=>{let l=A(o,n,t,i),d=f?A(f,n,t,i):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(i=>b(n,i))}}function H(e){let{mod:n,namespace:t,snapshotModulesSet:i}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),s=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,s),events:be(r,t),effects:Se(r,t,u,s),sources:r.sources,constraints:Me(r,t,u,s),resolvers:Re(r,t,u,s),hooks:r.hooks,meta:r.meta,history:Oe(r,t,i)}}function xe(e){let n=Object.keys(e),t=new Set(n),i=new Set,r=new Set,u=[],s=[];function c(o){if(i.has(o))return;if(r.has(o)){let l=s.indexOf(o),d=[...s.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),s.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);s.pop(),r.delete(o),i.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let i of Object.keys(n.schema.facts))t.push(`${e}${m}${i}`);if(n.schema.derivations)for(let i of Object.keys(n.schema.derivations))t.push(`${e}${m}${i}`);return t}function ze(e){if(!e||!("module"in e)&&!("modules"in e))throw new Error("[Directive] createSystem requires either `{ module }` (single-module form) or `{ modules: { name: module } }` (namespaced form). Got an options object with neither.");if("module"in e){if(!e.module)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof e.module}`);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array. | ||
| Instead of: | ||
| createSystem({ modules: [authModule, dataModule] }) | ||
| Use: | ||
| createSystem({ modules: { auth: authModule, data: dataModule } }) | ||
| Or for a single module: | ||
| createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead: | ||
| createSystem({ module: myModule }) | ||
| For multiple modules, wrap in an object: | ||
| createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e){let n=e.modules,t=new Set(Object.keys(n)),i=typeof e.history=="object"?e.history:null,r=i?.snapshotModules?new Set(i.snapshotModules):null;if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(chunkGBCWXTXW_cjs.a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let w of Object.keys(y.crossModuleDeps))w===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(w)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${w}, but no module with namespace "${w}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(chunkGBCWXTXW_cjs.a&&i?.snapshotModules)for(let a of i.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,s=e.initOrder??"auto";if(Array.isArray(s)){let a=s,y=Object.keys(n).filter(w=>!a.includes(w));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else s==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f}=de(e);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let w of Object.keys(y.schema.facts))if(w.includes(m))throw new Error(`[Directive] Schema key "${w}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l={names:null};function d(){return l.names===null&&(l.names=Object.keys(n)),l.names}let h=u.map(a=>{let y=n[a];return y?H({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);chunkGBCWXTXW_cjs.a&&e.tickMs&&e.tickMs>0&&(h.some(y=>y.events&&Object.keys(y.events).some(w=>w.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but no module defines a "tick" event handler.`));let k=null,g=null;function P(a){for(let[y,w]of Object.entries(a)){if(chunkGKMJ7NMP_cjs.k.has(y)){chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(w&&typeof w=="object"&&!chunkGBCWXTXW_cjs.f(w))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,D]of Object.entries(w))chunkGKMJ7NMP_cjs.k.has(M)||(g.facts[`${y}${m}${M}`]=D);}}g=chunkQTY2FXZY_cjs.A({modules:h,plugins:e.plugins,history:c,trace:o,errorBoundary:f,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{e.initialFacts&&P(e.initialFacts),k&&(P(k),k=null);}});let x=new Map;for(let a of Object.keys(n)){let y=n[a];y&&x.set(a,ue(a,y));}let q=re(g.facts,n,d),ye=se(g.derive,n,d),ge=ie(g,n,d),R=null,F=e.tickMs,_={_mode:"namespaced",facts:q,history:g.history,derive:ye,events:ge,constraints:g.constraints,effects:g.effects,resolvers:g.resolvers,async hydrate(a){if(g.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k=y);},initialize(){g.initialize();},start(){if(g.start(),F&&F>0){let a;for(let y of h)if(y?.events&&(a=Object.keys(y.events).find(w=>w.endsWith(`${m}tick`)),a))break;if(a){let y=a;R=setInterval(()=>{g.dispatch({type:y});},F);}}},stop(){R&&(clearInterval(R),R=null),g.stop();},async stopAsync(){R&&(clearInterval(R),R=null),await g.stopAsync();},destroy(){this.stop(),g.destroy();},async destroyAsync(){await this.stopAsync(),await g.destroyAsync();},async evict(a){R&&(clearInterval(R),R=null),await g.evict(a);},dispatch(a){g.dispatch(a);},read(a){return g.read(S(a))},subscribe(a,y){let w=[];for(let M of a)if(M.endsWith(".*")){let D=M.slice(0,-2),W=x.get(D);W?w.push(...W):chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${D}" not found.`);}else w.push(S(M));return g.subscribe(w,y)},subscribeModule(a,y){let w=x.get(a);return !w||w.length===0?(chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] subscribeModule("${a}") \u2014 namespace not found. Available: ${[...x.keys()].join(", ")}`),()=>{}):g.subscribe(w,y)},watch(a,y,w){return g.watch(S(a),y,w)},when(a,y){return g.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)},w=g.getDistributableSnapshot(y);return {...w,data:B(w.data)}},watchDistributableSnapshot(a,y){let w={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)};return g.watchDistributableSnapshot(w,M=>{y({...M,data:B(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(chunkGKMJ7NMP_cjs.k.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let D of Object.keys(y.schema.facts))if(D.includes(m))throw new Error(`[Directive] Schema key "${D}" in module "${a}" contains the reserved separator "${m}".`);let w=y,M=H({mod:w,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=w,l.names=null,x.set(a,ue(a,w)),g.registerModule(M);}};return le(_,g),fe(_),_}function de(e){let n=e.history,t=e.trace,i=e.errorBoundary;return e.zeroConfig&&(n=n??chunkGBCWXTXW_cjs.a,i={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:i}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n),n.notify&&(e.notify=n.notify);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let i of t)i in e||(e[i]=n[i].bind(n));}function fe(e){chunkGBCWXTXW_cjs.a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e){let n=e.module;if(!n)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof n}`);if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e.initialFacts&&!chunkGBCWXTXW_cjs.f(e.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");chunkGBCWXTXW_cjs.a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e.tickMs&&e.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but module has no "tick" event handler.`)),(typeof e.history=="object"?e.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:i,errorBoundary:r}=de(e),u=null,s=null;s=chunkQTY2FXZY_cjs.A({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,sources:n.sources,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e.plugins,history:t,trace:i,errorBoundary:r,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{if(e.initialFacts)for(let[d,h]of Object.entries(e.initialFacts))chunkGKMJ7NMP_cjs.k.has(d)||(s.facts[d]=h);if(u){if(!chunkGBCWXTXW_cjs.f(u))chunkGBCWXTXW_cjs.a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,h]of Object.entries(u))chunkGKMJ7NMP_cjs.k.has(d)||(s.facts[d]=h);u=null;}}});let c=new Proxy({},{get(d,h){if(typeof h!="symbol"&&!chunkGKMJ7NMP_cjs.k.has(h))return k=>{s.dispatch({type:h,...k});}},has(d,h){return typeof h=="symbol"||chunkGKMJ7NMP_cjs.k.has(h)?false:n.events?h in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,h){if(typeof h!="symbol"&&!chunkGKMJ7NMP_cjs.k.has(h)&&n.events&&h in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f=e.tickMs,l={_mode:"single",facts:s.facts,history:s.history,derive:s.derive,events:c,constraints:s.constraints,effects:s.effects,resolvers:s.resolvers,async hydrate(d){if(s.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let h=await d();h&&typeof h=="object"&&(u=h);},initialize(){s.initialize();},start(){s.start(),f&&f>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{s.dispatch({type:"tick"});},f));},stop(){o&&(clearInterval(o),o=null),s.stop();},async stopAsync(){o&&(clearInterval(o),o=null),await s.stopAsync();},destroy(){this.stop(),s.destroy();},async destroyAsync(){await this.stopAsync(),await s.destroyAsync();},async evict(d){o&&(clearInterval(o),o=null),await s.evict(d);},registerModule(d){s.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,sources:d.sources,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l,s),fe(l),l}exports.a=ze;//# sourceMappingURL=chunk-OAPD3HIG.cjs.map | ||
| //# sourceMappingURL=chunk-OAPD3HIG.cjs.map |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import {A as A$1,a as a$1}from'./chunk-6NCC6RBC.js';import {k as k$1,h,q,s,v}from'./chunk-RBF653NR.js';import {k,l,m as m$1}from'./chunk-6PF2FRBG.js';import {a,f,b as b$1}from'./chunk-SFUVPP4L.js';var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function $(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!k.has(t))return e.get(t)},set(n,t,i){return typeof t=="symbol"||k.has(t)?false:e.set?e.set(t,i):false},has(n,t){return typeof t=="symbol"||k.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||k.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function j(e,n){let t=Z.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,Z.set(e,t);let i=$({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n}${m}${r}`],set:(r,u)=>{if(a){let s=l(u);s&&m$1(`${n}.${r}`,s);}return e[`${n}${m}${r}`]=u,true},has:r=>`${n}${m}${r}`in e,delete:r=>(delete e[`${n}${m}${r}`],true)});return t.set(n,i),i}function re(e,n,t){let i=Q.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return j(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let i=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(i);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),s=["self",...t],c=$({get:o=>{if(o==="self")return j(e,n);if(u.has(o))return j(e,o);a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>s});return r.set(i,c),c}function K(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let i=$({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,i),i}function se(e,n,t){let i=X.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return K(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let i=te.get(e);return i||(i=new Map,te.set(e,i)),$({get:r=>{if(!Object.hasOwn(n,r))return;let u=i.get(r);if(u)return u;let s=$({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return i.set(r,s),s},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function S(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function B(e){let n={};for(let[t,i]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),s=t.slice(r+m.length);n[u]||(n[u]={}),n[u][s]=i;}else n._root||(n._root={}),n._root[t]=i;}return n}function A(e,n,t,i){return t?oe(e,n,i):j(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let s=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return b$1(s),s}if(!e||typeof e!="object")return e;let i=e;if("$all"in i||"$any"in i){let s="$all"in i?"$all":"$any",c=i[s],o={[s]:c.map(f=>E(f,n,t))};return b$1(o),o}if("$not"in i){let s={$not:E(i.$not,n,t)};return b$1(s),s}function r(s,c){return E(s,c,ce)}let u={};for(let s of Object.keys(i)){if(s.startsWith("$")||ae(s)){u[s]=i[s];continue}if(s==="self"){let c=i[s];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(s)){let c=i[s];if(c&&typeof c=="object"){let o=r(c,s);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,s)]=i[s];}return b$1(u),u}var ce=new Set;function me(e,n){let t=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,i=e.constraints;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t)},c=true;continue}o[f]=l;}c&&(i=o);}let r=e.derive;if(r){let c=false,o={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o[f]=l;continue}let h$1=d.compute;if(typeof h$1=="function"){o[f]=l;continue}if(k$1(h$1)){b$1(h$1);let k=g=>s(h$1,g);o[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(h(h$1)){b$1(h$1);let k=q(h$1),g=P=>k(P);o[f]=d.meta?{compute:g,meta:d.meta}:g,c=true;continue}o[f]=l;}c&&(r=o);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),h=Object.hasOwn(l,"patch");if(d&&h&&a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),h&&!d){let k=l;b$1(k.patch);let g=(P,x)=>v(k.patch,P,x??{});o[f]=k.meta?{handler:g,meta:k.meta}:g,c=true;continue}}o[f]=l;}c&&(u=o);}let s$1=e.effects;if(s$1){let c=false,o={};for(let[f,l]of Object.entries(s$1)){let d=l;if(d.on!==void 0&&h(d.on)){o[f]={...d,on:E(d.on,n,t)},c=true;continue}o[f]=l;}c&&(s$1=o);}return i===e.constraints&&r===e.derive&&u===e.events&&s$1===e.effects?e:{...e,constraints:i,derive:r,events:u,effects:s$1}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[i,r]of Object.entries(e.schema.facts))t[b(n,i)]=r;return t}function pe(e,n){if(e.init)return t=>{let i=j(t,n);e.init(i);}}function ve(e,n,t,i){if(!e.derive)return;let r={};for(let[u,s]of Object.entries(e.derive)){let c=a$1(s),o=c?s.compute:s,f=c?s.meta:void 0,l=(d,h)=>{let k=A(d,n,t,i),g=K(h,n);return o(k,g)};r[b(n,u)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[i,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),s=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=j(f,n);s(d,l);};t[b(n,i)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,i){if(!e.constraints)return;let r={};for(let[u,s]of Object.entries(e.constraints)){let c=s,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),abortOn:c.abortOn?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=A(f,n,t,i);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=A(f,n,t,i);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,i){if(!e.resolvers)return;let r={};for(let[s,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:A(l.facts,n,t,i),signal:l.signal}};let o=c;r[b(n,s)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,i){if(!e.effects)return;let r={};for(let[u,s]of Object.entries(e.effects)){let c=s;r[b(n,u)]={...c,run:(o,f)=>{let l=A(o,n,t,i),d=f?A(f,n,t,i):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(i=>b(n,i))}}function H(e){let{mod:n,namespace:t,snapshotModulesSet:i}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),s=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,s),events:be(r,t),effects:Se(r,t,u,s),sources:r.sources,constraints:Me(r,t,u,s),resolvers:Re(r,t,u,s),hooks:r.hooks,meta:r.meta,history:Oe(r,t,i)}}function xe(e){let n=Object.keys(e),t=new Set(n),i=new Set,r=new Set,u=[],s=[];function c(o){if(i.has(o))return;if(r.has(o)){let l=s.indexOf(o),d=[...s.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),s.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);s.pop(),r.delete(o),i.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let i of Object.keys(n.schema.facts))t.push(`${e}${m}${i}`);if(n.schema.derivations)for(let i of Object.keys(n.schema.derivations))t.push(`${e}${m}${i}`);return t}function ze(e){if(!e||!("module"in e)&&!("modules"in e))throw new Error("[Directive] createSystem requires either `{ module }` (single-module form) or `{ modules: { name: module } }` (namespaced form). Got an options object with neither.");if("module"in e){if(!e.module)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof e.module}`);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array. | ||
| Instead of: | ||
| createSystem({ modules: [authModule, dataModule] }) | ||
| Use: | ||
| createSystem({ modules: { auth: authModule, data: dataModule } }) | ||
| Or for a single module: | ||
| createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead: | ||
| createSystem({ module: myModule }) | ||
| For multiple modules, wrap in an object: | ||
| createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e){let n=e.modules,t=new Set(Object.keys(n)),i=typeof e.history=="object"?e.history:null,r=i?.snapshotModules?new Set(i.snapshotModules):null;if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let w of Object.keys(y.crossModuleDeps))w===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(w)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${w}, but no module with namespace "${w}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(a&&i?.snapshotModules)for(let a of i.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,s=e.initOrder??"auto";if(Array.isArray(s)){let a=s,y=Object.keys(n).filter(w=>!a.includes(w));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else s==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f$1}=de(e);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let w of Object.keys(y.schema.facts))if(w.includes(m))throw new Error(`[Directive] Schema key "${w}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l={names:null};function d(){return l.names===null&&(l.names=Object.keys(n)),l.names}let h=u.map(a=>{let y=n[a];return y?H({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);a&&e.tickMs&&e.tickMs>0&&(h.some(y=>y.events&&Object.keys(y.events).some(w=>w.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but no module defines a "tick" event handler.`));let k$1=null,g=null;function P(a$1){for(let[y,w]of Object.entries(a$1)){if(k.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(w&&typeof w=="object"&&!f(w))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,D]of Object.entries(w))k.has(M)||(g.facts[`${y}${m}${M}`]=D);}}g=A$1({modules:h,plugins:e.plugins,history:c,trace:o,errorBoundary:f$1,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{e.initialFacts&&P(e.initialFacts),k$1&&(P(k$1),k$1=null);}});let x=new Map;for(let a of Object.keys(n)){let y=n[a];y&&x.set(a,ue(a,y));}let q=re(g.facts,n,d),ye=se(g.derive,n,d),ge=ie(g,n,d),R=null,F=e.tickMs,_={_mode:"namespaced",facts:q,history:g.history,derive:ye,events:ge,constraints:g.constraints,effects:g.effects,resolvers:g.resolvers,async hydrate(a){if(g.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k$1=y);},initialize(){g.initialize();},start(){if(g.start(),F&&F>0){let a;for(let y of h)if(y?.events&&(a=Object.keys(y.events).find(w=>w.endsWith(`${m}tick`)),a))break;if(a){let y=a;R=setInterval(()=>{g.dispatch({type:y});},F);}}},stop(){R&&(clearInterval(R),R=null),g.stop();},async stopAsync(){R&&(clearInterval(R),R=null),await g.stopAsync();},destroy(){this.stop(),g.destroy();},async destroyAsync(){await this.stopAsync(),await g.destroyAsync();},async evict(a){R&&(clearInterval(R),R=null),await g.evict(a);},dispatch(a){g.dispatch(a);},read(a){return g.read(S(a))},subscribe(a$1,y){let w=[];for(let M of a$1)if(M.endsWith(".*")){let D=M.slice(0,-2),W=x.get(D);W?w.push(...W):a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${D}" not found.`);}else w.push(S(M));return g.subscribe(w,y)},subscribeModule(a$1,y){let w=x.get(a$1);return !w||w.length===0?(a&&console.warn(`[Directive] subscribeModule("${a$1}") \u2014 namespace not found. Available: ${[...x.keys()].join(", ")}`),()=>{}):g.subscribe(w,y)},watch(a,y,w){return g.watch(S(a),y,w)},when(a,y){return g.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)},w=g.getDistributableSnapshot(y);return {...w,data:B(w.data)}},watchDistributableSnapshot(a,y){let w={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)};return g.watchDistributableSnapshot(w,M=>{y({...M,data:B(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(k.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let D of Object.keys(y.schema.facts))if(D.includes(m))throw new Error(`[Directive] Schema key "${D}" in module "${a}" contains the reserved separator "${m}".`);let w=y,M=H({mod:w,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=w,l.names=null,x.set(a,ue(a,w)),g.registerModule(M);}};return le(_,g),fe(_),_}function de(e){let n=e.history,t=e.trace,i=e.errorBoundary;return e.zeroConfig&&(n=n??a,i={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:i}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n),n.notify&&(e.notify=n.notify);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let i of t)i in e||(e[i]=n[i].bind(n));}function fe(e){a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e){let n=e.module;if(!n)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof n}`);if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e.initialFacts&&!f(e.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e.tickMs&&e.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but module has no "tick" event handler.`)),(typeof e.history=="object"?e.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:i,errorBoundary:r}=de(e),u=null,s=null;s=A$1({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,sources:n.sources,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e.plugins,history:t,trace:i,errorBoundary:r,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{if(e.initialFacts)for(let[d,h]of Object.entries(e.initialFacts))k.has(d)||(s.facts[d]=h);if(u){if(!f(u))a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,h]of Object.entries(u))k.has(d)||(s.facts[d]=h);u=null;}}});let c=new Proxy({},{get(d,h){if(typeof h!="symbol"&&!k.has(h))return k=>{s.dispatch({type:h,...k});}},has(d,h){return typeof h=="symbol"||k.has(h)?false:n.events?h in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,h){if(typeof h!="symbol"&&!k.has(h)&&n.events&&h in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f$1=e.tickMs,l={_mode:"single",facts:s.facts,history:s.history,derive:s.derive,events:c,constraints:s.constraints,effects:s.effects,resolvers:s.resolvers,async hydrate(d){if(s.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let h=await d();h&&typeof h=="object"&&(u=h);},initialize(){s.initialize();},start(){s.start(),f$1&&f$1>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{s.dispatch({type:"tick"});},f$1));},stop(){o&&(clearInterval(o),o=null),s.stop();},async stopAsync(){o&&(clearInterval(o),o=null),await s.stopAsync();},destroy(){this.stop(),s.destroy();},async destroyAsync(){await this.stopAsync(),await s.destroyAsync();},async evict(d){o&&(clearInterval(o),o=null),await s.evict(d);},registerModule(d){s.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,sources:d.sources,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l,s),fe(l),l}export{ze as a};//# sourceMappingURL=chunk-YJEDX2JX.js.map | ||
| //# sourceMappingURL=chunk-YJEDX2JX.js.map |
Sorry, the diff of this file is too big to display
| import { F as FactPredicate, C as ClauseResult, P as Plugin, M as ModuleSchema } from './plugins-5Supk7it.js'; | ||
| /** | ||
| * Audit-ledger type definitions — entry shapes, sink interface, query | ||
| * filter, verify result, and plugin options. Pure types + the two | ||
| * schema-version constants (`HASH_ALGO`, `SCHEMA_VERSION`) that are | ||
| * referenced by the entry shape. | ||
| * | ||
| * Kept free of runtime imports so the hash/freeze/sink modules can pull | ||
| * types from here without a cycle. | ||
| */ | ||
| /** Hash algorithm tag — bumped if canonicalization or hash function changes. */ | ||
| declare const HASH_ALGO: "djb2-1"; | ||
| /** | ||
| * Entry schema version. Bumped if `AuditEntry` field shape changes in | ||
| * a way that breaks back-compat parsers. Persisted on every entry so | ||
| * exports remain self-describing across library upgrades. (F-5) | ||
| */ | ||
| declare const SCHEMA_VERSION: 1; | ||
| type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "source.attach" | "source.detach" | "source.error" | "system.init" | "system.start" | "system.stop" | "system.destroy" | "system.snapshot" | "system.history.navigate" | "system.truncated" | "system.entry-erased" | "system.subject-erased"; | ||
| /** | ||
| * Internal sentinel symbol type. The actual symbol VALUE lives in | ||
| * `hash.ts` and is never exported from this folder's public surface — | ||
| * but the TYPE must be referenceable here so `AuditEntryBase` can | ||
| * declare the optional `__internal` field. | ||
| * | ||
| * We use `symbol` rather than `typeof LEDGER_INTERNAL_TOKEN` because | ||
| * importing the symbol value into types.ts would either re-export it | ||
| * (defeating the defense) or create a circular import. The runtime | ||
| * check in `verify()` compares against the actual symbol reference. | ||
| */ | ||
| type LedgerInternalSentinel = symbol; | ||
| interface AuditEntryBase { | ||
| /** Monotonic sequence number, starting at 0. */ | ||
| readonly seq: number; | ||
| /** Wall-clock timestamp (ms epoch). */ | ||
| readonly ts: number; | ||
| /** Discriminator. */ | ||
| readonly kind: AuditEntryKind; | ||
| /** Hash of the previous entry's full payload. null on the genesis entry. */ | ||
| readonly prevHash: string | null; | ||
| /** | ||
| * Hash algorithm tag identifying the canonicalization + hash | ||
| * function in use. Bumped if the algorithm or canonical form | ||
| * changes, so exports remain verifiable across versions. | ||
| */ | ||
| readonly hashAlgo: typeof HASH_ALGO; | ||
| /** | ||
| * Entry schema version — bumped if any `AuditEntry` field shape | ||
| * changes in a way that breaks back-compat. Pair with `hashAlgo` | ||
| * when migrating older exports. (F-5) | ||
| */ | ||
| readonly schemaVersion: typeof SCHEMA_VERSION; | ||
| /** | ||
| * Private sentinel — present (and equal to the in-module token) only | ||
| * on legitimate tombstones minted by `ledger.erase()`. Filtered out | ||
| * of all public read paths (`query`, `recent`, `toJSON`, etc.) so | ||
| * consumers never see or copy it. (N7) | ||
| * | ||
| * NOT serialized. NOT exported. Forging this from outside the module | ||
| * is impossible without the symbol reference; `verify()` rejects any | ||
| * `system.entry-erased` entry that lacks it. | ||
| * | ||
| * @internal | ||
| */ | ||
| readonly __internal?: LedgerInternalSentinel; | ||
| } | ||
| type AuditEntry = (AuditEntryBase & { | ||
| kind: "constraint.evaluate"; | ||
| constraintId: string; | ||
| active: boolean; | ||
| /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. Refreshed on `register()`/`assign()`/`unregister()`. May be undefined for function-form constraints (see `whenSource`). PII operands redacted unless `capturePII: true`. */ | ||
| whenSpec?: FactPredicate<unknown>; | ||
| whenExplain?: readonly ClauseResult[]; | ||
| /** | ||
| * For function-form constraints (no `whenSpec`), a tamper-evident | ||
| * identity for the function. We DO NOT capture the raw source — | ||
| * closures routinely reference secrets, API keys, or PII (e.g. | ||
| * `if (apiKey === "sk-live-xxx")`) and a preview would leak them | ||
| * into the audit log. Instead, we capture a djb2 hash of the | ||
| * stringified function (`hashObject(String(fn))`). Auditors can | ||
| * detect "the function changed between deploys" by comparing | ||
| * hashes across entries, without ever seeing the function body. | ||
| * | ||
| * Informational only — NOT replayable. (N5, M22) | ||
| */ | ||
| whenSource?: { | ||
| kind: "function"; | ||
| sourceHash: string; | ||
| }; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.write.rejected"; | ||
| rejection: "rejection" | "summary"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| reason: string; | ||
| fact?: string; | ||
| expected?: unknown; | ||
| actual?: unknown; | ||
| dropped?: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "fact.change"; | ||
| key: string; | ||
| prior: unknown; | ||
| next: unknown; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.complete"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| duration: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.error"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.attach" | "source.detach"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.error"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| /** | ||
| * `phase: "runtime"` (RFC 0008) flags errors the source reported | ||
| * mid-flight via the `reportError` callback `attach` receives as | ||
| * its second argument — distinct from lifecycle `"attach"` / | ||
| * `"cleanup"` failures. | ||
| */ | ||
| phase: "attach" | "cleanup" | "runtime"; | ||
| /** | ||
| * Truncated error message — capped at a fixed length by the source | ||
| * manager before it reaches the ledger. Source authors who embed | ||
| * payloads in error messages get a bounded leak surface rather than | ||
| * an unbounded one. Pair with the matching `source.attach` / | ||
| * `source.detach` entries for full lifecycle context. | ||
| */ | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.init" | "system.start" | "system.stop" | "system.destroy"; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.snapshot"; | ||
| snapshotId: number; | ||
| trigger: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.history.navigate"; | ||
| from: number; | ||
| to: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.truncated"; | ||
| droppedSeq: number; | ||
| droppedCount: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.entry-erased"; | ||
| originalKind: AuditEntryKind; | ||
| erasedAt: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.subject-erased"; | ||
| /** | ||
| * djb2 hash of the filter (via `hashObject(filter)`). PII-safe — | ||
| * the raw filter values never land in the ledger. Pair with | ||
| * `filterShape` to see which filter fields were used. (N2) | ||
| */ | ||
| filterHash: string; | ||
| /** | ||
| * Stripped-values shape of the filter — captures WHICH fields were | ||
| * present without recording their values. (N2) | ||
| */ | ||
| filterShape: { | ||
| factPath: boolean; | ||
| constraintId: boolean; | ||
| kind: AuditEntryKind | readonly AuditEntryKind[] | undefined; | ||
| changedBetween: "[range]" | undefined; | ||
| }; | ||
| erased: number; | ||
| }); | ||
| interface QueryFilter { | ||
| /** Exact-match fact path. */ | ||
| factPath?: string; | ||
| /** Filter by constraint id. */ | ||
| constraintId?: string; | ||
| /** Filter by entry kind. */ | ||
| kind?: AuditEntryKind | readonly AuditEntryKind[]; | ||
| /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */ | ||
| changedBetween?: [string | number | Date, string | number | Date]; | ||
| /** Maximum entries returned. Default 1000. */ | ||
| limit?: number; | ||
| } | ||
| /** | ||
| * Verify result — chain valid OR a break with full context for tamper visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain breaks — | ||
| * `verify()` reports them in `erasedSeqs` and continues the walk from the | ||
| * tombstone's own hash. Real tamper still surfaces as `valid: false`. | ||
| * | ||
| * Forged tombstones (a caller writes `kind: "system.entry-erased"` | ||
| * directly via `sink.write()` to mask tamper as erasure) are detected: | ||
| * legitimate tombstones carry an in-module sentinel that forgeries | ||
| * cannot mint, so `verify()` reports them as tamper. (N7) | ||
| */ | ||
| type VerifyResult = { | ||
| valid: true; | ||
| entryCount: number; | ||
| /** | ||
| * Seq numbers of entries legitimately broken by `erase()` | ||
| * tombstones. NOT timestamps — each entry pairs this seq with | ||
| * the per-entry `system.entry-erased.erasedAt` (ms epoch) for | ||
| * the timestamp. Empty unless the chain contains erasures. | ||
| * (N1 + M1; renamed from `erasedAt` in R3) | ||
| */ | ||
| erasedSeqs?: number[]; | ||
| } | { | ||
| valid: false; | ||
| brokenAt: number; | ||
| expectedHash: string; | ||
| actualHash: string; | ||
| entry: AuditEntry; | ||
| /** | ||
| * Human-readable reason for the break — populated for cases | ||
| * where the cause is more specific than "hash mismatch" (e.g. | ||
| * tombstone forgery detected via missing sentinel). | ||
| */ | ||
| reason?: string; | ||
| }; | ||
| interface AuditLedgerSink { | ||
| write(entry: AuditEntry): void; | ||
| query(filter: QueryFilter): readonly AuditEntry[]; | ||
| recent(n: number): readonly AuditEntry[]; | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| clear(): void; | ||
| destroy(): void; | ||
| /** | ||
| * Replace matching entries with marker entries IN PLACE (preserving seq + | ||
| * prevHash so the hash chain still verifies — the marker is a | ||
| * tombstone in chain terms; the chain break is what makes erasure | ||
| * visible to `verify()`). v1 implementation matches on the same | ||
| * `QueryFilter` shape used by `query()`. Returns the count of entries | ||
| * replaced. | ||
| * | ||
| * WARNING: erases only from this sink. Any external copies (toJSON | ||
| * exports, downstream pipelines) must be erased separately. | ||
| */ | ||
| erase?(filter: QueryFilter, markerEntryFactory: (e: AuditEntry) => AuditEntry): number; | ||
| /** | ||
| * Optional hook fired by the sink BEFORE shifting the oldest entry | ||
| * out of a bounded ring buffer. The ledger plugin uses this to emit | ||
| * a `system.truncated` marker so an auditor sees that the log was | ||
| * truncated and where. (M23) | ||
| */ | ||
| onTruncate?(handler: (droppedSeq: number, droppedCount: number) => void): void; | ||
| } | ||
| interface AuditLedgerOptions { | ||
| /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */ | ||
| sink?: AuditLedgerSink; | ||
| /** | ||
| * Whether to capture raw fact values (`prior`/`next` on fact.change, | ||
| * `actual` in whenExplain). Default `false` — PII-tagged facts are | ||
| * redacted by default. Set `true` to opt out of redaction. | ||
| */ | ||
| capturePII?: boolean; | ||
| /** | ||
| * Optional caller-supplied redactor. Runs AFTER the default | ||
| * pii-tag-based redaction. Useful for additional sanitization. | ||
| */ | ||
| redact?: (entry: AuditEntry) => AuditEntry; | ||
| } | ||
| interface AuditLedger { | ||
| /** The plugin to pass to `createSystem({ plugins: [...] })`. */ | ||
| readonly plugin: Plugin<ModuleSchema>; | ||
| /** Query entries matching the filter. */ | ||
| query(filter?: QueryFilter): readonly AuditEntry[]; | ||
| /** Most recent N entries (chronological). */ | ||
| recent(n: number): readonly AuditEntry[]; | ||
| /** All entries that touch this fact path (exact match). */ | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** All entries for this constraint id. */ | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** Full ledger snapshot for export / serialization. */ | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| /** | ||
| * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff | ||
| * every entry's `prevHash` matches the (sync, djb2-based) hash of | ||
| * the previous entry. On break, returns the index of the first | ||
| * broken link plus the expected vs actual hashes — feed into a | ||
| * "TAMPERED" visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain | ||
| * breaks — `verify()` reports them in `erasedSeqs` and continues | ||
| * the walk from the tombstone's actual hash. Real tamper still | ||
| * surfaces as `valid: false`. (N1 + M1) | ||
| * | ||
| * Forged tombstones — `kind: "system.entry-erased"` entries written | ||
| * directly via `sink.write()` to mask tamper — are detected as | ||
| * forgery. Legitimate tombstones carry an in-module sentinel that | ||
| * forgeries cannot mint. (N7) | ||
| * | ||
| * v1 ships sync djb2 only. `verify({ strong: true })` is reserved | ||
| * for v2 (SHA-256) and THROWS today — there is no silent fallback. | ||
| * Call `verify()` (no args) for tamper detection. | ||
| */ | ||
| verify(opts?: { | ||
| strong?: boolean; | ||
| }): VerifyResult; | ||
| /** | ||
| * Per-subject erasure (GDPR Art. 17 stub). Replaces matching entries | ||
| * in this sink with `system.entry-erased` tombstones (preserving | ||
| * seq + prevHash so verify() can resync), then appends a chained | ||
| * `system.subject-erased` marker entry that summarises the erasure. | ||
| * | ||
| * Returns `{ erased, markerEntry }` — `markerEntry` is the chained | ||
| * `system.subject-erased` summary (the N per-entry tombstones live | ||
| * in the sink, not on the return value). (M7) | ||
| * | ||
| * When `erased === 0` (filter matched nothing), `markerEntry` is | ||
| * `null` and no marker is emitted into the chain — avoids polluting | ||
| * the audit trail with empty "erased: 0" records. (MAJOR-3) | ||
| * | ||
| * WARNING: v1 erases only from THIS sink. External copies (toJSON | ||
| * exports, downstream pipelines, persisted backups) must be erased | ||
| * separately. (C8) | ||
| */ | ||
| erase(filter: QueryFilter): { | ||
| erased: number; | ||
| markerEntry: AuditEntry | null; | ||
| }; | ||
| /** Empty the sink. */ | ||
| clear(): void; | ||
| /** Unsubscribe + drop the sink. */ | ||
| destroy(): void; | ||
| } | ||
| /** | ||
| * `memorySink()` — bounded ring-buffer implementation of | ||
| * `AuditLedgerSink`. Drops the oldest entry past `capacity` | ||
| * (default 10,000), exposes a truncation hook so the ledger plugin | ||
| * can emit a `system.truncated` marker before the shift, and | ||
| * supports in-place tombstone erasure for GDPR Art. 17. | ||
| * | ||
| * Pure storage layer — no hash chain awareness, no PII redaction. | ||
| * The plugin in `./index.ts` owns those concerns and routes them | ||
| * through this sink via `write()` / `erase()`. | ||
| */ | ||
| /** | ||
| * In-memory bounded ring-buffer sink. Drops oldest entries past | ||
| * `capacity` (default 10,000). Use this as the default sink for dev, | ||
| * tests, and StackBlitz demos. | ||
| */ | ||
| declare function memorySink(opts?: { | ||
| capacity?: number; | ||
| }): AuditLedgerSink; | ||
| /** | ||
| * createAuditLedger — append-only, queryable, hash-chained | ||
| * (djb2; SHA-256 reserved for v2) audit of every state change. For | ||
| * forensics and "show me why this user got that decision." | ||
| * | ||
| * Captures (per observation event): | ||
| * | ||
| * - `constraint.evaluate` → { whenSpec, whenExplain, active, whenSource? } | ||
| * - `resolver.write.rejected` (rejection + summary kinds) | ||
| * - `fact.change` → { key, prior, next } | ||
| * - `resolver.complete` → { resolverId, requirementId, duration } | ||
| * - `system.init` / `system.start` / `system.stop` / `system.destroy` | ||
| * - `system.snapshot` / `system.history.navigate` (lifecycle markers) | ||
| * - `system.truncated` (ring-buffer overflow marker) | ||
| * - `system.entry-erased` / `system.subject-erased` (GDPR Art.17 stub) | ||
| * | ||
| * PII redaction: by default, fact keys whose meta carries the `pii` | ||
| * tag (via `system.meta.byTag("pii")`) have their values replaced with | ||
| * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, | ||
| * `fact.change.next`, and the cached `whenSpec` operands. Opt out with | ||
| * `capturePII: true`. | ||
| * | ||
| * Folder layout: | ||
| * types.ts — public type surface + version stamps | ||
| * hash.ts — djb2 dispatch + freeze helper + INTERNAL TOKEN | ||
| * sink.ts — memorySink() ring buffer | ||
| * predicate-redact.ts — PII-aware redactWhenSpec | ||
| * verify.ts — tombstone-aware chain walk | ||
| * index.ts (this) — createAuditLedger factory + plugin wiring | ||
| */ | ||
| /** | ||
| * Create an audit ledger that subscribes to the given system's | ||
| * observation stream. Returns a `Plugin` to install + a query/verify | ||
| * API for the ledger. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createAuditLedger } from "@directive-run/core/plugins"; | ||
| * | ||
| * const ledger = createAuditLedger(); | ||
| * const system = createSystem({ module, plugins: [ledger.plugin] }); | ||
| * system.start(); | ||
| * | ||
| * // Six months later — auditor asks "what changed cart-total in March?" | ||
| * ledger.query({ | ||
| * factPath: "cartTotal", | ||
| * changedBetween: ["2026-03-01", "2026-04-01"], | ||
| * }); | ||
| * | ||
| * // Verify nobody tampered with the ledger | ||
| * const verdict = await ledger.verify(); | ||
| * if (!verdict.valid) { | ||
| * console.error("Tamper at entry", verdict.brokenAt); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger; | ||
| export { type AuditEntry as A, type QueryFilter as Q, type VerifyResult as V, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m }; |
| import { F as FactPredicate, C as ClauseResult, P as Plugin, M as ModuleSchema } from './plugins-5Supk7it.cjs'; | ||
| /** | ||
| * Audit-ledger type definitions — entry shapes, sink interface, query | ||
| * filter, verify result, and plugin options. Pure types + the two | ||
| * schema-version constants (`HASH_ALGO`, `SCHEMA_VERSION`) that are | ||
| * referenced by the entry shape. | ||
| * | ||
| * Kept free of runtime imports so the hash/freeze/sink modules can pull | ||
| * types from here without a cycle. | ||
| */ | ||
| /** Hash algorithm tag — bumped if canonicalization or hash function changes. */ | ||
| declare const HASH_ALGO: "djb2-1"; | ||
| /** | ||
| * Entry schema version. Bumped if `AuditEntry` field shape changes in | ||
| * a way that breaks back-compat parsers. Persisted on every entry so | ||
| * exports remain self-describing across library upgrades. (F-5) | ||
| */ | ||
| declare const SCHEMA_VERSION: 1; | ||
| type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "source.attach" | "source.detach" | "source.error" | "system.init" | "system.start" | "system.stop" | "system.destroy" | "system.snapshot" | "system.history.navigate" | "system.truncated" | "system.entry-erased" | "system.subject-erased"; | ||
| /** | ||
| * Internal sentinel symbol type. The actual symbol VALUE lives in | ||
| * `hash.ts` and is never exported from this folder's public surface — | ||
| * but the TYPE must be referenceable here so `AuditEntryBase` can | ||
| * declare the optional `__internal` field. | ||
| * | ||
| * We use `symbol` rather than `typeof LEDGER_INTERNAL_TOKEN` because | ||
| * importing the symbol value into types.ts would either re-export it | ||
| * (defeating the defense) or create a circular import. The runtime | ||
| * check in `verify()` compares against the actual symbol reference. | ||
| */ | ||
| type LedgerInternalSentinel = symbol; | ||
| interface AuditEntryBase { | ||
| /** Monotonic sequence number, starting at 0. */ | ||
| readonly seq: number; | ||
| /** Wall-clock timestamp (ms epoch). */ | ||
| readonly ts: number; | ||
| /** Discriminator. */ | ||
| readonly kind: AuditEntryKind; | ||
| /** Hash of the previous entry's full payload. null on the genesis entry. */ | ||
| readonly prevHash: string | null; | ||
| /** | ||
| * Hash algorithm tag identifying the canonicalization + hash | ||
| * function in use. Bumped if the algorithm or canonical form | ||
| * changes, so exports remain verifiable across versions. | ||
| */ | ||
| readonly hashAlgo: typeof HASH_ALGO; | ||
| /** | ||
| * Entry schema version — bumped if any `AuditEntry` field shape | ||
| * changes in a way that breaks back-compat. Pair with `hashAlgo` | ||
| * when migrating older exports. (F-5) | ||
| */ | ||
| readonly schemaVersion: typeof SCHEMA_VERSION; | ||
| /** | ||
| * Private sentinel — present (and equal to the in-module token) only | ||
| * on legitimate tombstones minted by `ledger.erase()`. Filtered out | ||
| * of all public read paths (`query`, `recent`, `toJSON`, etc.) so | ||
| * consumers never see or copy it. (N7) | ||
| * | ||
| * NOT serialized. NOT exported. Forging this from outside the module | ||
| * is impossible without the symbol reference; `verify()` rejects any | ||
| * `system.entry-erased` entry that lacks it. | ||
| * | ||
| * @internal | ||
| */ | ||
| readonly __internal?: LedgerInternalSentinel; | ||
| } | ||
| type AuditEntry = (AuditEntryBase & { | ||
| kind: "constraint.evaluate"; | ||
| constraintId: string; | ||
| active: boolean; | ||
| /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. Refreshed on `register()`/`assign()`/`unregister()`. May be undefined for function-form constraints (see `whenSource`). PII operands redacted unless `capturePII: true`. */ | ||
| whenSpec?: FactPredicate<unknown>; | ||
| whenExplain?: readonly ClauseResult[]; | ||
| /** | ||
| * For function-form constraints (no `whenSpec`), a tamper-evident | ||
| * identity for the function. We DO NOT capture the raw source — | ||
| * closures routinely reference secrets, API keys, or PII (e.g. | ||
| * `if (apiKey === "sk-live-xxx")`) and a preview would leak them | ||
| * into the audit log. Instead, we capture a djb2 hash of the | ||
| * stringified function (`hashObject(String(fn))`). Auditors can | ||
| * detect "the function changed between deploys" by comparing | ||
| * hashes across entries, without ever seeing the function body. | ||
| * | ||
| * Informational only — NOT replayable. (N5, M22) | ||
| */ | ||
| whenSource?: { | ||
| kind: "function"; | ||
| sourceHash: string; | ||
| }; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.write.rejected"; | ||
| rejection: "rejection" | "summary"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| reason: string; | ||
| fact?: string; | ||
| expected?: unknown; | ||
| actual?: unknown; | ||
| dropped?: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "fact.change"; | ||
| key: string; | ||
| prior: unknown; | ||
| next: unknown; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.complete"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| duration: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.error"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.attach" | "source.detach"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.error"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| /** | ||
| * `phase: "runtime"` (RFC 0008) flags errors the source reported | ||
| * mid-flight via the `reportError` callback `attach` receives as | ||
| * its second argument — distinct from lifecycle `"attach"` / | ||
| * `"cleanup"` failures. | ||
| */ | ||
| phase: "attach" | "cleanup" | "runtime"; | ||
| /** | ||
| * Truncated error message — capped at a fixed length by the source | ||
| * manager before it reaches the ledger. Source authors who embed | ||
| * payloads in error messages get a bounded leak surface rather than | ||
| * an unbounded one. Pair with the matching `source.attach` / | ||
| * `source.detach` entries for full lifecycle context. | ||
| */ | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.init" | "system.start" | "system.stop" | "system.destroy"; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.snapshot"; | ||
| snapshotId: number; | ||
| trigger: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.history.navigate"; | ||
| from: number; | ||
| to: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.truncated"; | ||
| droppedSeq: number; | ||
| droppedCount: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.entry-erased"; | ||
| originalKind: AuditEntryKind; | ||
| erasedAt: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.subject-erased"; | ||
| /** | ||
| * djb2 hash of the filter (via `hashObject(filter)`). PII-safe — | ||
| * the raw filter values never land in the ledger. Pair with | ||
| * `filterShape` to see which filter fields were used. (N2) | ||
| */ | ||
| filterHash: string; | ||
| /** | ||
| * Stripped-values shape of the filter — captures WHICH fields were | ||
| * present without recording their values. (N2) | ||
| */ | ||
| filterShape: { | ||
| factPath: boolean; | ||
| constraintId: boolean; | ||
| kind: AuditEntryKind | readonly AuditEntryKind[] | undefined; | ||
| changedBetween: "[range]" | undefined; | ||
| }; | ||
| erased: number; | ||
| }); | ||
| interface QueryFilter { | ||
| /** Exact-match fact path. */ | ||
| factPath?: string; | ||
| /** Filter by constraint id. */ | ||
| constraintId?: string; | ||
| /** Filter by entry kind. */ | ||
| kind?: AuditEntryKind | readonly AuditEntryKind[]; | ||
| /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */ | ||
| changedBetween?: [string | number | Date, string | number | Date]; | ||
| /** Maximum entries returned. Default 1000. */ | ||
| limit?: number; | ||
| } | ||
| /** | ||
| * Verify result — chain valid OR a break with full context for tamper visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain breaks — | ||
| * `verify()` reports them in `erasedSeqs` and continues the walk from the | ||
| * tombstone's own hash. Real tamper still surfaces as `valid: false`. | ||
| * | ||
| * Forged tombstones (a caller writes `kind: "system.entry-erased"` | ||
| * directly via `sink.write()` to mask tamper as erasure) are detected: | ||
| * legitimate tombstones carry an in-module sentinel that forgeries | ||
| * cannot mint, so `verify()` reports them as tamper. (N7) | ||
| */ | ||
| type VerifyResult = { | ||
| valid: true; | ||
| entryCount: number; | ||
| /** | ||
| * Seq numbers of entries legitimately broken by `erase()` | ||
| * tombstones. NOT timestamps — each entry pairs this seq with | ||
| * the per-entry `system.entry-erased.erasedAt` (ms epoch) for | ||
| * the timestamp. Empty unless the chain contains erasures. | ||
| * (N1 + M1; renamed from `erasedAt` in R3) | ||
| */ | ||
| erasedSeqs?: number[]; | ||
| } | { | ||
| valid: false; | ||
| brokenAt: number; | ||
| expectedHash: string; | ||
| actualHash: string; | ||
| entry: AuditEntry; | ||
| /** | ||
| * Human-readable reason for the break — populated for cases | ||
| * where the cause is more specific than "hash mismatch" (e.g. | ||
| * tombstone forgery detected via missing sentinel). | ||
| */ | ||
| reason?: string; | ||
| }; | ||
| interface AuditLedgerSink { | ||
| write(entry: AuditEntry): void; | ||
| query(filter: QueryFilter): readonly AuditEntry[]; | ||
| recent(n: number): readonly AuditEntry[]; | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| clear(): void; | ||
| destroy(): void; | ||
| /** | ||
| * Replace matching entries with marker entries IN PLACE (preserving seq + | ||
| * prevHash so the hash chain still verifies — the marker is a | ||
| * tombstone in chain terms; the chain break is what makes erasure | ||
| * visible to `verify()`). v1 implementation matches on the same | ||
| * `QueryFilter` shape used by `query()`. Returns the count of entries | ||
| * replaced. | ||
| * | ||
| * WARNING: erases only from this sink. Any external copies (toJSON | ||
| * exports, downstream pipelines) must be erased separately. | ||
| */ | ||
| erase?(filter: QueryFilter, markerEntryFactory: (e: AuditEntry) => AuditEntry): number; | ||
| /** | ||
| * Optional hook fired by the sink BEFORE shifting the oldest entry | ||
| * out of a bounded ring buffer. The ledger plugin uses this to emit | ||
| * a `system.truncated` marker so an auditor sees that the log was | ||
| * truncated and where. (M23) | ||
| */ | ||
| onTruncate?(handler: (droppedSeq: number, droppedCount: number) => void): void; | ||
| } | ||
| interface AuditLedgerOptions { | ||
| /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */ | ||
| sink?: AuditLedgerSink; | ||
| /** | ||
| * Whether to capture raw fact values (`prior`/`next` on fact.change, | ||
| * `actual` in whenExplain). Default `false` — PII-tagged facts are | ||
| * redacted by default. Set `true` to opt out of redaction. | ||
| */ | ||
| capturePII?: boolean; | ||
| /** | ||
| * Optional caller-supplied redactor. Runs AFTER the default | ||
| * pii-tag-based redaction. Useful for additional sanitization. | ||
| */ | ||
| redact?: (entry: AuditEntry) => AuditEntry; | ||
| } | ||
| interface AuditLedger { | ||
| /** The plugin to pass to `createSystem({ plugins: [...] })`. */ | ||
| readonly plugin: Plugin<ModuleSchema>; | ||
| /** Query entries matching the filter. */ | ||
| query(filter?: QueryFilter): readonly AuditEntry[]; | ||
| /** Most recent N entries (chronological). */ | ||
| recent(n: number): readonly AuditEntry[]; | ||
| /** All entries that touch this fact path (exact match). */ | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** All entries for this constraint id. */ | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** Full ledger snapshot for export / serialization. */ | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| /** | ||
| * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff | ||
| * every entry's `prevHash` matches the (sync, djb2-based) hash of | ||
| * the previous entry. On break, returns the index of the first | ||
| * broken link plus the expected vs actual hashes — feed into a | ||
| * "TAMPERED" visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain | ||
| * breaks — `verify()` reports them in `erasedSeqs` and continues | ||
| * the walk from the tombstone's actual hash. Real tamper still | ||
| * surfaces as `valid: false`. (N1 + M1) | ||
| * | ||
| * Forged tombstones — `kind: "system.entry-erased"` entries written | ||
| * directly via `sink.write()` to mask tamper — are detected as | ||
| * forgery. Legitimate tombstones carry an in-module sentinel that | ||
| * forgeries cannot mint. (N7) | ||
| * | ||
| * v1 ships sync djb2 only. `verify({ strong: true })` is reserved | ||
| * for v2 (SHA-256) and THROWS today — there is no silent fallback. | ||
| * Call `verify()` (no args) for tamper detection. | ||
| */ | ||
| verify(opts?: { | ||
| strong?: boolean; | ||
| }): VerifyResult; | ||
| /** | ||
| * Per-subject erasure (GDPR Art. 17 stub). Replaces matching entries | ||
| * in this sink with `system.entry-erased` tombstones (preserving | ||
| * seq + prevHash so verify() can resync), then appends a chained | ||
| * `system.subject-erased` marker entry that summarises the erasure. | ||
| * | ||
| * Returns `{ erased, markerEntry }` — `markerEntry` is the chained | ||
| * `system.subject-erased` summary (the N per-entry tombstones live | ||
| * in the sink, not on the return value). (M7) | ||
| * | ||
| * When `erased === 0` (filter matched nothing), `markerEntry` is | ||
| * `null` and no marker is emitted into the chain — avoids polluting | ||
| * the audit trail with empty "erased: 0" records. (MAJOR-3) | ||
| * | ||
| * WARNING: v1 erases only from THIS sink. External copies (toJSON | ||
| * exports, downstream pipelines, persisted backups) must be erased | ||
| * separately. (C8) | ||
| */ | ||
| erase(filter: QueryFilter): { | ||
| erased: number; | ||
| markerEntry: AuditEntry | null; | ||
| }; | ||
| /** Empty the sink. */ | ||
| clear(): void; | ||
| /** Unsubscribe + drop the sink. */ | ||
| destroy(): void; | ||
| } | ||
| /** | ||
| * `memorySink()` — bounded ring-buffer implementation of | ||
| * `AuditLedgerSink`. Drops the oldest entry past `capacity` | ||
| * (default 10,000), exposes a truncation hook so the ledger plugin | ||
| * can emit a `system.truncated` marker before the shift, and | ||
| * supports in-place tombstone erasure for GDPR Art. 17. | ||
| * | ||
| * Pure storage layer — no hash chain awareness, no PII redaction. | ||
| * The plugin in `./index.ts` owns those concerns and routes them | ||
| * through this sink via `write()` / `erase()`. | ||
| */ | ||
| /** | ||
| * In-memory bounded ring-buffer sink. Drops oldest entries past | ||
| * `capacity` (default 10,000). Use this as the default sink for dev, | ||
| * tests, and StackBlitz demos. | ||
| */ | ||
| declare function memorySink(opts?: { | ||
| capacity?: number; | ||
| }): AuditLedgerSink; | ||
| /** | ||
| * createAuditLedger — append-only, queryable, hash-chained | ||
| * (djb2; SHA-256 reserved for v2) audit of every state change. For | ||
| * forensics and "show me why this user got that decision." | ||
| * | ||
| * Captures (per observation event): | ||
| * | ||
| * - `constraint.evaluate` → { whenSpec, whenExplain, active, whenSource? } | ||
| * - `resolver.write.rejected` (rejection + summary kinds) | ||
| * - `fact.change` → { key, prior, next } | ||
| * - `resolver.complete` → { resolverId, requirementId, duration } | ||
| * - `system.init` / `system.start` / `system.stop` / `system.destroy` | ||
| * - `system.snapshot` / `system.history.navigate` (lifecycle markers) | ||
| * - `system.truncated` (ring-buffer overflow marker) | ||
| * - `system.entry-erased` / `system.subject-erased` (GDPR Art.17 stub) | ||
| * | ||
| * PII redaction: by default, fact keys whose meta carries the `pii` | ||
| * tag (via `system.meta.byTag("pii")`) have their values replaced with | ||
| * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, | ||
| * `fact.change.next`, and the cached `whenSpec` operands. Opt out with | ||
| * `capturePII: true`. | ||
| * | ||
| * Folder layout: | ||
| * types.ts — public type surface + version stamps | ||
| * hash.ts — djb2 dispatch + freeze helper + INTERNAL TOKEN | ||
| * sink.ts — memorySink() ring buffer | ||
| * predicate-redact.ts — PII-aware redactWhenSpec | ||
| * verify.ts — tombstone-aware chain walk | ||
| * index.ts (this) — createAuditLedger factory + plugin wiring | ||
| */ | ||
| /** | ||
| * Create an audit ledger that subscribes to the given system's | ||
| * observation stream. Returns a `Plugin` to install + a query/verify | ||
| * API for the ledger. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createAuditLedger } from "@directive-run/core/plugins"; | ||
| * | ||
| * const ledger = createAuditLedger(); | ||
| * const system = createSystem({ module, plugins: [ledger.plugin] }); | ||
| * system.start(); | ||
| * | ||
| * // Six months later — auditor asks "what changed cart-total in March?" | ||
| * ledger.query({ | ||
| * factPath: "cartTotal", | ||
| * changedBetween: ["2026-03-01", "2026-04-01"], | ||
| * }); | ||
| * | ||
| * // Verify nobody tampered with the ledger | ||
| * const verdict = await ledger.verify(); | ||
| * if (!verdict.valid) { | ||
| * console.error("Tamper at entry", verdict.brokenAt); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger; | ||
| export { type AuditEntry as A, type QueryFilter as Q, type VerifyResult as V, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { ah as Schema, a as Facts, F as FactPredicate, b4 as InferSchema, L as FactTemplate, D as DefinitionMeta, r as Requirement, bl as RequirementOutput, ag as RetryPolicy, B as BatchConfig, be as ResolverContext, ad as PredicateOp, a6 as PatchSpec, C as ClauseResult } from './plugins-5Supk7it.js'; | ||
| /** | ||
| * Derivation Types - Type definitions for derivations | ||
| */ | ||
| /** Derivation definition function signature. */ | ||
| interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| (facts: Facts<S>, derived: DerivedValues<S, D>): T; | ||
| } | ||
| /** | ||
| * Derivation definition with metadata (object form). | ||
| * Use this when you want to attach debugging metadata to a derivation. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * derive: { | ||
| * displayName: { | ||
| * compute: (facts) => `${facts.firstName} ${facts.lastName}`, | ||
| * meta: { label: "Display Name", description: "Full name for UI" }, | ||
| * }, | ||
| * }, | ||
| * ``` | ||
| */ | ||
| interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| /** | ||
| * The derivation body. Either: | ||
| * - a function `(facts, derived) => T` (original form), or | ||
| * - a {@link FactPredicate} data spec — boolean derivations only, or | ||
| * - a {@link FactTemplate} `{ $template: "..." }` — string derivations only. | ||
| * | ||
| * Data forms are normalized to a wrapper function at registration; the | ||
| * wrapper reads through the facts proxy so existing auto-tracking | ||
| * captures dependencies. | ||
| */ | ||
| compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never); | ||
| meta?: DefinitionMeta; | ||
| } | ||
| /** Map of derivation definitions (internal — always bare functions after unwrap). */ | ||
| type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>; | ||
| /** Computed derived values. */ | ||
| type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = { | ||
| readonly [K in keyof D]: ReturnType<D[K]>; | ||
| }; | ||
| /** Internal derivation state */ | ||
| interface DerivationState<T> { | ||
| id: string; | ||
| compute: () => T; | ||
| cachedValue: T | undefined; | ||
| dependencies: Set<string>; | ||
| isStale: boolean; | ||
| isComputing: boolean; | ||
| /** Consecutive runs producing the same deps (auto-tracked only) */ | ||
| stableRunCount: number; | ||
| /** Once true, skip withTracking() overhead until a tracked fact mutates */ | ||
| depsStable: boolean; | ||
| } | ||
| /** | ||
| * Type Helpers - External typed constraint and resolver definitions | ||
| * | ||
| * These types enable defining constraints and resolvers with full type safety | ||
| * outside of module definitions, while maintaining proper type inference. | ||
| */ | ||
| /** | ||
| * External constraint definition with full typing. | ||
| * Use this when defining constraints outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed constraint factory | ||
| * const createMaxCountConstraint = <S extends Schema>( | ||
| * maxCount: number | ||
| * ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({ | ||
| * priority: 10, | ||
| * when: (facts) => (facts as { count: number }).count > maxCount, | ||
| * require: { type: "RESET_COUNT" }, | ||
| * }); | ||
| * | ||
| * // Use in module | ||
| * const module = createModule("counter", { | ||
| * schema: { count: t.number() }, | ||
| * constraints: { | ||
| * maxCount: createMaxCountConstraint(100), | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> { | ||
| /** Priority for ordering (higher runs first) */ | ||
| priority?: number; | ||
| /** Mark this constraint as async (avoids runtime detection) */ | ||
| async?: boolean; | ||
| /** Condition function (sync or async) */ | ||
| when: (facts: Facts<S>) => boolean | Promise<boolean>; | ||
| /** | ||
| * Requirement(s) to produce when condition is met. | ||
| */ | ||
| require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>); | ||
| /** Timeout for async constraints (ms) */ | ||
| timeout?: number; | ||
| /** | ||
| * Constraint IDs whose resolvers must complete before this constraint is evaluated. | ||
| * - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for) | ||
| * - If dependency's resolver fails, this constraint remains blocked until it succeeds | ||
| * - Cross-module: use the constraint ID as it appears in the merged system | ||
| */ | ||
| after?: string[]; | ||
| } | ||
| /** | ||
| * External resolver definition with full typing. | ||
| * Use this when defining resolvers outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed resolver factory | ||
| * interface FetchUserReq extends Requirement { | ||
| * type: "FETCH_USER"; | ||
| * userId: string; | ||
| * } | ||
| * | ||
| * const createFetchUserResolver = <S extends Schema>( | ||
| * fetchFn: (userId: string) => Promise<User> | ||
| * ): TypedResolver<S, FetchUserReq> => ({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * key: (req) => `fetch-user-${req.userId}`, | ||
| * retry: { attempts: 3, backoff: "exponential" }, | ||
| * resolve: async (req, ctx) => { | ||
| * const user = await fetchFn(req.userId); | ||
| * (ctx.facts as { user: User }).user = user; | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedResolver<S extends Schema, R extends Requirement = Requirement> { | ||
| /** | ||
| * Requirement type to handle. | ||
| * - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`) | ||
| * - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`) | ||
| */ | ||
| requirement: R["type"] | ((req: Requirement) => req is R); | ||
| /** Custom key function for deduplication */ | ||
| key?: (req: R) => string; | ||
| /** Retry policy */ | ||
| retry?: RetryPolicy; | ||
| /** Timeout for resolver execution (ms) */ | ||
| timeout?: number; | ||
| /** Batch configuration */ | ||
| batch?: BatchConfig; | ||
| /** Resolve function for single requirement */ | ||
| resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>; | ||
| /** Resolve function for batched requirements */ | ||
| resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>; | ||
| } | ||
| /** | ||
| * Create a typed constraint factory for a specific schema. | ||
| * This enables creating reusable constraint definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { count: t.number(), threshold: t.number() }; | ||
| * const factory = createConstraintFactory<typeof schema>(); | ||
| * | ||
| * const maxCountConstraint = factory.create({ | ||
| * when: (facts) => facts.count > facts.threshold, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createConstraintFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed constraint | ||
| */ | ||
| create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| }; | ||
| /** | ||
| * Create a typed resolver factory for a specific schema. | ||
| * This enables creating reusable resolver definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { user: t.object<User>() }; | ||
| * const factory = createResolverFactory<typeof schema>(); | ||
| * | ||
| * const fetchUserResolver = factory.create<FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createResolverFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed resolver | ||
| */ | ||
| create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| }; | ||
| /** | ||
| * Type-safe constraint creator. | ||
| * Simpler alternative to createConstraintFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const constraint = typedConstraint<typeof schema, { type: "RESET" }>({ | ||
| * when: (facts) => facts.count > 100, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| /** | ||
| * Type-safe resolver creator. | ||
| * Simpler alternative to createResolverFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const resolver = typedResolver<typeof schema, FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| /** | ||
| * Schema Introspection | ||
| * | ||
| * A runtime discriminant for every `t.*()` builder result, so downstream | ||
| * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`) | ||
| * can ask "what kind is this fact?" without grepping the source. | ||
| * | ||
| * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`. | ||
| * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.) | ||
| * preserve / decorate it. When `_kind` is absent (legacy or third-party | ||
| * builder), the parser falls back to reading the freeform `_typeName` | ||
| * string. When even that fails: `{ kind: "unknown" }` — graceful close. | ||
| * | ||
| * This module has zero hot-path cost; it is only invoked when an | ||
| * introspecting caller asks for it. | ||
| */ | ||
| /** | ||
| * The closed set of kinds a Directive schema field can be. | ||
| * | ||
| * Drives operator availability via {@link getOperatorsForKind}: e.g. | ||
| * `"number"` gets the orderable operators (`$gte`, `$lte`); `"boolean"` | ||
| * does not. | ||
| */ | ||
| type SchemaKind = "number" | "string" | "boolean" | "bigint" | "date" | "array" | "object" | "record" | "tuple" | "enum" | "literal" | "union" | "branded" | "unknown"; | ||
| /** | ||
| * A tree-shaped discriminator for a schema field. Composite kinds | ||
| * (array, object, tuple, etc.) carry their element / shape information | ||
| * so an LLM-prompt builder can show "cartTotal is a number" AND | ||
| * "items is an array of { sku: string, qty: number }". | ||
| * | ||
| * `nullable` / `hasDefault` flags appear on the inner node (NOT a | ||
| * wrapping kind) so operator-lookup on `t.number().nullable()` returns | ||
| * the number's operators unchanged — `$gte` works on the non-null arm. | ||
| */ | ||
| type SchemaKindNode = ({ | ||
| kind: "number" | "string" | "boolean" | "bigint" | "date" | "unknown"; | ||
| } | { | ||
| kind: "literal"; | ||
| value: string | number | boolean | null; | ||
| primitive: "string" | "number" | "boolean" | "null"; | ||
| } | { | ||
| kind: "enum"; | ||
| values: readonly (string | number)[]; | ||
| primitive: "string" | "number"; | ||
| } | { | ||
| kind: "array"; | ||
| element: SchemaKindNode; | ||
| } | { | ||
| kind: "tuple"; | ||
| elements: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "object"; | ||
| shape: Record<string, SchemaKindNode>; | ||
| } | { | ||
| kind: "record"; | ||
| value: SchemaKindNode; | ||
| } | { | ||
| kind: "union"; | ||
| members: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "branded"; | ||
| inner: SchemaKindNode; | ||
| }) & { | ||
| /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */ | ||
| nullable?: boolean; | ||
| /** True if the schema has a `.default()`. */ | ||
| hasDefault?: boolean; | ||
| }; | ||
| /** | ||
| * Return the {@link SchemaKindNode} for a schema field. Prefers the | ||
| * explicit `_kind` discriminant set by the builder; falls back to | ||
| * parsing the freeform `_typeName` string for legacy / third-party | ||
| * builders that don't set `_kind`. | ||
| * | ||
| * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder | ||
| * that throws on property access returns `{ kind: "unknown" }` instead of | ||
| * propagating the throw to introspecting callers. | ||
| * | ||
| * In dev mode, a function input (`typeof schema === "function"`) emits a | ||
| * warning — common foot-gun where the caller forgot to invoke a builder | ||
| * factory (e.g. wrote `t.number` instead of `t.number()`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * getKind(t.number()) // → { kind: "number" } | ||
| * getKind(t.string().nullable()) // → { kind: "string", nullable: true } | ||
| * getKind(t.array(t.number())) // → { kind: "array", element: { kind: "number" } } | ||
| * ``` | ||
| */ | ||
| declare function getKind(schema: unknown): SchemaKindNode; | ||
| /** | ||
| * Walk the `facts` block of a module schema and emit a flat map from | ||
| * dotted path → kind node. Nested `t.object()` shapes flatten using | ||
| * `.` as the separator, matching the convention used by | ||
| * `OperatorObject<V>`'s nested-path support. | ||
| * | ||
| * Passing a top-level schema directly (without the `facts:` wrapper) | ||
| * also works — anything iterable as `Record<string, ExtendedSchemaType>` | ||
| * is acceptable. | ||
| * | ||
| * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is | ||
| * silently skipped (treated as `{ kind: "unknown" }` for that field) | ||
| * rather than aborting the whole walk. | ||
| * | ||
| * In dev mode, a top-level schema that yields an empty map (no | ||
| * introspectable keys) emits a warning — common foot-gun where the | ||
| * caller passed `myModule` instead of `myModule.schema`. | ||
| */ | ||
| declare function getSchemaFieldKinds(schema: unknown): Map<string, SchemaKindNode>; | ||
| /** | ||
| * Return the set of `PredicateOp` strings that are valid against a | ||
| * given {@link SchemaKindNode}. | ||
| * | ||
| * Mirrors the type-level matrix encoded in `OperatorObject<V>` in | ||
| * `types/predicate.ts` — drift between the two is enforced by the | ||
| * compile-time conformance test | ||
| * (`schema-introspection-conformance.test-d.ts`). | ||
| * | ||
| * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists` | ||
| * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`, | ||
| * `$lt`, `$lte`, `$between` | ||
| * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains` | ||
| * - **Array:** + `$contains` (over the element type) | ||
| * - **Union:** *intersection* across members (the operand must be valid | ||
| * for every branch). | ||
| * - **Branded:** delegates to the inner kind. | ||
| * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in` | ||
| * operand restricted at the LLM-prompt layer (not enforced here). | ||
| * | ||
| * `nullable` does not change operator availability — `$gte` on a | ||
| * nullable number is fine on the non-null arm; `$exists` handles null. | ||
| */ | ||
| declare function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[]; | ||
| /** | ||
| * Return all known predicate operators — convenience for prompt builders | ||
| * that need to show the LLM the full set. | ||
| */ | ||
| declare function listAllPredicateOperators(): readonly PredicateOp[]; | ||
| /** | ||
| * Runtime for data-configuration predicates and templates. | ||
| * | ||
| * Pure module — imports only its own types. Reads facts through whatever | ||
| * object it is handed (the reactive `Facts` proxy in production, a plain | ||
| * snapshot in tests), so it never depends on the engine, store, or tracking. | ||
| */ | ||
| /** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */ | ||
| type Scope = Record<string, unknown>; | ||
| /** | ||
| * True when `v` is a data-form spec (predicate object/array) rather than a | ||
| * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.) | ||
| * — only plain `{}` literals and arrays of plain clause shapes qualify. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isPredicate({ phase: "red" }); // true | ||
| * isPredicate((f) => f.phase === "red"); // false | ||
| * isPredicate([{ fact: "phase", op: "$eq", value: "red" }]); // true | ||
| * ``` | ||
| */ | ||
| declare function isPredicate(v: unknown): boolean; | ||
| /** | ||
| * True when `v` is a {@link FactTemplate} (`{ $template: string }`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isTemplate({ $template: "Hi ${name}" }); // true | ||
| * isTemplate({ $set: { name: "x" } }); // false | ||
| * ``` | ||
| */ | ||
| declare function isTemplate(v: unknown): v is FactTemplate; | ||
| /** | ||
| * Throw when a predicate spec contains an operand that cannot survive a | ||
| * JSON round-trip — i.e. that would silently mis-evaluate if the spec was | ||
| * loaded from `JSON.parse`. | ||
| * | ||
| * Three failure classes are detected: | ||
| * | ||
| * - **Lost `RegExp` operand.** A `$matches` operand that is not a | ||
| * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as | ||
| * `{}`, so a `$matches` clause with an empty-object operand is the | ||
| * signature of a regex that did not survive serialization. Reify it | ||
| * with `new RegExp(pattern, flags)` before installing the predicate. | ||
| * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a | ||
| * `bigint` operand cannot have been produced by a JSON pipeline and | ||
| * cannot be persisted by one either. | ||
| * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all | ||
| * members; a predicate carrying one is not JSON-safe. | ||
| * | ||
| * This is an opt-in helper — the engine does not call it automatically. | ||
| * Users who load predicates from JSON should call it after `JSON.parse` | ||
| * to fail loud rather than silently mis-evaluate. See the | ||
| * "Serialization" section of RFC-0004. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * validatePredicate({ phase: { $matches: {} } }); | ||
| * // throws — empty object where a RegExp is required | ||
| * | ||
| * validatePredicate({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // ok — JSON-clean operands | ||
| * ``` | ||
| */ | ||
| declare function validatePredicate(spec: unknown, path?: string): void; | ||
| interface SchemaValidationError { | ||
| /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */ | ||
| readonly path: string; | ||
| /** The operator that failed (or the literal-equality marker `$eq`). */ | ||
| readonly op: string; | ||
| /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */ | ||
| readonly kind?: SchemaKindNode; | ||
| /** The operators that ARE allowed for this fact's kind. */ | ||
| readonly allowedOps?: readonly string[]; | ||
| /** Human-readable failure reason (suitable for feeding back to an LLM). */ | ||
| readonly reason: string; | ||
| } | ||
| interface SchemaValidationOptions { | ||
| /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */ | ||
| readonly maxOperatorCount?: number; | ||
| /** | ||
| * Reject `$in` / `$nin` operands that contain more than this many elements | ||
| * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000 | ||
| * — beyond that, a downstream query compiler may degrade quadratically. | ||
| */ | ||
| readonly maxArrayOperandLength?: number; | ||
| } | ||
| /** | ||
| * Heuristic: flag a regex source string that has obvious nested quantifiers | ||
| * (e.g. `(.+)+`, `(.*)*`, `(\w+)+`, `(a|a)+`) — the classic ReDoS shapes. | ||
| * Not a full ReDoS prover; intentionally conservative so a string-rehydrated | ||
| * `$matches` operand can be rejected before it ever reaches `RegExp.test`. | ||
| * | ||
| * Callers MUST NOT treat a `false` result as "safe" — a determined adversary | ||
| * can craft patterns this heuristic misses. The right answer for untrusted | ||
| * regex is "don't accept untrusted regex"; this helper exists to catch the | ||
| * obvious foot-guns. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * dangerousRegex("(a+)+"); // → true | ||
| * dangerousRegex("(.*)*"); // → true | ||
| * dangerousRegex("(\\w+)+"); // → true | ||
| * dangerousRegex("^[a-z]+$"); // → false | ||
| * ``` | ||
| */ | ||
| declare function dangerousRegex(source: string): boolean; | ||
| type SchemaValidationResult = { | ||
| ok: true; | ||
| operatorCount: number; | ||
| } | { | ||
| ok: false; | ||
| errors: readonly SchemaValidationError[]; | ||
| operatorCount: number; | ||
| }; | ||
| /** | ||
| * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate | ||
| * against a schema's runtime kind map. Catches errors that | ||
| * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a | ||
| * boolean fact), unknown fact paths, and (optionally) operator-count | ||
| * exhaustion DoS attempts. | ||
| * | ||
| * Pair with {@link validatePredicate} (structural / JSON safety) for full | ||
| * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a | ||
| * module schema. | ||
| * | ||
| * Designed for the LLM-emit retry loop: returns a list of errors with | ||
| * structured `{path, op, kind, allowedOps, reason}` rather than throwing, | ||
| * so the caller can feed the errors back to the model. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } }); | ||
| * const result = validatePredicateAgainstSchema( | ||
| * { cartTotal: { $gte: 50 }, active: { $gte: true } }, | ||
| * kindMap, | ||
| * ); | ||
| * // → { ok: false, errors: [{ path: "active", op: "$gte", reason: "..." }], operatorCount: 2 } | ||
| * ``` | ||
| */ | ||
| declare function validatePredicateAgainstSchema(spec: unknown, kindMap: Map<string, SchemaKindNode>, opts?: SchemaValidationOptions): SchemaValidationResult; | ||
| /** | ||
| * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous | ||
| * snapshot) is consulted only by the `$changed` operator. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicate({ phase: "red", elapsed: { $gte: 30 } }, { phase: "red", elapsed: 45 }); | ||
| * // → true | ||
| * evaluatePredicate({ $any: [{ phase: "red" }, { phase: "yellow" }] }, { phase: "green" }); | ||
| * // → false | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicate(spec: unknown, facts: Scope, prev?: Scope, depth?: number): boolean; | ||
| /** | ||
| * Evaluate a predicate and return a per-clause breakdown — the data feed for | ||
| * devtools, `system.explain()`, and `directive explain`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicateExplained( | ||
| * { phase: "red", elapsed: { $gte: 30 } }, | ||
| * { phase: "red", elapsed: 20 }, | ||
| * ); | ||
| * // → [ | ||
| * // { path: "phase", op: "$eq", expected: "red", actual: "red", pass: true }, | ||
| * // { path: "elapsed", op: "$gte", expected: 30, actual: 20, pass: false }, | ||
| * // ] | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicateExplained(spec: unknown, facts: Scope, prev?: Scope, pathPrefix?: string): ClauseResult[]; | ||
| /** | ||
| * Memoize a predicate as a reusable evaluation closure. | ||
| * | ||
| * The returned function accepts any `facts` scope (the reactive proxy in | ||
| * production, a plain object in tests) plus an optional `prev` snapshot for | ||
| * `$changed`. The closure is cached **by predicate identity** in a | ||
| * `WeakMap`, so passing the same `predicate` reference repeatedly is | ||
| * allocation-free; cleanup is automatic once the predicate is no longer | ||
| * reachable. | ||
| * | ||
| * Note: no actual compilation happens — the returned closure re-walks the | ||
| * spec on every call via `evaluatePredicate`. The name reflects what the | ||
| * function does (closure memoization keyed by predicate identity), not a | ||
| * bytecode/AST compile step. | ||
| * | ||
| * Intended for advanced users who want a stable function reference per | ||
| * predicate (custom devtools, batched analyses). Regular module code does | ||
| * not need to call this — the engine wraps data-form `when` / `on` specs | ||
| * automatically at registration. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const predicate = { phase: "red", elapsed: { $gte: 30 } }; | ||
| * const check = memoizePredicate(predicate); | ||
| * check({ phase: "red", elapsed: 45 }); // → true | ||
| * check({ phase: "red", elapsed: 5 }); // → false | ||
| * ``` | ||
| */ | ||
| declare function memoizePredicate(predicate: object): (facts: Scope, prev?: Scope) => boolean; | ||
| /** | ||
| * Collect the fact keys a predicate references. Used for static analysis, | ||
| * devtools, and effect `on` dependency wiring. Nested predicates contribute | ||
| * dotted keys (`auth.token`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractDeps({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // → Set { "phase", "elapsed" } | ||
| * extractDeps({ self: { phase: "red" }, auth: { token: { $exists: true } } }); | ||
| * // → Set { "self.phase", "auth.token" } | ||
| * ``` | ||
| */ | ||
| declare function extractDeps(spec: unknown, prefix?: string): Set<string>; | ||
| /** | ||
| * Interpolate a {@link FactTemplate} against a scope. Single-pass character | ||
| * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal | ||
| * `${`; unknown keys dev-warn and yield an empty string. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateTemplate({ $template: "Hi ${name}!" }, { name: "Ada" }); | ||
| * // → "Hi Ada!" | ||
| * evaluateTemplate({ $template: "$${price}" }, {}); | ||
| * // → "${price}" | ||
| * ``` | ||
| */ | ||
| declare function evaluateTemplate(spec: FactTemplate, scope: Scope): string; | ||
| /** | ||
| * Collect the placeholder keys referenced by a template. The static-analysis | ||
| * counterpart to {@link extractDeps} — useful for devtools, codegen, and | ||
| * "which facts does this template read" inspections. Only valid identifier | ||
| * placeholders are collected; malformed ones are ignored. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractTemplateKeys({ $template: "${firstName} ${lastName}" }); | ||
| * // → Set { "firstName", "lastName" } | ||
| * extractTemplateKeys({ $template: "$${literal}" }); | ||
| * // → Set {} (escaped — not a placeholder) | ||
| * ``` | ||
| */ | ||
| declare function extractTemplateKeys(spec: FactTemplate): Set<string>; | ||
| /** | ||
| * Build a stable dedup key by selecting fields from a requirement payload. | ||
| * Order-as-declared; values are stable-stringified (keys sorted recursively) | ||
| * so two payloads with the same fields in different orders dedupe to the | ||
| * same key. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateKeySelector(["url", "method"], { url: "/a", method: "GET" }); | ||
| * // → '"/a"|"GET"' | ||
| * evaluateKeySelector(["id"], { id: 42 }); | ||
| * // → '42' | ||
| * ``` | ||
| */ | ||
| declare function evaluateKeySelector(selector: readonly string[], source: Record<string, unknown>): string; | ||
| /** | ||
| * Apply a {@link PatchSpec} — assign facts from literals, payload copies | ||
| * (`$ref`), or interpolated strings (`$template`). Mutates through the passed | ||
| * `facts` proxy so change-tracking and downstream invalidation fire. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spec = { | ||
| * $set: { | ||
| * active: true, | ||
| * userId: { $ref: "id" }, | ||
| * label: { $template: "user ${name}" }, | ||
| * }, | ||
| * }; | ||
| * applyPatch(spec, facts, { id: "u_1", name: "Ada" }); | ||
| * // facts.active = true; facts.userId = "u_1"; facts.label = "user Ada" | ||
| * ``` | ||
| */ | ||
| declare function applyPatch(spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>, facts: Record<string, unknown>, payload: Record<string, unknown>): void; | ||
| export { type TypedResolver as A, createConstraintFactory as B, createResolverFactory as C, type DerivationDefWithMeta as D, dangerousRegex as E, type SchemaKindNode as S, type TypedConstraint as T, type DerivationDef as a, type DerivationsDef as b, type SchemaKind as c, type SchemaValidationError as d, type SchemaValidationOptions as e, type SchemaValidationResult as f, applyPatch as g, evaluateKeySelector as h, evaluatePredicate as i, evaluatePredicateExplained as j, evaluateTemplate as k, extractDeps as l, extractTemplateKeys as m, getKind as n, getOperatorsForKind as o, getSchemaFieldKinds as p, isPredicate as q, isTemplate as r, listAllPredicateOperators as s, memoizePredicate as t, typedConstraint as u, typedResolver as v, validatePredicate as w, validatePredicateAgainstSchema as x, type DerivedValues as y, type DerivationState as z }; |
| import { ah as Schema, a as Facts, F as FactPredicate, b4 as InferSchema, L as FactTemplate, D as DefinitionMeta, r as Requirement, bl as RequirementOutput, ag as RetryPolicy, B as BatchConfig, be as ResolverContext, ad as PredicateOp, a6 as PatchSpec, C as ClauseResult } from './plugins-5Supk7it.cjs'; | ||
| /** | ||
| * Derivation Types - Type definitions for derivations | ||
| */ | ||
| /** Derivation definition function signature. */ | ||
| interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| (facts: Facts<S>, derived: DerivedValues<S, D>): T; | ||
| } | ||
| /** | ||
| * Derivation definition with metadata (object form). | ||
| * Use this when you want to attach debugging metadata to a derivation. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * derive: { | ||
| * displayName: { | ||
| * compute: (facts) => `${facts.firstName} ${facts.lastName}`, | ||
| * meta: { label: "Display Name", description: "Full name for UI" }, | ||
| * }, | ||
| * }, | ||
| * ``` | ||
| */ | ||
| interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| /** | ||
| * The derivation body. Either: | ||
| * - a function `(facts, derived) => T` (original form), or | ||
| * - a {@link FactPredicate} data spec — boolean derivations only, or | ||
| * - a {@link FactTemplate} `{ $template: "..." }` — string derivations only. | ||
| * | ||
| * Data forms are normalized to a wrapper function at registration; the | ||
| * wrapper reads through the facts proxy so existing auto-tracking | ||
| * captures dependencies. | ||
| */ | ||
| compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never); | ||
| meta?: DefinitionMeta; | ||
| } | ||
| /** Map of derivation definitions (internal — always bare functions after unwrap). */ | ||
| type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>; | ||
| /** Computed derived values. */ | ||
| type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = { | ||
| readonly [K in keyof D]: ReturnType<D[K]>; | ||
| }; | ||
| /** Internal derivation state */ | ||
| interface DerivationState<T> { | ||
| id: string; | ||
| compute: () => T; | ||
| cachedValue: T | undefined; | ||
| dependencies: Set<string>; | ||
| isStale: boolean; | ||
| isComputing: boolean; | ||
| /** Consecutive runs producing the same deps (auto-tracked only) */ | ||
| stableRunCount: number; | ||
| /** Once true, skip withTracking() overhead until a tracked fact mutates */ | ||
| depsStable: boolean; | ||
| } | ||
| /** | ||
| * Type Helpers - External typed constraint and resolver definitions | ||
| * | ||
| * These types enable defining constraints and resolvers with full type safety | ||
| * outside of module definitions, while maintaining proper type inference. | ||
| */ | ||
| /** | ||
| * External constraint definition with full typing. | ||
| * Use this when defining constraints outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed constraint factory | ||
| * const createMaxCountConstraint = <S extends Schema>( | ||
| * maxCount: number | ||
| * ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({ | ||
| * priority: 10, | ||
| * when: (facts) => (facts as { count: number }).count > maxCount, | ||
| * require: { type: "RESET_COUNT" }, | ||
| * }); | ||
| * | ||
| * // Use in module | ||
| * const module = createModule("counter", { | ||
| * schema: { count: t.number() }, | ||
| * constraints: { | ||
| * maxCount: createMaxCountConstraint(100), | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> { | ||
| /** Priority for ordering (higher runs first) */ | ||
| priority?: number; | ||
| /** Mark this constraint as async (avoids runtime detection) */ | ||
| async?: boolean; | ||
| /** Condition function (sync or async) */ | ||
| when: (facts: Facts<S>) => boolean | Promise<boolean>; | ||
| /** | ||
| * Requirement(s) to produce when condition is met. | ||
| */ | ||
| require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>); | ||
| /** Timeout for async constraints (ms) */ | ||
| timeout?: number; | ||
| /** | ||
| * Constraint IDs whose resolvers must complete before this constraint is evaluated. | ||
| * - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for) | ||
| * - If dependency's resolver fails, this constraint remains blocked until it succeeds | ||
| * - Cross-module: use the constraint ID as it appears in the merged system | ||
| */ | ||
| after?: string[]; | ||
| } | ||
| /** | ||
| * External resolver definition with full typing. | ||
| * Use this when defining resolvers outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed resolver factory | ||
| * interface FetchUserReq extends Requirement { | ||
| * type: "FETCH_USER"; | ||
| * userId: string; | ||
| * } | ||
| * | ||
| * const createFetchUserResolver = <S extends Schema>( | ||
| * fetchFn: (userId: string) => Promise<User> | ||
| * ): TypedResolver<S, FetchUserReq> => ({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * key: (req) => `fetch-user-${req.userId}`, | ||
| * retry: { attempts: 3, backoff: "exponential" }, | ||
| * resolve: async (req, ctx) => { | ||
| * const user = await fetchFn(req.userId); | ||
| * (ctx.facts as { user: User }).user = user; | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedResolver<S extends Schema, R extends Requirement = Requirement> { | ||
| /** | ||
| * Requirement type to handle. | ||
| * - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`) | ||
| * - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`) | ||
| */ | ||
| requirement: R["type"] | ((req: Requirement) => req is R); | ||
| /** Custom key function for deduplication */ | ||
| key?: (req: R) => string; | ||
| /** Retry policy */ | ||
| retry?: RetryPolicy; | ||
| /** Timeout for resolver execution (ms) */ | ||
| timeout?: number; | ||
| /** Batch configuration */ | ||
| batch?: BatchConfig; | ||
| /** Resolve function for single requirement */ | ||
| resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>; | ||
| /** Resolve function for batched requirements */ | ||
| resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>; | ||
| } | ||
| /** | ||
| * Create a typed constraint factory for a specific schema. | ||
| * This enables creating reusable constraint definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { count: t.number(), threshold: t.number() }; | ||
| * const factory = createConstraintFactory<typeof schema>(); | ||
| * | ||
| * const maxCountConstraint = factory.create({ | ||
| * when: (facts) => facts.count > facts.threshold, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createConstraintFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed constraint | ||
| */ | ||
| create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| }; | ||
| /** | ||
| * Create a typed resolver factory for a specific schema. | ||
| * This enables creating reusable resolver definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { user: t.object<User>() }; | ||
| * const factory = createResolverFactory<typeof schema>(); | ||
| * | ||
| * const fetchUserResolver = factory.create<FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createResolverFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed resolver | ||
| */ | ||
| create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| }; | ||
| /** | ||
| * Type-safe constraint creator. | ||
| * Simpler alternative to createConstraintFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const constraint = typedConstraint<typeof schema, { type: "RESET" }>({ | ||
| * when: (facts) => facts.count > 100, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| /** | ||
| * Type-safe resolver creator. | ||
| * Simpler alternative to createResolverFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const resolver = typedResolver<typeof schema, FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| /** | ||
| * Schema Introspection | ||
| * | ||
| * A runtime discriminant for every `t.*()` builder result, so downstream | ||
| * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`) | ||
| * can ask "what kind is this fact?" without grepping the source. | ||
| * | ||
| * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`. | ||
| * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.) | ||
| * preserve / decorate it. When `_kind` is absent (legacy or third-party | ||
| * builder), the parser falls back to reading the freeform `_typeName` | ||
| * string. When even that fails: `{ kind: "unknown" }` — graceful close. | ||
| * | ||
| * This module has zero hot-path cost; it is only invoked when an | ||
| * introspecting caller asks for it. | ||
| */ | ||
| /** | ||
| * The closed set of kinds a Directive schema field can be. | ||
| * | ||
| * Drives operator availability via {@link getOperatorsForKind}: e.g. | ||
| * `"number"` gets the orderable operators (`$gte`, `$lte`); `"boolean"` | ||
| * does not. | ||
| */ | ||
| type SchemaKind = "number" | "string" | "boolean" | "bigint" | "date" | "array" | "object" | "record" | "tuple" | "enum" | "literal" | "union" | "branded" | "unknown"; | ||
| /** | ||
| * A tree-shaped discriminator for a schema field. Composite kinds | ||
| * (array, object, tuple, etc.) carry their element / shape information | ||
| * so an LLM-prompt builder can show "cartTotal is a number" AND | ||
| * "items is an array of { sku: string, qty: number }". | ||
| * | ||
| * `nullable` / `hasDefault` flags appear on the inner node (NOT a | ||
| * wrapping kind) so operator-lookup on `t.number().nullable()` returns | ||
| * the number's operators unchanged — `$gte` works on the non-null arm. | ||
| */ | ||
| type SchemaKindNode = ({ | ||
| kind: "number" | "string" | "boolean" | "bigint" | "date" | "unknown"; | ||
| } | { | ||
| kind: "literal"; | ||
| value: string | number | boolean | null; | ||
| primitive: "string" | "number" | "boolean" | "null"; | ||
| } | { | ||
| kind: "enum"; | ||
| values: readonly (string | number)[]; | ||
| primitive: "string" | "number"; | ||
| } | { | ||
| kind: "array"; | ||
| element: SchemaKindNode; | ||
| } | { | ||
| kind: "tuple"; | ||
| elements: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "object"; | ||
| shape: Record<string, SchemaKindNode>; | ||
| } | { | ||
| kind: "record"; | ||
| value: SchemaKindNode; | ||
| } | { | ||
| kind: "union"; | ||
| members: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "branded"; | ||
| inner: SchemaKindNode; | ||
| }) & { | ||
| /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */ | ||
| nullable?: boolean; | ||
| /** True if the schema has a `.default()`. */ | ||
| hasDefault?: boolean; | ||
| }; | ||
| /** | ||
| * Return the {@link SchemaKindNode} for a schema field. Prefers the | ||
| * explicit `_kind` discriminant set by the builder; falls back to | ||
| * parsing the freeform `_typeName` string for legacy / third-party | ||
| * builders that don't set `_kind`. | ||
| * | ||
| * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder | ||
| * that throws on property access returns `{ kind: "unknown" }` instead of | ||
| * propagating the throw to introspecting callers. | ||
| * | ||
| * In dev mode, a function input (`typeof schema === "function"`) emits a | ||
| * warning — common foot-gun where the caller forgot to invoke a builder | ||
| * factory (e.g. wrote `t.number` instead of `t.number()`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * getKind(t.number()) // → { kind: "number" } | ||
| * getKind(t.string().nullable()) // → { kind: "string", nullable: true } | ||
| * getKind(t.array(t.number())) // → { kind: "array", element: { kind: "number" } } | ||
| * ``` | ||
| */ | ||
| declare function getKind(schema: unknown): SchemaKindNode; | ||
| /** | ||
| * Walk the `facts` block of a module schema and emit a flat map from | ||
| * dotted path → kind node. Nested `t.object()` shapes flatten using | ||
| * `.` as the separator, matching the convention used by | ||
| * `OperatorObject<V>`'s nested-path support. | ||
| * | ||
| * Passing a top-level schema directly (without the `facts:` wrapper) | ||
| * also works — anything iterable as `Record<string, ExtendedSchemaType>` | ||
| * is acceptable. | ||
| * | ||
| * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is | ||
| * silently skipped (treated as `{ kind: "unknown" }` for that field) | ||
| * rather than aborting the whole walk. | ||
| * | ||
| * In dev mode, a top-level schema that yields an empty map (no | ||
| * introspectable keys) emits a warning — common foot-gun where the | ||
| * caller passed `myModule` instead of `myModule.schema`. | ||
| */ | ||
| declare function getSchemaFieldKinds(schema: unknown): Map<string, SchemaKindNode>; | ||
| /** | ||
| * Return the set of `PredicateOp` strings that are valid against a | ||
| * given {@link SchemaKindNode}. | ||
| * | ||
| * Mirrors the type-level matrix encoded in `OperatorObject<V>` in | ||
| * `types/predicate.ts` — drift between the two is enforced by the | ||
| * compile-time conformance test | ||
| * (`schema-introspection-conformance.test-d.ts`). | ||
| * | ||
| * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists` | ||
| * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`, | ||
| * `$lt`, `$lte`, `$between` | ||
| * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains` | ||
| * - **Array:** + `$contains` (over the element type) | ||
| * - **Union:** *intersection* across members (the operand must be valid | ||
| * for every branch). | ||
| * - **Branded:** delegates to the inner kind. | ||
| * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in` | ||
| * operand restricted at the LLM-prompt layer (not enforced here). | ||
| * | ||
| * `nullable` does not change operator availability — `$gte` on a | ||
| * nullable number is fine on the non-null arm; `$exists` handles null. | ||
| */ | ||
| declare function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[]; | ||
| /** | ||
| * Return all known predicate operators — convenience for prompt builders | ||
| * that need to show the LLM the full set. | ||
| */ | ||
| declare function listAllPredicateOperators(): readonly PredicateOp[]; | ||
| /** | ||
| * Runtime for data-configuration predicates and templates. | ||
| * | ||
| * Pure module — imports only its own types. Reads facts through whatever | ||
| * object it is handed (the reactive `Facts` proxy in production, a plain | ||
| * snapshot in tests), so it never depends on the engine, store, or tracking. | ||
| */ | ||
| /** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */ | ||
| type Scope = Record<string, unknown>; | ||
| /** | ||
| * True when `v` is a data-form spec (predicate object/array) rather than a | ||
| * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.) | ||
| * — only plain `{}` literals and arrays of plain clause shapes qualify. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isPredicate({ phase: "red" }); // true | ||
| * isPredicate((f) => f.phase === "red"); // false | ||
| * isPredicate([{ fact: "phase", op: "$eq", value: "red" }]); // true | ||
| * ``` | ||
| */ | ||
| declare function isPredicate(v: unknown): boolean; | ||
| /** | ||
| * True when `v` is a {@link FactTemplate} (`{ $template: string }`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isTemplate({ $template: "Hi ${name}" }); // true | ||
| * isTemplate({ $set: { name: "x" } }); // false | ||
| * ``` | ||
| */ | ||
| declare function isTemplate(v: unknown): v is FactTemplate; | ||
| /** | ||
| * Throw when a predicate spec contains an operand that cannot survive a | ||
| * JSON round-trip — i.e. that would silently mis-evaluate if the spec was | ||
| * loaded from `JSON.parse`. | ||
| * | ||
| * Three failure classes are detected: | ||
| * | ||
| * - **Lost `RegExp` operand.** A `$matches` operand that is not a | ||
| * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as | ||
| * `{}`, so a `$matches` clause with an empty-object operand is the | ||
| * signature of a regex that did not survive serialization. Reify it | ||
| * with `new RegExp(pattern, flags)` before installing the predicate. | ||
| * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a | ||
| * `bigint` operand cannot have been produced by a JSON pipeline and | ||
| * cannot be persisted by one either. | ||
| * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all | ||
| * members; a predicate carrying one is not JSON-safe. | ||
| * | ||
| * This is an opt-in helper — the engine does not call it automatically. | ||
| * Users who load predicates from JSON should call it after `JSON.parse` | ||
| * to fail loud rather than silently mis-evaluate. See the | ||
| * "Serialization" section of RFC-0004. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * validatePredicate({ phase: { $matches: {} } }); | ||
| * // throws — empty object where a RegExp is required | ||
| * | ||
| * validatePredicate({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // ok — JSON-clean operands | ||
| * ``` | ||
| */ | ||
| declare function validatePredicate(spec: unknown, path?: string): void; | ||
| interface SchemaValidationError { | ||
| /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */ | ||
| readonly path: string; | ||
| /** The operator that failed (or the literal-equality marker `$eq`). */ | ||
| readonly op: string; | ||
| /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */ | ||
| readonly kind?: SchemaKindNode; | ||
| /** The operators that ARE allowed for this fact's kind. */ | ||
| readonly allowedOps?: readonly string[]; | ||
| /** Human-readable failure reason (suitable for feeding back to an LLM). */ | ||
| readonly reason: string; | ||
| } | ||
| interface SchemaValidationOptions { | ||
| /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */ | ||
| readonly maxOperatorCount?: number; | ||
| /** | ||
| * Reject `$in` / `$nin` operands that contain more than this many elements | ||
| * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000 | ||
| * — beyond that, a downstream query compiler may degrade quadratically. | ||
| */ | ||
| readonly maxArrayOperandLength?: number; | ||
| } | ||
| /** | ||
| * Heuristic: flag a regex source string that has obvious nested quantifiers | ||
| * (e.g. `(.+)+`, `(.*)*`, `(\w+)+`, `(a|a)+`) — the classic ReDoS shapes. | ||
| * Not a full ReDoS prover; intentionally conservative so a string-rehydrated | ||
| * `$matches` operand can be rejected before it ever reaches `RegExp.test`. | ||
| * | ||
| * Callers MUST NOT treat a `false` result as "safe" — a determined adversary | ||
| * can craft patterns this heuristic misses. The right answer for untrusted | ||
| * regex is "don't accept untrusted regex"; this helper exists to catch the | ||
| * obvious foot-guns. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * dangerousRegex("(a+)+"); // → true | ||
| * dangerousRegex("(.*)*"); // → true | ||
| * dangerousRegex("(\\w+)+"); // → true | ||
| * dangerousRegex("^[a-z]+$"); // → false | ||
| * ``` | ||
| */ | ||
| declare function dangerousRegex(source: string): boolean; | ||
| type SchemaValidationResult = { | ||
| ok: true; | ||
| operatorCount: number; | ||
| } | { | ||
| ok: false; | ||
| errors: readonly SchemaValidationError[]; | ||
| operatorCount: number; | ||
| }; | ||
| /** | ||
| * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate | ||
| * against a schema's runtime kind map. Catches errors that | ||
| * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a | ||
| * boolean fact), unknown fact paths, and (optionally) operator-count | ||
| * exhaustion DoS attempts. | ||
| * | ||
| * Pair with {@link validatePredicate} (structural / JSON safety) for full | ||
| * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a | ||
| * module schema. | ||
| * | ||
| * Designed for the LLM-emit retry loop: returns a list of errors with | ||
| * structured `{path, op, kind, allowedOps, reason}` rather than throwing, | ||
| * so the caller can feed the errors back to the model. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } }); | ||
| * const result = validatePredicateAgainstSchema( | ||
| * { cartTotal: { $gte: 50 }, active: { $gte: true } }, | ||
| * kindMap, | ||
| * ); | ||
| * // → { ok: false, errors: [{ path: "active", op: "$gte", reason: "..." }], operatorCount: 2 } | ||
| * ``` | ||
| */ | ||
| declare function validatePredicateAgainstSchema(spec: unknown, kindMap: Map<string, SchemaKindNode>, opts?: SchemaValidationOptions): SchemaValidationResult; | ||
| /** | ||
| * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous | ||
| * snapshot) is consulted only by the `$changed` operator. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicate({ phase: "red", elapsed: { $gte: 30 } }, { phase: "red", elapsed: 45 }); | ||
| * // → true | ||
| * evaluatePredicate({ $any: [{ phase: "red" }, { phase: "yellow" }] }, { phase: "green" }); | ||
| * // → false | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicate(spec: unknown, facts: Scope, prev?: Scope, depth?: number): boolean; | ||
| /** | ||
| * Evaluate a predicate and return a per-clause breakdown — the data feed for | ||
| * devtools, `system.explain()`, and `directive explain`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicateExplained( | ||
| * { phase: "red", elapsed: { $gte: 30 } }, | ||
| * { phase: "red", elapsed: 20 }, | ||
| * ); | ||
| * // → [ | ||
| * // { path: "phase", op: "$eq", expected: "red", actual: "red", pass: true }, | ||
| * // { path: "elapsed", op: "$gte", expected: 30, actual: 20, pass: false }, | ||
| * // ] | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicateExplained(spec: unknown, facts: Scope, prev?: Scope, pathPrefix?: string): ClauseResult[]; | ||
| /** | ||
| * Memoize a predicate as a reusable evaluation closure. | ||
| * | ||
| * The returned function accepts any `facts` scope (the reactive proxy in | ||
| * production, a plain object in tests) plus an optional `prev` snapshot for | ||
| * `$changed`. The closure is cached **by predicate identity** in a | ||
| * `WeakMap`, so passing the same `predicate` reference repeatedly is | ||
| * allocation-free; cleanup is automatic once the predicate is no longer | ||
| * reachable. | ||
| * | ||
| * Note: no actual compilation happens — the returned closure re-walks the | ||
| * spec on every call via `evaluatePredicate`. The name reflects what the | ||
| * function does (closure memoization keyed by predicate identity), not a | ||
| * bytecode/AST compile step. | ||
| * | ||
| * Intended for advanced users who want a stable function reference per | ||
| * predicate (custom devtools, batched analyses). Regular module code does | ||
| * not need to call this — the engine wraps data-form `when` / `on` specs | ||
| * automatically at registration. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const predicate = { phase: "red", elapsed: { $gte: 30 } }; | ||
| * const check = memoizePredicate(predicate); | ||
| * check({ phase: "red", elapsed: 45 }); // → true | ||
| * check({ phase: "red", elapsed: 5 }); // → false | ||
| * ``` | ||
| */ | ||
| declare function memoizePredicate(predicate: object): (facts: Scope, prev?: Scope) => boolean; | ||
| /** | ||
| * Collect the fact keys a predicate references. Used for static analysis, | ||
| * devtools, and effect `on` dependency wiring. Nested predicates contribute | ||
| * dotted keys (`auth.token`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractDeps({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // → Set { "phase", "elapsed" } | ||
| * extractDeps({ self: { phase: "red" }, auth: { token: { $exists: true } } }); | ||
| * // → Set { "self.phase", "auth.token" } | ||
| * ``` | ||
| */ | ||
| declare function extractDeps(spec: unknown, prefix?: string): Set<string>; | ||
| /** | ||
| * Interpolate a {@link FactTemplate} against a scope. Single-pass character | ||
| * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal | ||
| * `${`; unknown keys dev-warn and yield an empty string. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateTemplate({ $template: "Hi ${name}!" }, { name: "Ada" }); | ||
| * // → "Hi Ada!" | ||
| * evaluateTemplate({ $template: "$${price}" }, {}); | ||
| * // → "${price}" | ||
| * ``` | ||
| */ | ||
| declare function evaluateTemplate(spec: FactTemplate, scope: Scope): string; | ||
| /** | ||
| * Collect the placeholder keys referenced by a template. The static-analysis | ||
| * counterpart to {@link extractDeps} — useful for devtools, codegen, and | ||
| * "which facts does this template read" inspections. Only valid identifier | ||
| * placeholders are collected; malformed ones are ignored. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractTemplateKeys({ $template: "${firstName} ${lastName}" }); | ||
| * // → Set { "firstName", "lastName" } | ||
| * extractTemplateKeys({ $template: "$${literal}" }); | ||
| * // → Set {} (escaped — not a placeholder) | ||
| * ``` | ||
| */ | ||
| declare function extractTemplateKeys(spec: FactTemplate): Set<string>; | ||
| /** | ||
| * Build a stable dedup key by selecting fields from a requirement payload. | ||
| * Order-as-declared; values are stable-stringified (keys sorted recursively) | ||
| * so two payloads with the same fields in different orders dedupe to the | ||
| * same key. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateKeySelector(["url", "method"], { url: "/a", method: "GET" }); | ||
| * // → '"/a"|"GET"' | ||
| * evaluateKeySelector(["id"], { id: 42 }); | ||
| * // → '42' | ||
| * ``` | ||
| */ | ||
| declare function evaluateKeySelector(selector: readonly string[], source: Record<string, unknown>): string; | ||
| /** | ||
| * Apply a {@link PatchSpec} — assign facts from literals, payload copies | ||
| * (`$ref`), or interpolated strings (`$template`). Mutates through the passed | ||
| * `facts` proxy so change-tracking and downstream invalidation fire. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spec = { | ||
| * $set: { | ||
| * active: true, | ||
| * userId: { $ref: "id" }, | ||
| * label: { $template: "user ${name}" }, | ||
| * }, | ||
| * }; | ||
| * applyPatch(spec, facts, { id: "u_1", name: "Ada" }); | ||
| * // facts.active = true; facts.userId = "u_1"; facts.label = "user Ada" | ||
| * ``` | ||
| */ | ||
| declare function applyPatch(spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>, facts: Record<string, unknown>, payload: Record<string, unknown>): void; | ||
| export { type TypedResolver as A, createConstraintFactory as B, createResolverFactory as C, type DerivationDefWithMeta as D, dangerousRegex as E, type SchemaKindNode as S, type TypedConstraint as T, type DerivationDef as a, type DerivationsDef as b, type SchemaKind as c, type SchemaValidationError as d, type SchemaValidationOptions as e, type SchemaValidationResult as f, applyPatch as g, evaluateKeySelector as h, evaluatePredicate as i, evaluatePredicateExplained as j, evaluateTemplate as k, extractDeps as l, extractTemplateKeys as m, getKind as n, getOperatorsForKind as o, getSchemaFieldKinds as p, isPredicate as q, isTemplate as r, listAllPredicateOperators as s, memoizePredicate as t, typedConstraint as u, typedResolver as v, validatePredicate as w, validatePredicateAgainstSchema as x, type DerivedValues as y, type DerivationState as z }; |
| 'use strict';var chunkOAPD3HIG_cjs=require('./chunk-OAPD3HIG.cjs');require('./chunk-QTY2FXZY.cjs'),require('./chunk-GACC2DMS.cjs'),require('./chunk-GKMJ7NMP.cjs'),require('./chunk-GBCWXTXW.cjs');Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunkOAPD3HIG_cjs.a}});//# sourceMappingURL=system-5FKUBLLV.cjs.map | ||
| //# sourceMappingURL=system-5FKUBLLV.cjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"system-5FKUBLLV.cjs"} |
| export{a as createSystem}from'./chunk-YJEDX2JX.js';import'./chunk-6NCC6RBC.js';import'./chunk-RBF653NR.js';import'./chunk-6PF2FRBG.js';import'./chunk-SFUVPP4L.js';//# sourceMappingURL=system-6YWCXQOQ.js.map | ||
| //# sourceMappingURL=system-6YWCXQOQ.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"system-6YWCXQOQ.js"} |
@@ -1,2 +0,2 @@ | ||
| import { r as Requirement, P as Plugin, a as Facts, ah as Schema, Q as HistoryAPI, at as SystemInspection, V as HistoryState } from './plugins-4IfhJV32.cjs'; | ||
| import { r as Requirement, P as Plugin, a as Facts, ah as Schema, Q as HistoryAPI, at as SystemInspection, V as HistoryState } from './plugins-5Supk7it.cjs'; | ||
| export { s as shallowEqual } from './utils-DY8KTiD6.cjs'; | ||
@@ -3,0 +3,0 @@ |
@@ -1,2 +0,2 @@ | ||
| import { r as Requirement, P as Plugin, a as Facts, ah as Schema, Q as HistoryAPI, at as SystemInspection, V as HistoryState } from './plugins-4IfhJV32.js'; | ||
| import { r as Requirement, P as Plugin, a as Facts, ah as Schema, Q as HistoryAPI, at as SystemInspection, V as HistoryState } from './plugins-5Supk7it.js'; | ||
| export { s as shallowEqual } from './utils-DY8KTiD6.js'; | ||
@@ -3,0 +3,0 @@ |
+2
-2
@@ -1,5 +0,5 @@ | ||
| 'use strict';var chunkMARZI3EY_cjs=require('./chunk-MARZI3EY.cjs'),chunk4OXCKDKS_cjs=require('./chunk-4OXCKDKS.cjs'),chunkM5PEB553_cjs=require('./chunk-M5PEB553.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');var A=1e6;function Me(e,t){try{chunkGACC2DMS_cjs.l(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!chunkGACC2DMS_cjs.h(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(chunkGACC2DMS_cjs.i(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!chunkGACC2DMS_cjs.a.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!chunkGACC2DMS_cjs.a.has(r)&&!chunkGACC2DMS_cjs.b.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}function Re(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Ce(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>A)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,s={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(s.timestamp=i.timestamp),s}return {id:`#${r}`,facts:n??{}}})}function Ce(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return se(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return se(n.snapshots)}function se(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>A)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return Re(e)}function H(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,s=e.maxSamples??20,o=s>0?s:0;if(t.length>A)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);Me(n,"original"),Me(r,"proposed");let u=0,a=0,c=0,l=0,d=0,g=[],y=[],$=i?new Set:void 0,m=i?new Set:void 0,M;for(let F of t){let T=F.facts,v=chunkGACC2DMS_cjs.o(n,T,M),R=chunkGACC2DMS_cjs.o(r,T,M);v&&(u++,$?.add(T[i])),R&&(a++,m?.add(T[i])),v===R?d++:!v&&R?(c++,g.length<o&&g.push(De(F,n,r,M))):(l++,y.length<o&&y.push(De(F,n,r,M))),M=T;}let E={framesEvaluated:t.length,original:{matched:u},proposed:{matched:a},delta:a-u,newMatchCount:c,lostMatchCount:l,unchanged:d,newMatches:g,lostMatches:y};return $&&m&&(E.original.matchedEntities=$.size,E.proposed.matchedEntities=m.size),E}function De(e,t,n,r){let i=e.facts,s={frameId:e.id,facts:i,originalExplain:chunkGACC2DMS_cjs.p(t,i,r),proposedExplain:chunkGACC2DMS_cjs.p(n,i,r)};return e.timestamp!==void 0&&(s.timestamp=e.timestamp),s}var ae=1e4,Ae=5e7;function It(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function ue(e,t,n=new Set,r=0){if(r>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${chunkGACC2DMS_cjs.g}) \u2014 flatten the template or split the sweep`);if(It(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(s=>ue(s,t,n,r+1));let i={};for(let[s,o]of Object.entries(e))i[s]=ue(o,t,n,r+1);return i}finally{n.delete(e);}}function*Ee(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let s of i)for(let o of Ee(r,t))yield {[n]:s,...o};}function Lt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function qt(e){let{frames:t,original:n,template:r,sweep:i,objective:s=T=>T.proposed.matched,entityKey:o,maxSamples:u=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let c=Lt(i);if(c>ae)throw new Error(`[Directive] sweepUnder: grid has ${c} points, exceeds the MAX_SWEEP_POINTS limit (${ae}) \u2014 narrow the sweep ranges or split the run`);if(c===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=c*t.length;if(l>Ae)throw new Error(`[Directive] sweepUnder: ${c} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Ae}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,g=T=>{let v;try{v=s(T);}catch(R){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${R.message})`)),Number.NEGATIVE_INFINITY}return typeof v!="number"||!Number.isFinite(v)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(v)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):v},y=H({frames:t,original:n,proposed:n,entityKey:o,maxSamples:u}),$={values:{},report:y,score:g(y)},m=[],M=0,E=Number.NEGATIVE_INFINITY;for(let T of Ee(a,i)){let v=ue(r,T),R=H({frames:t,original:n,proposed:v,entityKey:o,maxSamples:u}),te=g(R);te>E&&(E=te,M=m.length),m.push({values:T,report:R,score:te});}let F=m[M];return {points:m,bestIndex:M,best:F,baseline:$}}function ce(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var Wt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Bt=new Set(["$all","$any","$not"]);function xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ut(e){if(!xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;Wt.has(r)&&(n=true);}return n}function S(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,s)=>{S(i,`${t}$all[${s}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,s)=>{S(i,`${t}$any[${s}]`,n);}),n;if("$not"in e)return S(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let s=t?`${t}.${r}`:r;if(Ut(i))for(let[o,u]of Object.entries(i))n.push({path:s,op:o,value:u});else xe(i)&&!Bt.has(r)?S(i,s,n):n.push({path:s,op:"$eq",value:i});}return n}function C(e){return typeof e=="number"&&Number.isFinite(e)}function Kt(e,t,n){switch(e){case "$gte":case "$gt":if(C(t)&&C(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(C(t)&&C(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&C(t[0])&&C(t[1])&&C(n[0])&&C(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function zt(e){let t=ce(e.before),n=ce(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),s=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let u of i){let a=t[u],c=n[u],l=u in t,d=u in n;if(l&&!d){let y=S(a),$=y.length===0?[{path:"(function-form predicate)",kind:"removed"}]:y.map(m=>({path:m.path,kind:"removed",before:{op:m.op,value:m.value}}));le($),s.push({id:u,status:"removed",changes:$}),o.removed++,o.totalClauseChanges+=$.length;continue}if(!l&&d){let y=S(c),$=y.length===0?[{path:"(function-form predicate)",kind:"added"}]:y.map(m=>({path:m.path,kind:"added",after:{op:m.op,value:m.value}}));le($),s.push({id:u,status:"added",changes:$}),o.added++,o.totalClauseChanges+=$.length;continue}let g=Oe(a,c);g.length===0?(s.push({id:u,status:"unchanged",changes:[]}),o.unchanged++):(s.push({id:u,status:"changed",changes:g}),o.changed++,o.totalClauseChanges+=g.length);}return {constraints:s,summary:o}}function Oe(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return chunkGBCWXTXW_cjs.e(e)===chunkGBCWXTXW_cjs.e(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let n=e===void 0?[]:S(e),r=t===void 0?[]:S(t),i=c=>`${c.path}::${c.op}`,s=new Map(n.map(c=>[i(c),c])),o=new Map(r.map(c=>[i(c),c])),u=new Set([...s.keys(),...o.keys()]),a=[];for(let c of u){let l=s.get(c),d=o.get(c);if(l&&!d){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(l&&d){if(chunkGBCWXTXW_cjs.e(l.value)===chunkGBCWXTXW_cjs.e(d.value))continue;let g=Kt(l.op,l.value,d.value);a.push({path:l.path,kind:g??"changed",before:{op:l.op,value:l.value},after:{op:d.op,value:d.value}});}}return le(a),a}function le(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",s=n.before?.op??n.after?.op??"";return i.localeCompare(s)});}function Ht(e){return chunkGBCWXTXW_cjs.h(e)}function J(e){return e===null?"null":e===void 0?"undefined":e instanceof Date?e.toISOString():typeof e=="string"||typeof e=="object"?JSON.stringify(e):String(e)}function Jt(e){let t=e.path,n=J(e.expected),r=J(e.actual);switch(e.op){case "$eq":return `set ${t} to ${n} (currently ${r})`;case "$ne":return `change ${t} to anything other than ${n} (currently ${r})`;case "$gt":return `set ${t} above ${n} (currently ${r})`;case "$gte":return `set ${t} to at least ${n} (currently ${r})`;case "$lt":return `set ${t} below ${n} (currently ${r})`;case "$lte":return `set ${t} to at most ${n} (currently ${r})`;case "$in":return `set ${t} to one of ${n} (currently ${r})`;case "$nin":return `set ${t} to something other than ${n} (currently ${r})`;case "$exists":return e.expected===true?`set ${t} to a non-null value (currently null/missing)`:`unset ${t} (currently ${r})`;case "$between":return Array.isArray(e.expected)&&e.expected.length===2?`set ${t} between ${J(e.expected[0])} and ${J(e.expected[1])} (currently ${r})`:`set ${t} within range ${n} (currently ${r})`;case "$startsWith":return `set ${t} to start with ${n} (currently ${r})`;case "$endsWith":return `set ${t} to end with ${n} (currently ${r})`;case "$contains":return `set ${t} to contain ${n} (currently ${r})`;case "$matches":return `set ${t} to match the pattern ${n} (currently ${r})`;case "$changed":return `the previous-vs-current change of ${t} is required to differ (currently they match: ${r})`;case "$all":case "$any":case "$not":return `the ${e.op} group at "${t}" did not pass \u2014 see its child clauses`;default:return `clause at ${t} (${e.op}) failed: expected ${n}, got ${r}`}}function je(e,t){for(let n of e)if(!n.pass){if((n.op==="$all"||n.op==="$any"||n.op==="$not")&&n.children){je(n.children,t);continue}t.push({path:n.path,op:n.op,expected:n.expected,actual:n.actual,suggestion:Jt(n)});}}function Qt(e,t,n){let r=chunkGACC2DMS_cjs.p(e,t,n),i=r.every(o=>o.pass),s=[];if(i||je(r,s),!i&&n===void 0){let o=[];chunkGACC2DMS_cjs.i(e,{operator(u,a){a==="$changed"&&o.push(u);}});for(let u of o)s.push({path:u,op:"$changed",expected:true,actual:void 0,suggestion:`$changed clause at "${u}" cannot be evaluated without a \`prev\` snapshot \u2014 pass predict(predicate, facts, prev).`});}return {wouldFire:i,whenExplain:r,missingChanges:s}}var Pe=new Set(["$eq","$ne","$gt","$gte","$lt","$lte","$in","$nin"]);function Q(e,t){if(e===t)return 0;if(typeof e=="number"&&typeof t=="number"||typeof e=="bigint"&&typeof t=="bigint")return e<t?-1:e>t?1:0;if(e instanceof Date&&t instanceof Date){let n=e.getTime(),r=t.getTime();return n<r?-1:n>r?1:0}return typeof e=="string"&&typeof t=="string"?e<t?-1:e>t?1:0:Number.NaN}function _(e,t){if(e===t)return true;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let i=0;i<e.length;i++)if(!_(e[i],t[i]))return false;return true}let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return false;for(let i of n)if(!_(e[i],t[i]))return false;return true}function Xt(e,t){if(!Pe.has(e.op)||!Pe.has(t.op))return {type:"overlap",reason:`Both rules touch "${e.path}".`};if(e.op==="$eq"&&t.op==="$eq")return _(e.value,t.value)?{type:"subset",reason:`Both rules require ${e.path} = ${JSON.stringify(e.value)} \u2014 candidate is redundant.`}:{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires ${e.path} = ${JSON.stringify(t.value)} \u2014 they cannot both fire.`};if(e.op==="$eq"&&t.op==="$ne")return _(e.value,t.value)?{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule excludes that value.`}:null;if(e.op==="$ne"&&t.op==="$eq")return _(e.value,t.value)?{type:"direct",reason:`Candidate excludes ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires that exact value.`}:null;if(e.op==="$in"&&t.op==="$in"){let o=new Set(Array.isArray(e.value)?e.value:[]),u=new Set(Array.isArray(t.value)?t.value:[]),a=[...o].filter(c=>u.has(c));return a.length===0?{type:"direct",reason:`Candidate $in set for ${e.path} (${JSON.stringify([...o])}) and existing $in set (${JSON.stringify([...u])}) have no values in common \u2014 the candidate can never fire while the existing rule holds.`}:a.length===o.size&&a.length<u.size?{type:"subset",reason:`Candidate $in set for ${e.path} is a strict subset of the existing rule's $in set.`}:null}let n=e.op==="$gt"||e.op==="$gte"?e.value:void 0,r=e.op==="$lt"||e.op==="$lte"?e.value:void 0,i=t.op==="$gt"||t.op==="$gte"?t.value:void 0,s=t.op==="$lt"||t.op==="$lte"?t.value:void 0;if(n!==void 0&&s!==void 0){let o=Q(n,s);if(!Number.isNaN(o)&&(o>0||o===0&&(e.op==="$gt"||t.op==="$lt")))return {type:"direct",reason:`Candidate requires ${e.path} ${e.op==="$gt"?">":"\u2265"} ${JSON.stringify(n)} but an existing rule caps it at ${t.op==="$lt"?"<":"\u2264"} ${JSON.stringify(s)}.`}}if(i!==void 0&&r!==void 0){let o=Q(i,r);if(!Number.isNaN(o)&&(o>0||o===0&&(t.op==="$gt"||e.op==="$lt")))return {type:"direct",reason:`Candidate caps ${e.path} at ${e.op==="$lt"?"<":"\u2264"} ${JSON.stringify(r)} but an existing rule requires it ${t.op==="$gt"?">":"\u2265"} ${JSON.stringify(i)}.`}}if(n!==void 0&&i!==void 0){let o=Q(n,i);if(!Number.isNaN(o)&&o>0)return {type:"subset",reason:`Candidate's lower bound on ${e.path} (${JSON.stringify(n)}) is stricter than the existing rule's lower bound (${JSON.stringify(i)}) \u2014 candidate is a subset.`}}if(r!==void 0&&s!==void 0){let o=Q(r,s);if(!Number.isNaN(o)&&o<0)return {type:"subset",reason:`Candidate's upper bound on ${e.path} (${JSON.stringify(r)}) is stricter than the existing rule's upper bound (${JSON.stringify(s)}) \u2014 candidate is a subset.`}}return {type:"overlap",reason:`Both rules constrain "${e.path}".`}}function Fe(e){return typeof e=="object"&&e!==null&&typeof e.id=="string"}var Zt={checkAgainst(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {contradictions:[],warnings:[]};let i=new Map;for(let u of r){let a=i.get(u.path)??[];a.push(u),i.set(u.path,a);}let s=[],o=[];for(let u of n){if(!Fe(u)||u.whenSpec===void 0)continue;let a=S(u.whenSpec);for(let c of a){let l=i.get(c.path);if(l)for(let d of l){let g=Xt(d,c);if(!g)continue;let y={constraintId:u.id,type:g.type,reason:g.reason,candidatePath:d.path,candidate:{op:d.op,value:d.value},existing:{op:c.op,value:c.value}};g.type==="overlap"||g.type==="subset"?o.push(y):s.push(y);}}}return {contradictions:s,warnings:o}},checkOwns(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {warnings:[]};let i=new Set(r.map(o=>o.path)),s=[];for(let o of n){if(!Fe(o))continue;let u=Array.isArray(o.owns)?o.owns:[],a=Array.isArray(o.bind)?o.bind:[];for(let c of u)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"owns",reason:`Constraint "${o.id}" already owns "${c}" \u2014 candidate would race or shadow its writes.`,severity:"warning"});for(let c of a)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"bind",reason:`Constraint "${o.id}" binds "${c}" \u2014 candidate would write to a bound field.`,severity:"warning"});}return {warnings:s}}};var I=new Map,Yt=50;function Gt(e){let t=I.get(e);if(!t){try{t=new Intl.NumberFormat(e);}catch{t=new Intl.NumberFormat("en-US");}if(I.size>=Yt){let n=I.keys().next().value;n!==void 0&&I.delete(n);}I.set(e,t);}return t}function Vt(e,t={}){let n=t.style??"natural",r=t.parenthesize??true,i=t.locale??"en-US",s=t.factName??(a=>a);if(e===null||typeof e!="object")return "<invalid predicate>";let o={style:n,parenthesize:r,locale:i,factName:s,seen:new WeakSet,cycle:false},u=X(e,o,0);return o.cycle?"<invalid predicate: cycle>":u}var Ie=" AND ",en=" OR ",tn="NOT",Le=" \u2227 ",nn=" \u2228 ",rn="\xAC";function q(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function on(e){if(!q(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function X(e,t,n){if(n>chunkGACC2DMS_cjs.g)return chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] describePredicate: depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 bailing.`),t.style==="formal"?"\u22A5":"always true";if(Array.isArray(e))return sn(e,t);if(!q(e))return f(e,t);if(t.seen.has(e))return t.cycle=true,"<invalid predicate: cycle>";t.seen.add(e);let r=e,i=Object.keys(r);for(let o of ["$all","$any","$not"])if(o in r)return an(o,r[o],t,n);let s=[];for(let o of i)o.startsWith("$")||s.push(qe(o,r[o],t,n));return Z(s,t)}function sn(e,t,n){let r=[];for(let i of e){if(!q(i))continue;let s=i;typeof s.fact!="string"||typeof s.op!="string"||r.push(L(s.fact,s.op,s.value,t));}return r.length===0?t.style==="formal"?"\u22A4":"always true":Z(r,t)}function an(e,t,n,r){if(e==="$not"){if(q(t)&&Object.keys(t).length===0)return n.style==="formal"?"\u22A5":"never";let o=X(t,n,r+1);return o==="always true"?"never":o==="\u22A4"?"\u22A5":`${n.style==="formal"?rn:`${tn} `}(${o})`}if(!Array.isArray(t))return n.style==="formal"?"\u22A5":"<invalid predicate>";if(t.length===0)return e==="$all"?n.style==="formal"?"\u22A4":"always true":n.style==="formal"?"\u22A5":"never";let i=[];for(let o of t){let u=X(o,n,r+1);i.push(u);}if(i.length===1)return i[0];let s=n.parenthesize?i.map(o=>`(${o})`):i;return e==="$all"?s.join(n.style==="formal"?Le:Ie):s.join(n.style==="formal"?nn:en)}function qe(e,t,n,r){if(on(t)){let i=t,s=Object.keys(i);if(s.length===1)return L(e,s[0],i[s[0]],n);let o=s.map(u=>L(e,u,i[u],n));return Z(o,n)}if(q(t)){let i=t;if("$all"in i||"$any"in i||"$not"in i)return X(t,n,r+1);let o=[];for(let u of Object.keys(i))u.startsWith("$")||o.push(qe(`${e}.${u}`,i[u],n,r+1));return o.length===0?L(e,"$eq",t,n):Z(o,n)}return L(e,"$eq",t,n)}function L(e,t,n,r){let i=r.style==="formal"?e:r.factName(e);return r.style==="formal"?cn(i,t,n,r):un(i,t,n,r)}function un(e,t,n,r){switch(t){case "$eq":return n===null?`${e} is null`:`${e} is ${f(n,r)}`;case "$ne":return n===null?`${e} is not null`:`${e} is not ${f(n,r)}`;case "$gt":return `${e} is more than ${f(n,r)}`;case "$gte":return `${e} is at least ${f(n,r)}`;case "$lt":return `${e} is less than ${f(n,r)}`;case "$lte":return `${e} is at most ${f(n,r)}`;case "$in":return `${e} is one of ${Ne(n,r)}`;case "$nin":return `${e} is not one of ${Ne(n,r)}`;case "$exists":return n===true?`${e} is set`:`${e} is not set`;case "$between":return Array.isArray(n)&&n.length===2?`${e} is between ${f(n[0],r)} and ${f(n[1],r)}`:`${e} is between ${f(n,r)}`;case "$startsWith":return `${e} starts with ${O(n,r,true)}`;case "$endsWith":return `${e} ends with ${O(n,r,true)}`;case "$contains":return `${e} contains ${O(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} matches ${n.toString()}`:`${e} matches ${f(n,r)}`;case "$changed":return `${e} changed`;default:return chunkGBCWXTXW_cjs.a&&!chunkGACC2DMS_cjs.a.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function cn(e,t,n,r){switch(t){case "$eq":return `${e} = ${f(n,r)}`;case "$ne":return `${e} \u2260 ${f(n,r)}`;case "$gt":return `${e} > ${f(n,r)}`;case "$gte":return `${e} \u2265 ${f(n,r)}`;case "$lt":return `${e} < ${f(n,r)}`;case "$lte":return `${e} \u2264 ${f(n,r)}`;case "$in":return `${e} \u2208 {${_e(n,r)}}`;case "$nin":return `${e} \u2209 {${_e(n,r)}}`;case "$exists":return n===true?`\u2203 ${e}`:`\u2204 ${e}`;case "$between":return Array.isArray(n)&&n.length===2?`${f(n[0],r)} \u2264 ${e} \u2264 ${f(n[1],r)}`:`${e} \u2208 [${f(n,r)}]`;case "$startsWith":return `${e} ^= ${O(n,r,true)}`;case "$endsWith":return `${e} $= ${O(n,r,true)}`;case "$contains":return `${e} \u2287 ${O(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} ~ ${n.toString()}`:`${e} ~ ${f(n,r)}`;case "$changed":return `\u0394${e}`;default:return chunkGBCWXTXW_cjs.a&&!chunkGACC2DMS_cjs.a.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function Y(e){return e.length===0?true:/[\s,"']/.test(e)}function O(e,t,n){return typeof e!="string"||n||Y(e)?JSON.stringify(e):e}function f(e,t){if(e===null)return "null";if(e===void 0)return "undefined";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"){if(!Number.isFinite(e))return String(e);try{return Gt(t.locale).format(e)}catch{return String(e)}}if(typeof e=="bigint")return t.style==="formal"?`${e.toString()}n`:e.toString();if(typeof e=="string")return t.style==="formal"||Y(e)?JSON.stringify(e):e;if(e instanceof Date)return e.toISOString();if(e instanceof RegExp)return e.toString();if(Array.isArray(e))return `[${e.map(n=>f(n,t)).join(", ")}]`;if(typeof e=="object")try{return JSON.stringify(e)}catch{return "[object]"}return String(e)}function Ne(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function _e(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function Z(e,t){if(e.length===0)return t.style==="formal"?"\u22A4":"always true";if(e.length===1)return e[0];let n=t.style==="formal"?Le:Ie;return t.parenthesize,e.join(n)}var ln=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function B(e,t){if(typeof e!="string"||!ln.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function We(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function dn(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)B(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(B(t,"column"),t)}function b(e,t){return e.params.push(t),e.placeholder(e.params.length)}function de(e,t,n,r){switch(t){case "$eq":return `${e} = ${b(r,n)}`;case "$ne":return `${e} <> ${b(r,n)}`;case "$gt":return `${e} > ${b(r,n)}`;case "$gte":return `${e} >= ${b(r,n)}`;case "$lt":return `${e} < ${b(r,n)}`;case "$lte":return `${e} <= ${b(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${b(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${b(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${b(r,n[0])} AND ${b(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${b(r,fe(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${b(r,fe(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${b(r,fe(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${b(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function fe(e){return e.replace(/[\\%_]/g,"\\$&")}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function fn(e){if(!Be(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function pe(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function W(e,t,n){if(n>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(s=>{if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let o=s;return B(o.fact,"column"),We(o.fact,t.allowed),de(o.fact,o.op,o.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){pe(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" AND ")})`}if("$any"in e){pe(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" OR ")})`}if("$not"in e){pe(e,"$not");let i=e.$not;return `NOT (${W(i,t,n+1)})`}let r=[];for(let[i,s]of Object.entries(e))if(B(i,"column"),We(i,t.allowed),fn(s))for(let[o,u]of Object.entries(s)){if(!chunkGACC2DMS_cjs.a.has(o))throw new Error(`[Directive] predicateToSQL: unknown operator "${o}" on column "${i}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);r.push(de(i,o,u,t));}else {if(Be(s))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(de(i,"$eq",s,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var Ue=e=>`$${e}`;function pn(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??Ue,s=t.select??"*";B(n,"table");let o=dn(s),u={params:[],placeholder:i,allowed:r},a=W(e,u,0);return {sql:`SELECT ${o} FROM ${n} WHERE ${a}`,where:a,params:u.params}}function gn(e,t={}){let n=t.placeholder??Ue,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:W(e,r,0),params:r.params}}function ge(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function he(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function yn(e){if(!he(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var hn=/^[A-Za-z_][A-Za-z0-9_]*$/,mn=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function Ke(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?mn:hn).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function ze(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function ye(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function He(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${ge(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${ge(t)}$`};case "$contains":if(typeof t=="string")return {$regex:ge(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function j(e,t,n){if(n>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let u=o;Ke(u.fact,t),ze(u.fact,t.allowedKeys);let a=He(u.op,u.value);if(u.fact in i&&he(i[u.fact])){let c=i[u.fact];Object.keys(a).some(d=>d in c)?s.push({[u.fact]:a}):i[u.fact]={...c,...a};}else u.fact in i?s.push({[u.fact]:a}):i[u.fact]=a;}if(s.length>0){let o=[];for(let[u,a]of Object.entries(i))o.push({[u]:a});return o.push(...s),{$and:o}}return i}if("$all"in e){ye(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?j(i[0],t,n+1):{$and:i.map(s=>j(s,t,n+1))}}if("$any"in e){ye(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?j(i[0],t,n+1):{$or:i.map(s=>j(s,t,n+1))}}if("$not"in e){ye(e,"$not");let i=e.$not;return {$nor:[j(i,t,n+1)]}}let r={};for(let[i,s]of Object.entries(e))if(Ke(i,t),ze(i,t.allowedKeys),yn(s)){let o={};for(let[u,a]of Object.entries(s)){if(!chunkGACC2DMS_cjs.a.has(u))throw new Error(`[Directive] predicateToMongo: unknown operator "${u}" on field "${i}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);Object.assign(o,He(u,a));}r[i]=o;}else r[i]=s;return r}function $n(e,t={}){return j(e,t,0)}var wn=/^[A-Za-z_][A-Za-z0-9_]*$/;function Je(e,t){if(typeof e!="string"||!wn.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function me(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function k(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function Qe(e){return `(${e.map(k).join(",")})`}function $e(e){return e.replace(/[\\%_*]/g,"\\$&")}function P(e,t){switch(e){case "$eq":return `eq.${k(t)}`;case "$ne":return `neq.${k(t)}`;case "$gt":return `gt.${k(t)}`;case "$gte":return `gte.${k(t)}`;case "$lt":return `lt.${k(t)}`;case "$lte":return `lte.${k(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${Qe(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${Qe(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${k(`${$e(t)}*`)}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${k(`*${$e(t)}`)}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${k(`*${$e(t)}*`)}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${k(t.source)}`;if(typeof t=="string")return `match.${k(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function Xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function bn(e){if(!Xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function we(e,t){return `${e}=${t}`}function G(e,t){return `${e}=(${t.join(",")})`}function be(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?we(e,P("$gte",n[0])):`${e}.${P("$gte",n[0])}`,s=r?we(e,P("$lte",n[1])):`${e}.${P("$lte",n[1])}`;return [i,s]}return [r?we(e,P(t,n)):`${e}.${P(t,n)}`]}function U(e,t,n,r){if(r>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let u=o;Je(u.fact,t),s.push(...be(u.fact,u.op,u.value,n));}return s}if("$all"in e){me(e,"$all");let s=e.$all;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let u=[];for(let a of s)u.push(...U(a,t,true,r+1));return u}let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("and",o)]}if("$any"in e){me(e,"$any");let s=e.$any;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(s.length===0)return n?["id=is.null","id=not.is.null"]:[G("and",["id.is.null","id.not.is.null"])];let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("or",o)]}if("$not"in e){me(e,"$not");let s=e.$not,o=U(s,t,false,r+1);return [G("not.and",o)]}let i=[];for(let[s,o]of Object.entries(e))if(Je(s,t),bn(o))for(let[u,a]of Object.entries(o)){if(!chunkGACC2DMS_cjs.a.has(u))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${u}" on column "${s}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);i.push(...be(s,u,a,n));}else {if(Xe(o))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${s}" \u2014 single-table queries only`);i.push(...be(s,"$eq",o,n));}return i}function Sn(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Tn(e,t={}){let n=t.mode??"querystring",r=U(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(Sn).join("&")}function V(e=[],t,n,r,i,s,o){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:s,_meta:o,validate(u){return V([...e,u],t,n,r,i,s,o)}}}function p(e,t,n,r,i,s,o){return {...V(e,t,n,r,i,s,o),default(a){return p(e,t,a,r,i,s,o)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,o)},brand(){return p(e,`Branded<${t}>`,n,r,i,s,o)},describe(a){return p(e,t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return p([...e,a],t,n,r,i,l,o)},nullable(){return p([a=>a===null||e.every(c=>c(a))],`${t} | null`,n,r,i,void 0,o)},optional(){return p([a=>a===void 0||e.every(c=>c(a))],`${t} | undefined`,n,r,i,void 0,o)},meta(a){return p(e,t,n,r,i,s,a)}}}var kn=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),vn={string(){let e=(t,n,r,i,s,o)=>({...p(t,"string",n,r,i,s,o),minLength(a){return e([...t,c=>c.length>=a],n,r,i,s,o)},maxLength(a){return e([...t,c=>c.length<=a],n,r,i,s,o)},pattern(a){return e([...t,c=>a.test(c)],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,s,o)=>({...p(t,"number",n,r,i,s,o),min(a){return e([...t,c=>c>=a],n,r,i,s,o)},max(a){return e([...t,c=>c<=a],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,s,o)=>{let u=p(t,"array",r,void 0,i,void 0,o),a=s??{value:-1};return {...u,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,g=>{for(let y=0;y<g.length;y++)if(!l._validators.every($=>$(g[y])))return d.value=y,false;return true}],l,r,i,d,o)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,o)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,o)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,o)},default(l){return e(t,n,l,i,a,o)},describe(l){return e(t,n,r,l,a,o)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(o){return e([...t,u=>{for(let[a,c]of Object.entries(o)){let l=u[a],d=c;if(d&&!d._validators.every(g=>g(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,o=>o!=null],n,r,i)},hasKeys(...o){return e([...t,u=>o.every(a=>a in u)],n,r,i)},default(o){return e(t,o,r,i)},describe(o){return e(t,n,o,i)},meta(o){return e(t,n,r,o)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){chunkGBCWXTXW_cjs.a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return V([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return V([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:kn,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){chunkGBCWXTXW_cjs.a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(s=>s(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Mn(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function Ze(e,t,n,r,i){for(let s of e)t.has(s)||console.warn(`[Directive] ${n} "${s}" not declared in ${r}`);for(let s of t)e.has(s)||console.warn(`[Directive] ${r}["${s}"] ${i}`);}function Dn(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Rn(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let s=i;typeof s.requirement=="string"&&!n.has(s.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${s.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function Cn(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),s="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let o of s)i.add(o);for(let o of r)if(i.has(o))throw new Error(`[Directive] module '${e}': fact key '${o}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes: | ||
| 'use strict';var chunkMARZI3EY_cjs=require('./chunk-MARZI3EY.cjs'),chunkOAPD3HIG_cjs=require('./chunk-OAPD3HIG.cjs'),chunkQTY2FXZY_cjs=require('./chunk-QTY2FXZY.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');var A=1e6;function Me(e,t){try{chunkGACC2DMS_cjs.l(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!chunkGACC2DMS_cjs.h(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(chunkGACC2DMS_cjs.i(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!chunkGACC2DMS_cjs.a.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!chunkGACC2DMS_cjs.a.has(r)&&!chunkGACC2DMS_cjs.b.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}function Re(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Ce(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>A)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,s={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(s.timestamp=i.timestamp),s}return {id:`#${r}`,facts:n??{}}})}function Ce(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return ae(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return ae(n.snapshots)}function ae(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>A)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return Re(e)}function H(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,s=e.maxSamples??20,o=s>0?s:0;if(t.length>A)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);Me(n,"original"),Me(r,"proposed");let u=0,a=0,c=0,l=0,d=0,g=[],y=[],$=i?new Set:void 0,m=i?new Set:void 0,M;for(let F of t){let T=F.facts,v=chunkGACC2DMS_cjs.o(n,T,M),R=chunkGACC2DMS_cjs.o(r,T,M);v&&(u++,$?.add(T[i])),R&&(a++,m?.add(T[i])),v===R?d++:!v&&R?(c++,g.length<o&&g.push(De(F,n,r,M))):(l++,y.length<o&&y.push(De(F,n,r,M))),M=T;}let E={framesEvaluated:t.length,original:{matched:u},proposed:{matched:a},delta:a-u,newMatchCount:c,lostMatchCount:l,unchanged:d,newMatches:g,lostMatches:y};return $&&m&&(E.original.matchedEntities=$.size,E.proposed.matchedEntities=m.size),E}function De(e,t,n,r){let i=e.facts,s={frameId:e.id,facts:i,originalExplain:chunkGACC2DMS_cjs.p(t,i,r),proposedExplain:chunkGACC2DMS_cjs.p(n,i,r)};return e.timestamp!==void 0&&(s.timestamp=e.timestamp),s}var ue=1e4,Ae=5e7;function It(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function ce(e,t,n=new Set,r=0){if(r>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${chunkGACC2DMS_cjs.g}) \u2014 flatten the template or split the sweep`);if(It(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(s=>ce(s,t,n,r+1));let i={};for(let[s,o]of Object.entries(e))i[s]=ce(o,t,n,r+1);return i}finally{n.delete(e);}}function*Ee(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let s of i)for(let o of Ee(r,t))yield {[n]:s,...o};}function Lt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function qt(e){let{frames:t,original:n,template:r,sweep:i,objective:s=T=>T.proposed.matched,entityKey:o,maxSamples:u=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let c=Lt(i);if(c>ue)throw new Error(`[Directive] sweepUnder: grid has ${c} points, exceeds the MAX_SWEEP_POINTS limit (${ue}) \u2014 narrow the sweep ranges or split the run`);if(c===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=c*t.length;if(l>Ae)throw new Error(`[Directive] sweepUnder: ${c} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Ae}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,g=T=>{let v;try{v=s(T);}catch(R){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${R.message})`)),Number.NEGATIVE_INFINITY}return typeof v!="number"||!Number.isFinite(v)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(v)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):v},y=H({frames:t,original:n,proposed:n,entityKey:o,maxSamples:u}),$={values:{},report:y,score:g(y)},m=[],M=0,E=Number.NEGATIVE_INFINITY;for(let T of Ee(a,i)){let v=ce(r,T),R=H({frames:t,original:n,proposed:v,entityKey:o,maxSamples:u}),te=g(R);te>E&&(E=te,M=m.length),m.push({values:T,report:R,score:te});}let F=m[M];return {points:m,bestIndex:M,best:F,baseline:$}}function le(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var Wt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Bt=new Set(["$all","$any","$not"]);function Oe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ut(e){if(!Oe(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;Wt.has(r)&&(n=true);}return n}function S(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,s)=>{S(i,`${t}$all[${s}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,s)=>{S(i,`${t}$any[${s}]`,n);}),n;if("$not"in e)return S(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let s=t?`${t}.${r}`:r;if(Ut(i))for(let[o,u]of Object.entries(i))n.push({path:s,op:o,value:u});else Oe(i)&&!Bt.has(r)?S(i,s,n):n.push({path:s,op:"$eq",value:i});}return n}function C(e){return typeof e=="number"&&Number.isFinite(e)}function Kt(e,t,n){switch(e){case "$gte":case "$gt":if(C(t)&&C(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(C(t)&&C(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&C(t[0])&&C(t[1])&&C(n[0])&&C(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function zt(e){let t=le(e.before),n=le(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),s=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let u of i){let a=t[u],c=n[u],l=u in t,d=u in n;if(l&&!d){let y=S(a),$=y.length===0?[{path:"(function-form predicate)",kind:"removed"}]:y.map(m=>({path:m.path,kind:"removed",before:{op:m.op,value:m.value}}));de($),s.push({id:u,status:"removed",changes:$}),o.removed++,o.totalClauseChanges+=$.length;continue}if(!l&&d){let y=S(c),$=y.length===0?[{path:"(function-form predicate)",kind:"added"}]:y.map(m=>({path:m.path,kind:"added",after:{op:m.op,value:m.value}}));de($),s.push({id:u,status:"added",changes:$}),o.added++,o.totalClauseChanges+=$.length;continue}let g=xe(a,c);g.length===0?(s.push({id:u,status:"unchanged",changes:[]}),o.unchanged++):(s.push({id:u,status:"changed",changes:g}),o.changed++,o.totalClauseChanges+=g.length);}return {constraints:s,summary:o}}function xe(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return chunkGBCWXTXW_cjs.e(e)===chunkGBCWXTXW_cjs.e(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let n=e===void 0?[]:S(e),r=t===void 0?[]:S(t),i=c=>`${c.path}::${c.op}`,s=new Map(n.map(c=>[i(c),c])),o=new Map(r.map(c=>[i(c),c])),u=new Set([...s.keys(),...o.keys()]),a=[];for(let c of u){let l=s.get(c),d=o.get(c);if(l&&!d){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(l&&d){if(chunkGBCWXTXW_cjs.e(l.value)===chunkGBCWXTXW_cjs.e(d.value))continue;let g=Kt(l.op,l.value,d.value);a.push({path:l.path,kind:g??"changed",before:{op:l.op,value:l.value},after:{op:d.op,value:d.value}});}}return de(a),a}function de(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",s=n.before?.op??n.after?.op??"";return i.localeCompare(s)});}function Ht(e){return chunkGBCWXTXW_cjs.h(e)}function J(e){return e===null?"null":e===void 0?"undefined":e instanceof Date?e.toISOString():typeof e=="string"||typeof e=="object"?JSON.stringify(e):String(e)}function Jt(e){let t=e.path,n=J(e.expected),r=J(e.actual);switch(e.op){case "$eq":return `set ${t} to ${n} (currently ${r})`;case "$ne":return `change ${t} to anything other than ${n} (currently ${r})`;case "$gt":return `set ${t} above ${n} (currently ${r})`;case "$gte":return `set ${t} to at least ${n} (currently ${r})`;case "$lt":return `set ${t} below ${n} (currently ${r})`;case "$lte":return `set ${t} to at most ${n} (currently ${r})`;case "$in":return `set ${t} to one of ${n} (currently ${r})`;case "$nin":return `set ${t} to something other than ${n} (currently ${r})`;case "$exists":return e.expected===true?`set ${t} to a non-null value (currently null/missing)`:`unset ${t} (currently ${r})`;case "$between":return Array.isArray(e.expected)&&e.expected.length===2?`set ${t} between ${J(e.expected[0])} and ${J(e.expected[1])} (currently ${r})`:`set ${t} within range ${n} (currently ${r})`;case "$startsWith":return `set ${t} to start with ${n} (currently ${r})`;case "$endsWith":return `set ${t} to end with ${n} (currently ${r})`;case "$contains":return `set ${t} to contain ${n} (currently ${r})`;case "$matches":return `set ${t} to match the pattern ${n} (currently ${r})`;case "$changed":return `the previous-vs-current change of ${t} is required to differ (currently they match: ${r})`;case "$all":case "$any":case "$not":return `the ${e.op} group at "${t}" did not pass \u2014 see its child clauses`;default:return `clause at ${t} (${e.op}) failed: expected ${n}, got ${r}`}}function je(e,t){for(let n of e)if(!n.pass){if((n.op==="$all"||n.op==="$any"||n.op==="$not")&&n.children){je(n.children,t);continue}t.push({path:n.path,op:n.op,expected:n.expected,actual:n.actual,suggestion:Jt(n)});}}function Qt(e,t,n){let r=chunkGACC2DMS_cjs.p(e,t,n),i=r.every(o=>o.pass),s=[];if(i||je(r,s),!i&&n===void 0){let o=[];chunkGACC2DMS_cjs.i(e,{operator(u,a){a==="$changed"&&o.push(u);}});for(let u of o)s.push({path:u,op:"$changed",expected:true,actual:void 0,suggestion:`$changed clause at "${u}" cannot be evaluated without a \`prev\` snapshot \u2014 pass predict(predicate, facts, prev).`});}return {wouldFire:i,whenExplain:r,missingChanges:s}}var Pe=new Set(["$eq","$ne","$gt","$gte","$lt","$lte","$in","$nin"]);function Q(e,t){if(e===t)return 0;if(typeof e=="number"&&typeof t=="number"||typeof e=="bigint"&&typeof t=="bigint")return e<t?-1:e>t?1:0;if(e instanceof Date&&t instanceof Date){let n=e.getTime(),r=t.getTime();return n<r?-1:n>r?1:0}return typeof e=="string"&&typeof t=="string"?e<t?-1:e>t?1:0:Number.NaN}function _(e,t){if(e===t)return true;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let i=0;i<e.length;i++)if(!_(e[i],t[i]))return false;return true}let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return false;for(let i of n)if(!_(e[i],t[i]))return false;return true}function Xt(e,t){if(!Pe.has(e.op)||!Pe.has(t.op))return {type:"overlap",reason:`Both rules touch "${e.path}".`};if(e.op==="$eq"&&t.op==="$eq")return _(e.value,t.value)?{type:"subset",reason:`Both rules require ${e.path} = ${JSON.stringify(e.value)} \u2014 candidate is redundant.`}:{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires ${e.path} = ${JSON.stringify(t.value)} \u2014 they cannot both fire.`};if(e.op==="$eq"&&t.op==="$ne")return _(e.value,t.value)?{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule excludes that value.`}:null;if(e.op==="$ne"&&t.op==="$eq")return _(e.value,t.value)?{type:"direct",reason:`Candidate excludes ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires that exact value.`}:null;if(e.op==="$in"&&t.op==="$in"){let o=new Set(Array.isArray(e.value)?e.value:[]),u=new Set(Array.isArray(t.value)?t.value:[]),a=[...o].filter(c=>u.has(c));return a.length===0?{type:"direct",reason:`Candidate $in set for ${e.path} (${JSON.stringify([...o])}) and existing $in set (${JSON.stringify([...u])}) have no values in common \u2014 the candidate can never fire while the existing rule holds.`}:a.length===o.size&&a.length<u.size?{type:"subset",reason:`Candidate $in set for ${e.path} is a strict subset of the existing rule's $in set.`}:null}let n=e.op==="$gt"||e.op==="$gte"?e.value:void 0,r=e.op==="$lt"||e.op==="$lte"?e.value:void 0,i=t.op==="$gt"||t.op==="$gte"?t.value:void 0,s=t.op==="$lt"||t.op==="$lte"?t.value:void 0;if(n!==void 0&&s!==void 0){let o=Q(n,s);if(!Number.isNaN(o)&&(o>0||o===0&&(e.op==="$gt"||t.op==="$lt")))return {type:"direct",reason:`Candidate requires ${e.path} ${e.op==="$gt"?">":"\u2265"} ${JSON.stringify(n)} but an existing rule caps it at ${t.op==="$lt"?"<":"\u2264"} ${JSON.stringify(s)}.`}}if(i!==void 0&&r!==void 0){let o=Q(i,r);if(!Number.isNaN(o)&&(o>0||o===0&&(t.op==="$gt"||e.op==="$lt")))return {type:"direct",reason:`Candidate caps ${e.path} at ${e.op==="$lt"?"<":"\u2264"} ${JSON.stringify(r)} but an existing rule requires it ${t.op==="$gt"?">":"\u2265"} ${JSON.stringify(i)}.`}}if(n!==void 0&&i!==void 0){let o=Q(n,i);if(!Number.isNaN(o)&&o>0)return {type:"subset",reason:`Candidate's lower bound on ${e.path} (${JSON.stringify(n)}) is stricter than the existing rule's lower bound (${JSON.stringify(i)}) \u2014 candidate is a subset.`}}if(r!==void 0&&s!==void 0){let o=Q(r,s);if(!Number.isNaN(o)&&o<0)return {type:"subset",reason:`Candidate's upper bound on ${e.path} (${JSON.stringify(r)}) is stricter than the existing rule's upper bound (${JSON.stringify(s)}) \u2014 candidate is a subset.`}}return {type:"overlap",reason:`Both rules constrain "${e.path}".`}}function Fe(e){return typeof e=="object"&&e!==null&&typeof e.id=="string"}var Zt={checkAgainst(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {contradictions:[],warnings:[]};let i=new Map;for(let u of r){let a=i.get(u.path)??[];a.push(u),i.set(u.path,a);}let s=[],o=[];for(let u of n){if(!Fe(u)||u.whenSpec===void 0)continue;let a=S(u.whenSpec);for(let c of a){let l=i.get(c.path);if(l)for(let d of l){let g=Xt(d,c);if(!g)continue;let y={constraintId:u.id,type:g.type,reason:g.reason,candidatePath:d.path,candidate:{op:d.op,value:d.value},existing:{op:c.op,value:c.value}};g.type==="overlap"||g.type==="subset"?o.push(y):s.push(y);}}}return {contradictions:s,warnings:o}},checkAbortOn(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {warnings:[]};let i=new Set(r.map(o=>o.path)),s=[];for(let o of n){if(!Fe(o))continue;let u=Array.isArray(o.abortOn)?o.abortOn:[],a=Array.isArray(o.bind)?o.bind:[];for(let c of u)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"abortOn",reason:`Constraint "${o.id}" aborts on "${c}" \u2014 candidate would race or shadow its writes.`,severity:"warning"});for(let c of a)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"bind",reason:`Constraint "${o.id}" binds "${c}" \u2014 candidate would write to a bound field.`,severity:"warning"});}return {warnings:s}}};var I=new Map,Yt=50;function Gt(e){let t=I.get(e);if(!t){try{t=new Intl.NumberFormat(e);}catch{t=new Intl.NumberFormat("en-US");}if(I.size>=Yt){let n=I.keys().next().value;n!==void 0&&I.delete(n);}I.set(e,t);}return t}function Vt(e,t={}){let n=t.style??"natural",r=t.parenthesize??true,i=t.locale??"en-US",s=t.factName??(a=>a);if(e===null||typeof e!="object")return "<invalid predicate>";let o={style:n,parenthesize:r,locale:i,factName:s,seen:new WeakSet,cycle:false},u=X(e,o,0);return o.cycle?"<invalid predicate: cycle>":u}var Ie=" AND ",en=" OR ",tn="NOT",Le=" \u2227 ",nn=" \u2228 ",rn="\xAC";function q(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function on(e){if(!q(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function X(e,t,n){if(n>chunkGACC2DMS_cjs.g)return chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] describePredicate: depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 bailing.`),t.style==="formal"?"\u22A5":"always true";if(Array.isArray(e))return sn(e,t);if(!q(e))return f(e,t);if(t.seen.has(e))return t.cycle=true,"<invalid predicate: cycle>";t.seen.add(e);let r=e,i=Object.keys(r);for(let o of ["$all","$any","$not"])if(o in r)return an(o,r[o],t,n);let s=[];for(let o of i)o.startsWith("$")||s.push(qe(o,r[o],t,n));return Z(s,t)}function sn(e,t,n){let r=[];for(let i of e){if(!q(i))continue;let s=i;typeof s.fact!="string"||typeof s.op!="string"||r.push(L(s.fact,s.op,s.value,t));}return r.length===0?t.style==="formal"?"\u22A4":"always true":Z(r,t)}function an(e,t,n,r){if(e==="$not"){if(q(t)&&Object.keys(t).length===0)return n.style==="formal"?"\u22A5":"never";let o=X(t,n,r+1);return o==="always true"?"never":o==="\u22A4"?"\u22A5":`${n.style==="formal"?rn:`${tn} `}(${o})`}if(!Array.isArray(t))return n.style==="formal"?"\u22A5":"<invalid predicate>";if(t.length===0)return e==="$all"?n.style==="formal"?"\u22A4":"always true":n.style==="formal"?"\u22A5":"never";let i=[];for(let o of t){let u=X(o,n,r+1);i.push(u);}if(i.length===1)return i[0];let s=n.parenthesize?i.map(o=>`(${o})`):i;return e==="$all"?s.join(n.style==="formal"?Le:Ie):s.join(n.style==="formal"?nn:en)}function qe(e,t,n,r){if(on(t)){let i=t,s=Object.keys(i);if(s.length===1)return L(e,s[0],i[s[0]],n);let o=s.map(u=>L(e,u,i[u],n));return Z(o,n)}if(q(t)){let i=t;if("$all"in i||"$any"in i||"$not"in i)return X(t,n,r+1);let o=[];for(let u of Object.keys(i))u.startsWith("$")||o.push(qe(`${e}.${u}`,i[u],n,r+1));return o.length===0?L(e,"$eq",t,n):Z(o,n)}return L(e,"$eq",t,n)}function L(e,t,n,r){let i=r.style==="formal"?e:r.factName(e);return r.style==="formal"?cn(i,t,n,r):un(i,t,n,r)}function un(e,t,n,r){switch(t){case "$eq":return n===null?`${e} is null`:`${e} is ${f(n,r)}`;case "$ne":return n===null?`${e} is not null`:`${e} is not ${f(n,r)}`;case "$gt":return `${e} is more than ${f(n,r)}`;case "$gte":return `${e} is at least ${f(n,r)}`;case "$lt":return `${e} is less than ${f(n,r)}`;case "$lte":return `${e} is at most ${f(n,r)}`;case "$in":return `${e} is one of ${Ne(n,r)}`;case "$nin":return `${e} is not one of ${Ne(n,r)}`;case "$exists":return n===true?`${e} is set`:`${e} is not set`;case "$between":return Array.isArray(n)&&n.length===2?`${e} is between ${f(n[0],r)} and ${f(n[1],r)}`:`${e} is between ${f(n,r)}`;case "$startsWith":return `${e} starts with ${x(n,r,true)}`;case "$endsWith":return `${e} ends with ${x(n,r,true)}`;case "$contains":return `${e} contains ${x(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} matches ${n.toString()}`:`${e} matches ${f(n,r)}`;case "$changed":return `${e} changed`;default:return chunkGBCWXTXW_cjs.a&&!chunkGACC2DMS_cjs.a.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function cn(e,t,n,r){switch(t){case "$eq":return `${e} = ${f(n,r)}`;case "$ne":return `${e} \u2260 ${f(n,r)}`;case "$gt":return `${e} > ${f(n,r)}`;case "$gte":return `${e} \u2265 ${f(n,r)}`;case "$lt":return `${e} < ${f(n,r)}`;case "$lte":return `${e} \u2264 ${f(n,r)}`;case "$in":return `${e} \u2208 {${_e(n,r)}}`;case "$nin":return `${e} \u2209 {${_e(n,r)}}`;case "$exists":return n===true?`\u2203 ${e}`:`\u2204 ${e}`;case "$between":return Array.isArray(n)&&n.length===2?`${f(n[0],r)} \u2264 ${e} \u2264 ${f(n[1],r)}`:`${e} \u2208 [${f(n,r)}]`;case "$startsWith":return `${e} ^= ${x(n,r,true)}`;case "$endsWith":return `${e} $= ${x(n,r,true)}`;case "$contains":return `${e} \u2287 ${x(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} ~ ${n.toString()}`:`${e} ~ ${f(n,r)}`;case "$changed":return `\u0394${e}`;default:return chunkGBCWXTXW_cjs.a&&!chunkGACC2DMS_cjs.a.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function Y(e){return e.length===0?true:/[\s,"']/.test(e)}function x(e,t,n){return typeof e!="string"||n||Y(e)?JSON.stringify(e):e}function f(e,t){if(e===null)return "null";if(e===void 0)return "undefined";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"){if(!Number.isFinite(e))return String(e);try{return Gt(t.locale).format(e)}catch{return String(e)}}if(typeof e=="bigint")return t.style==="formal"?`${e.toString()}n`:e.toString();if(typeof e=="string")return t.style==="formal"||Y(e)?JSON.stringify(e):e;if(e instanceof Date)return e.toISOString();if(e instanceof RegExp)return e.toString();if(Array.isArray(e))return `[${e.map(n=>f(n,t)).join(", ")}]`;if(typeof e=="object")try{return JSON.stringify(e)}catch{return "[object]"}return String(e)}function Ne(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function _e(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function Z(e,t){if(e.length===0)return t.style==="formal"?"\u22A4":"always true";if(e.length===1)return e[0];let n=t.style==="formal"?Le:Ie;return t.parenthesize,e.join(n)}var ln=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function B(e,t){if(typeof e!="string"||!ln.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function We(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function dn(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)B(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(B(t,"column"),t)}function b(e,t){return e.params.push(t),e.placeholder(e.params.length)}function fe(e,t,n,r){switch(t){case "$eq":return `${e} = ${b(r,n)}`;case "$ne":return `${e} <> ${b(r,n)}`;case "$gt":return `${e} > ${b(r,n)}`;case "$gte":return `${e} >= ${b(r,n)}`;case "$lt":return `${e} < ${b(r,n)}`;case "$lte":return `${e} <= ${b(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${b(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${b(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${b(r,n[0])} AND ${b(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${b(r,pe(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${b(r,pe(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${b(r,pe(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${b(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function pe(e){return e.replace(/[\\%_]/g,"\\$&")}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function fn(e){if(!Be(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function ge(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function W(e,t,n){if(n>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(s=>{if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let o=s;return B(o.fact,"column"),We(o.fact,t.allowed),fe(o.fact,o.op,o.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){ge(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" AND ")})`}if("$any"in e){ge(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" OR ")})`}if("$not"in e){ge(e,"$not");let i=e.$not;return `NOT (${W(i,t,n+1)})`}let r=[];for(let[i,s]of Object.entries(e))if(B(i,"column"),We(i,t.allowed),fn(s))for(let[o,u]of Object.entries(s)){if(!chunkGACC2DMS_cjs.a.has(o))throw new Error(`[Directive] predicateToSQL: unknown operator "${o}" on column "${i}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);r.push(fe(i,o,u,t));}else {if(Be(s))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(fe(i,"$eq",s,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var Ue=e=>`$${e}`;function pn(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??Ue,s=t.select??"*";B(n,"table");let o=dn(s),u={params:[],placeholder:i,allowed:r},a=W(e,u,0);return {sql:`SELECT ${o} FROM ${n} WHERE ${a}`,where:a,params:u.params}}function gn(e,t={}){let n=t.placeholder??Ue,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:W(e,r,0),params:r.params}}function ye(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function me(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function yn(e){if(!me(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var hn=/^[A-Za-z_][A-Za-z0-9_]*$/,mn=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function Ke(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?mn:hn).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function ze(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function he(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function He(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${ye(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${ye(t)}$`};case "$contains":if(typeof t=="string")return {$regex:ye(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function j(e,t,n){if(n>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let u=o;Ke(u.fact,t),ze(u.fact,t.allowedKeys);let a=He(u.op,u.value);if(u.fact in i&&me(i[u.fact])){let c=i[u.fact];Object.keys(a).some(d=>d in c)?s.push({[u.fact]:a}):i[u.fact]={...c,...a};}else u.fact in i?s.push({[u.fact]:a}):i[u.fact]=a;}if(s.length>0){let o=[];for(let[u,a]of Object.entries(i))o.push({[u]:a});return o.push(...s),{$and:o}}return i}if("$all"in e){he(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?j(i[0],t,n+1):{$and:i.map(s=>j(s,t,n+1))}}if("$any"in e){he(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?j(i[0],t,n+1):{$or:i.map(s=>j(s,t,n+1))}}if("$not"in e){he(e,"$not");let i=e.$not;return {$nor:[j(i,t,n+1)]}}let r={};for(let[i,s]of Object.entries(e))if(Ke(i,t),ze(i,t.allowedKeys),yn(s)){let o={};for(let[u,a]of Object.entries(s)){if(!chunkGACC2DMS_cjs.a.has(u))throw new Error(`[Directive] predicateToMongo: unknown operator "${u}" on field "${i}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);Object.assign(o,He(u,a));}r[i]=o;}else r[i]=s;return r}function $n(e,t={}){return j(e,t,0)}var wn=/^[A-Za-z_][A-Za-z0-9_]*$/;function Je(e,t){if(typeof e!="string"||!wn.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function $e(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function k(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function Qe(e){return `(${e.map(k).join(",")})`}function we(e){return e.replace(/[\\%_*]/g,"\\$&")}function P(e,t){switch(e){case "$eq":return `eq.${k(t)}`;case "$ne":return `neq.${k(t)}`;case "$gt":return `gt.${k(t)}`;case "$gte":return `gte.${k(t)}`;case "$lt":return `lt.${k(t)}`;case "$lte":return `lte.${k(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${Qe(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${Qe(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${k(`${we(t)}*`)}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${k(`*${we(t)}`)}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${k(`*${we(t)}*`)}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${k(t.source)}`;if(typeof t=="string")return `match.${k(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`)}}function Xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function bn(e){if(!Xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function be(e,t){return `${e}=${t}`}function G(e,t){return `${e}=(${t.join(",")})`}function Se(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?be(e,P("$gte",n[0])):`${e}.${P("$gte",n[0])}`,s=r?be(e,P("$lte",n[1])):`${e}.${P("$lte",n[1])}`;return [i,s]}return [r?be(e,P(t,n)):`${e}.${P(t,n)}`]}function U(e,t,n,r){if(r>chunkGACC2DMS_cjs.g)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${chunkGACC2DMS_cjs.g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let u=o;Je(u.fact,t),s.push(...Se(u.fact,u.op,u.value,n));}return s}if("$all"in e){$e(e,"$all");let s=e.$all;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let u=[];for(let a of s)u.push(...U(a,t,true,r+1));return u}let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("and",o)]}if("$any"in e){$e(e,"$any");let s=e.$any;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(s.length===0)return n?["id=is.null","id=not.is.null"]:[G("and",["id.is.null","id.not.is.null"])];let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("or",o)]}if("$not"in e){$e(e,"$not");let s=e.$not,o=U(s,t,false,r+1);return [G("not.and",o)]}let i=[];for(let[s,o]of Object.entries(e))if(Je(s,t),bn(o))for(let[u,a]of Object.entries(o)){if(!chunkGACC2DMS_cjs.a.has(u))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${u}" on column "${s}" \u2014 known: ${[...chunkGACC2DMS_cjs.a].join(", ")}`);i.push(...Se(s,u,a,n));}else {if(Xe(o))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${s}" \u2014 single-table queries only`);i.push(...Se(s,"$eq",o,n));}return i}function Sn(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Tn(e,t={}){let n=t.mode??"querystring",r=U(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(Sn).join("&")}function V(e=[],t,n,r,i,s,o){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:s,_meta:o,validate(u){return V([...e,u],t,n,r,i,s,o)}}}function p(e,t,n,r,i,s,o){return {...V(e,t,n,r,i,s,o),default(a){return p(e,t,a,r,i,s,o)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,o)},brand(){return p(e,`Branded<${t}>`,n,r,i,s,o)},describe(a){return p(e,t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return p([...e,a],t,n,r,i,l,o)},nullable(){return p([a=>a===null||e.every(c=>c(a))],`${t} | null`,n,r,i,void 0,o)},optional(){return p([a=>a===void 0||e.every(c=>c(a))],`${t} | undefined`,n,r,i,void 0,o)},meta(a){return p(e,t,n,r,i,s,a)}}}var kn=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),vn={string(){let e=(t,n,r,i,s,o)=>({...p(t,"string",n,r,i,s,o),minLength(a){return e([...t,c=>c.length>=a],n,r,i,s,o)},maxLength(a){return e([...t,c=>c.length<=a],n,r,i,s,o)},pattern(a){return e([...t,c=>a.test(c)],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,s,o)=>({...p(t,"number",n,r,i,s,o),min(a){return e([...t,c=>c>=a],n,r,i,s,o)},max(a){return e([...t,c=>c<=a],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,s,o)=>{let u=p(t,"array",r,void 0,i,void 0,o),a=s??{value:-1};return {...u,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,g=>{for(let y=0;y<g.length;y++)if(!l._validators.every($=>$(g[y])))return d.value=y,false;return true}],l,r,i,d,o)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,o)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,o)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,o)},default(l){return e(t,n,l,i,a,o)},describe(l){return e(t,n,r,l,a,o)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(o){return e([...t,u=>{for(let[a,c]of Object.entries(o)){let l=u[a],d=c;if(d&&!d._validators.every(g=>g(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,o=>o!=null],n,r,i)},hasKeys(...o){return e([...t,u=>o.every(a=>a in u)],n,r,i)},default(o){return e(t,o,r,i)},describe(o){return e(t,n,o,i)},meta(o){return e(t,n,r,o)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){chunkGBCWXTXW_cjs.a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return V([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return V([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:kn,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){chunkGBCWXTXW_cjs.a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(s=>s(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Mn(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function Ze(e,t,n,r,i){for(let s of e)t.has(s)||console.warn(`[Directive] ${n} "${s}" not declared in ${r}`);for(let s of t)e.has(s)||console.warn(`[Directive] ${r}["${s}"] ${i}`);}function Dn(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Rn(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let s=i;typeof s.requirement=="string"&&!n.has(s.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${s.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function Cn(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),s="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let o of s)i.add(o);for(let o of r)if(i.has(o))throw new Error(`[Directive] module '${e}': fact key '${o}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes: | ||
| 1. Rename the fact (e.g. ${o}_) | ||
| 2. Remove '${o}' from this module's crossModuleDeps if it's not actually needed | ||
| 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function An(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.owns;if(s){for(let o of s)if(chunkGKMJ7NMP_cjs.k.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': owns key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function En(e,t){Mn(e),t.schema?t.schema.facts||(Object.values(t.schema).some(r=>r!=null&&typeof r=="object"&&"_typeName"in r)&&console.warn(`[Directive] Module "${e}" schema appears to contain fact declarations directly. Did you mean \`schema: { facts: { ... } }\` instead of \`schema: { ... }\`?`),console.warn("[Directive] Module schema.facts is required")):console.warn("[Directive] Module schema is required"),Ze(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),Ze(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Dn(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&Rn(t.resolvers,t.schema.requirements);}function Ye(e,t){Cn(e,t),An(e,t),chunkGBCWXTXW_cjs.a&&En(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,sources:t.sources,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function xn(e){return t=>Ye(t,e)}function Se(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,c){let l=a.get(c);return l||(l=new Set,a.set(c,l)),l}function r(a){let c=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,g=e.errors.get(a)??null;return {pending:c.size,inflight:l.size,failed:d.size,isLoading:c.size>0||l.size>0,hasError:d.size>0,lastError:g}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),c=new Map;for(let l of a)c.set(l,r(l));return c}function s(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function o(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let c=a.requirement.type;n(e.pending,c).add(a.id),e.failed.get(c)?.delete(a.id),t();},onResolverStart(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),n(e.inflight,l).add(c.id),t();},onResolverComplete(a,c){let l=c.requirement.type;e.inflight.get(l)?.delete(c.id),e.pending.get(l)?.delete(c.id),t();},onResolverError(a,c,l){let d=c.requirement.type;e.inflight.get(d)?.delete(c.id),n(e.failed,d).add(c.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),e.inflight.get(l)?.delete(c.id),t();},onRequirementMet(a){let c=a.requirement.type;e.pending.get(c)?.delete(a.id),e.inflight.get(c)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:s,reset:o}}function On(e){return t=>e.getStatus(t)}function jn(e){let t=Se(),r=[...e.plugins??[],t.plugin];return {system:chunk4OXCKDKS_cjs.a({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function Ge(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function Pn(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,s)=>{let o={id:n++,deadlineMs:t+s,cb:i,canceled:false};return r.push(o),()=>{o.canceled=true;}},advanceBy:i=>{let s=t+i;for(;;){let o=r.filter(a=>!a.canceled&&a.deadlineMs<=s).sort((a,c)=>a.deadlineMs!==c.deadlineMs?a.deadlineMs-c.deadlineMs:a.id-c.id);if(o.length===0)break;let u=o[0];t=Math.max(t,u.deadlineMs),u.canceled=true,u.cb();}t=Math.max(t,s);}}}function Fn(){return Ge()}function Te(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function ee(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function Ve(e,t,n){return Math.max(0,n-ee(e,t))}function et(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function tt(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function nt(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function rt(){return Te()}function it(e){return {...e,status:"completed"}}function ot(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function st(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=ee(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function Nn(e){return {initial:Te,start:et,pause:tt,resume:nt,reset:rt,complete:it,registerRepeat:t=>ot(t,e.ms),tick:(t,n)=>st(t,n,e),elapsedMs:ee,remainingMs:(t,n)=>Ve(t,n,e.ms)}}var Sr={None:"none",Linear:"linear",Exponential:"exponential"};Object.defineProperty(exports,"createAuditLedger",{enumerable:true,get:function(){return chunkMARZI3EY_cjs.b}});Object.defineProperty(exports,"memorySink",{enumerable:true,get:function(){return chunkMARZI3EY_cjs.a}});Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunk4OXCKDKS_cjs.a}});Object.defineProperty(exports,"DirectiveError",{enumerable:true,get:function(){return chunkM5PEB553_cjs.b}});Object.defineProperty(exports,"RequirementSet",{enumerable:true,get:function(){return chunkM5PEB553_cjs.o}});Object.defineProperty(exports,"forType",{enumerable:true,get:function(){return chunkM5PEB553_cjs.n}});Object.defineProperty(exports,"generateRequirementId",{enumerable:true,get:function(){return chunkM5PEB553_cjs.k}});Object.defineProperty(exports,"isNamespacedSystem",{enumerable:true,get:function(){return chunkM5PEB553_cjs.h}});Object.defineProperty(exports,"isRequirementType",{enumerable:true,get:function(){return chunkM5PEB553_cjs.m}});Object.defineProperty(exports,"isSingleModuleSystem",{enumerable:true,get:function(){return chunkM5PEB553_cjs.g}});Object.defineProperty(exports,"req",{enumerable:true,get:function(){return chunkM5PEB553_cjs.l}});Object.defineProperty(exports,"typedConstraint",{enumerable:true,get:function(){return chunkM5PEB553_cjs.e}});Object.defineProperty(exports,"typedResolver",{enumerable:true,get:function(){return chunkM5PEB553_cjs.f}});Object.defineProperty(exports,"applyPatch",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.v}});Object.defineProperty(exports,"evaluateKeySelector",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.u}});Object.defineProperty(exports,"evaluatePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.o}});Object.defineProperty(exports,"evaluatePredicateExplained",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.p}});Object.defineProperty(exports,"evaluateTemplate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.s}});Object.defineProperty(exports,"extractDeps",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.r}});Object.defineProperty(exports,"extractTemplateKeys",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.t}});Object.defineProperty(exports,"getKind",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.c}});Object.defineProperty(exports,"getOperatorsForKind",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.e}});Object.defineProperty(exports,"getSchemaFieldKinds",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.d}});Object.defineProperty(exports,"isPredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.h}});Object.defineProperty(exports,"isTemplate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.k}});Object.defineProperty(exports,"listAllPredicateOperators",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.f}});Object.defineProperty(exports,"memoizePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.q}});Object.defineProperty(exports,"validatePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.l}});Object.defineProperty(exports,"validatePredicateAgainstSchema",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.n}});Object.defineProperty(exports,"diffSnapshots",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.k}});Object.defineProperty(exports,"isSignedSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.l}});Object.defineProperty(exports,"isSnapshotExpired",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.i}});Object.defineProperty(exports,"shallowEqual",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.g}});Object.defineProperty(exports,"signSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.m}});Object.defineProperty(exports,"validateSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.j}});Object.defineProperty(exports,"verifySnapshotSignature",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.n}});exports.Backoff=Sr;exports.MAX_REPLAY_FRAMES=A;exports.MAX_SWEEP_POINTS=ae;exports.completeTimer=it;exports.createModule=Ye;exports.createModuleFactory=xn;exports.createRequirementStatusPlugin=Se;exports.createStatusHook=On;exports.createSystemWithStatus=jn;exports.defaultClock=Fn;exports.describePredicate=Vt;exports.diffClauses=Oe;exports.diffRules=zt;exports.doctor=Zt;exports.elapsedMs=ee;exports.flattenPredicate=S;exports.framesFromHistory=Ce;exports.framesFromSnapshots=se;exports.initialTimerState=Te;exports.pauseTimer=tt;exports.predicateHash=Ht;exports.predicateToMongo=$n;exports.predicateToPostgrest=Tn;exports.predicateToSQL=pn;exports.predicateToWhere=gn;exports.predict=Qt;exports.realClock=Ge;exports.registerRepeat=ot;exports.remainingMs=Ve;exports.replayUnder=H;exports.resetTimer=rt;exports.resumeTimer=nt;exports.startTimer=et;exports.sweepUnder=qt;exports.t=vn;exports.tickTimer=st;exports.timerOps=Nn;exports.toReplayFrames=Re;exports.toRulesMap=ce;exports.virtualClock=Pn;//# sourceMappingURL=index.cjs.map | ||
| 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function An(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.abortOn;if(s){for(let o of s)if(chunkGKMJ7NMP_cjs.k.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': abortOn key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function En(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.bind;if(s){for(let o of s)if(chunkGKMJ7NMP_cjs.k.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': bind key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function On(e,t){Mn(e),t.schema?t.schema.facts||(Object.values(t.schema).some(r=>r!=null&&typeof r=="object"&&"_typeName"in r)&&console.warn(`[Directive] Module "${e}" schema appears to contain fact declarations directly. Did you mean \`schema: { facts: { ... } }\` instead of \`schema: { ... }\`?`),console.warn("[Directive] Module schema.facts is required")):console.warn("[Directive] Module schema is required"),Ze(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),Ze(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Dn(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&Rn(t.resolvers,t.schema.requirements);}function Ye(e,t){Cn(e,t),An(e,t),En(e,t),chunkGBCWXTXW_cjs.a&&On(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,sources:t.sources,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function xn(e){return t=>Ye(t,e)}function Te(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,c){let l=a.get(c);return l||(l=new Set,a.set(c,l)),l}function r(a){let c=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,g=e.errors.get(a)??null;return {pending:c.size,inflight:l.size,failed:d.size,isLoading:c.size>0||l.size>0,hasError:d.size>0,lastError:g}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),c=new Map;for(let l of a)c.set(l,r(l));return c}function s(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function o(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let c=a.requirement.type;n(e.pending,c).add(a.id),e.failed.get(c)?.delete(a.id),t();},onResolverStart(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),n(e.inflight,l).add(c.id),t();},onResolverComplete(a,c){let l=c.requirement.type;e.inflight.get(l)?.delete(c.id),e.pending.get(l)?.delete(c.id),t();},onResolverError(a,c,l){let d=c.requirement.type;e.inflight.get(d)?.delete(c.id),n(e.failed,d).add(c.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),e.inflight.get(l)?.delete(c.id),t();},onRequirementMet(a){let c=a.requirement.type;e.pending.get(c)?.delete(a.id),e.inflight.get(c)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:s,reset:o}}function jn(e){return t=>e.getStatus(t)}function Pn(e){let t=Te(),r=[...e.plugins??[],t.plugin];return {system:chunkOAPD3HIG_cjs.a({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function Ge(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function Fn(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,s)=>{let o={id:n++,deadlineMs:t+s,cb:i,canceled:false};return r.push(o),()=>{o.canceled=true;}},advanceBy:i=>{let s=t+i;for(;;){let o=r.filter(a=>!a.canceled&&a.deadlineMs<=s).sort((a,c)=>a.deadlineMs!==c.deadlineMs?a.deadlineMs-c.deadlineMs:a.id-c.id);if(o.length===0)break;let u=o[0];t=Math.max(t,u.deadlineMs),u.canceled=true,u.cb();}t=Math.max(t,s);}}}function Nn(){return Ge()}function ke(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function ee(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function Ve(e,t,n){return Math.max(0,n-ee(e,t))}function et(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function tt(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function nt(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function rt(){return ke()}function it(e){return {...e,status:"completed"}}function ot(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function st(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=ee(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function _n(e){return {initial:ke,start:et,pause:tt,resume:nt,reset:rt,complete:it,registerRepeat:t=>ot(t,e.ms),tick:(t,n)=>st(t,n,e),elapsedMs:ee,remainingMs:(t,n)=>Ve(t,n,e.ms)}}var Tr={None:"none",Linear:"linear",Exponential:"exponential"};Object.defineProperty(exports,"createAuditLedger",{enumerable:true,get:function(){return chunkMARZI3EY_cjs.b}});Object.defineProperty(exports,"memorySink",{enumerable:true,get:function(){return chunkMARZI3EY_cjs.a}});Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunkOAPD3HIG_cjs.a}});Object.defineProperty(exports,"DirectiveError",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.b}});Object.defineProperty(exports,"RequirementSet",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.o}});Object.defineProperty(exports,"forType",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.n}});Object.defineProperty(exports,"generateRequirementId",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.k}});Object.defineProperty(exports,"isNamespacedSystem",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.h}});Object.defineProperty(exports,"isRequirementType",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.m}});Object.defineProperty(exports,"isSingleModuleSystem",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.g}});Object.defineProperty(exports,"req",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.l}});Object.defineProperty(exports,"typedConstraint",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.e}});Object.defineProperty(exports,"typedResolver",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.f}});Object.defineProperty(exports,"applyPatch",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.v}});Object.defineProperty(exports,"evaluateKeySelector",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.u}});Object.defineProperty(exports,"evaluatePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.o}});Object.defineProperty(exports,"evaluatePredicateExplained",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.p}});Object.defineProperty(exports,"evaluateTemplate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.s}});Object.defineProperty(exports,"extractDeps",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.r}});Object.defineProperty(exports,"extractTemplateKeys",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.t}});Object.defineProperty(exports,"getKind",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.c}});Object.defineProperty(exports,"getOperatorsForKind",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.e}});Object.defineProperty(exports,"getSchemaFieldKinds",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.d}});Object.defineProperty(exports,"isPredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.h}});Object.defineProperty(exports,"isTemplate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.k}});Object.defineProperty(exports,"listAllPredicateOperators",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.f}});Object.defineProperty(exports,"memoizePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.q}});Object.defineProperty(exports,"validatePredicate",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.l}});Object.defineProperty(exports,"validatePredicateAgainstSchema",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.n}});Object.defineProperty(exports,"diffSnapshots",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.k}});Object.defineProperty(exports,"isSignedSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.l}});Object.defineProperty(exports,"isSnapshotExpired",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.i}});Object.defineProperty(exports,"shallowEqual",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.g}});Object.defineProperty(exports,"signSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.m}});Object.defineProperty(exports,"validateSnapshot",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.j}});Object.defineProperty(exports,"verifySnapshotSignature",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.n}});exports.Backoff=Tr;exports.MAX_REPLAY_FRAMES=A;exports.MAX_SWEEP_POINTS=ue;exports.completeTimer=it;exports.createModule=Ye;exports.createModuleFactory=xn;exports.createRequirementStatusPlugin=Te;exports.createStatusHook=jn;exports.createSystemWithStatus=Pn;exports.defaultClock=Nn;exports.describePredicate=Vt;exports.diffClauses=xe;exports.diffRules=zt;exports.doctor=Zt;exports.elapsedMs=ee;exports.flattenPredicate=S;exports.framesFromHistory=Ce;exports.framesFromSnapshots=ae;exports.initialTimerState=ke;exports.pauseTimer=tt;exports.predicateHash=Ht;exports.predicateToMongo=$n;exports.predicateToPostgrest=Tn;exports.predicateToSQL=pn;exports.predicateToWhere=gn;exports.predict=Qt;exports.realClock=Ge;exports.registerRepeat=ot;exports.remainingMs=Ve;exports.replayUnder=H;exports.resetTimer=rt;exports.resumeTimer=nt;exports.startTimer=et;exports.sweepUnder=qt;exports.t=vn;exports.tickTimer=st;exports.timerOps=_n;exports.toReplayFrames=Re;exports.toRulesMap=le;exports.virtualClock=Fn;//# sourceMappingURL=index.cjs.map | ||
| //# sourceMappingURL=index.cjs.map |
+2
-2
@@ -1,5 +0,5 @@ | ||
| export{b as createAuditLedger,a as memorySink}from'./chunk-KGTBTGOY.js';import {a as a$2}from'./chunk-E53A4NHM.js';export{a as createSystem}from'./chunk-E53A4NHM.js';export{b as DirectiveError,o as RequirementSet,n as forType,k as generateRequirementId,h as isNamespacedSystem,m as isRequirementType,g as isSingleModuleSystem,l as req,e as typedConstraint,f as typedResolver}from'./chunk-6QAUJFQH.js';import {o,p as p$1,i,g,a as a$1,l,h as h$1,b as b$1}from'./chunk-RBF653NR.js';export{v as applyPatch,u as evaluateKeySelector,o as evaluatePredicate,p as evaluatePredicateExplained,s as evaluateTemplate,r as extractDeps,t as extractTemplateKeys,c as getKind,e as getOperatorsForKind,d as getSchemaFieldKinds,h as isPredicate,k as isTemplate,f as listAllPredicateOperators,q as memoizePredicate,l as validatePredicate,n as validatePredicateAgainstSchema}from'./chunk-RBF653NR.js';import {k as k$1}from'./chunk-6PF2FRBG.js';import {e,h,a}from'./chunk-SFUVPP4L.js';export{k as diffSnapshots,l as isSignedSnapshot,i as isSnapshotExpired,g as shallowEqual,m as signSnapshot,j as validateSnapshot,n as verifySnapshotSignature}from'./chunk-SFUVPP4L.js';var A=1e6;function Me(e,t){try{l(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!h$1(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(i(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!a$1.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!a$1.has(r)&&!b$1.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...a$1].join(", ")}`)}function Re(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Ce(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>A)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,s={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(s.timestamp=i.timestamp),s}return {id:`#${r}`,facts:n??{}}})}function Ce(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return se(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return se(n.snapshots)}function se(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>A)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return Re(e)}function H(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,s=e.maxSamples??20,o$1=s>0?s:0;if(t.length>A)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);Me(n,"original"),Me(r,"proposed");let u=0,a=0,c=0,l=0,d=0,g=[],y=[],$=i?new Set:void 0,m=i?new Set:void 0,M;for(let F of t){let T=F.facts,v=o(n,T,M),R=o(r,T,M);v&&(u++,$?.add(T[i])),R&&(a++,m?.add(T[i])),v===R?d++:!v&&R?(c++,g.length<o$1&&g.push(De(F,n,r,M))):(l++,y.length<o$1&&y.push(De(F,n,r,M))),M=T;}let E={framesEvaluated:t.length,original:{matched:u},proposed:{matched:a},delta:a-u,newMatchCount:c,lostMatchCount:l,unchanged:d,newMatches:g,lostMatches:y};return $&&m&&(E.original.matchedEntities=$.size,E.proposed.matchedEntities=m.size),E}function De(e,t,n,r){let i=e.facts,s={frameId:e.id,facts:i,originalExplain:p$1(t,i,r),proposedExplain:p$1(n,i,r)};return e.timestamp!==void 0&&(s.timestamp=e.timestamp),s}var ae=1e4,Ae=5e7;function It(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function ue(e,t,n=new Set,r=0){if(r>g)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${g}) \u2014 flatten the template or split the sweep`);if(It(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(s=>ue(s,t,n,r+1));let i={};for(let[s,o]of Object.entries(e))i[s]=ue(o,t,n,r+1);return i}finally{n.delete(e);}}function*Ee(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let s of i)for(let o of Ee(r,t))yield {[n]:s,...o};}function Lt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function qt(e){let{frames:t,original:n,template:r,sweep:i,objective:s=T=>T.proposed.matched,entityKey:o,maxSamples:u=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let c=Lt(i);if(c>ae)throw new Error(`[Directive] sweepUnder: grid has ${c} points, exceeds the MAX_SWEEP_POINTS limit (${ae}) \u2014 narrow the sweep ranges or split the run`);if(c===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=c*t.length;if(l>Ae)throw new Error(`[Directive] sweepUnder: ${c} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Ae}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,g=T=>{let v;try{v=s(T);}catch(R){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${R.message})`)),Number.NEGATIVE_INFINITY}return typeof v!="number"||!Number.isFinite(v)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(v)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):v},y=H({frames:t,original:n,proposed:n,entityKey:o,maxSamples:u}),$={values:{},report:y,score:g(y)},m=[],M=0,E=Number.NEGATIVE_INFINITY;for(let T of Ee(a,i)){let v=ue(r,T),R=H({frames:t,original:n,proposed:v,entityKey:o,maxSamples:u}),te=g(R);te>E&&(E=te,M=m.length),m.push({values:T,report:R,score:te});}let F=m[M];return {points:m,bestIndex:M,best:F,baseline:$}}function ce(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var Wt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Bt=new Set(["$all","$any","$not"]);function xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ut(e){if(!xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;Wt.has(r)&&(n=true);}return n}function S(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,s)=>{S(i,`${t}$all[${s}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,s)=>{S(i,`${t}$any[${s}]`,n);}),n;if("$not"in e)return S(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let s=t?`${t}.${r}`:r;if(Ut(i))for(let[o,u]of Object.entries(i))n.push({path:s,op:o,value:u});else xe(i)&&!Bt.has(r)?S(i,s,n):n.push({path:s,op:"$eq",value:i});}return n}function C(e){return typeof e=="number"&&Number.isFinite(e)}function Kt(e,t,n){switch(e){case "$gte":case "$gt":if(C(t)&&C(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(C(t)&&C(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&C(t[0])&&C(t[1])&&C(n[0])&&C(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function zt(e){let t=ce(e.before),n=ce(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),s=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let u of i){let a=t[u],c=n[u],l=u in t,d=u in n;if(l&&!d){let y=S(a),$=y.length===0?[{path:"(function-form predicate)",kind:"removed"}]:y.map(m=>({path:m.path,kind:"removed",before:{op:m.op,value:m.value}}));le($),s.push({id:u,status:"removed",changes:$}),o.removed++,o.totalClauseChanges+=$.length;continue}if(!l&&d){let y=S(c),$=y.length===0?[{path:"(function-form predicate)",kind:"added"}]:y.map(m=>({path:m.path,kind:"added",after:{op:m.op,value:m.value}}));le($),s.push({id:u,status:"added",changes:$}),o.added++,o.totalClauseChanges+=$.length;continue}let g=Oe(a,c);g.length===0?(s.push({id:u,status:"unchanged",changes:[]}),o.unchanged++):(s.push({id:u,status:"changed",changes:g}),o.changed++,o.totalClauseChanges+=g.length);}return {constraints:s,summary:o}}function Oe(e$1,t){if(e$1!==void 0&&t!==void 0&&(e$1===null||t===null||typeof e$1!="object"||typeof t!="object"))return e(e$1)===e(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e$1},after:{op:"$eq",value:t}}];let n=e$1===void 0?[]:S(e$1),r=t===void 0?[]:S(t),i=c=>`${c.path}::${c.op}`,s=new Map(n.map(c=>[i(c),c])),o=new Map(r.map(c=>[i(c),c])),u=new Set([...s.keys(),...o.keys()]),a=[];for(let c of u){let l=s.get(c),d=o.get(c);if(l&&!d){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(l&&d){if(e(l.value)===e(d.value))continue;let g=Kt(l.op,l.value,d.value);a.push({path:l.path,kind:g??"changed",before:{op:l.op,value:l.value},after:{op:d.op,value:d.value}});}}return le(a),a}function le(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",s=n.before?.op??n.after?.op??"";return i.localeCompare(s)});}function Ht(e){return h(e)}function J(e){return e===null?"null":e===void 0?"undefined":e instanceof Date?e.toISOString():typeof e=="string"||typeof e=="object"?JSON.stringify(e):String(e)}function Jt(e){let t=e.path,n=J(e.expected),r=J(e.actual);switch(e.op){case "$eq":return `set ${t} to ${n} (currently ${r})`;case "$ne":return `change ${t} to anything other than ${n} (currently ${r})`;case "$gt":return `set ${t} above ${n} (currently ${r})`;case "$gte":return `set ${t} to at least ${n} (currently ${r})`;case "$lt":return `set ${t} below ${n} (currently ${r})`;case "$lte":return `set ${t} to at most ${n} (currently ${r})`;case "$in":return `set ${t} to one of ${n} (currently ${r})`;case "$nin":return `set ${t} to something other than ${n} (currently ${r})`;case "$exists":return e.expected===true?`set ${t} to a non-null value (currently null/missing)`:`unset ${t} (currently ${r})`;case "$between":return Array.isArray(e.expected)&&e.expected.length===2?`set ${t} between ${J(e.expected[0])} and ${J(e.expected[1])} (currently ${r})`:`set ${t} within range ${n} (currently ${r})`;case "$startsWith":return `set ${t} to start with ${n} (currently ${r})`;case "$endsWith":return `set ${t} to end with ${n} (currently ${r})`;case "$contains":return `set ${t} to contain ${n} (currently ${r})`;case "$matches":return `set ${t} to match the pattern ${n} (currently ${r})`;case "$changed":return `the previous-vs-current change of ${t} is required to differ (currently they match: ${r})`;case "$all":case "$any":case "$not":return `the ${e.op} group at "${t}" did not pass \u2014 see its child clauses`;default:return `clause at ${t} (${e.op}) failed: expected ${n}, got ${r}`}}function je(e,t){for(let n of e)if(!n.pass){if((n.op==="$all"||n.op==="$any"||n.op==="$not")&&n.children){je(n.children,t);continue}t.push({path:n.path,op:n.op,expected:n.expected,actual:n.actual,suggestion:Jt(n)});}}function Qt(e,t,n){let r=p$1(e,t,n),i$1=r.every(o=>o.pass),s=[];if(i$1||je(r,s),!i$1&&n===void 0){let o=[];i(e,{operator(u,a){a==="$changed"&&o.push(u);}});for(let u of o)s.push({path:u,op:"$changed",expected:true,actual:void 0,suggestion:`$changed clause at "${u}" cannot be evaluated without a \`prev\` snapshot \u2014 pass predict(predicate, facts, prev).`});}return {wouldFire:i$1,whenExplain:r,missingChanges:s}}var Pe=new Set(["$eq","$ne","$gt","$gte","$lt","$lte","$in","$nin"]);function Q(e,t){if(e===t)return 0;if(typeof e=="number"&&typeof t=="number"||typeof e=="bigint"&&typeof t=="bigint")return e<t?-1:e>t?1:0;if(e instanceof Date&&t instanceof Date){let n=e.getTime(),r=t.getTime();return n<r?-1:n>r?1:0}return typeof e=="string"&&typeof t=="string"?e<t?-1:e>t?1:0:Number.NaN}function _(e,t){if(e===t)return true;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let i=0;i<e.length;i++)if(!_(e[i],t[i]))return false;return true}let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return false;for(let i of n)if(!_(e[i],t[i]))return false;return true}function Xt(e,t){if(!Pe.has(e.op)||!Pe.has(t.op))return {type:"overlap",reason:`Both rules touch "${e.path}".`};if(e.op==="$eq"&&t.op==="$eq")return _(e.value,t.value)?{type:"subset",reason:`Both rules require ${e.path} = ${JSON.stringify(e.value)} \u2014 candidate is redundant.`}:{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires ${e.path} = ${JSON.stringify(t.value)} \u2014 they cannot both fire.`};if(e.op==="$eq"&&t.op==="$ne")return _(e.value,t.value)?{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule excludes that value.`}:null;if(e.op==="$ne"&&t.op==="$eq")return _(e.value,t.value)?{type:"direct",reason:`Candidate excludes ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires that exact value.`}:null;if(e.op==="$in"&&t.op==="$in"){let o=new Set(Array.isArray(e.value)?e.value:[]),u=new Set(Array.isArray(t.value)?t.value:[]),a=[...o].filter(c=>u.has(c));return a.length===0?{type:"direct",reason:`Candidate $in set for ${e.path} (${JSON.stringify([...o])}) and existing $in set (${JSON.stringify([...u])}) have no values in common \u2014 the candidate can never fire while the existing rule holds.`}:a.length===o.size&&a.length<u.size?{type:"subset",reason:`Candidate $in set for ${e.path} is a strict subset of the existing rule's $in set.`}:null}let n=e.op==="$gt"||e.op==="$gte"?e.value:void 0,r=e.op==="$lt"||e.op==="$lte"?e.value:void 0,i=t.op==="$gt"||t.op==="$gte"?t.value:void 0,s=t.op==="$lt"||t.op==="$lte"?t.value:void 0;if(n!==void 0&&s!==void 0){let o=Q(n,s);if(!Number.isNaN(o)&&(o>0||o===0&&(e.op==="$gt"||t.op==="$lt")))return {type:"direct",reason:`Candidate requires ${e.path} ${e.op==="$gt"?">":"\u2265"} ${JSON.stringify(n)} but an existing rule caps it at ${t.op==="$lt"?"<":"\u2264"} ${JSON.stringify(s)}.`}}if(i!==void 0&&r!==void 0){let o=Q(i,r);if(!Number.isNaN(o)&&(o>0||o===0&&(t.op==="$gt"||e.op==="$lt")))return {type:"direct",reason:`Candidate caps ${e.path} at ${e.op==="$lt"?"<":"\u2264"} ${JSON.stringify(r)} but an existing rule requires it ${t.op==="$gt"?">":"\u2265"} ${JSON.stringify(i)}.`}}if(n!==void 0&&i!==void 0){let o=Q(n,i);if(!Number.isNaN(o)&&o>0)return {type:"subset",reason:`Candidate's lower bound on ${e.path} (${JSON.stringify(n)}) is stricter than the existing rule's lower bound (${JSON.stringify(i)}) \u2014 candidate is a subset.`}}if(r!==void 0&&s!==void 0){let o=Q(r,s);if(!Number.isNaN(o)&&o<0)return {type:"subset",reason:`Candidate's upper bound on ${e.path} (${JSON.stringify(r)}) is stricter than the existing rule's upper bound (${JSON.stringify(s)}) \u2014 candidate is a subset.`}}return {type:"overlap",reason:`Both rules constrain "${e.path}".`}}function Fe(e){return typeof e=="object"&&e!==null&&typeof e.id=="string"}var Zt={checkAgainst(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {contradictions:[],warnings:[]};let i=new Map;for(let u of r){let a=i.get(u.path)??[];a.push(u),i.set(u.path,a);}let s=[],o=[];for(let u of n){if(!Fe(u)||u.whenSpec===void 0)continue;let a=S(u.whenSpec);for(let c of a){let l=i.get(c.path);if(l)for(let d of l){let g=Xt(d,c);if(!g)continue;let y={constraintId:u.id,type:g.type,reason:g.reason,candidatePath:d.path,candidate:{op:d.op,value:d.value},existing:{op:c.op,value:c.value}};g.type==="overlap"||g.type==="subset"?o.push(y):s.push(y);}}}return {contradictions:s,warnings:o}},checkOwns(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {warnings:[]};let i=new Set(r.map(o=>o.path)),s=[];for(let o of n){if(!Fe(o))continue;let u=Array.isArray(o.owns)?o.owns:[],a=Array.isArray(o.bind)?o.bind:[];for(let c of u)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"owns",reason:`Constraint "${o.id}" already owns "${c}" \u2014 candidate would race or shadow its writes.`,severity:"warning"});for(let c of a)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"bind",reason:`Constraint "${o.id}" binds "${c}" \u2014 candidate would write to a bound field.`,severity:"warning"});}return {warnings:s}}};var I=new Map,Yt=50;function Gt(e){let t=I.get(e);if(!t){try{t=new Intl.NumberFormat(e);}catch{t=new Intl.NumberFormat("en-US");}if(I.size>=Yt){let n=I.keys().next().value;n!==void 0&&I.delete(n);}I.set(e,t);}return t}function Vt(e,t={}){let n=t.style??"natural",r=t.parenthesize??true,i=t.locale??"en-US",s=t.factName??(a=>a);if(e===null||typeof e!="object")return "<invalid predicate>";let o={style:n,parenthesize:r,locale:i,factName:s,seen:new WeakSet,cycle:false},u=X(e,o,0);return o.cycle?"<invalid predicate: cycle>":u}var Ie=" AND ",en=" OR ",tn="NOT",Le=" \u2227 ",nn=" \u2228 ",rn="\xAC";function q(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function on(e){if(!q(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function X(e,t,n){if(n>g)return a&&console.warn(`[Directive] describePredicate: depth limit (${g}) exceeded \u2014 bailing.`),t.style==="formal"?"\u22A5":"always true";if(Array.isArray(e))return sn(e,t);if(!q(e))return f(e,t);if(t.seen.has(e))return t.cycle=true,"<invalid predicate: cycle>";t.seen.add(e);let r=e,i=Object.keys(r);for(let o of ["$all","$any","$not"])if(o in r)return an(o,r[o],t,n);let s=[];for(let o of i)o.startsWith("$")||s.push(qe(o,r[o],t,n));return Z(s,t)}function sn(e,t,n){let r=[];for(let i of e){if(!q(i))continue;let s=i;typeof s.fact!="string"||typeof s.op!="string"||r.push(L(s.fact,s.op,s.value,t));}return r.length===0?t.style==="formal"?"\u22A4":"always true":Z(r,t)}function an(e,t,n,r){if(e==="$not"){if(q(t)&&Object.keys(t).length===0)return n.style==="formal"?"\u22A5":"never";let o=X(t,n,r+1);return o==="always true"?"never":o==="\u22A4"?"\u22A5":`${n.style==="formal"?rn:`${tn} `}(${o})`}if(!Array.isArray(t))return n.style==="formal"?"\u22A5":"<invalid predicate>";if(t.length===0)return e==="$all"?n.style==="formal"?"\u22A4":"always true":n.style==="formal"?"\u22A5":"never";let i=[];for(let o of t){let u=X(o,n,r+1);i.push(u);}if(i.length===1)return i[0];let s=n.parenthesize?i.map(o=>`(${o})`):i;return e==="$all"?s.join(n.style==="formal"?Le:Ie):s.join(n.style==="formal"?nn:en)}function qe(e,t,n,r){if(on(t)){let i=t,s=Object.keys(i);if(s.length===1)return L(e,s[0],i[s[0]],n);let o=s.map(u=>L(e,u,i[u],n));return Z(o,n)}if(q(t)){let i=t;if("$all"in i||"$any"in i||"$not"in i)return X(t,n,r+1);let o=[];for(let u of Object.keys(i))u.startsWith("$")||o.push(qe(`${e}.${u}`,i[u],n,r+1));return o.length===0?L(e,"$eq",t,n):Z(o,n)}return L(e,"$eq",t,n)}function L(e,t,n,r){let i=r.style==="formal"?e:r.factName(e);return r.style==="formal"?cn(i,t,n,r):un(i,t,n,r)}function un(e,t,n,r){switch(t){case "$eq":return n===null?`${e} is null`:`${e} is ${f(n,r)}`;case "$ne":return n===null?`${e} is not null`:`${e} is not ${f(n,r)}`;case "$gt":return `${e} is more than ${f(n,r)}`;case "$gte":return `${e} is at least ${f(n,r)}`;case "$lt":return `${e} is less than ${f(n,r)}`;case "$lte":return `${e} is at most ${f(n,r)}`;case "$in":return `${e} is one of ${Ne(n,r)}`;case "$nin":return `${e} is not one of ${Ne(n,r)}`;case "$exists":return n===true?`${e} is set`:`${e} is not set`;case "$between":return Array.isArray(n)&&n.length===2?`${e} is between ${f(n[0],r)} and ${f(n[1],r)}`:`${e} is between ${f(n,r)}`;case "$startsWith":return `${e} starts with ${O(n,r,true)}`;case "$endsWith":return `${e} ends with ${O(n,r,true)}`;case "$contains":return `${e} contains ${O(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} matches ${n.toString()}`:`${e} matches ${f(n,r)}`;case "$changed":return `${e} changed`;default:return a&&!a$1.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function cn(e,t,n,r){switch(t){case "$eq":return `${e} = ${f(n,r)}`;case "$ne":return `${e} \u2260 ${f(n,r)}`;case "$gt":return `${e} > ${f(n,r)}`;case "$gte":return `${e} \u2265 ${f(n,r)}`;case "$lt":return `${e} < ${f(n,r)}`;case "$lte":return `${e} \u2264 ${f(n,r)}`;case "$in":return `${e} \u2208 {${_e(n,r)}}`;case "$nin":return `${e} \u2209 {${_e(n,r)}}`;case "$exists":return n===true?`\u2203 ${e}`:`\u2204 ${e}`;case "$between":return Array.isArray(n)&&n.length===2?`${f(n[0],r)} \u2264 ${e} \u2264 ${f(n[1],r)}`:`${e} \u2208 [${f(n,r)}]`;case "$startsWith":return `${e} ^= ${O(n,r,true)}`;case "$endsWith":return `${e} $= ${O(n,r,true)}`;case "$contains":return `${e} \u2287 ${O(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} ~ ${n.toString()}`:`${e} ~ ${f(n,r)}`;case "$changed":return `\u0394${e}`;default:return a&&!a$1.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function Y(e){return e.length===0?true:/[\s,"']/.test(e)}function O(e,t,n){return typeof e!="string"||n||Y(e)?JSON.stringify(e):e}function f(e,t){if(e===null)return "null";if(e===void 0)return "undefined";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"){if(!Number.isFinite(e))return String(e);try{return Gt(t.locale).format(e)}catch{return String(e)}}if(typeof e=="bigint")return t.style==="formal"?`${e.toString()}n`:e.toString();if(typeof e=="string")return t.style==="formal"||Y(e)?JSON.stringify(e):e;if(e instanceof Date)return e.toISOString();if(e instanceof RegExp)return e.toString();if(Array.isArray(e))return `[${e.map(n=>f(n,t)).join(", ")}]`;if(typeof e=="object")try{return JSON.stringify(e)}catch{return "[object]"}return String(e)}function Ne(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function _e(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function Z(e,t){if(e.length===0)return t.style==="formal"?"\u22A4":"always true";if(e.length===1)return e[0];let n=t.style==="formal"?Le:Ie;return t.parenthesize,e.join(n)}var ln=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function B(e,t){if(typeof e!="string"||!ln.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function We(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function dn(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)B(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(B(t,"column"),t)}function b(e,t){return e.params.push(t),e.placeholder(e.params.length)}function de(e,t,n,r){switch(t){case "$eq":return `${e} = ${b(r,n)}`;case "$ne":return `${e} <> ${b(r,n)}`;case "$gt":return `${e} > ${b(r,n)}`;case "$gte":return `${e} >= ${b(r,n)}`;case "$lt":return `${e} < ${b(r,n)}`;case "$lte":return `${e} <= ${b(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${b(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${b(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${b(r,n[0])} AND ${b(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${b(r,fe(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${b(r,fe(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${b(r,fe(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${b(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...a$1].join(", ")}`)}}function fe(e){return e.replace(/[\\%_]/g,"\\$&")}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function fn(e){if(!Be(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function pe(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function W(e,t,n){if(n>g)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(s=>{if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let o=s;return B(o.fact,"column"),We(o.fact,t.allowed),de(o.fact,o.op,o.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){pe(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" AND ")})`}if("$any"in e){pe(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" OR ")})`}if("$not"in e){pe(e,"$not");let i=e.$not;return `NOT (${W(i,t,n+1)})`}let r=[];for(let[i,s]of Object.entries(e))if(B(i,"column"),We(i,t.allowed),fn(s))for(let[o,u]of Object.entries(s)){if(!a$1.has(o))throw new Error(`[Directive] predicateToSQL: unknown operator "${o}" on column "${i}" \u2014 known: ${[...a$1].join(", ")}`);r.push(de(i,o,u,t));}else {if(Be(s))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(de(i,"$eq",s,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var Ue=e=>`$${e}`;function pn(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??Ue,s=t.select??"*";B(n,"table");let o=dn(s),u={params:[],placeholder:i,allowed:r},a=W(e,u,0);return {sql:`SELECT ${o} FROM ${n} WHERE ${a}`,where:a,params:u.params}}function gn(e,t={}){let n=t.placeholder??Ue,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:W(e,r,0),params:r.params}}function ge(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function he(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function yn(e){if(!he(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var hn=/^[A-Za-z_][A-Za-z0-9_]*$/,mn=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function Ke(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?mn:hn).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function ze(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function ye(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function He(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${ge(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${ge(t)}$`};case "$contains":if(typeof t=="string")return {$regex:ge(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...a$1].join(", ")}`)}}function j(e,t,n){if(n>g)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let u=o;Ke(u.fact,t),ze(u.fact,t.allowedKeys);let a=He(u.op,u.value);if(u.fact in i&&he(i[u.fact])){let c=i[u.fact];Object.keys(a).some(d=>d in c)?s.push({[u.fact]:a}):i[u.fact]={...c,...a};}else u.fact in i?s.push({[u.fact]:a}):i[u.fact]=a;}if(s.length>0){let o=[];for(let[u,a]of Object.entries(i))o.push({[u]:a});return o.push(...s),{$and:o}}return i}if("$all"in e){ye(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?j(i[0],t,n+1):{$and:i.map(s=>j(s,t,n+1))}}if("$any"in e){ye(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?j(i[0],t,n+1):{$or:i.map(s=>j(s,t,n+1))}}if("$not"in e){ye(e,"$not");let i=e.$not;return {$nor:[j(i,t,n+1)]}}let r={};for(let[i,s]of Object.entries(e))if(Ke(i,t),ze(i,t.allowedKeys),yn(s)){let o={};for(let[u,a]of Object.entries(s)){if(!a$1.has(u))throw new Error(`[Directive] predicateToMongo: unknown operator "${u}" on field "${i}" \u2014 known: ${[...a$1].join(", ")}`);Object.assign(o,He(u,a));}r[i]=o;}else r[i]=s;return r}function $n(e,t={}){return j(e,t,0)}var wn=/^[A-Za-z_][A-Za-z0-9_]*$/;function Je(e,t){if(typeof e!="string"||!wn.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function me(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function k(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function Qe(e){return `(${e.map(k).join(",")})`}function $e(e){return e.replace(/[\\%_*]/g,"\\$&")}function P(e,t){switch(e){case "$eq":return `eq.${k(t)}`;case "$ne":return `neq.${k(t)}`;case "$gt":return `gt.${k(t)}`;case "$gte":return `gte.${k(t)}`;case "$lt":return `lt.${k(t)}`;case "$lte":return `lte.${k(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${Qe(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${Qe(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${k(`${$e(t)}*`)}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${k(`*${$e(t)}`)}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${k(`*${$e(t)}*`)}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${k(t.source)}`;if(typeof t=="string")return `match.${k(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...a$1].join(", ")}`)}}function Xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function bn(e){if(!Xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function we(e,t){return `${e}=${t}`}function G(e,t){return `${e}=(${t.join(",")})`}function be(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?we(e,P("$gte",n[0])):`${e}.${P("$gte",n[0])}`,s=r?we(e,P("$lte",n[1])):`${e}.${P("$lte",n[1])}`;return [i,s]}return [r?we(e,P(t,n)):`${e}.${P(t,n)}`]}function U(e,t,n,r){if(r>g)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let u=o;Je(u.fact,t),s.push(...be(u.fact,u.op,u.value,n));}return s}if("$all"in e){me(e,"$all");let s=e.$all;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let u=[];for(let a of s)u.push(...U(a,t,true,r+1));return u}let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("and",o)]}if("$any"in e){me(e,"$any");let s=e.$any;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(s.length===0)return n?["id=is.null","id=not.is.null"]:[G("and",["id.is.null","id.not.is.null"])];let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("or",o)]}if("$not"in e){me(e,"$not");let s=e.$not,o=U(s,t,false,r+1);return [G("not.and",o)]}let i=[];for(let[s,o]of Object.entries(e))if(Je(s,t),bn(o))for(let[u,a]of Object.entries(o)){if(!a$1.has(u))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${u}" on column "${s}" \u2014 known: ${[...a$1].join(", ")}`);i.push(...be(s,u,a,n));}else {if(Xe(o))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${s}" \u2014 single-table queries only`);i.push(...be(s,"$eq",o,n));}return i}function Sn(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Tn(e,t={}){let n=t.mode??"querystring",r=U(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(Sn).join("&")}function V(e=[],t,n,r,i,s,o){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:s,_meta:o,validate(u){return V([...e,u],t,n,r,i,s,o)}}}function p(e,t,n,r,i,s,o){return {...V(e,t,n,r,i,s,o),default(a){return p(e,t,a,r,i,s,o)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,o)},brand(){return p(e,`Branded<${t}>`,n,r,i,s,o)},describe(a){return p(e,t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return p([...e,a],t,n,r,i,l,o)},nullable(){return p([a=>a===null||e.every(c=>c(a))],`${t} | null`,n,r,i,void 0,o)},optional(){return p([a=>a===void 0||e.every(c=>c(a))],`${t} | undefined`,n,r,i,void 0,o)},meta(a){return p(e,t,n,r,i,s,a)}}}var kn=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),vn={string(){let e=(t,n,r,i,s,o)=>({...p(t,"string",n,r,i,s,o),minLength(a){return e([...t,c=>c.length>=a],n,r,i,s,o)},maxLength(a){return e([...t,c=>c.length<=a],n,r,i,s,o)},pattern(a){return e([...t,c=>a.test(c)],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,s,o)=>({...p(t,"number",n,r,i,s,o),min(a){return e([...t,c=>c>=a],n,r,i,s,o)},max(a){return e([...t,c=>c<=a],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,s,o)=>{let u=p(t,"array",r,void 0,i,void 0,o),a=s??{value:-1};return {...u,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,g=>{for(let y=0;y<g.length;y++)if(!l._validators.every($=>$(g[y])))return d.value=y,false;return true}],l,r,i,d,o)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,o)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,o)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,o)},default(l){return e(t,n,l,i,a,o)},describe(l){return e(t,n,r,l,a,o)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(o){return e([...t,u=>{for(let[a,c]of Object.entries(o)){let l=u[a],d=c;if(d&&!d._validators.every(g=>g(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,o=>o!=null],n,r,i)},hasKeys(...o){return e([...t,u=>o.every(a=>a in u)],n,r,i)},default(o){return e(t,o,r,i)},describe(o){return e(t,n,o,i)},meta(o){return e(t,n,r,o)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return V([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return V([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:kn,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(s=>s(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Mn(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function Ze(e,t,n,r,i){for(let s of e)t.has(s)||console.warn(`[Directive] ${n} "${s}" not declared in ${r}`);for(let s of t)e.has(s)||console.warn(`[Directive] ${r}["${s}"] ${i}`);}function Dn(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Rn(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let s=i;typeof s.requirement=="string"&&!n.has(s.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${s.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function Cn(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),s="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let o of s)i.add(o);for(let o of r)if(i.has(o))throw new Error(`[Directive] module '${e}': fact key '${o}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes: | ||
| export{b as createAuditLedger,a as memorySink}from'./chunk-KGTBTGOY.js';import {a as a$2}from'./chunk-YJEDX2JX.js';export{a as createSystem}from'./chunk-YJEDX2JX.js';export{b as DirectiveError,o as RequirementSet,n as forType,k as generateRequirementId,h as isNamespacedSystem,m as isRequirementType,g as isSingleModuleSystem,l as req,e as typedConstraint,f as typedResolver}from'./chunk-6NCC6RBC.js';import {o,p as p$1,i,g,a as a$1,l,h as h$1,b as b$1}from'./chunk-RBF653NR.js';export{v as applyPatch,u as evaluateKeySelector,o as evaluatePredicate,p as evaluatePredicateExplained,s as evaluateTemplate,r as extractDeps,t as extractTemplateKeys,c as getKind,e as getOperatorsForKind,d as getSchemaFieldKinds,h as isPredicate,k as isTemplate,f as listAllPredicateOperators,q as memoizePredicate,l as validatePredicate,n as validatePredicateAgainstSchema}from'./chunk-RBF653NR.js';import {k as k$1}from'./chunk-6PF2FRBG.js';import {e,h,a}from'./chunk-SFUVPP4L.js';export{k as diffSnapshots,l as isSignedSnapshot,i as isSnapshotExpired,g as shallowEqual,m as signSnapshot,j as validateSnapshot,n as verifySnapshotSignature}from'./chunk-SFUVPP4L.js';var A=1e6;function Me(e,t){try{l(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!h$1(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(i(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!a$1.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!a$1.has(r)&&!b$1.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...a$1].join(", ")}`)}function Re(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Ce(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>A)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,s={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(s.timestamp=i.timestamp),s}return {id:`#${r}`,facts:n??{}}})}function Ce(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return ae(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return ae(n.snapshots)}function ae(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>A)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return Re(e)}function H(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,s=e.maxSamples??20,o$1=s>0?s:0;if(t.length>A)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${A}) \u2014 split or down-sample the history`);Me(n,"original"),Me(r,"proposed");let u=0,a=0,c=0,l=0,d=0,g=[],y=[],$=i?new Set:void 0,m=i?new Set:void 0,M;for(let F of t){let T=F.facts,v=o(n,T,M),R=o(r,T,M);v&&(u++,$?.add(T[i])),R&&(a++,m?.add(T[i])),v===R?d++:!v&&R?(c++,g.length<o$1&&g.push(De(F,n,r,M))):(l++,y.length<o$1&&y.push(De(F,n,r,M))),M=T;}let E={framesEvaluated:t.length,original:{matched:u},proposed:{matched:a},delta:a-u,newMatchCount:c,lostMatchCount:l,unchanged:d,newMatches:g,lostMatches:y};return $&&m&&(E.original.matchedEntities=$.size,E.proposed.matchedEntities=m.size),E}function De(e,t,n,r){let i=e.facts,s={frameId:e.id,facts:i,originalExplain:p$1(t,i,r),proposedExplain:p$1(n,i,r)};return e.timestamp!==void 0&&(s.timestamp=e.timestamp),s}var ue=1e4,Ae=5e7;function It(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function ce(e,t,n=new Set,r=0){if(r>g)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${g}) \u2014 flatten the template or split the sweep`);if(It(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(s=>ce(s,t,n,r+1));let i={};for(let[s,o]of Object.entries(e))i[s]=ce(o,t,n,r+1);return i}finally{n.delete(e);}}function*Ee(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let s of i)for(let o of Ee(r,t))yield {[n]:s,...o};}function Lt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function qt(e){let{frames:t,original:n,template:r,sweep:i,objective:s=T=>T.proposed.matched,entityKey:o,maxSamples:u=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let c=Lt(i);if(c>ue)throw new Error(`[Directive] sweepUnder: grid has ${c} points, exceeds the MAX_SWEEP_POINTS limit (${ue}) \u2014 narrow the sweep ranges or split the run`);if(c===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=c*t.length;if(l>Ae)throw new Error(`[Directive] sweepUnder: ${c} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Ae}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,g=T=>{let v;try{v=s(T);}catch(R){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${R.message})`)),Number.NEGATIVE_INFINITY}return typeof v!="number"||!Number.isFinite(v)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(v)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):v},y=H({frames:t,original:n,proposed:n,entityKey:o,maxSamples:u}),$={values:{},report:y,score:g(y)},m=[],M=0,E=Number.NEGATIVE_INFINITY;for(let T of Ee(a,i)){let v=ce(r,T),R=H({frames:t,original:n,proposed:v,entityKey:o,maxSamples:u}),te=g(R);te>E&&(E=te,M=m.length),m.push({values:T,report:R,score:te});}let F=m[M];return {points:m,bestIndex:M,best:F,baseline:$}}function le(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var Wt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Bt=new Set(["$all","$any","$not"]);function Oe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ut(e){if(!Oe(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;Wt.has(r)&&(n=true);}return n}function S(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,s)=>{S(i,`${t}$all[${s}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,s)=>{S(i,`${t}$any[${s}]`,n);}),n;if("$not"in e)return S(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let s=t?`${t}.${r}`:r;if(Ut(i))for(let[o,u]of Object.entries(i))n.push({path:s,op:o,value:u});else Oe(i)&&!Bt.has(r)?S(i,s,n):n.push({path:s,op:"$eq",value:i});}return n}function C(e){return typeof e=="number"&&Number.isFinite(e)}function Kt(e,t,n){switch(e){case "$gte":case "$gt":if(C(t)&&C(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(C(t)&&C(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&C(t[0])&&C(t[1])&&C(n[0])&&C(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function zt(e){let t=le(e.before),n=le(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),s=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let u of i){let a=t[u],c=n[u],l=u in t,d=u in n;if(l&&!d){let y=S(a),$=y.length===0?[{path:"(function-form predicate)",kind:"removed"}]:y.map(m=>({path:m.path,kind:"removed",before:{op:m.op,value:m.value}}));de($),s.push({id:u,status:"removed",changes:$}),o.removed++,o.totalClauseChanges+=$.length;continue}if(!l&&d){let y=S(c),$=y.length===0?[{path:"(function-form predicate)",kind:"added"}]:y.map(m=>({path:m.path,kind:"added",after:{op:m.op,value:m.value}}));de($),s.push({id:u,status:"added",changes:$}),o.added++,o.totalClauseChanges+=$.length;continue}let g=xe(a,c);g.length===0?(s.push({id:u,status:"unchanged",changes:[]}),o.unchanged++):(s.push({id:u,status:"changed",changes:g}),o.changed++,o.totalClauseChanges+=g.length);}return {constraints:s,summary:o}}function xe(e$1,t){if(e$1!==void 0&&t!==void 0&&(e$1===null||t===null||typeof e$1!="object"||typeof t!="object"))return e(e$1)===e(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e$1},after:{op:"$eq",value:t}}];let n=e$1===void 0?[]:S(e$1),r=t===void 0?[]:S(t),i=c=>`${c.path}::${c.op}`,s=new Map(n.map(c=>[i(c),c])),o=new Map(r.map(c=>[i(c),c])),u=new Set([...s.keys(),...o.keys()]),a=[];for(let c of u){let l=s.get(c),d=o.get(c);if(l&&!d){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(l&&d){if(e(l.value)===e(d.value))continue;let g=Kt(l.op,l.value,d.value);a.push({path:l.path,kind:g??"changed",before:{op:l.op,value:l.value},after:{op:d.op,value:d.value}});}}return de(a),a}function de(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",s=n.before?.op??n.after?.op??"";return i.localeCompare(s)});}function Ht(e){return h(e)}function J(e){return e===null?"null":e===void 0?"undefined":e instanceof Date?e.toISOString():typeof e=="string"||typeof e=="object"?JSON.stringify(e):String(e)}function Jt(e){let t=e.path,n=J(e.expected),r=J(e.actual);switch(e.op){case "$eq":return `set ${t} to ${n} (currently ${r})`;case "$ne":return `change ${t} to anything other than ${n} (currently ${r})`;case "$gt":return `set ${t} above ${n} (currently ${r})`;case "$gte":return `set ${t} to at least ${n} (currently ${r})`;case "$lt":return `set ${t} below ${n} (currently ${r})`;case "$lte":return `set ${t} to at most ${n} (currently ${r})`;case "$in":return `set ${t} to one of ${n} (currently ${r})`;case "$nin":return `set ${t} to something other than ${n} (currently ${r})`;case "$exists":return e.expected===true?`set ${t} to a non-null value (currently null/missing)`:`unset ${t} (currently ${r})`;case "$between":return Array.isArray(e.expected)&&e.expected.length===2?`set ${t} between ${J(e.expected[0])} and ${J(e.expected[1])} (currently ${r})`:`set ${t} within range ${n} (currently ${r})`;case "$startsWith":return `set ${t} to start with ${n} (currently ${r})`;case "$endsWith":return `set ${t} to end with ${n} (currently ${r})`;case "$contains":return `set ${t} to contain ${n} (currently ${r})`;case "$matches":return `set ${t} to match the pattern ${n} (currently ${r})`;case "$changed":return `the previous-vs-current change of ${t} is required to differ (currently they match: ${r})`;case "$all":case "$any":case "$not":return `the ${e.op} group at "${t}" did not pass \u2014 see its child clauses`;default:return `clause at ${t} (${e.op}) failed: expected ${n}, got ${r}`}}function je(e,t){for(let n of e)if(!n.pass){if((n.op==="$all"||n.op==="$any"||n.op==="$not")&&n.children){je(n.children,t);continue}t.push({path:n.path,op:n.op,expected:n.expected,actual:n.actual,suggestion:Jt(n)});}}function Qt(e,t,n){let r=p$1(e,t,n),i$1=r.every(o=>o.pass),s=[];if(i$1||je(r,s),!i$1&&n===void 0){let o=[];i(e,{operator(u,a){a==="$changed"&&o.push(u);}});for(let u of o)s.push({path:u,op:"$changed",expected:true,actual:void 0,suggestion:`$changed clause at "${u}" cannot be evaluated without a \`prev\` snapshot \u2014 pass predict(predicate, facts, prev).`});}return {wouldFire:i$1,whenExplain:r,missingChanges:s}}var Pe=new Set(["$eq","$ne","$gt","$gte","$lt","$lte","$in","$nin"]);function Q(e,t){if(e===t)return 0;if(typeof e=="number"&&typeof t=="number"||typeof e=="bigint"&&typeof t=="bigint")return e<t?-1:e>t?1:0;if(e instanceof Date&&t instanceof Date){let n=e.getTime(),r=t.getTime();return n<r?-1:n>r?1:0}return typeof e=="string"&&typeof t=="string"?e<t?-1:e>t?1:0:Number.NaN}function _(e,t){if(e===t)return true;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let i=0;i<e.length;i++)if(!_(e[i],t[i]))return false;return true}let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return false;for(let i of n)if(!_(e[i],t[i]))return false;return true}function Xt(e,t){if(!Pe.has(e.op)||!Pe.has(t.op))return {type:"overlap",reason:`Both rules touch "${e.path}".`};if(e.op==="$eq"&&t.op==="$eq")return _(e.value,t.value)?{type:"subset",reason:`Both rules require ${e.path} = ${JSON.stringify(e.value)} \u2014 candidate is redundant.`}:{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires ${e.path} = ${JSON.stringify(t.value)} \u2014 they cannot both fire.`};if(e.op==="$eq"&&t.op==="$ne")return _(e.value,t.value)?{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule excludes that value.`}:null;if(e.op==="$ne"&&t.op==="$eq")return _(e.value,t.value)?{type:"direct",reason:`Candidate excludes ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires that exact value.`}:null;if(e.op==="$in"&&t.op==="$in"){let o=new Set(Array.isArray(e.value)?e.value:[]),u=new Set(Array.isArray(t.value)?t.value:[]),a=[...o].filter(c=>u.has(c));return a.length===0?{type:"direct",reason:`Candidate $in set for ${e.path} (${JSON.stringify([...o])}) and existing $in set (${JSON.stringify([...u])}) have no values in common \u2014 the candidate can never fire while the existing rule holds.`}:a.length===o.size&&a.length<u.size?{type:"subset",reason:`Candidate $in set for ${e.path} is a strict subset of the existing rule's $in set.`}:null}let n=e.op==="$gt"||e.op==="$gte"?e.value:void 0,r=e.op==="$lt"||e.op==="$lte"?e.value:void 0,i=t.op==="$gt"||t.op==="$gte"?t.value:void 0,s=t.op==="$lt"||t.op==="$lte"?t.value:void 0;if(n!==void 0&&s!==void 0){let o=Q(n,s);if(!Number.isNaN(o)&&(o>0||o===0&&(e.op==="$gt"||t.op==="$lt")))return {type:"direct",reason:`Candidate requires ${e.path} ${e.op==="$gt"?">":"\u2265"} ${JSON.stringify(n)} but an existing rule caps it at ${t.op==="$lt"?"<":"\u2264"} ${JSON.stringify(s)}.`}}if(i!==void 0&&r!==void 0){let o=Q(i,r);if(!Number.isNaN(o)&&(o>0||o===0&&(t.op==="$gt"||e.op==="$lt")))return {type:"direct",reason:`Candidate caps ${e.path} at ${e.op==="$lt"?"<":"\u2264"} ${JSON.stringify(r)} but an existing rule requires it ${t.op==="$gt"?">":"\u2265"} ${JSON.stringify(i)}.`}}if(n!==void 0&&i!==void 0){let o=Q(n,i);if(!Number.isNaN(o)&&o>0)return {type:"subset",reason:`Candidate's lower bound on ${e.path} (${JSON.stringify(n)}) is stricter than the existing rule's lower bound (${JSON.stringify(i)}) \u2014 candidate is a subset.`}}if(r!==void 0&&s!==void 0){let o=Q(r,s);if(!Number.isNaN(o)&&o<0)return {type:"subset",reason:`Candidate's upper bound on ${e.path} (${JSON.stringify(r)}) is stricter than the existing rule's upper bound (${JSON.stringify(s)}) \u2014 candidate is a subset.`}}return {type:"overlap",reason:`Both rules constrain "${e.path}".`}}function Fe(e){return typeof e=="object"&&e!==null&&typeof e.id=="string"}var Zt={checkAgainst(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {contradictions:[],warnings:[]};let i=new Map;for(let u of r){let a=i.get(u.path)??[];a.push(u),i.set(u.path,a);}let s=[],o=[];for(let u of n){if(!Fe(u)||u.whenSpec===void 0)continue;let a=S(u.whenSpec);for(let c of a){let l=i.get(c.path);if(l)for(let d of l){let g=Xt(d,c);if(!g)continue;let y={constraintId:u.id,type:g.type,reason:g.reason,candidatePath:d.path,candidate:{op:d.op,value:d.value},existing:{op:c.op,value:c.value}};g.type==="overlap"||g.type==="subset"?o.push(y):s.push(y);}}}return {contradictions:s,warnings:o}},checkAbortOn(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=S(e);if(r.length===0)return {warnings:[]};let i=new Set(r.map(o=>o.path)),s=[];for(let o of n){if(!Fe(o))continue;let u=Array.isArray(o.abortOn)?o.abortOn:[],a=Array.isArray(o.bind)?o.bind:[];for(let c of u)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"abortOn",reason:`Constraint "${o.id}" aborts on "${c}" \u2014 candidate would race or shadow its writes.`,severity:"warning"});for(let c of a)i.has(c)&&s.push({constraintId:o.id,candidatePath:c,source:"bind",reason:`Constraint "${o.id}" binds "${c}" \u2014 candidate would write to a bound field.`,severity:"warning"});}return {warnings:s}}};var I=new Map,Yt=50;function Gt(e){let t=I.get(e);if(!t){try{t=new Intl.NumberFormat(e);}catch{t=new Intl.NumberFormat("en-US");}if(I.size>=Yt){let n=I.keys().next().value;n!==void 0&&I.delete(n);}I.set(e,t);}return t}function Vt(e,t={}){let n=t.style??"natural",r=t.parenthesize??true,i=t.locale??"en-US",s=t.factName??(a=>a);if(e===null||typeof e!="object")return "<invalid predicate>";let o={style:n,parenthesize:r,locale:i,factName:s,seen:new WeakSet,cycle:false},u=X(e,o,0);return o.cycle?"<invalid predicate: cycle>":u}var Ie=" AND ",en=" OR ",tn="NOT",Le=" \u2227 ",nn=" \u2228 ",rn="\xAC";function q(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function on(e){if(!q(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function X(e,t,n){if(n>g)return a&&console.warn(`[Directive] describePredicate: depth limit (${g}) exceeded \u2014 bailing.`),t.style==="formal"?"\u22A5":"always true";if(Array.isArray(e))return sn(e,t);if(!q(e))return f(e,t);if(t.seen.has(e))return t.cycle=true,"<invalid predicate: cycle>";t.seen.add(e);let r=e,i=Object.keys(r);for(let o of ["$all","$any","$not"])if(o in r)return an(o,r[o],t,n);let s=[];for(let o of i)o.startsWith("$")||s.push(qe(o,r[o],t,n));return Z(s,t)}function sn(e,t,n){let r=[];for(let i of e){if(!q(i))continue;let s=i;typeof s.fact!="string"||typeof s.op!="string"||r.push(L(s.fact,s.op,s.value,t));}return r.length===0?t.style==="formal"?"\u22A4":"always true":Z(r,t)}function an(e,t,n,r){if(e==="$not"){if(q(t)&&Object.keys(t).length===0)return n.style==="formal"?"\u22A5":"never";let o=X(t,n,r+1);return o==="always true"?"never":o==="\u22A4"?"\u22A5":`${n.style==="formal"?rn:`${tn} `}(${o})`}if(!Array.isArray(t))return n.style==="formal"?"\u22A5":"<invalid predicate>";if(t.length===0)return e==="$all"?n.style==="formal"?"\u22A4":"always true":n.style==="formal"?"\u22A5":"never";let i=[];for(let o of t){let u=X(o,n,r+1);i.push(u);}if(i.length===1)return i[0];let s=n.parenthesize?i.map(o=>`(${o})`):i;return e==="$all"?s.join(n.style==="formal"?Le:Ie):s.join(n.style==="formal"?nn:en)}function qe(e,t,n,r){if(on(t)){let i=t,s=Object.keys(i);if(s.length===1)return L(e,s[0],i[s[0]],n);let o=s.map(u=>L(e,u,i[u],n));return Z(o,n)}if(q(t)){let i=t;if("$all"in i||"$any"in i||"$not"in i)return X(t,n,r+1);let o=[];for(let u of Object.keys(i))u.startsWith("$")||o.push(qe(`${e}.${u}`,i[u],n,r+1));return o.length===0?L(e,"$eq",t,n):Z(o,n)}return L(e,"$eq",t,n)}function L(e,t,n,r){let i=r.style==="formal"?e:r.factName(e);return r.style==="formal"?cn(i,t,n,r):un(i,t,n,r)}function un(e,t,n,r){switch(t){case "$eq":return n===null?`${e} is null`:`${e} is ${f(n,r)}`;case "$ne":return n===null?`${e} is not null`:`${e} is not ${f(n,r)}`;case "$gt":return `${e} is more than ${f(n,r)}`;case "$gte":return `${e} is at least ${f(n,r)}`;case "$lt":return `${e} is less than ${f(n,r)}`;case "$lte":return `${e} is at most ${f(n,r)}`;case "$in":return `${e} is one of ${Ne(n,r)}`;case "$nin":return `${e} is not one of ${Ne(n,r)}`;case "$exists":return n===true?`${e} is set`:`${e} is not set`;case "$between":return Array.isArray(n)&&n.length===2?`${e} is between ${f(n[0],r)} and ${f(n[1],r)}`:`${e} is between ${f(n,r)}`;case "$startsWith":return `${e} starts with ${x(n,r,true)}`;case "$endsWith":return `${e} ends with ${x(n,r,true)}`;case "$contains":return `${e} contains ${x(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} matches ${n.toString()}`:`${e} matches ${f(n,r)}`;case "$changed":return `${e} changed`;default:return a&&!a$1.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function cn(e,t,n,r){switch(t){case "$eq":return `${e} = ${f(n,r)}`;case "$ne":return `${e} \u2260 ${f(n,r)}`;case "$gt":return `${e} > ${f(n,r)}`;case "$gte":return `${e} \u2265 ${f(n,r)}`;case "$lt":return `${e} < ${f(n,r)}`;case "$lte":return `${e} \u2264 ${f(n,r)}`;case "$in":return `${e} \u2208 {${_e(n,r)}}`;case "$nin":return `${e} \u2209 {${_e(n,r)}}`;case "$exists":return n===true?`\u2203 ${e}`:`\u2204 ${e}`;case "$between":return Array.isArray(n)&&n.length===2?`${f(n[0],r)} \u2264 ${e} \u2264 ${f(n[1],r)}`:`${e} \u2208 [${f(n,r)}]`;case "$startsWith":return `${e} ^= ${x(n,r,true)}`;case "$endsWith":return `${e} $= ${x(n,r,true)}`;case "$contains":return `${e} \u2287 ${x(n,r,true)}`;case "$matches":return n instanceof RegExp?`${e} ~ ${n.toString()}`:`${e} ~ ${f(n,r)}`;case "$changed":return `\u0394${e}`;default:return a&&!a$1.has(t)&&console.warn(`[Directive] describePredicate: unknown operator "${t}" \u2014 falling through to generic rendering.`),`${e} ${t} ${f(n,r)}`}}function Y(e){return e.length===0?true:/[\s,"']/.test(e)}function x(e,t,n){return typeof e!="string"||n||Y(e)?JSON.stringify(e):e}function f(e,t){if(e===null)return "null";if(e===void 0)return "undefined";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"){if(!Number.isFinite(e))return String(e);try{return Gt(t.locale).format(e)}catch{return String(e)}}if(typeof e=="bigint")return t.style==="formal"?`${e.toString()}n`:e.toString();if(typeof e=="string")return t.style==="formal"||Y(e)?JSON.stringify(e):e;if(e instanceof Date)return e.toISOString();if(e instanceof RegExp)return e.toString();if(Array.isArray(e))return `[${e.map(n=>f(n,t)).join(", ")}]`;if(typeof e=="object")try{return JSON.stringify(e)}catch{return "[object]"}return String(e)}function Ne(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function _e(e,t){return Array.isArray(e)?e.map(n=>typeof n=="string"?Y(n)?JSON.stringify(n):n:f(n,t)).join(", "):f(e,t)}function Z(e,t){if(e.length===0)return t.style==="formal"?"\u22A4":"always true";if(e.length===1)return e[0];let n=t.style==="formal"?Le:Ie;return t.parenthesize,e.join(n)}var ln=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function B(e,t){if(typeof e!="string"||!ln.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function We(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function dn(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)B(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(B(t,"column"),t)}function b(e,t){return e.params.push(t),e.placeholder(e.params.length)}function fe(e,t,n,r){switch(t){case "$eq":return `${e} = ${b(r,n)}`;case "$ne":return `${e} <> ${b(r,n)}`;case "$gt":return `${e} > ${b(r,n)}`;case "$gte":return `${e} >= ${b(r,n)}`;case "$lt":return `${e} < ${b(r,n)}`;case "$lte":return `${e} <= ${b(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${b(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${b(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${b(r,n[0])} AND ${b(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${b(r,pe(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${b(r,pe(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${b(r,pe(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${b(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...a$1].join(", ")}`)}}function pe(e){return e.replace(/[\\%_]/g,"\\$&")}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function fn(e){if(!Be(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function ge(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function W(e,t,n){if(n>g)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(s=>{if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let o=s;return B(o.fact,"column"),We(o.fact,t.allowed),fe(o.fact,o.op,o.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){ge(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" AND ")})`}if("$any"in e){ge(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let s=i.map(o=>W(o,t,n+1));return s.length===1?s[0]:`(${s.join(" OR ")})`}if("$not"in e){ge(e,"$not");let i=e.$not;return `NOT (${W(i,t,n+1)})`}let r=[];for(let[i,s]of Object.entries(e))if(B(i,"column"),We(i,t.allowed),fn(s))for(let[o,u]of Object.entries(s)){if(!a$1.has(o))throw new Error(`[Directive] predicateToSQL: unknown operator "${o}" on column "${i}" \u2014 known: ${[...a$1].join(", ")}`);r.push(fe(i,o,u,t));}else {if(Be(s))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(fe(i,"$eq",s,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var Ue=e=>`$${e}`;function pn(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??Ue,s=t.select??"*";B(n,"table");let o=dn(s),u={params:[],placeholder:i,allowed:r},a=W(e,u,0);return {sql:`SELECT ${o} FROM ${n} WHERE ${a}`,where:a,params:u.params}}function gn(e,t={}){let n=t.placeholder??Ue,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:W(e,r,0),params:r.params}}function ye(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function me(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function yn(e){if(!me(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var hn=/^[A-Za-z_][A-Za-z0-9_]*$/,mn=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function Ke(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?mn:hn).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function ze(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function he(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function He(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${ye(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${ye(t)}$`};case "$contains":if(typeof t=="string")return {$regex:ye(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...a$1].join(", ")}`)}}function j(e,t,n){if(n>g)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let u=o;Ke(u.fact,t),ze(u.fact,t.allowedKeys);let a=He(u.op,u.value);if(u.fact in i&&me(i[u.fact])){let c=i[u.fact];Object.keys(a).some(d=>d in c)?s.push({[u.fact]:a}):i[u.fact]={...c,...a};}else u.fact in i?s.push({[u.fact]:a}):i[u.fact]=a;}if(s.length>0){let o=[];for(let[u,a]of Object.entries(i))o.push({[u]:a});return o.push(...s),{$and:o}}return i}if("$all"in e){he(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?j(i[0],t,n+1):{$and:i.map(s=>j(s,t,n+1))}}if("$any"in e){he(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?j(i[0],t,n+1):{$or:i.map(s=>j(s,t,n+1))}}if("$not"in e){he(e,"$not");let i=e.$not;return {$nor:[j(i,t,n+1)]}}let r={};for(let[i,s]of Object.entries(e))if(Ke(i,t),ze(i,t.allowedKeys),yn(s)){let o={};for(let[u,a]of Object.entries(s)){if(!a$1.has(u))throw new Error(`[Directive] predicateToMongo: unknown operator "${u}" on field "${i}" \u2014 known: ${[...a$1].join(", ")}`);Object.assign(o,He(u,a));}r[i]=o;}else r[i]=s;return r}function $n(e,t={}){return j(e,t,0)}var wn=/^[A-Za-z_][A-Za-z0-9_]*$/;function Je(e,t){if(typeof e!="string"||!wn.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function $e(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function k(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function Qe(e){return `(${e.map(k).join(",")})`}function we(e){return e.replace(/[\\%_*]/g,"\\$&")}function P(e,t){switch(e){case "$eq":return `eq.${k(t)}`;case "$ne":return `neq.${k(t)}`;case "$gt":return `gt.${k(t)}`;case "$gte":return `gte.${k(t)}`;case "$lt":return `lt.${k(t)}`;case "$lte":return `lte.${k(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${Qe(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${Qe(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${k(`${we(t)}*`)}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${k(`*${we(t)}`)}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${k(`*${we(t)}*`)}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${k(t.source)}`;if(typeof t=="string")return `match.${k(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...a$1].join(", ")}`)}}function Xe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function bn(e){if(!Xe(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function be(e,t){return `${e}=${t}`}function G(e,t){return `${e}=(${t.join(",")})`}function Se(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?be(e,P("$gte",n[0])):`${e}.${P("$gte",n[0])}`,s=r?be(e,P("$lte",n[1])):`${e}.${P("$lte",n[1])}`;return [i,s]}return [r?be(e,P(t,n)):`${e}.${P(t,n)}`]}function U(e,t,n,r){if(r>g)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let u=o;Je(u.fact,t),s.push(...Se(u.fact,u.op,u.value,n));}return s}if("$all"in e){$e(e,"$all");let s=e.$all;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let u=[];for(let a of s)u.push(...U(a,t,true,r+1));return u}let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("and",o)]}if("$any"in e){$e(e,"$any");let s=e.$any;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(s.length===0)return n?["id=is.null","id=not.is.null"]:[G("and",["id.is.null","id.not.is.null"])];let o=[];for(let u of s)o.push(...U(u,t,false,r+1));return [G("or",o)]}if("$not"in e){$e(e,"$not");let s=e.$not,o=U(s,t,false,r+1);return [G("not.and",o)]}let i=[];for(let[s,o]of Object.entries(e))if(Je(s,t),bn(o))for(let[u,a]of Object.entries(o)){if(!a$1.has(u))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${u}" on column "${s}" \u2014 known: ${[...a$1].join(", ")}`);i.push(...Se(s,u,a,n));}else {if(Xe(o))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${s}" \u2014 single-table queries only`);i.push(...Se(s,"$eq",o,n));}return i}function Sn(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Tn(e,t={}){let n=t.mode??"querystring",r=U(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(Sn).join("&")}function V(e=[],t,n,r,i,s,o){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:s,_meta:o,validate(u){return V([...e,u],t,n,r,i,s,o)}}}function p(e,t,n,r,i,s,o){return {...V(e,t,n,r,i,s,o),default(a){return p(e,t,a,r,i,s,o)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,o)},brand(){return p(e,`Branded<${t}>`,n,r,i,s,o)},describe(a){return p(e,t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return p([...e,a],t,n,r,i,l,o)},nullable(){return p([a=>a===null||e.every(c=>c(a))],`${t} | null`,n,r,i,void 0,o)},optional(){return p([a=>a===void 0||e.every(c=>c(a))],`${t} | undefined`,n,r,i,void 0,o)},meta(a){return p(e,t,n,r,i,s,a)}}}var kn=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),vn={string(){let e=(t,n,r,i,s,o)=>({...p(t,"string",n,r,i,s,o),minLength(a){return e([...t,c=>c.length>=a],n,r,i,s,o)},maxLength(a){return e([...t,c=>c.length<=a],n,r,i,s,o)},pattern(a){return e([...t,c=>a.test(c)],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,s,o)=>({...p(t,"number",n,r,i,s,o),min(a){return e([...t,c=>c>=a],n,r,i,s,o)},max(a){return e([...t,c=>c<=a],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,c){let l=[...s??[],{predicate:a,message:c}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,s,o)=>{let u=p(t,"array",r,void 0,i,void 0,o),a=s??{value:-1};return {...u,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,g=>{for(let y=0;y<g.length;y++)if(!l._validators.every($=>$(g[y])))return d.value=y,false;return true}],l,r,i,d,o)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,o)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,o)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,o)},default(l){return e(t,n,l,i,a,o)},describe(l){return e(t,n,r,l,a,o)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(o){return e([...t,u=>{for(let[a,c]of Object.entries(o)){let l=u[a],d=c;if(d&&!d._validators.every(g=>g(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,o=>o!=null],n,r,i)},hasKeys(...o){return e([...t,u=>o.every(a=>a in u)],n,r,i)},default(o){return e(t,o,r,i)},describe(o){return e(t,n,o,i)},meta(o){return e(t,n,r,o)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return V([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return V([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:kn,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(s=>s(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Mn(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function Ze(e,t,n,r,i){for(let s of e)t.has(s)||console.warn(`[Directive] ${n} "${s}" not declared in ${r}`);for(let s of t)e.has(s)||console.warn(`[Directive] ${r}["${s}"] ${i}`);}function Dn(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Rn(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let s=i;typeof s.requirement=="string"&&!n.has(s.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${s.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function Cn(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),s="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let o of s)i.add(o);for(let o of r)if(i.has(o))throw new Error(`[Directive] module '${e}': fact key '${o}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes: | ||
| 1. Rename the fact (e.g. ${o}_) | ||
| 2. Remove '${o}' from this module's crossModuleDeps if it's not actually needed | ||
| 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function An(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.owns;if(s){for(let o of s)if(k$1.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': owns key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function En(e,t){Mn(e),t.schema?t.schema.facts||(Object.values(t.schema).some(r=>r!=null&&typeof r=="object"&&"_typeName"in r)&&console.warn(`[Directive] Module "${e}" schema appears to contain fact declarations directly. Did you mean \`schema: { facts: { ... } }\` instead of \`schema: { ... }\`?`),console.warn("[Directive] Module schema.facts is required")):console.warn("[Directive] Module schema is required"),Ze(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),Ze(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Dn(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&Rn(t.resolvers,t.schema.requirements);}function Ye(e,t){Cn(e,t),An(e,t),a&&En(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,sources:t.sources,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function xn(e){return t=>Ye(t,e)}function Se(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,c){let l=a.get(c);return l||(l=new Set,a.set(c,l)),l}function r(a){let c=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,g=e.errors.get(a)??null;return {pending:c.size,inflight:l.size,failed:d.size,isLoading:c.size>0||l.size>0,hasError:d.size>0,lastError:g}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),c=new Map;for(let l of a)c.set(l,r(l));return c}function s(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function o(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let c=a.requirement.type;n(e.pending,c).add(a.id),e.failed.get(c)?.delete(a.id),t();},onResolverStart(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),n(e.inflight,l).add(c.id),t();},onResolverComplete(a,c){let l=c.requirement.type;e.inflight.get(l)?.delete(c.id),e.pending.get(l)?.delete(c.id),t();},onResolverError(a,c,l){let d=c.requirement.type;e.inflight.get(d)?.delete(c.id),n(e.failed,d).add(c.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),e.inflight.get(l)?.delete(c.id),t();},onRequirementMet(a){let c=a.requirement.type;e.pending.get(c)?.delete(a.id),e.inflight.get(c)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:s,reset:o}}function On(e){return t=>e.getStatus(t)}function jn(e){let t=Se(),r=[...e.plugins??[],t.plugin];return {system:a$2({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function Ge(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function Pn(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,s)=>{let o={id:n++,deadlineMs:t+s,cb:i,canceled:false};return r.push(o),()=>{o.canceled=true;}},advanceBy:i=>{let s=t+i;for(;;){let o=r.filter(a=>!a.canceled&&a.deadlineMs<=s).sort((a,c)=>a.deadlineMs!==c.deadlineMs?a.deadlineMs-c.deadlineMs:a.id-c.id);if(o.length===0)break;let u=o[0];t=Math.max(t,u.deadlineMs),u.canceled=true,u.cb();}t=Math.max(t,s);}}}function Fn(){return Ge()}function Te(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function ee(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function Ve(e,t,n){return Math.max(0,n-ee(e,t))}function et(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function tt(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function nt(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function rt(){return Te()}function it(e){return {...e,status:"completed"}}function ot(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function st(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=ee(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function Nn(e){return {initial:Te,start:et,pause:tt,resume:nt,reset:rt,complete:it,registerRepeat:t=>ot(t,e.ms),tick:(t,n)=>st(t,n,e),elapsedMs:ee,remainingMs:(t,n)=>Ve(t,n,e.ms)}}var Sr={None:"none",Linear:"linear",Exponential:"exponential"};export{Sr as Backoff,A as MAX_REPLAY_FRAMES,ae as MAX_SWEEP_POINTS,it as completeTimer,Ye as createModule,xn as createModuleFactory,Se as createRequirementStatusPlugin,On as createStatusHook,jn as createSystemWithStatus,Fn as defaultClock,Vt as describePredicate,Oe as diffClauses,zt as diffRules,Zt as doctor,ee as elapsedMs,S as flattenPredicate,Ce as framesFromHistory,se as framesFromSnapshots,Te as initialTimerState,tt as pauseTimer,Ht as predicateHash,$n as predicateToMongo,Tn as predicateToPostgrest,pn as predicateToSQL,gn as predicateToWhere,Qt as predict,Ge as realClock,ot as registerRepeat,Ve as remainingMs,H as replayUnder,rt as resetTimer,nt as resumeTimer,et as startTimer,qt as sweepUnder,vn as t,st as tickTimer,Nn as timerOps,Re as toReplayFrames,ce as toRulesMap,Pn as virtualClock};//# sourceMappingURL=index.js.map | ||
| 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function An(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.abortOn;if(s){for(let o of s)if(k$1.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': abortOn key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function En(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.bind;if(s){for(let o of s)if(k$1.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': bind key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function On(e,t){Mn(e),t.schema?t.schema.facts||(Object.values(t.schema).some(r=>r!=null&&typeof r=="object"&&"_typeName"in r)&&console.warn(`[Directive] Module "${e}" schema appears to contain fact declarations directly. Did you mean \`schema: { facts: { ... } }\` instead of \`schema: { ... }\`?`),console.warn("[Directive] Module schema.facts is required")):console.warn("[Directive] Module schema is required"),Ze(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),Ze(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Dn(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&Rn(t.resolvers,t.schema.requirements);}function Ye(e,t){Cn(e,t),An(e,t),En(e,t),a&&On(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,sources:t.sources,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function xn(e){return t=>Ye(t,e)}function Te(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,c){let l=a.get(c);return l||(l=new Set,a.set(c,l)),l}function r(a){let c=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,g=e.errors.get(a)??null;return {pending:c.size,inflight:l.size,failed:d.size,isLoading:c.size>0||l.size>0,hasError:d.size>0,lastError:g}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),c=new Map;for(let l of a)c.set(l,r(l));return c}function s(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function o(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let c=a.requirement.type;n(e.pending,c).add(a.id),e.failed.get(c)?.delete(a.id),t();},onResolverStart(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),n(e.inflight,l).add(c.id),t();},onResolverComplete(a,c){let l=c.requirement.type;e.inflight.get(l)?.delete(c.id),e.pending.get(l)?.delete(c.id),t();},onResolverError(a,c,l){let d=c.requirement.type;e.inflight.get(d)?.delete(c.id),n(e.failed,d).add(c.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,c){let l=c.requirement.type;e.pending.get(l)?.delete(c.id),e.inflight.get(l)?.delete(c.id),t();},onRequirementMet(a){let c=a.requirement.type;e.pending.get(c)?.delete(a.id),e.inflight.get(c)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:s,reset:o}}function jn(e){return t=>e.getStatus(t)}function Pn(e){let t=Te(),r=[...e.plugins??[],t.plugin];return {system:a$2({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function Ge(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function Fn(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,s)=>{let o={id:n++,deadlineMs:t+s,cb:i,canceled:false};return r.push(o),()=>{o.canceled=true;}},advanceBy:i=>{let s=t+i;for(;;){let o=r.filter(a=>!a.canceled&&a.deadlineMs<=s).sort((a,c)=>a.deadlineMs!==c.deadlineMs?a.deadlineMs-c.deadlineMs:a.id-c.id);if(o.length===0)break;let u=o[0];t=Math.max(t,u.deadlineMs),u.canceled=true,u.cb();}t=Math.max(t,s);}}}function Nn(){return Ge()}function ke(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function ee(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function Ve(e,t,n){return Math.max(0,n-ee(e,t))}function et(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function tt(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function nt(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function rt(){return ke()}function it(e){return {...e,status:"completed"}}function ot(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function st(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=ee(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function _n(e){return {initial:ke,start:et,pause:tt,resume:nt,reset:rt,complete:it,registerRepeat:t=>ot(t,e.ms),tick:(t,n)=>st(t,n,e),elapsedMs:ee,remainingMs:(t,n)=>Ve(t,n,e.ms)}}var Tr={None:"none",Linear:"linear",Exponential:"exponential"};export{Tr as Backoff,A as MAX_REPLAY_FRAMES,ue as MAX_SWEEP_POINTS,it as completeTimer,Ye as createModule,xn as createModuleFactory,Te as createRequirementStatusPlugin,jn as createStatusHook,Pn as createSystemWithStatus,Nn as defaultClock,Vt as describePredicate,xe as diffClauses,zt as diffRules,Zt as doctor,ee as elapsedMs,S as flattenPredicate,Ce as framesFromHistory,ae as framesFromSnapshots,ke as initialTimerState,tt as pauseTimer,Ht as predicateHash,$n as predicateToMongo,Tn as predicateToPostgrest,pn as predicateToSQL,gn as predicateToWhere,Qt as predict,Ge as realClock,ot as registerRepeat,Ve as remainingMs,H as replayUnder,rt as resetTimer,nt as resumeTimer,et as startTimer,qt as sweepUnder,vn as t,st as tickTimer,_n as timerOps,Re as toReplayFrames,le as toRulesMap,Fn as virtualClock};//# sourceMappingURL=index.js.map | ||
| //# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
| 'use strict';var chunkM5PEB553_cjs=require('./chunk-M5PEB553.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');Object.defineProperty(exports,"createConstraintFactory",{enumerable:true,get:function(){return chunkM5PEB553_cjs.c}});Object.defineProperty(exports,"createConstraintsManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.p}});Object.defineProperty(exports,"createDerivationsManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.q}});Object.defineProperty(exports,"createDisabledHistory",{enumerable:true,get:function(){return chunkM5PEB553_cjs.j}});Object.defineProperty(exports,"createEffectsManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.r}});Object.defineProperty(exports,"createEngine",{enumerable:true,get:function(){return chunkM5PEB553_cjs.A}});Object.defineProperty(exports,"createErrorBoundaryManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.t}});Object.defineProperty(exports,"createFacts",{enumerable:true,get:function(){return chunkM5PEB553_cjs.w}});Object.defineProperty(exports,"createFactsProxy",{enumerable:true,get:function(){return chunkM5PEB553_cjs.v}});Object.defineProperty(exports,"createFactsStore",{enumerable:true,get:function(){return chunkM5PEB553_cjs.u}});Object.defineProperty(exports,"createHistoryManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.i}});Object.defineProperty(exports,"createPluginManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.x}});Object.defineProperty(exports,"createResolverFactory",{enumerable:true,get:function(){return chunkM5PEB553_cjs.d}});Object.defineProperty(exports,"createResolversManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.y}});Object.defineProperty(exports,"createRetryLaterManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.s}});Object.defineProperty(exports,"createSourcesManager",{enumerable:true,get:function(){return chunkM5PEB553_cjs.z}});Object.defineProperty(exports,"dangerousRegex",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.m}});Object.defineProperty(exports,"getCurrentDeps",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.f}});Object.defineProperty(exports,"isTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.g}});Object.defineProperty(exports,"trackAccess",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.j}});Object.defineProperty(exports,"withTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.h}});Object.defineProperty(exports,"withoutTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.i}});Object.defineProperty(exports,"hashObject",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.h}});Object.defineProperty(exports,"isPrototypeSafe",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.f}});Object.defineProperty(exports,"safeStringify",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.o}});Object.defineProperty(exports,"stableStringify",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.e}});//# sourceMappingURL=internals.cjs.map | ||
| 'use strict';var chunkQTY2FXZY_cjs=require('./chunk-QTY2FXZY.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');Object.defineProperty(exports,"createConstraintFactory",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.c}});Object.defineProperty(exports,"createConstraintsManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.p}});Object.defineProperty(exports,"createDerivationsManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.q}});Object.defineProperty(exports,"createDisabledHistory",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.j}});Object.defineProperty(exports,"createEffectsManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.r}});Object.defineProperty(exports,"createEngine",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.A}});Object.defineProperty(exports,"createErrorBoundaryManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.t}});Object.defineProperty(exports,"createFacts",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.w}});Object.defineProperty(exports,"createFactsProxy",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.v}});Object.defineProperty(exports,"createFactsStore",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.u}});Object.defineProperty(exports,"createHistoryManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.i}});Object.defineProperty(exports,"createPluginManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.x}});Object.defineProperty(exports,"createResolverFactory",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.d}});Object.defineProperty(exports,"createResolversManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.y}});Object.defineProperty(exports,"createRetryLaterManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.s}});Object.defineProperty(exports,"createSourcesManager",{enumerable:true,get:function(){return chunkQTY2FXZY_cjs.z}});Object.defineProperty(exports,"dangerousRegex",{enumerable:true,get:function(){return chunkGACC2DMS_cjs.m}});Object.defineProperty(exports,"getCurrentDeps",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.f}});Object.defineProperty(exports,"isTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.g}});Object.defineProperty(exports,"trackAccess",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.j}});Object.defineProperty(exports,"withTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.h}});Object.defineProperty(exports,"withoutTracking",{enumerable:true,get:function(){return chunkGKMJ7NMP_cjs.i}});Object.defineProperty(exports,"hashObject",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.h}});Object.defineProperty(exports,"isPrototypeSafe",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.f}});Object.defineProperty(exports,"safeStringify",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.o}});Object.defineProperty(exports,"stableStringify",{enumerable:true,get:function(){return chunkGBCWXTXW_cjs.e}});//# sourceMappingURL=internals.cjs.map | ||
| //# sourceMappingURL=internals.cjs.map |
+39
-25
@@ -1,5 +0,5 @@ | ||
| import { ah as Schema, aB as FactsStore, a as Facts, D as DefinitionMeta, E as EffectsDef, u as ConstraintsDef, s as RequirementKeyFn, R as RequirementWithId, aC as ConstraintState, F as FactPredicate, C as ClauseResult, af as ResolversDef, aD as ResolverStatus, r as Requirement, al as SourceDropReason, ak as SourceDef, P as Plugin, ap as System, aE as FactChange, O as FactsSnapshot, aF as ReconcileResult, aj as Snapshot, x as DirectiveError, aG as RecoveryStrategy, aw as TraceEntry, aH as ErrorSource, q as ErrorBoundaryConfig, aI as RetryLaterConfig, Q as HistoryAPI, U as HistoryOption, aq as SystemConfig } from './plugins-4IfhJV32.cjs'; | ||
| export { aJ as BatchItemResult, aK as BatchResolveResults, aL as ConstraintsControl, v as CrossModuleConstraintDef, j as CrossModuleConstraintsDef, aM as CrossModuleDerivationFn, h as CrossModuleDerivationsDef, w as CrossModuleEffectDef, i as CrossModuleEffectsDef, aN as CrossModuleFactsWithSelf, aO as DerivationKeys, aP as DerivationReturnType, aQ as DerivationsControl, aR as DerivationsSchema, aS as DeriveAccessor, aT as DispatchEventsFromSchema, y as DistributableSnapshot, z as DistributableSnapshotOptions, aU as EffectCleanup, aV as EffectsControl, aW as EventPayloadSchema, aX as EventsAccessor, aY as EventsAccessorFromSchema, K as EventsDef, aZ as EventsSchema, a_ as FactKeys, a$ as FactReturnType, b0 as FlexibleEventHandler, b1 as HistoryConfig, b2 as InferEventPayloadFromSchema, b3 as InferRequirementPayloadFromSchema, b4 as InferSchema, b5 as MutableNamespacedFacts, b6 as NamespacedDerivations, b7 as NamespacedEventsAccessor, b8 as NamespacedFacts, b9 as ObservableKeys, ba as RequirementExplanation, bb as RequirementOutput, bc as RequirementPayloadSchema, bd as RequirementsSchema, be as ResolverContext, bf as ResolversControl, bg as SnapshotMeta, bh as SystemEvent, bi as TraceConfig, ax as TypedConstraintDef, d as TypedConstraintsDef, T as TypedDerivationsDef, b as TypedEventsDef, bj as TypedResolverContext, ay as TypedResolverDef, e as TypedResolversDef, bk as UnionEvents } from './plugins-4IfhJV32.cjs'; | ||
| import { b as DerivationsDef, y as DerivedValues } from './predicate-DBTPnlg6.cjs'; | ||
| export { z as DerivationState, T as TypedConstraint, A as TypedResolver, B as createConstraintFactory, C as createResolverFactory, E as dangerousRegex } from './predicate-DBTPnlg6.cjs'; | ||
| import { ah as Schema, aB as FactsStore, a as Facts, D as DefinitionMeta, E as EffectsDef, u as ConstraintsDef, s as RequirementKeyFn, R as RequirementWithId, aC as ConstraintState, F as FactPredicate, C as ClauseResult, af as ResolversDef, aD as ResolverStatus, r as Requirement, al as SourceDropReason, ak as SourceDef, P as Plugin, ap as System, aE as FactChange, O as FactsSnapshot, aF as ReconcileResult, aj as Snapshot, x as DirectiveError, aG as RecoveryStrategy, aw as TraceEntry, aH as ErrorSource, q as ErrorBoundaryConfig, aI as RetryLaterConfig, Q as HistoryAPI, U as HistoryOption, aq as SystemConfig } from './plugins-5Supk7it.cjs'; | ||
| export { aJ as BatchItemResult, aK as BatchResolveResults, aL as ConstraintsControl, v as CrossModuleConstraintDef, j as CrossModuleConstraintsDef, aM as CrossModuleDerivationFn, h as CrossModuleDerivationsDef, w as CrossModuleEffectDef, i as CrossModuleEffectsDef, aN as CrossModuleFactsWithSelf, aO as DerivationKeys, aP as DerivationReturnType, aQ as DerivationsControl, aR as DerivationsSchema, aS as DeriveAccessor, aT as DispatchEventsFromSchema, y as DistributableSnapshot, z as DistributableSnapshotOptions, aU as EffectCleanup, aV as EffectsControl, aW as EventPayloadSchema, aX as EventsAccessor, aY as EventsAccessorFromSchema, K as EventsDef, aZ as EventsSchema, a_ as FactKeys, a$ as FactReturnType, b0 as FlexibleEventHandler, b1 as HistoryConfig, b2 as InferEventPayloadFromSchema, b3 as InferRequirementPayloadFromSchema, b4 as InferSchema, b5 as MutableNamespacedFacts, b6 as NamespacedDerivations, b7 as NamespacedEventsAccessor, b8 as NamespacedFacts, b9 as ObservableKeys, ba as RequirementExplanation, bb as RequirementOutput, bc as RequirementPayloadSchema, bd as RequirementsSchema, be as ResolverContext, bf as ResolversControl, bg as SnapshotMeta, bh as SystemEvent, bi as TraceConfig, ax as TypedConstraintDef, d as TypedConstraintsDef, T as TypedDerivationsDef, b as TypedEventsDef, bj as TypedResolverContext, ay as TypedResolverDef, e as TypedResolversDef, bk as UnionEvents } from './plugins-5Supk7it.cjs'; | ||
| import { b as DerivationsDef, y as DerivedValues } from './predicate-DYb-3Mvl.cjs'; | ||
| export { z as DerivationState, T as TypedConstraint, A as TypedResolver, B as createConstraintFactory, C as createResolverFactory, E as dangerousRegex } from './predicate-DYb-3Mvl.cjs'; | ||
| export { h as hashObject, g as isPrototypeSafe, j as safeStringify, k as stableStringify } from './utils-DY8KTiD6.cjs'; | ||
@@ -618,3 +618,3 @@ | ||
| * shared by every resolver dispatched in the same reconcile tick. Used | ||
| * by RFC-1 constraint-binding to seed each resolver's `expected` map | ||
| * by RFC-0003 constraint-binding to seed each resolver's `expected` map | ||
| * from a value that pre-dates any sibling resolver's writes, preventing | ||
@@ -628,11 +628,13 @@ * the sibling-clobber gap where resolver 2 silently overwrites | ||
| /** | ||
| * Cancel an in-flight or batch-queued resolver by requirement ID. | ||
| * Abort an in-flight or batch-queued resolver by requirement ID. | ||
| * | ||
| * @remarks | ||
| * Aborts the `AbortController` for in-flight resolvers. For batch-queued | ||
| * requirements, removes the requirement from the pending batch. | ||
| * requirements, removes the requirement from the pending batch. Named to | ||
| * match `AbortController.abort()` and the declarative `abortOn:` key on | ||
| * constraints — three surfaces, one verb, one signal. | ||
| * | ||
| * @param requirementId - The unique requirement ID to cancel. | ||
| * @param requirementId - The unique requirement ID to abort. | ||
| */ | ||
| cancel(requirementId: string): void; | ||
| abort(requirementId: string): void; | ||
| /** | ||
@@ -645,5 +647,5 @@ * Untrack an in-flight resolver by requirement ID **without** aborting it | ||
| * resolver runs to completion (its data writes land; the binding still | ||
| * guards owned facts) but it no longer occupies the `inflight` slot, so the | ||
| * same requirement re-dispatches cleanly if it returns. A no-op if the | ||
| * requirement is not in-flight. | ||
| * guards abort-bound facts) but it no longer occupies the `inflight` | ||
| * slot, so the same requirement re-dispatches cleanly if it returns. A | ||
| * no-op if the requirement is not in-flight. | ||
| * | ||
@@ -654,5 +656,5 @@ * @param requirementId - The unique requirement ID to detach. | ||
| /** | ||
| * Cancel every in-flight resolver and flush all pending batch queues. | ||
| * Abort every in-flight resolver and flush all pending batch queues. | ||
| */ | ||
| cancelAll(): void; | ||
| abortAll(): void; | ||
| /** | ||
@@ -738,11 +740,11 @@ * Get the current status of a resolver by requirement ID. | ||
| /** | ||
| * Per-constraint binding info, used by RFC-1 (resolver constraint-binding). | ||
| * Per-constraint binding info, used by RFC-0003 (resolver constraint-binding). | ||
| * | ||
| * The engine wires this lookup into the resolvers manager so that a resolver | ||
| * dispatched from a constraint with an `owns` field knows which facts it | ||
| * *owns* — writes to those are clobber-checked (see {@link createBoundFacts}). | ||
| * dispatched from a constraint with an `abortOn` field knows which facts it | ||
| * compare-and-swaps on dispatch (see {@link createBoundFacts}). | ||
| * | ||
| * Returns `undefined`/`null` when the source constraint is unknown or has no | ||
| * `owns` field — in which case binding is a no-op and the resolver behaves | ||
| * exactly as before. | ||
| * `abortOn` field — in which case binding is a no-op and the resolver | ||
| * behaves exactly as before. | ||
| * | ||
@@ -752,3 +754,3 @@ * @internal | ||
| interface ConstraintBindingInfo { | ||
| /** Fact keys the triggering resolver owns; writes to these are clobber-checked. */ | ||
| /** Fact keys this resolver aborts on when changed mid-flight; writes to these are clobber-checked. */ | ||
| readonly fields: readonly string[]; | ||
@@ -769,7 +771,7 @@ } | ||
| /** | ||
| * Look up binding info for a source constraint id (RFC-1). | ||
| * Look up binding info for a source constraint id (RFC-0003). | ||
| * | ||
| * Wired by the engine — given the `fromConstraint` of a `RequirementWithId`, | ||
| * returns the constraint's owned fact keys. Return `undefined` if the | ||
| * constraint is unknown or has no `owns` field. | ||
| * returns the constraint's abort-binding fact keys. Return `undefined` if | ||
| * the constraint is unknown or has no `abortOn` field. | ||
| */ | ||
@@ -785,3 +787,3 @@ getConstraintBinding?: (constraintId: string) => ConstraintBindingInfo | undefined; | ||
| onRetry?: (resolver: string, req: RequirementWithId, attempt: number) => void; | ||
| /** Called when a resolver is canceled via {@link ResolversManager.cancel | cancel}. */ | ||
| /** Called when a resolver is aborted via {@link ResolversManager.abort | abort}. */ | ||
| onCancel?: (resolver: string, req: RequirementWithId) => void; | ||
@@ -813,3 +815,3 @@ /** | ||
| * Creates a resolver manager that tracks active resolver instances and | ||
| * coordinates their lifecycle (start / complete / error / cancel) against | ||
| * coordinates their lifecycle (start / complete / error / abort) against | ||
| * the engine's requirement graph. | ||
@@ -1077,2 +1079,14 @@ * | ||
| emitConstraintError(id: string, error: unknown): void; | ||
| /** | ||
| * Fired once per lookup when the engine silently disables a | ||
| * constraint's `abortOn:` binding because the constraint is async. | ||
| * Pairs with the dev-mode `console.warn` for SIEM visibility — without | ||
| * this signal, a production constraint loses its clobber-protection | ||
| * with no plugin trail. | ||
| * | ||
| * `"async-declared"` means the def has `async: true` (author opted in); | ||
| * `"async-promoted"` means `when()` returned a Promise at runtime | ||
| * (author probably did not realize). | ||
| */ | ||
| emitConstraintBindingDisabled(id: string, reason: "async-declared" | "async-promoted"): void; | ||
| emitRequirementCreated(req: RequirementWithId): void; | ||
@@ -1079,0 +1093,0 @@ emitRequirementMet(req: RequirementWithId, byResolver: string): void; |
+39
-25
@@ -1,5 +0,5 @@ | ||
| import { ah as Schema, aB as FactsStore, a as Facts, D as DefinitionMeta, E as EffectsDef, u as ConstraintsDef, s as RequirementKeyFn, R as RequirementWithId, aC as ConstraintState, F as FactPredicate, C as ClauseResult, af as ResolversDef, aD as ResolverStatus, r as Requirement, al as SourceDropReason, ak as SourceDef, P as Plugin, ap as System, aE as FactChange, O as FactsSnapshot, aF as ReconcileResult, aj as Snapshot, x as DirectiveError, aG as RecoveryStrategy, aw as TraceEntry, aH as ErrorSource, q as ErrorBoundaryConfig, aI as RetryLaterConfig, Q as HistoryAPI, U as HistoryOption, aq as SystemConfig } from './plugins-4IfhJV32.js'; | ||
| export { aJ as BatchItemResult, aK as BatchResolveResults, aL as ConstraintsControl, v as CrossModuleConstraintDef, j as CrossModuleConstraintsDef, aM as CrossModuleDerivationFn, h as CrossModuleDerivationsDef, w as CrossModuleEffectDef, i as CrossModuleEffectsDef, aN as CrossModuleFactsWithSelf, aO as DerivationKeys, aP as DerivationReturnType, aQ as DerivationsControl, aR as DerivationsSchema, aS as DeriveAccessor, aT as DispatchEventsFromSchema, y as DistributableSnapshot, z as DistributableSnapshotOptions, aU as EffectCleanup, aV as EffectsControl, aW as EventPayloadSchema, aX as EventsAccessor, aY as EventsAccessorFromSchema, K as EventsDef, aZ as EventsSchema, a_ as FactKeys, a$ as FactReturnType, b0 as FlexibleEventHandler, b1 as HistoryConfig, b2 as InferEventPayloadFromSchema, b3 as InferRequirementPayloadFromSchema, b4 as InferSchema, b5 as MutableNamespacedFacts, b6 as NamespacedDerivations, b7 as NamespacedEventsAccessor, b8 as NamespacedFacts, b9 as ObservableKeys, ba as RequirementExplanation, bb as RequirementOutput, bc as RequirementPayloadSchema, bd as RequirementsSchema, be as ResolverContext, bf as ResolversControl, bg as SnapshotMeta, bh as SystemEvent, bi as TraceConfig, ax as TypedConstraintDef, d as TypedConstraintsDef, T as TypedDerivationsDef, b as TypedEventsDef, bj as TypedResolverContext, ay as TypedResolverDef, e as TypedResolversDef, bk as UnionEvents } from './plugins-4IfhJV32.js'; | ||
| import { b as DerivationsDef, y as DerivedValues } from './predicate-BW05x5el.js'; | ||
| export { z as DerivationState, T as TypedConstraint, A as TypedResolver, B as createConstraintFactory, C as createResolverFactory, E as dangerousRegex } from './predicate-BW05x5el.js'; | ||
| import { ah as Schema, aB as FactsStore, a as Facts, D as DefinitionMeta, E as EffectsDef, u as ConstraintsDef, s as RequirementKeyFn, R as RequirementWithId, aC as ConstraintState, F as FactPredicate, C as ClauseResult, af as ResolversDef, aD as ResolverStatus, r as Requirement, al as SourceDropReason, ak as SourceDef, P as Plugin, ap as System, aE as FactChange, O as FactsSnapshot, aF as ReconcileResult, aj as Snapshot, x as DirectiveError, aG as RecoveryStrategy, aw as TraceEntry, aH as ErrorSource, q as ErrorBoundaryConfig, aI as RetryLaterConfig, Q as HistoryAPI, U as HistoryOption, aq as SystemConfig } from './plugins-5Supk7it.js'; | ||
| export { aJ as BatchItemResult, aK as BatchResolveResults, aL as ConstraintsControl, v as CrossModuleConstraintDef, j as CrossModuleConstraintsDef, aM as CrossModuleDerivationFn, h as CrossModuleDerivationsDef, w as CrossModuleEffectDef, i as CrossModuleEffectsDef, aN as CrossModuleFactsWithSelf, aO as DerivationKeys, aP as DerivationReturnType, aQ as DerivationsControl, aR as DerivationsSchema, aS as DeriveAccessor, aT as DispatchEventsFromSchema, y as DistributableSnapshot, z as DistributableSnapshotOptions, aU as EffectCleanup, aV as EffectsControl, aW as EventPayloadSchema, aX as EventsAccessor, aY as EventsAccessorFromSchema, K as EventsDef, aZ as EventsSchema, a_ as FactKeys, a$ as FactReturnType, b0 as FlexibleEventHandler, b1 as HistoryConfig, b2 as InferEventPayloadFromSchema, b3 as InferRequirementPayloadFromSchema, b4 as InferSchema, b5 as MutableNamespacedFacts, b6 as NamespacedDerivations, b7 as NamespacedEventsAccessor, b8 as NamespacedFacts, b9 as ObservableKeys, ba as RequirementExplanation, bb as RequirementOutput, bc as RequirementPayloadSchema, bd as RequirementsSchema, be as ResolverContext, bf as ResolversControl, bg as SnapshotMeta, bh as SystemEvent, bi as TraceConfig, ax as TypedConstraintDef, d as TypedConstraintsDef, T as TypedDerivationsDef, b as TypedEventsDef, bj as TypedResolverContext, ay as TypedResolverDef, e as TypedResolversDef, bk as UnionEvents } from './plugins-5Supk7it.js'; | ||
| import { b as DerivationsDef, y as DerivedValues } from './predicate-C9oMO_ny.js'; | ||
| export { z as DerivationState, T as TypedConstraint, A as TypedResolver, B as createConstraintFactory, C as createResolverFactory, E as dangerousRegex } from './predicate-C9oMO_ny.js'; | ||
| export { h as hashObject, g as isPrototypeSafe, j as safeStringify, k as stableStringify } from './utils-DY8KTiD6.js'; | ||
@@ -618,3 +618,3 @@ | ||
| * shared by every resolver dispatched in the same reconcile tick. Used | ||
| * by RFC-1 constraint-binding to seed each resolver's `expected` map | ||
| * by RFC-0003 constraint-binding to seed each resolver's `expected` map | ||
| * from a value that pre-dates any sibling resolver's writes, preventing | ||
@@ -628,11 +628,13 @@ * the sibling-clobber gap where resolver 2 silently overwrites | ||
| /** | ||
| * Cancel an in-flight or batch-queued resolver by requirement ID. | ||
| * Abort an in-flight or batch-queued resolver by requirement ID. | ||
| * | ||
| * @remarks | ||
| * Aborts the `AbortController` for in-flight resolvers. For batch-queued | ||
| * requirements, removes the requirement from the pending batch. | ||
| * requirements, removes the requirement from the pending batch. Named to | ||
| * match `AbortController.abort()` and the declarative `abortOn:` key on | ||
| * constraints — three surfaces, one verb, one signal. | ||
| * | ||
| * @param requirementId - The unique requirement ID to cancel. | ||
| * @param requirementId - The unique requirement ID to abort. | ||
| */ | ||
| cancel(requirementId: string): void; | ||
| abort(requirementId: string): void; | ||
| /** | ||
@@ -645,5 +647,5 @@ * Untrack an in-flight resolver by requirement ID **without** aborting it | ||
| * resolver runs to completion (its data writes land; the binding still | ||
| * guards owned facts) but it no longer occupies the `inflight` slot, so the | ||
| * same requirement re-dispatches cleanly if it returns. A no-op if the | ||
| * requirement is not in-flight. | ||
| * guards abort-bound facts) but it no longer occupies the `inflight` | ||
| * slot, so the same requirement re-dispatches cleanly if it returns. A | ||
| * no-op if the requirement is not in-flight. | ||
| * | ||
@@ -654,5 +656,5 @@ * @param requirementId - The unique requirement ID to detach. | ||
| /** | ||
| * Cancel every in-flight resolver and flush all pending batch queues. | ||
| * Abort every in-flight resolver and flush all pending batch queues. | ||
| */ | ||
| cancelAll(): void; | ||
| abortAll(): void; | ||
| /** | ||
@@ -738,11 +740,11 @@ * Get the current status of a resolver by requirement ID. | ||
| /** | ||
| * Per-constraint binding info, used by RFC-1 (resolver constraint-binding). | ||
| * Per-constraint binding info, used by RFC-0003 (resolver constraint-binding). | ||
| * | ||
| * The engine wires this lookup into the resolvers manager so that a resolver | ||
| * dispatched from a constraint with an `owns` field knows which facts it | ||
| * *owns* — writes to those are clobber-checked (see {@link createBoundFacts}). | ||
| * dispatched from a constraint with an `abortOn` field knows which facts it | ||
| * compare-and-swaps on dispatch (see {@link createBoundFacts}). | ||
| * | ||
| * Returns `undefined`/`null` when the source constraint is unknown or has no | ||
| * `owns` field — in which case binding is a no-op and the resolver behaves | ||
| * exactly as before. | ||
| * `abortOn` field — in which case binding is a no-op and the resolver | ||
| * behaves exactly as before. | ||
| * | ||
@@ -752,3 +754,3 @@ * @internal | ||
| interface ConstraintBindingInfo { | ||
| /** Fact keys the triggering resolver owns; writes to these are clobber-checked. */ | ||
| /** Fact keys this resolver aborts on when changed mid-flight; writes to these are clobber-checked. */ | ||
| readonly fields: readonly string[]; | ||
@@ -769,7 +771,7 @@ } | ||
| /** | ||
| * Look up binding info for a source constraint id (RFC-1). | ||
| * Look up binding info for a source constraint id (RFC-0003). | ||
| * | ||
| * Wired by the engine — given the `fromConstraint` of a `RequirementWithId`, | ||
| * returns the constraint's owned fact keys. Return `undefined` if the | ||
| * constraint is unknown or has no `owns` field. | ||
| * returns the constraint's abort-binding fact keys. Return `undefined` if | ||
| * the constraint is unknown or has no `abortOn` field. | ||
| */ | ||
@@ -785,3 +787,3 @@ getConstraintBinding?: (constraintId: string) => ConstraintBindingInfo | undefined; | ||
| onRetry?: (resolver: string, req: RequirementWithId, attempt: number) => void; | ||
| /** Called when a resolver is canceled via {@link ResolversManager.cancel | cancel}. */ | ||
| /** Called when a resolver is aborted via {@link ResolversManager.abort | abort}. */ | ||
| onCancel?: (resolver: string, req: RequirementWithId) => void; | ||
@@ -813,3 +815,3 @@ /** | ||
| * Creates a resolver manager that tracks active resolver instances and | ||
| * coordinates their lifecycle (start / complete / error / cancel) against | ||
| * coordinates their lifecycle (start / complete / error / abort) against | ||
| * the engine's requirement graph. | ||
@@ -1077,2 +1079,14 @@ * | ||
| emitConstraintError(id: string, error: unknown): void; | ||
| /** | ||
| * Fired once per lookup when the engine silently disables a | ||
| * constraint's `abortOn:` binding because the constraint is async. | ||
| * Pairs with the dev-mode `console.warn` for SIEM visibility — without | ||
| * this signal, a production constraint loses its clobber-protection | ||
| * with no plugin trail. | ||
| * | ||
| * `"async-declared"` means the def has `async: true` (author opted in); | ||
| * `"async-promoted"` means `when()` returned a Promise at runtime | ||
| * (author probably did not realize). | ||
| */ | ||
| emitConstraintBindingDisabled(id: string, reason: "async-declared" | "async-promoted"): void; | ||
| emitRequirementCreated(req: RequirementWithId): void; | ||
@@ -1079,0 +1093,0 @@ emitRequirementMet(req: RequirementWithId, byResolver: string): void; |
@@ -1,2 +0,2 @@ | ||
| export{c as createConstraintFactory,p as createConstraintsManager,q as createDerivationsManager,j as createDisabledHistory,r as createEffectsManager,A as createEngine,t as createErrorBoundaryManager,w as createFacts,v as createFactsProxy,u as createFactsStore,i as createHistoryManager,x as createPluginManager,d as createResolverFactory,y as createResolversManager,s as createRetryLaterManager,z as createSourcesManager}from'./chunk-6QAUJFQH.js';export{m as dangerousRegex}from'./chunk-RBF653NR.js';export{f as getCurrentDeps,g as isTracking,j as trackAccess,h as withTracking,i as withoutTracking}from'./chunk-6PF2FRBG.js';export{h as hashObject,f as isPrototypeSafe,o as safeStringify,e as stableStringify}from'./chunk-SFUVPP4L.js';//# sourceMappingURL=internals.js.map | ||
| export{c as createConstraintFactory,p as createConstraintsManager,q as createDerivationsManager,j as createDisabledHistory,r as createEffectsManager,A as createEngine,t as createErrorBoundaryManager,w as createFacts,v as createFactsProxy,u as createFactsStore,i as createHistoryManager,x as createPluginManager,d as createResolverFactory,y as createResolversManager,s as createRetryLaterManager,z as createSourcesManager}from'./chunk-6NCC6RBC.js';export{m as dangerousRegex}from'./chunk-RBF653NR.js';export{f as getCurrentDeps,g as isTracking,j as trackAccess,h as withTracking,i as withoutTracking}from'./chunk-6PF2FRBG.js';export{h as hashObject,f as isPrototypeSafe,o as safeStringify,e as stableStringify}from'./chunk-SFUVPP4L.js';//# sourceMappingURL=internals.js.map | ||
| //# sourceMappingURL=internals.js.map |
+159
-3
@@ -1,3 +0,3 @@ | ||
| export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, e as createAuditLedger, m as memorySink } from '../index-CvQuu0tu.cjs'; | ||
| import { M as ModuleSchema, P as Plugin, ap as System } from '../plugins-4IfhJV32.cjs'; | ||
| export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, e as createAuditLedger, m as memorySink } from '../index-DRPkZ8HE.cjs'; | ||
| import { M as ModuleSchema, P as Plugin, ap as System } from '../plugins-5Supk7it.cjs'; | ||
@@ -848,2 +848,158 @@ /** | ||
| export { type AggregatedMetric, type AlertConfig, type AlertEvent, type CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, type ConstraintMetrics, DEVTOOLS_EVENT_NAME, type DashboardData, type DevtoolsPluginOptions, type EffectMetrics, type HistogramBucket, type LoggingPluginOptions, type MetricDataPoint, type MetricType, type OTLPExporter, type OTLPExporterConfig, type ObservabilityConfig, type ObservabilityInstance, type PerformancePluginOptions, type PerformanceSnapshot, type PersistencePluginOptions, type ReconcileMetrics, type ResolverMetrics, type TraceEvent, type TraceSpan, createAgentMetrics, createCircuitBreaker, createOTLPExporter, createObservability, devtoolsPlugin, emitDevToolsEvent, loggingPlugin, performancePlugin, persistencePlugin }; | ||
| /** | ||
| * Clobber Alert Plugin – default high-severity alerting for | ||
| * `resolver.write.rejected { reason: "clobbered" }` events landing on | ||
| * facts tagged irreversible. | ||
| * | ||
| * The audit ledger already records every clobber event with full | ||
| * forensic detail (fact, expected, actual, resolver, requirementId). | ||
| * But a clobber on a fact tagged `"money"` / `"pii"` / `"irreversible"` | ||
| * is operationally far more urgent than a clobber on a UI status fact. | ||
| * Without this plugin, a consumer has to write their own SIEM rule to | ||
| * separate "noise" from "page an engineer NOW." | ||
| * | ||
| * Default behaviour: fire `console.error` on every clobber whose fact's | ||
| * schema meta carries any tag in `irreversibleTags`. Replace the | ||
| * `onAlert` callback to route to PagerDuty / Slack / Sentry / your SIEM | ||
| * of choice. | ||
| * | ||
| * @public | ||
| */ | ||
| /** Configuration for the {@link clobberAlertPlugin}. */ | ||
| interface ClobberAlertPluginOptions { | ||
| /** | ||
| * Fact-meta tags that promote a clobber event from "noise" to | ||
| * "high-severity alert." A clobber whose fact's schema meta carries | ||
| * ANY of these tags fires `onAlert`. | ||
| * | ||
| * **Why tag the fact, not the resolver?** A clobber is detected at | ||
| * fact-write time. The audit event payload (`fact`, `expected`, | ||
| * `actual`) names the fact, not the side effect — the fact is the | ||
| * trigger surface for any irreversible work the resolver is about | ||
| * to do (a charge, a send, a delete). Tagging `payment.amount` with | ||
| * `"money"` marks the fact whose race-loss should page someone. | ||
| * | ||
| * If your model puts the irreversibility on the resolver rather than | ||
| * the fact, use `irreversibleResolvers` — both filters OR. | ||
| * | ||
| * Default: `["money", "pii", "irreversible"]`. | ||
| */ | ||
| irreversibleTags?: readonly string[]; | ||
| /** | ||
| * Resolver IDs whose clobbered writes should always alert, regardless | ||
| * of fact tags. Use this when irreversibility is modeled on the | ||
| * resolver (e.g. `stripeCharge`) rather than on the trigger fact. | ||
| * Defaults to empty — the fact-tag path covers most cases. | ||
| */ | ||
| irreversibleResolvers?: readonly string[]; | ||
| /** | ||
| * Callback fired when a clobber lands on a fact whose tags overlap | ||
| * `irreversibleTags`, or whose resolver is in `irreversibleResolvers`. | ||
| * Default: `console.error(...)`. | ||
| */ | ||
| onAlert?: (event: ClobberAlertEvent) => void; | ||
| /** | ||
| * Callback fired when the engine's per-resolver rate limit aggregates | ||
| * multiple per-write clobber events into a single | ||
| * `kind: "summary"` event (default cap: 10 per-resolver-instance). | ||
| * The summary names the resolver + dropped count but loses per-fact | ||
| * attribution — the engine has no way to enumerate every dropped | ||
| * write inside the cap. | ||
| * | ||
| * Only fires when EITHER: | ||
| * - the resolver is listed in `irreversibleResolvers`, OR | ||
| * - this plugin has previously fired `onAlert` for the resolver | ||
| * (i.e. the resolver has touched an irreversible fact in this | ||
| * session, so a follow-on burst is operationally relevant) | ||
| * | ||
| * Default: undefined (no summary alerts). Set this to preserve | ||
| * SIEM telemetry past the engine's rate-limit cap on a hot | ||
| * resolver fighting an irreversible fact. | ||
| */ | ||
| onSummary?: (event: ClobberSummaryEvent) => void; | ||
| /** | ||
| * Cooldown window keyed by `(fact, resolver)` pair. A second clobber | ||
| * from the same resolver on the same fact within this window does not | ||
| * re-fire `onAlert`. A clobber from a *different* resolver on the | ||
| * same fact still fires — fighting writers are a different | ||
| * operational incident than a single resolver retrying. | ||
| * | ||
| * The audit ledger records every clobber regardless of cooldown. | ||
| * | ||
| * Default: `0` (no cooldown — every event alerts). | ||
| */ | ||
| cooldownMs?: number; | ||
| } | ||
| /** Payload passed to {@link ClobberAlertPluginOptions.onAlert}. */ | ||
| interface ClobberAlertEvent { | ||
| readonly fact: string; | ||
| /** | ||
| * Fact-meta tags that matched `irreversibleTags`. Empty when the alert | ||
| * fired only because the resolver matched `irreversibleResolvers`. | ||
| * Use {@link matchedBy} to distinguish without checking length. | ||
| */ | ||
| readonly tags: readonly string[]; | ||
| /** | ||
| * Which filter triggered the alert: | ||
| * - `"tag"` — fact-meta tags overlapped `irreversibleTags` | ||
| * - `"resolver"` — resolver ID matched `irreversibleResolvers` | ||
| * - `"both"` — both filters matched | ||
| */ | ||
| readonly matchedBy: "tag" | "resolver" | "both"; | ||
| readonly resolver: string; | ||
| readonly requirementId: string; | ||
| readonly expected: unknown; | ||
| readonly actual: unknown; | ||
| /** `Date.now()` at the moment the alert fired. */ | ||
| readonly timestamp: number; | ||
| } | ||
| /** | ||
| * Payload passed to {@link ClobberAlertPluginOptions.onSummary}. | ||
| * | ||
| * Fired when the engine's per-resolver clobber rate-limit aggregates | ||
| * multiple per-write events into one summary. Per-fact attribution is | ||
| * lost (the engine cannot enumerate every dropped write inside the | ||
| * cap), but the resolver + dropped count are preserved so SIEM can | ||
| * page on "this resolver is still fighting an irreversible fact | ||
| * past the cap." | ||
| */ | ||
| interface ClobberSummaryEvent { | ||
| readonly resolver: string; | ||
| readonly requirementId: string; | ||
| /** Number of per-write clobber events the engine suppressed under the cap. */ | ||
| readonly dropped: number; | ||
| /** | ||
| * Why the summary surfaced from this plugin's filter: | ||
| * - `"resolver-listed"` — the resolver was in `irreversibleResolvers` | ||
| * - `"prior-irreversible-alert"` — the resolver had already fired | ||
| * `onAlert` on an irreversible fact in this session | ||
| */ | ||
| readonly matchedBy: "resolver-listed" | "prior-irreversible-alert"; | ||
| /** `Date.now()` at the moment the summary fired. */ | ||
| readonly timestamp: number; | ||
| } | ||
| /** | ||
| * Create a plugin that fires high-severity alerts for clobber events | ||
| * landing on irreversible-tagged facts. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * createSystem({ | ||
| * module: myModule, | ||
| * plugins: [ | ||
| * clobberAlertPlugin({ | ||
| * irreversibleTags: ["money", "pii"], | ||
| * onAlert: (e) => pagerduty.trigger({ | ||
| * severity: "critical", | ||
| * summary: `Clobber on ${e.fact} (${e.tags.join(", ")})`, | ||
| * details: e, | ||
| * }), | ||
| * }), | ||
| * ], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function clobberAlertPlugin<M extends ModuleSchema>(options?: ClobberAlertPluginOptions): Plugin<M>; | ||
| export { type AggregatedMetric, type AlertConfig, type AlertEvent, type CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, type ClobberAlertEvent, type ClobberAlertPluginOptions, type ConstraintMetrics, DEVTOOLS_EVENT_NAME, type DashboardData, type DevtoolsPluginOptions, type EffectMetrics, type HistogramBucket, type LoggingPluginOptions, type MetricDataPoint, type MetricType, type OTLPExporter, type OTLPExporterConfig, type ObservabilityConfig, type ObservabilityInstance, type PerformancePluginOptions, type PerformanceSnapshot, type PersistencePluginOptions, type ReconcileMetrics, type ResolverMetrics, type TraceEvent, type TraceSpan, clobberAlertPlugin, createAgentMetrics, createCircuitBreaker, createOTLPExporter, createObservability, devtoolsPlugin, emitDevToolsEvent, loggingPlugin, performancePlugin, persistencePlugin }; |
+159
-3
@@ -1,3 +0,3 @@ | ||
| export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, e as createAuditLedger, m as memorySink } from '../index-DUbpbGw8.js'; | ||
| import { M as ModuleSchema, P as Plugin, ap as System } from '../plugins-4IfhJV32.js'; | ||
| export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, e as createAuditLedger, m as memorySink } from '../index-BgKC_ZT_.js'; | ||
| import { M as ModuleSchema, P as Plugin, ap as System } from '../plugins-5Supk7it.js'; | ||
@@ -848,2 +848,158 @@ /** | ||
| export { type AggregatedMetric, type AlertConfig, type AlertEvent, type CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, type ConstraintMetrics, DEVTOOLS_EVENT_NAME, type DashboardData, type DevtoolsPluginOptions, type EffectMetrics, type HistogramBucket, type LoggingPluginOptions, type MetricDataPoint, type MetricType, type OTLPExporter, type OTLPExporterConfig, type ObservabilityConfig, type ObservabilityInstance, type PerformancePluginOptions, type PerformanceSnapshot, type PersistencePluginOptions, type ReconcileMetrics, type ResolverMetrics, type TraceEvent, type TraceSpan, createAgentMetrics, createCircuitBreaker, createOTLPExporter, createObservability, devtoolsPlugin, emitDevToolsEvent, loggingPlugin, performancePlugin, persistencePlugin }; | ||
| /** | ||
| * Clobber Alert Plugin – default high-severity alerting for | ||
| * `resolver.write.rejected { reason: "clobbered" }` events landing on | ||
| * facts tagged irreversible. | ||
| * | ||
| * The audit ledger already records every clobber event with full | ||
| * forensic detail (fact, expected, actual, resolver, requirementId). | ||
| * But a clobber on a fact tagged `"money"` / `"pii"` / `"irreversible"` | ||
| * is operationally far more urgent than a clobber on a UI status fact. | ||
| * Without this plugin, a consumer has to write their own SIEM rule to | ||
| * separate "noise" from "page an engineer NOW." | ||
| * | ||
| * Default behaviour: fire `console.error` on every clobber whose fact's | ||
| * schema meta carries any tag in `irreversibleTags`. Replace the | ||
| * `onAlert` callback to route to PagerDuty / Slack / Sentry / your SIEM | ||
| * of choice. | ||
| * | ||
| * @public | ||
| */ | ||
| /** Configuration for the {@link clobberAlertPlugin}. */ | ||
| interface ClobberAlertPluginOptions { | ||
| /** | ||
| * Fact-meta tags that promote a clobber event from "noise" to | ||
| * "high-severity alert." A clobber whose fact's schema meta carries | ||
| * ANY of these tags fires `onAlert`. | ||
| * | ||
| * **Why tag the fact, not the resolver?** A clobber is detected at | ||
| * fact-write time. The audit event payload (`fact`, `expected`, | ||
| * `actual`) names the fact, not the side effect — the fact is the | ||
| * trigger surface for any irreversible work the resolver is about | ||
| * to do (a charge, a send, a delete). Tagging `payment.amount` with | ||
| * `"money"` marks the fact whose race-loss should page someone. | ||
| * | ||
| * If your model puts the irreversibility on the resolver rather than | ||
| * the fact, use `irreversibleResolvers` — both filters OR. | ||
| * | ||
| * Default: `["money", "pii", "irreversible"]`. | ||
| */ | ||
| irreversibleTags?: readonly string[]; | ||
| /** | ||
| * Resolver IDs whose clobbered writes should always alert, regardless | ||
| * of fact tags. Use this when irreversibility is modeled on the | ||
| * resolver (e.g. `stripeCharge`) rather than on the trigger fact. | ||
| * Defaults to empty — the fact-tag path covers most cases. | ||
| */ | ||
| irreversibleResolvers?: readonly string[]; | ||
| /** | ||
| * Callback fired when a clobber lands on a fact whose tags overlap | ||
| * `irreversibleTags`, or whose resolver is in `irreversibleResolvers`. | ||
| * Default: `console.error(...)`. | ||
| */ | ||
| onAlert?: (event: ClobberAlertEvent) => void; | ||
| /** | ||
| * Callback fired when the engine's per-resolver rate limit aggregates | ||
| * multiple per-write clobber events into a single | ||
| * `kind: "summary"` event (default cap: 10 per-resolver-instance). | ||
| * The summary names the resolver + dropped count but loses per-fact | ||
| * attribution — the engine has no way to enumerate every dropped | ||
| * write inside the cap. | ||
| * | ||
| * Only fires when EITHER: | ||
| * - the resolver is listed in `irreversibleResolvers`, OR | ||
| * - this plugin has previously fired `onAlert` for the resolver | ||
| * (i.e. the resolver has touched an irreversible fact in this | ||
| * session, so a follow-on burst is operationally relevant) | ||
| * | ||
| * Default: undefined (no summary alerts). Set this to preserve | ||
| * SIEM telemetry past the engine's rate-limit cap on a hot | ||
| * resolver fighting an irreversible fact. | ||
| */ | ||
| onSummary?: (event: ClobberSummaryEvent) => void; | ||
| /** | ||
| * Cooldown window keyed by `(fact, resolver)` pair. A second clobber | ||
| * from the same resolver on the same fact within this window does not | ||
| * re-fire `onAlert`. A clobber from a *different* resolver on the | ||
| * same fact still fires — fighting writers are a different | ||
| * operational incident than a single resolver retrying. | ||
| * | ||
| * The audit ledger records every clobber regardless of cooldown. | ||
| * | ||
| * Default: `0` (no cooldown — every event alerts). | ||
| */ | ||
| cooldownMs?: number; | ||
| } | ||
| /** Payload passed to {@link ClobberAlertPluginOptions.onAlert}. */ | ||
| interface ClobberAlertEvent { | ||
| readonly fact: string; | ||
| /** | ||
| * Fact-meta tags that matched `irreversibleTags`. Empty when the alert | ||
| * fired only because the resolver matched `irreversibleResolvers`. | ||
| * Use {@link matchedBy} to distinguish without checking length. | ||
| */ | ||
| readonly tags: readonly string[]; | ||
| /** | ||
| * Which filter triggered the alert: | ||
| * - `"tag"` — fact-meta tags overlapped `irreversibleTags` | ||
| * - `"resolver"` — resolver ID matched `irreversibleResolvers` | ||
| * - `"both"` — both filters matched | ||
| */ | ||
| readonly matchedBy: "tag" | "resolver" | "both"; | ||
| readonly resolver: string; | ||
| readonly requirementId: string; | ||
| readonly expected: unknown; | ||
| readonly actual: unknown; | ||
| /** `Date.now()` at the moment the alert fired. */ | ||
| readonly timestamp: number; | ||
| } | ||
| /** | ||
| * Payload passed to {@link ClobberAlertPluginOptions.onSummary}. | ||
| * | ||
| * Fired when the engine's per-resolver clobber rate-limit aggregates | ||
| * multiple per-write events into one summary. Per-fact attribution is | ||
| * lost (the engine cannot enumerate every dropped write inside the | ||
| * cap), but the resolver + dropped count are preserved so SIEM can | ||
| * page on "this resolver is still fighting an irreversible fact | ||
| * past the cap." | ||
| */ | ||
| interface ClobberSummaryEvent { | ||
| readonly resolver: string; | ||
| readonly requirementId: string; | ||
| /** Number of per-write clobber events the engine suppressed under the cap. */ | ||
| readonly dropped: number; | ||
| /** | ||
| * Why the summary surfaced from this plugin's filter: | ||
| * - `"resolver-listed"` — the resolver was in `irreversibleResolvers` | ||
| * - `"prior-irreversible-alert"` — the resolver had already fired | ||
| * `onAlert` on an irreversible fact in this session | ||
| */ | ||
| readonly matchedBy: "resolver-listed" | "prior-irreversible-alert"; | ||
| /** `Date.now()` at the moment the summary fired. */ | ||
| readonly timestamp: number; | ||
| } | ||
| /** | ||
| * Create a plugin that fires high-severity alerts for clobber events | ||
| * landing on irreversible-tagged facts. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * createSystem({ | ||
| * module: myModule, | ||
| * plugins: [ | ||
| * clobberAlertPlugin({ | ||
| * irreversibleTags: ["money", "pii"], | ||
| * onAlert: (e) => pagerduty.trigger({ | ||
| * severity: "critical", | ||
| * summary: `Clobber on ${e.fact} (${e.tags.join(", ")})`, | ||
| * details: e, | ||
| * }), | ||
| * }), | ||
| * ], | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function clobberAlertPlugin<M extends ModuleSchema>(options?: ClobberAlertPluginOptions): Plugin<M>; | ||
| export { type AggregatedMetric, type AlertConfig, type AlertEvent, type CircuitBreaker, type CircuitBreakerConfig, CircuitBreakerOpenError, type CircuitBreakerStats, type CircuitState, type ClobberAlertEvent, type ClobberAlertPluginOptions, type ConstraintMetrics, DEVTOOLS_EVENT_NAME, type DashboardData, type DevtoolsPluginOptions, type EffectMetrics, type HistogramBucket, type LoggingPluginOptions, type MetricDataPoint, type MetricType, type OTLPExporter, type OTLPExporterConfig, type ObservabilityConfig, type ObservabilityInstance, type PerformancePluginOptions, type PerformanceSnapshot, type PersistencePluginOptions, type ReconcileMetrics, type ResolverMetrics, type TraceEvent, type TraceSpan, clobberAlertPlugin, createAgentMetrics, createCircuitBreaker, createOTLPExporter, createObservability, devtoolsPlugin, emitDevToolsEvent, loggingPlugin, performancePlugin, persistencePlugin }; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| 'use strict';var chunk4OXCKDKS_cjs=require('./chunk-4OXCKDKS.cjs');require('./chunk-M5PEB553.cjs'),require('./chunk-GACC2DMS.cjs'),require('./chunk-GKMJ7NMP.cjs'),require('./chunk-GBCWXTXW.cjs');async function R(){for(let e=0;e<10;e++)await Promise.resolve();}async function T(){for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();}async function D(e,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,d=0;for(;m<o&&d<l;){if(await R(),e.inspect().inflight.length===0){await R();return}s(c),m+=c,d++;}let v=e.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function C(){let e=0,s=[];return {async advance(r){let o=e+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();e=c.time,c.callback(),await Promise.resolve();}e=o;},async next(){if(s.length===0)return;let r=s.shift();e=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return e},reset(){e=0,s.length=0;}}}function b(e){let s=typeof e=="string"?{requirement:(o=>o.type===e)}:e,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function E(e){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((d,v)=>{r.push({requirement:l,resolve:f=>d(f),reject:v});}))}}function P(e){return "module"in e?x(e):M(e)}function x(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[i,t]of Object.entries(e.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...t,calls:n});}let m={...e.module,resolvers:{...e.module.resolvers,...l}},v=chunk4OXCKDKS_cjs.a({...e,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,t,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:t,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...e.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let t=Date.now(),n=async()=>{await new Promise(u=>setTimeout(u,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-t>i){let u=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${u}`)}return await new Promise(u=>setTimeout(u,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,t){let n=r.get(i)??[];if(t!==void 0){if(n.length!==t)throw new Error(`[Directive] Expected resolver "${i}" to be called ${t} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,t){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(t!==void 0&&!n.some(u=>u.newValue===t)){let u=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(t)} but got: ${u}`)}},assertFactChanges(i,t){let n=c.filter(a=>a.key===i);if(n.length!==t)throw new Error(`[Directive] Expected fact "${i}" to change ${t} times but it changed ${n.length} times`)}}}function M(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[t,n]of Object.entries(e.mocks.resolvers)){let a=[];r.set(t,a),l[t]=b({...n,calls:a});}let m={};for(let[t,n]of Object.entries(e.modules))m[t]={...n,resolvers:{...n.resolvers,...l}};let d=new Set(Object.keys(e.modules)),f=chunk4OXCKDKS_cjs.a({...e,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(t,n,a)=>{let g=t.indexOf("::"),y,h;if(g>0){let S=t.substring(0,g);d.has(S)?(y=S,h=t.substring(g+2)):h=t;}else h=t;c.push({key:h,fullKey:t,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:t=>{o.push(t);}},...e.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=t=>{s.push(t),p(t);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(t=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let u=f.inspect();if(u.inflight.length>0){if(Date.now()-n>t){let g=u.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${t}ms. ${u.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(t){if(!o.some(a=>a.requirement.type===t))throw new Error(`[Directive] Expected requirement of type "${t}" but none found`)},assertResolverCalled(t,n){let a=r.get(t)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${t}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${t}" to be called but it was not`)},assertFactSet(t,n){let a=c.filter(u=>u.key===t);if(a.length===0)throw new Error(`[Directive] Expected fact "${t}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${t}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(t,n){let a=c.filter(u=>u.key===t);if(a.length!==n)throw new Error(`[Directive] Expected fact "${t}" to change ${n} times but it changed ${a.length} times`)}}}function O(e,s,r){if(!k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(e,s,r){if(k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(e,s,r){switch(s){case "constraint":return e.constraints.isDynamic(r);case "resolver":return e.resolvers.isDynamic(r);case "derivation":return e.derive.isDynamic(r);case "effect":return e.effects.isDynamic(r)}}function F(e){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=e.observe(d=>{switch(d.type){case "constraint.evaluate":d.active&&s.add(d.id);break;case "resolver.start":r.add(d.resolver);break;case "effect.run":o.add(d.id);break;case "derivation.compute":c.add(d.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=e.inspect(),d=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of d)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:d.size===0?1:s.size/d.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function I(e){let s=[],r=e.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}exports.assertDynamic=O;exports.assertNotDynamic=$;exports.createCoverageTracker=F;exports.createFakeTimers=C;exports.createMockResolver=b;exports.createTestObserver=I;exports.createTestSystem=P;exports.flushAsync=T;exports.flushMicrotasks=R;exports.mockResolver=E;exports.settleWithFakeTimers=D;//# sourceMappingURL=testing.cjs.map | ||
| 'use strict';var chunkOAPD3HIG_cjs=require('./chunk-OAPD3HIG.cjs');require('./chunk-QTY2FXZY.cjs'),require('./chunk-GACC2DMS.cjs'),require('./chunk-GKMJ7NMP.cjs'),require('./chunk-GBCWXTXW.cjs');async function R(){for(let e=0;e<10;e++)await Promise.resolve();}async function T(){for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();}async function D(e,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,d=0;for(;m<o&&d<l;){if(await R(),e.inspect().inflight.length===0){await R();return}s(c),m+=c,d++;}let v=e.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function C(){let e=0,s=[];return {async advance(r){let o=e+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();e=c.time,c.callback(),await Promise.resolve();}e=o;},async next(){if(s.length===0)return;let r=s.shift();e=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return e},reset(){e=0,s.length=0;}}}function b(e){let s=typeof e=="string"?{requirement:(o=>o.type===e)}:e,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function E(e){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((d,v)=>{r.push({requirement:l,resolve:f=>d(f),reject:v});}))}}function P(e){return "module"in e?x(e):M(e)}function x(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[i,t]of Object.entries(e.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...t,calls:n});}let m={...e.module,resolvers:{...e.module.resolvers,...l}},v=chunkOAPD3HIG_cjs.a({...e,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,t,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:t,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...e.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let t=Date.now(),n=async()=>{await new Promise(u=>setTimeout(u,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-t>i){let u=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${u}`)}return await new Promise(u=>setTimeout(u,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,t){let n=r.get(i)??[];if(t!==void 0){if(n.length!==t)throw new Error(`[Directive] Expected resolver "${i}" to be called ${t} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,t){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(t!==void 0&&!n.some(u=>u.newValue===t)){let u=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(t)} but got: ${u}`)}},assertFactChanges(i,t){let n=c.filter(a=>a.key===i);if(n.length!==t)throw new Error(`[Directive] Expected fact "${i}" to change ${t} times but it changed ${n.length} times`)}}}function M(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[t,n]of Object.entries(e.mocks.resolvers)){let a=[];r.set(t,a),l[t]=b({...n,calls:a});}let m={};for(let[t,n]of Object.entries(e.modules))m[t]={...n,resolvers:{...n.resolvers,...l}};let d=new Set(Object.keys(e.modules)),f=chunkOAPD3HIG_cjs.a({...e,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(t,n,a)=>{let g=t.indexOf("::"),y,h;if(g>0){let S=t.substring(0,g);d.has(S)?(y=S,h=t.substring(g+2)):h=t;}else h=t;c.push({key:h,fullKey:t,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:t=>{o.push(t);}},...e.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=t=>{s.push(t),p(t);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(t=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let u=f.inspect();if(u.inflight.length>0){if(Date.now()-n>t){let g=u.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${t}ms. ${u.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(t){if(!o.some(a=>a.requirement.type===t))throw new Error(`[Directive] Expected requirement of type "${t}" but none found`)},assertResolverCalled(t,n){let a=r.get(t)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${t}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${t}" to be called but it was not`)},assertFactSet(t,n){let a=c.filter(u=>u.key===t);if(a.length===0)throw new Error(`[Directive] Expected fact "${t}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${t}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(t,n){let a=c.filter(u=>u.key===t);if(a.length!==n)throw new Error(`[Directive] Expected fact "${t}" to change ${n} times but it changed ${a.length} times`)}}}function O(e,s,r){if(!k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(e,s,r){if(k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(e,s,r){switch(s){case "constraint":return e.constraints.isDynamic(r);case "resolver":return e.resolvers.isDynamic(r);case "derivation":return e.derive.isDynamic(r);case "effect":return e.effects.isDynamic(r)}}function F(e){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=e.observe(d=>{switch(d.type){case "constraint.evaluate":d.active&&s.add(d.id);break;case "resolver.start":r.add(d.resolver);break;case "effect.run":o.add(d.id);break;case "derivation.compute":c.add(d.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=e.inspect(),d=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of d)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:d.size===0?1:s.size/d.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function I(e){let s=[],r=e.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}exports.assertDynamic=O;exports.assertNotDynamic=$;exports.createCoverageTracker=F;exports.createFakeTimers=C;exports.createMockResolver=b;exports.createTestObserver=I;exports.createTestSystem=P;exports.flushAsync=T;exports.flushMicrotasks=R;exports.mockResolver=E;exports.settleWithFakeTimers=D;//# sourceMappingURL=testing.cjs.map | ||
| //# sourceMappingURL=testing.cjs.map |
@@ -1,2 +0,2 @@ | ||
| import { n as ModulesMap, o as CreateSystemOptionsNamed, r as Requirement, M as ModuleSchema, l as CreateSystemOptionsSingle, N as NamespacedSystem, R as RequirementWithId, m as SingleModuleSystem, a4 as ObservationEvent, at as SystemInspection } from './plugins-4IfhJV32.cjs'; | ||
| import { n as ModulesMap, o as CreateSystemOptionsNamed, r as Requirement, M as ModuleSchema, l as CreateSystemOptionsSingle, N as NamespacedSystem, R as RequirementWithId, m as SingleModuleSystem, a4 as ObservationEvent, at as SystemInspection } from './plugins-5Supk7it.cjs'; | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
| import { n as ModulesMap, o as CreateSystemOptionsNamed, r as Requirement, M as ModuleSchema, l as CreateSystemOptionsSingle, N as NamespacedSystem, R as RequirementWithId, m as SingleModuleSystem, a4 as ObservationEvent, at as SystemInspection } from './plugins-4IfhJV32.js'; | ||
| import { n as ModulesMap, o as CreateSystemOptionsNamed, r as Requirement, M as ModuleSchema, l as CreateSystemOptionsSingle, N as NamespacedSystem, R as RequirementWithId, m as SingleModuleSystem, a4 as ObservationEvent, at as SystemInspection } from './plugins-5Supk7it.js'; | ||
@@ -3,0 +3,0 @@ /** |
+1
-1
@@ -1,2 +0,2 @@ | ||
| import {a}from'./chunk-E53A4NHM.js';import'./chunk-6QAUJFQH.js';import'./chunk-RBF653NR.js';import'./chunk-6PF2FRBG.js';import'./chunk-SFUVPP4L.js';async function R(){for(let e=0;e<10;e++)await Promise.resolve();}async function T(){for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();}async function D(e,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,d=0;for(;m<o&&d<l;){if(await R(),e.inspect().inflight.length===0){await R();return}s(c),m+=c,d++;}let v=e.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function C(){let e=0,s=[];return {async advance(r){let o=e+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();e=c.time,c.callback(),await Promise.resolve();}e=o;},async next(){if(s.length===0)return;let r=s.shift();e=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return e},reset(){e=0,s.length=0;}}}function b(e){let s=typeof e=="string"?{requirement:(o=>o.type===e)}:e,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function E(e){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((d,v)=>{r.push({requirement:l,resolve:f=>d(f),reject:v});}))}}function P(e){return "module"in e?x(e):M(e)}function x(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[i,t]of Object.entries(e.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...t,calls:n});}let m={...e.module,resolvers:{...e.module.resolvers,...l}},v=a({...e,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,t,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:t,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...e.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let t=Date.now(),n=async()=>{await new Promise(u=>setTimeout(u,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-t>i){let u=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${u}`)}return await new Promise(u=>setTimeout(u,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,t){let n=r.get(i)??[];if(t!==void 0){if(n.length!==t)throw new Error(`[Directive] Expected resolver "${i}" to be called ${t} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,t){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(t!==void 0&&!n.some(u=>u.newValue===t)){let u=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(t)} but got: ${u}`)}},assertFactChanges(i,t){let n=c.filter(a=>a.key===i);if(n.length!==t)throw new Error(`[Directive] Expected fact "${i}" to change ${t} times but it changed ${n.length} times`)}}}function M(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[t,n]of Object.entries(e.mocks.resolvers)){let a=[];r.set(t,a),l[t]=b({...n,calls:a});}let m={};for(let[t,n]of Object.entries(e.modules))m[t]={...n,resolvers:{...n.resolvers,...l}};let d=new Set(Object.keys(e.modules)),f=a({...e,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(t,n,a)=>{let g=t.indexOf("::"),y,h;if(g>0){let S=t.substring(0,g);d.has(S)?(y=S,h=t.substring(g+2)):h=t;}else h=t;c.push({key:h,fullKey:t,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:t=>{o.push(t);}},...e.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=t=>{s.push(t),p(t);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(t=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let u=f.inspect();if(u.inflight.length>0){if(Date.now()-n>t){let g=u.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${t}ms. ${u.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(t){if(!o.some(a=>a.requirement.type===t))throw new Error(`[Directive] Expected requirement of type "${t}" but none found`)},assertResolverCalled(t,n){let a=r.get(t)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${t}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${t}" to be called but it was not`)},assertFactSet(t,n){let a=c.filter(u=>u.key===t);if(a.length===0)throw new Error(`[Directive] Expected fact "${t}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${t}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(t,n){let a=c.filter(u=>u.key===t);if(a.length!==n)throw new Error(`[Directive] Expected fact "${t}" to change ${n} times but it changed ${a.length} times`)}}}function O(e,s,r){if(!k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(e,s,r){if(k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(e,s,r){switch(s){case "constraint":return e.constraints.isDynamic(r);case "resolver":return e.resolvers.isDynamic(r);case "derivation":return e.derive.isDynamic(r);case "effect":return e.effects.isDynamic(r)}}function F(e){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=e.observe(d=>{switch(d.type){case "constraint.evaluate":d.active&&s.add(d.id);break;case "resolver.start":r.add(d.resolver);break;case "effect.run":o.add(d.id);break;case "derivation.compute":c.add(d.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=e.inspect(),d=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of d)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:d.size===0?1:s.size/d.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function I(e){let s=[],r=e.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}export{O as assertDynamic,$ as assertNotDynamic,F as createCoverageTracker,C as createFakeTimers,b as createMockResolver,I as createTestObserver,P as createTestSystem,T as flushAsync,R as flushMicrotasks,E as mockResolver,D as settleWithFakeTimers};//# sourceMappingURL=testing.js.map | ||
| import {a}from'./chunk-YJEDX2JX.js';import'./chunk-6NCC6RBC.js';import'./chunk-RBF653NR.js';import'./chunk-6PF2FRBG.js';import'./chunk-SFUVPP4L.js';async function R(){for(let e=0;e<10;e++)await Promise.resolve();}async function T(){for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();}async function D(e,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,d=0;for(;m<o&&d<l;){if(await R(),e.inspect().inflight.length===0){await R();return}s(c),m+=c,d++;}let v=e.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function C(){let e=0,s=[];return {async advance(r){let o=e+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();e=c.time,c.callback(),await Promise.resolve();}e=o;},async next(){if(s.length===0)return;let r=s.shift();e=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return e},reset(){e=0,s.length=0;}}}function b(e){let s=typeof e=="string"?{requirement:(o=>o.type===e)}:e,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function E(e){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((d,v)=>{r.push({requirement:l,resolve:f=>d(f),reject:v});}))}}function P(e){return "module"in e?x(e):M(e)}function x(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[i,t]of Object.entries(e.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...t,calls:n});}let m={...e.module,resolvers:{...e.module.resolvers,...l}},v=a({...e,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,t,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:t,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...e.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let t=Date.now(),n=async()=>{await new Promise(u=>setTimeout(u,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-t>i){let u=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${u}`)}return await new Promise(u=>setTimeout(u,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,t){let n=r.get(i)??[];if(t!==void 0){if(n.length!==t)throw new Error(`[Directive] Expected resolver "${i}" to be called ${t} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,t){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(t!==void 0&&!n.some(u=>u.newValue===t)){let u=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(t)} but got: ${u}`)}},assertFactChanges(i,t){let n=c.filter(a=>a.key===i);if(n.length!==t)throw new Error(`[Directive] Expected fact "${i}" to change ${t} times but it changed ${n.length} times`)}}}function M(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[t,n]of Object.entries(e.mocks.resolvers)){let a=[];r.set(t,a),l[t]=b({...n,calls:a});}let m={};for(let[t,n]of Object.entries(e.modules))m[t]={...n,resolvers:{...n.resolvers,...l}};let d=new Set(Object.keys(e.modules)),f=a({...e,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(t,n,a)=>{let g=t.indexOf("::"),y,h;if(g>0){let S=t.substring(0,g);d.has(S)?(y=S,h=t.substring(g+2)):h=t;}else h=t;c.push({key:h,fullKey:t,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:t=>{o.push(t);}},...e.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=t=>{s.push(t),p(t);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(t=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let u=f.inspect();if(u.inflight.length>0){if(Date.now()-n>t){let g=u.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${t}ms. ${u.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(t){if(!o.some(a=>a.requirement.type===t))throw new Error(`[Directive] Expected requirement of type "${t}" but none found`)},assertResolverCalled(t,n){let a=r.get(t)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${t}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${t}" to be called but it was not`)},assertFactSet(t,n){let a=c.filter(u=>u.key===t);if(a.length===0)throw new Error(`[Directive] Expected fact "${t}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${t}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(t,n){let a=c.filter(u=>u.key===t);if(a.length!==n)throw new Error(`[Directive] Expected fact "${t}" to change ${n} times but it changed ${a.length} times`)}}}function O(e,s,r){if(!k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(e,s,r){if(k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(e,s,r){switch(s){case "constraint":return e.constraints.isDynamic(r);case "resolver":return e.resolvers.isDynamic(r);case "derivation":return e.derive.isDynamic(r);case "effect":return e.effects.isDynamic(r)}}function F(e){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=e.observe(d=>{switch(d.type){case "constraint.evaluate":d.active&&s.add(d.id);break;case "resolver.start":r.add(d.resolver);break;case "effect.run":o.add(d.id);break;case "derivation.compute":c.add(d.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=e.inspect(),d=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of d)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:d.size===0?1:s.size/d.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function I(e){let s=[],r=e.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}export{O as assertDynamic,$ as assertNotDynamic,F as createCoverageTracker,C as createFakeTimers,b as createMockResolver,I as createTestObserver,P as createTestSystem,T as flushAsync,R as flushMicrotasks,E as mockResolver,D as settleWithFakeTimers};//# sourceMappingURL=testing.js.map | ||
| //# sourceMappingURL=testing.js.map |
+1
-1
@@ -1,2 +0,2 @@ | ||
| 'use strict';function H(o){let{worker:c,onFactChange:T,onDerivationChange:y,onRequirementCreated:g,onRequirementMet:u,onError:n}=o,s=new Map,a=0,t=3e4;function i(e){let r=s.get(e);r?.timeoutHandle!==void 0&&clearTimeout(r.timeoutHandle);}let d=null,S=null,f=null,v=null;function k(e){return e?.(),null}function M(e,r){let p=s.get(e);p&&(i(e),p.resolve(r),s.delete(e));}function h(){d=k(d);}function O(){S=k(S);}function W(){f=k(f);}function C(){v=k(v);}function w(e){T?.(e.key,e.value,e.prev);}function D(e){y?.(e.key,e.value);}function P(e){g?.(e.requirement);}function q(e){u?.(e.requirementId,e.resolverId);}function _(e){n?.(e.error,e.source);}function A(e){M(e.requestId,e.snapshot);}function N(e){M(e.requestId,e.inspection);}function x(e){let r=s.get(e.requestId);r&&(i(e.requestId),e.success?r.resolve(void 0):r.reject(new Error(e.error||"Settle failed")),s.delete(e.requestId));}c.onmessage=e=>{let r=e.data;switch(r.type){case "READY":return h();case "STARTED":return O();case "STOPPED":return W();case "DESTROYED":return C();case "FACT_CHANGED":return w(r);case "DERIVATION_CHANGED":return D(r);case "REQUIREMENT_CREATED":return P(r);case "REQUIREMENT_MET":return q(r);case "ERROR":return _(r);case "SNAPSHOT_RESULT":return A(r);case "INSPECT_RESULT":return N(r);case "SETTLE_RESULT":return x(r)}},c.onerror=e=>{let r=e&&typeof e=="object"&&"message"in e?String(e.message??"unknown error"):"unknown error";if(s.size>0){let p=new Error(`[Directive] worker errored: ${r}`);for(let[,E]of s)E.timeoutHandle!==void 0&&clearTimeout(E.timeoutHandle),E.reject(p);s.clear();}n?.(r,"worker");};function l(e){c.postMessage(e);}function m(e,r=t){return new Promise((p,E)=>{let I={resolve:p,reject:E};Number.isFinite(r)&&r>0&&(I.timeoutHandle=setTimeout(()=>{s.has(e.requestId)&&(s.delete(e.requestId),E(new Error(`[Directive] worker request timed out after ${r}ms`)));},r)),s.set(e.requestId,I),l(e);})}return {init(e){return new Promise(r=>{d=r,l({type:"INIT",config:e});})},start(){return new Promise(e=>{S=e,l({type:"START"});})},stop(){return new Promise(e=>{f=e,l({type:"STOP"});})},destroy(){return new Promise(e=>{v=e,l({type:"DESTROY"});})},setFact(e,r){l({type:"SET_FACT",key:e,value:r});},setFacts(e){l({type:"SET_FACTS",facts:e});},dispatch(e){l({type:"DISPATCH",event:e});},getSnapshot(e,r){let p=`snapshot-${++a}`;return m({type:"GET_SNAPSHOT",options:e,requestId:p},r??t)},inspect(e){let r=`inspect-${++a}`;return m({type:"INSPECT",requestId:r},e??t)},settle(e,r){let p=`settle-${++a}`;return m({type:"SETTLE",timeout:e,requestId:p},r??t)},terminate(){c.terminate();}}}var R=null;function b(){return R||(R=new Map),R}function L(o,c){b().set(o,c);}function U(){let o=null;async function c(t){let i=await F(t.config);return postMessage({type:"READY"}),i}function T(t){t.start(),postMessage({type:"STARTED"});}function y(t){t.stop(),postMessage({type:"STOPPED"});}function g(t){t.destroy(),postMessage({type:"DESTROYED"});}function u(t,i){let d=t.getSnapshot(i.options);postMessage({type:"SNAPSHOT_RESULT",requestId:i.requestId,snapshot:d});}function n(t,i){let d=t.inspect();postMessage({type:"INSPECT_RESULT",requestId:i.requestId,inspection:d});}async function s(t,i){try{await t.settle(i.timeout),postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:!0});}catch(d){postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:false,error:d instanceof Error?d.message:String(d)});}}async function a(t){if(t.type==="INIT"){o=await c(t);return}if(o)switch(t.type){case "START":T(o);break;case "STOP":y(o);break;case "DESTROY":g(o),o=null;break;case "SET_FACT":o.setFact(t.key,t.value);break;case "SET_FACTS":o.setFacts(t.facts);break;case "DISPATCH":o.dispatch(t.event);break;case "GET_SNAPSHOT":u(o,t);break;case "INSPECT":n(o,t);break;case "SETTLE":await s(o,t);break}}self.onmessage=async t=>{try{await a(t.data);}catch(i){postMessage({type:"ERROR",error:i instanceof Error?i.message:String(i),source:t.data.type});}};}async function F(o){let{createSystem:c}=await import('./system-SB7JYMRB.cjs'),T=b(),y={};for(let n of o.moduleNames){let s=T.get(n);if(!s)throw new Error(`[Directive Worker] Module "${n}" not registered. Call registerWorkerModule('${n}', module) before handling messages.`);y[n]=s;}let u=c({modules:y,plugins:[{name:"__worker-tracking__",onFactSet:(n,s,a)=>{postMessage({type:"FACT_CHANGED",key:n,value:s,prev:a});},onDerivationCompute:(n,s)=>{postMessage({type:"DERIVATION_CHANGED",key:n,value:s});},onRequirementCreated:n=>{postMessage({type:"REQUIREMENT_CREATED",requirement:{...n.requirement,id:n.id}});},onRequirementMet:(n,s)=>{postMessage({type:"REQUIREMENT_MET",requirementId:n.id,resolverId:s});}}],history:o.history});return {start:()=>u.start(),stop:()=>u.stop(),destroy:()=>u.destroy(),setFact:(n,s)=>{u.facts[n]=s;},setFacts:n=>{let s=u.facts;if(s.$store?.batch)s.$store.batch(()=>{for(let[a,t]of Object.entries(n))s[a]=t;});else for(let[a,t]of Object.entries(n))s[a]=t;},dispatch:n=>{u.dispatch(n);},getSnapshot:n=>u.getDistributableSnapshot(n),inspect:()=>u.inspect(),settle:n=>u.settle(n)}}exports.createWorkerClient=H;exports.getWorkerModuleRegistry=b;exports.handleWorkerMessages=U;exports.registerWorkerModule=L;//# sourceMappingURL=worker.cjs.map | ||
| 'use strict';function H(o){let{worker:c,onFactChange:T,onDerivationChange:y,onRequirementCreated:g,onRequirementMet:u,onError:n}=o,s=new Map,a=0,t=3e4;function i(e){let r=s.get(e);r?.timeoutHandle!==void 0&&clearTimeout(r.timeoutHandle);}let d=null,S=null,f=null,v=null;function k(e){return e?.(),null}function M(e,r){let p=s.get(e);p&&(i(e),p.resolve(r),s.delete(e));}function h(){d=k(d);}function O(){S=k(S);}function W(){f=k(f);}function C(){v=k(v);}function w(e){T?.(e.key,e.value,e.prev);}function D(e){y?.(e.key,e.value);}function P(e){g?.(e.requirement);}function q(e){u?.(e.requirementId,e.resolverId);}function _(e){n?.(e.error,e.source);}function A(e){M(e.requestId,e.snapshot);}function N(e){M(e.requestId,e.inspection);}function x(e){let r=s.get(e.requestId);r&&(i(e.requestId),e.success?r.resolve(void 0):r.reject(new Error(e.error||"Settle failed")),s.delete(e.requestId));}c.onmessage=e=>{let r=e.data;switch(r.type){case "READY":return h();case "STARTED":return O();case "STOPPED":return W();case "DESTROYED":return C();case "FACT_CHANGED":return w(r);case "DERIVATION_CHANGED":return D(r);case "REQUIREMENT_CREATED":return P(r);case "REQUIREMENT_MET":return q(r);case "ERROR":return _(r);case "SNAPSHOT_RESULT":return A(r);case "INSPECT_RESULT":return N(r);case "SETTLE_RESULT":return x(r)}},c.onerror=e=>{let r=e&&typeof e=="object"&&"message"in e?String(e.message??"unknown error"):"unknown error";if(s.size>0){let p=new Error(`[Directive] worker errored: ${r}`);for(let[,E]of s)E.timeoutHandle!==void 0&&clearTimeout(E.timeoutHandle),E.reject(p);s.clear();}n?.(r,"worker");};function l(e){c.postMessage(e);}function m(e,r=t){return new Promise((p,E)=>{let I={resolve:p,reject:E};Number.isFinite(r)&&r>0&&(I.timeoutHandle=setTimeout(()=>{s.has(e.requestId)&&(s.delete(e.requestId),E(new Error(`[Directive] worker request timed out after ${r}ms`)));},r)),s.set(e.requestId,I),l(e);})}return {init(e){return new Promise(r=>{d=r,l({type:"INIT",config:e});})},start(){return new Promise(e=>{S=e,l({type:"START"});})},stop(){return new Promise(e=>{f=e,l({type:"STOP"});})},destroy(){return new Promise(e=>{v=e,l({type:"DESTROY"});})},setFact(e,r){l({type:"SET_FACT",key:e,value:r});},setFacts(e){l({type:"SET_FACTS",facts:e});},dispatch(e){l({type:"DISPATCH",event:e});},getSnapshot(e,r){let p=`snapshot-${++a}`;return m({type:"GET_SNAPSHOT",options:e,requestId:p},r??t)},inspect(e){let r=`inspect-${++a}`;return m({type:"INSPECT",requestId:r},e??t)},settle(e,r){let p=`settle-${++a}`;return m({type:"SETTLE",timeout:e,requestId:p},r??t)},terminate(){c.terminate();}}}var R=null;function b(){return R||(R=new Map),R}function L(o,c){b().set(o,c);}function U(){let o=null;async function c(t){let i=await F(t.config);return postMessage({type:"READY"}),i}function T(t){t.start(),postMessage({type:"STARTED"});}function y(t){t.stop(),postMessage({type:"STOPPED"});}function g(t){t.destroy(),postMessage({type:"DESTROYED"});}function u(t,i){let d=t.getSnapshot(i.options);postMessage({type:"SNAPSHOT_RESULT",requestId:i.requestId,snapshot:d});}function n(t,i){let d=t.inspect();postMessage({type:"INSPECT_RESULT",requestId:i.requestId,inspection:d});}async function s(t,i){try{await t.settle(i.timeout),postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:!0});}catch(d){postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:false,error:d instanceof Error?d.message:String(d)});}}async function a(t){if(t.type==="INIT"){o=await c(t);return}if(o)switch(t.type){case "START":T(o);break;case "STOP":y(o);break;case "DESTROY":g(o),o=null;break;case "SET_FACT":o.setFact(t.key,t.value);break;case "SET_FACTS":o.setFacts(t.facts);break;case "DISPATCH":o.dispatch(t.event);break;case "GET_SNAPSHOT":u(o,t);break;case "INSPECT":n(o,t);break;case "SETTLE":await s(o,t);break}}self.onmessage=async t=>{try{await a(t.data);}catch(i){postMessage({type:"ERROR",error:i instanceof Error?i.message:String(i),source:t.data.type});}};}async function F(o){let{createSystem:c}=await import('./system-5FKUBLLV.cjs'),T=b(),y={};for(let n of o.moduleNames){let s=T.get(n);if(!s)throw new Error(`[Directive Worker] Module "${n}" not registered. Call registerWorkerModule('${n}', module) before handling messages.`);y[n]=s;}let u=c({modules:y,plugins:[{name:"__worker-tracking__",onFactSet:(n,s,a)=>{postMessage({type:"FACT_CHANGED",key:n,value:s,prev:a});},onDerivationCompute:(n,s)=>{postMessage({type:"DERIVATION_CHANGED",key:n,value:s});},onRequirementCreated:n=>{postMessage({type:"REQUIREMENT_CREATED",requirement:{...n.requirement,id:n.id}});},onRequirementMet:(n,s)=>{postMessage({type:"REQUIREMENT_MET",requirementId:n.id,resolverId:s});}}],history:o.history});return {start:()=>u.start(),stop:()=>u.stop(),destroy:()=>u.destroy(),setFact:(n,s)=>{u.facts[n]=s;},setFacts:n=>{let s=u.facts;if(s.$store?.batch)s.$store.batch(()=>{for(let[a,t]of Object.entries(n))s[a]=t;});else for(let[a,t]of Object.entries(n))s[a]=t;},dispatch:n=>{u.dispatch(n);},getSnapshot:n=>u.getDistributableSnapshot(n),inspect:()=>u.inspect(),settle:n=>u.settle(n)}}exports.createWorkerClient=H;exports.getWorkerModuleRegistry=b;exports.handleWorkerMessages=U;exports.registerWorkerModule=L;//# sourceMappingURL=worker.cjs.map | ||
| //# sourceMappingURL=worker.cjs.map |
@@ -1,2 +0,2 @@ | ||
| import { M as ModuleSchema, z as DistributableSnapshotOptions, y as DistributableSnapshot, at as SystemInspection, r as Requirement } from './plugins-4IfhJV32.cjs'; | ||
| import { M as ModuleSchema, z as DistributableSnapshotOptions, y as DistributableSnapshot, at as SystemInspection, r as Requirement } from './plugins-5Supk7it.cjs'; | ||
@@ -3,0 +3,0 @@ /** |
+1
-1
@@ -1,2 +0,2 @@ | ||
| import { M as ModuleSchema, z as DistributableSnapshotOptions, y as DistributableSnapshot, at as SystemInspection, r as Requirement } from './plugins-4IfhJV32.js'; | ||
| import { M as ModuleSchema, z as DistributableSnapshotOptions, y as DistributableSnapshot, at as SystemInspection, r as Requirement } from './plugins-5Supk7it.js'; | ||
@@ -3,0 +3,0 @@ /** |
+1
-1
@@ -1,2 +0,2 @@ | ||
| function H(o){let{worker:c,onFactChange:T,onDerivationChange:y,onRequirementCreated:g,onRequirementMet:u,onError:n}=o,s=new Map,a=0,t=3e4;function i(e){let r=s.get(e);r?.timeoutHandle!==void 0&&clearTimeout(r.timeoutHandle);}let d=null,S=null,f=null,v=null;function k(e){return e?.(),null}function M(e,r){let p=s.get(e);p&&(i(e),p.resolve(r),s.delete(e));}function h(){d=k(d);}function O(){S=k(S);}function W(){f=k(f);}function C(){v=k(v);}function w(e){T?.(e.key,e.value,e.prev);}function D(e){y?.(e.key,e.value);}function P(e){g?.(e.requirement);}function q(e){u?.(e.requirementId,e.resolverId);}function _(e){n?.(e.error,e.source);}function A(e){M(e.requestId,e.snapshot);}function N(e){M(e.requestId,e.inspection);}function x(e){let r=s.get(e.requestId);r&&(i(e.requestId),e.success?r.resolve(void 0):r.reject(new Error(e.error||"Settle failed")),s.delete(e.requestId));}c.onmessage=e=>{let r=e.data;switch(r.type){case "READY":return h();case "STARTED":return O();case "STOPPED":return W();case "DESTROYED":return C();case "FACT_CHANGED":return w(r);case "DERIVATION_CHANGED":return D(r);case "REQUIREMENT_CREATED":return P(r);case "REQUIREMENT_MET":return q(r);case "ERROR":return _(r);case "SNAPSHOT_RESULT":return A(r);case "INSPECT_RESULT":return N(r);case "SETTLE_RESULT":return x(r)}},c.onerror=e=>{let r=e&&typeof e=="object"&&"message"in e?String(e.message??"unknown error"):"unknown error";if(s.size>0){let p=new Error(`[Directive] worker errored: ${r}`);for(let[,E]of s)E.timeoutHandle!==void 0&&clearTimeout(E.timeoutHandle),E.reject(p);s.clear();}n?.(r,"worker");};function l(e){c.postMessage(e);}function m(e,r=t){return new Promise((p,E)=>{let I={resolve:p,reject:E};Number.isFinite(r)&&r>0&&(I.timeoutHandle=setTimeout(()=>{s.has(e.requestId)&&(s.delete(e.requestId),E(new Error(`[Directive] worker request timed out after ${r}ms`)));},r)),s.set(e.requestId,I),l(e);})}return {init(e){return new Promise(r=>{d=r,l({type:"INIT",config:e});})},start(){return new Promise(e=>{S=e,l({type:"START"});})},stop(){return new Promise(e=>{f=e,l({type:"STOP"});})},destroy(){return new Promise(e=>{v=e,l({type:"DESTROY"});})},setFact(e,r){l({type:"SET_FACT",key:e,value:r});},setFacts(e){l({type:"SET_FACTS",facts:e});},dispatch(e){l({type:"DISPATCH",event:e});},getSnapshot(e,r){let p=`snapshot-${++a}`;return m({type:"GET_SNAPSHOT",options:e,requestId:p},r??t)},inspect(e){let r=`inspect-${++a}`;return m({type:"INSPECT",requestId:r},e??t)},settle(e,r){let p=`settle-${++a}`;return m({type:"SETTLE",timeout:e,requestId:p},r??t)},terminate(){c.terminate();}}}var R=null;function b(){return R||(R=new Map),R}function L(o,c){b().set(o,c);}function U(){let o=null;async function c(t){let i=await F(t.config);return postMessage({type:"READY"}),i}function T(t){t.start(),postMessage({type:"STARTED"});}function y(t){t.stop(),postMessage({type:"STOPPED"});}function g(t){t.destroy(),postMessage({type:"DESTROYED"});}function u(t,i){let d=t.getSnapshot(i.options);postMessage({type:"SNAPSHOT_RESULT",requestId:i.requestId,snapshot:d});}function n(t,i){let d=t.inspect();postMessage({type:"INSPECT_RESULT",requestId:i.requestId,inspection:d});}async function s(t,i){try{await t.settle(i.timeout),postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:!0});}catch(d){postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:false,error:d instanceof Error?d.message:String(d)});}}async function a(t){if(t.type==="INIT"){o=await c(t);return}if(o)switch(t.type){case "START":T(o);break;case "STOP":y(o);break;case "DESTROY":g(o),o=null;break;case "SET_FACT":o.setFact(t.key,t.value);break;case "SET_FACTS":o.setFacts(t.facts);break;case "DISPATCH":o.dispatch(t.event);break;case "GET_SNAPSHOT":u(o,t);break;case "INSPECT":n(o,t);break;case "SETTLE":await s(o,t);break}}self.onmessage=async t=>{try{await a(t.data);}catch(i){postMessage({type:"ERROR",error:i instanceof Error?i.message:String(i),source:t.data.type});}};}async function F(o){let{createSystem:c}=await import('./system-SJBP4TO5.js'),T=b(),y={};for(let n of o.moduleNames){let s=T.get(n);if(!s)throw new Error(`[Directive Worker] Module "${n}" not registered. Call registerWorkerModule('${n}', module) before handling messages.`);y[n]=s;}let u=c({modules:y,plugins:[{name:"__worker-tracking__",onFactSet:(n,s,a)=>{postMessage({type:"FACT_CHANGED",key:n,value:s,prev:a});},onDerivationCompute:(n,s)=>{postMessage({type:"DERIVATION_CHANGED",key:n,value:s});},onRequirementCreated:n=>{postMessage({type:"REQUIREMENT_CREATED",requirement:{...n.requirement,id:n.id}});},onRequirementMet:(n,s)=>{postMessage({type:"REQUIREMENT_MET",requirementId:n.id,resolverId:s});}}],history:o.history});return {start:()=>u.start(),stop:()=>u.stop(),destroy:()=>u.destroy(),setFact:(n,s)=>{u.facts[n]=s;},setFacts:n=>{let s=u.facts;if(s.$store?.batch)s.$store.batch(()=>{for(let[a,t]of Object.entries(n))s[a]=t;});else for(let[a,t]of Object.entries(n))s[a]=t;},dispatch:n=>{u.dispatch(n);},getSnapshot:n=>u.getDistributableSnapshot(n),inspect:()=>u.inspect(),settle:n=>u.settle(n)}}export{H as createWorkerClient,b as getWorkerModuleRegistry,U as handleWorkerMessages,L as registerWorkerModule};//# sourceMappingURL=worker.js.map | ||
| function H(o){let{worker:c,onFactChange:T,onDerivationChange:y,onRequirementCreated:g,onRequirementMet:u,onError:n}=o,s=new Map,a=0,t=3e4;function i(e){let r=s.get(e);r?.timeoutHandle!==void 0&&clearTimeout(r.timeoutHandle);}let d=null,S=null,f=null,v=null;function k(e){return e?.(),null}function M(e,r){let p=s.get(e);p&&(i(e),p.resolve(r),s.delete(e));}function h(){d=k(d);}function O(){S=k(S);}function W(){f=k(f);}function C(){v=k(v);}function w(e){T?.(e.key,e.value,e.prev);}function D(e){y?.(e.key,e.value);}function P(e){g?.(e.requirement);}function q(e){u?.(e.requirementId,e.resolverId);}function _(e){n?.(e.error,e.source);}function A(e){M(e.requestId,e.snapshot);}function N(e){M(e.requestId,e.inspection);}function x(e){let r=s.get(e.requestId);r&&(i(e.requestId),e.success?r.resolve(void 0):r.reject(new Error(e.error||"Settle failed")),s.delete(e.requestId));}c.onmessage=e=>{let r=e.data;switch(r.type){case "READY":return h();case "STARTED":return O();case "STOPPED":return W();case "DESTROYED":return C();case "FACT_CHANGED":return w(r);case "DERIVATION_CHANGED":return D(r);case "REQUIREMENT_CREATED":return P(r);case "REQUIREMENT_MET":return q(r);case "ERROR":return _(r);case "SNAPSHOT_RESULT":return A(r);case "INSPECT_RESULT":return N(r);case "SETTLE_RESULT":return x(r)}},c.onerror=e=>{let r=e&&typeof e=="object"&&"message"in e?String(e.message??"unknown error"):"unknown error";if(s.size>0){let p=new Error(`[Directive] worker errored: ${r}`);for(let[,E]of s)E.timeoutHandle!==void 0&&clearTimeout(E.timeoutHandle),E.reject(p);s.clear();}n?.(r,"worker");};function l(e){c.postMessage(e);}function m(e,r=t){return new Promise((p,E)=>{let I={resolve:p,reject:E};Number.isFinite(r)&&r>0&&(I.timeoutHandle=setTimeout(()=>{s.has(e.requestId)&&(s.delete(e.requestId),E(new Error(`[Directive] worker request timed out after ${r}ms`)));},r)),s.set(e.requestId,I),l(e);})}return {init(e){return new Promise(r=>{d=r,l({type:"INIT",config:e});})},start(){return new Promise(e=>{S=e,l({type:"START"});})},stop(){return new Promise(e=>{f=e,l({type:"STOP"});})},destroy(){return new Promise(e=>{v=e,l({type:"DESTROY"});})},setFact(e,r){l({type:"SET_FACT",key:e,value:r});},setFacts(e){l({type:"SET_FACTS",facts:e});},dispatch(e){l({type:"DISPATCH",event:e});},getSnapshot(e,r){let p=`snapshot-${++a}`;return m({type:"GET_SNAPSHOT",options:e,requestId:p},r??t)},inspect(e){let r=`inspect-${++a}`;return m({type:"INSPECT",requestId:r},e??t)},settle(e,r){let p=`settle-${++a}`;return m({type:"SETTLE",timeout:e,requestId:p},r??t)},terminate(){c.terminate();}}}var R=null;function b(){return R||(R=new Map),R}function L(o,c){b().set(o,c);}function U(){let o=null;async function c(t){let i=await F(t.config);return postMessage({type:"READY"}),i}function T(t){t.start(),postMessage({type:"STARTED"});}function y(t){t.stop(),postMessage({type:"STOPPED"});}function g(t){t.destroy(),postMessage({type:"DESTROYED"});}function u(t,i){let d=t.getSnapshot(i.options);postMessage({type:"SNAPSHOT_RESULT",requestId:i.requestId,snapshot:d});}function n(t,i){let d=t.inspect();postMessage({type:"INSPECT_RESULT",requestId:i.requestId,inspection:d});}async function s(t,i){try{await t.settle(i.timeout),postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:!0});}catch(d){postMessage({type:"SETTLE_RESULT",requestId:i.requestId,success:false,error:d instanceof Error?d.message:String(d)});}}async function a(t){if(t.type==="INIT"){o=await c(t);return}if(o)switch(t.type){case "START":T(o);break;case "STOP":y(o);break;case "DESTROY":g(o),o=null;break;case "SET_FACT":o.setFact(t.key,t.value);break;case "SET_FACTS":o.setFacts(t.facts);break;case "DISPATCH":o.dispatch(t.event);break;case "GET_SNAPSHOT":u(o,t);break;case "INSPECT":n(o,t);break;case "SETTLE":await s(o,t);break}}self.onmessage=async t=>{try{await a(t.data);}catch(i){postMessage({type:"ERROR",error:i instanceof Error?i.message:String(i),source:t.data.type});}};}async function F(o){let{createSystem:c}=await import('./system-6YWCXQOQ.js'),T=b(),y={};for(let n of o.moduleNames){let s=T.get(n);if(!s)throw new Error(`[Directive Worker] Module "${n}" not registered. Call registerWorkerModule('${n}', module) before handling messages.`);y[n]=s;}let u=c({modules:y,plugins:[{name:"__worker-tracking__",onFactSet:(n,s,a)=>{postMessage({type:"FACT_CHANGED",key:n,value:s,prev:a});},onDerivationCompute:(n,s)=>{postMessage({type:"DERIVATION_CHANGED",key:n,value:s});},onRequirementCreated:n=>{postMessage({type:"REQUIREMENT_CREATED",requirement:{...n.requirement,id:n.id}});},onRequirementMet:(n,s)=>{postMessage({type:"REQUIREMENT_MET",requirementId:n.id,resolverId:s});}}],history:o.history});return {start:()=>u.start(),stop:()=>u.stop(),destroy:()=>u.destroy(),setFact:(n,s)=>{u.facts[n]=s;},setFacts:n=>{let s=u.facts;if(s.$store?.batch)s.$store.batch(()=>{for(let[a,t]of Object.entries(n))s[a]=t;});else for(let[a,t]of Object.entries(n))s[a]=t;},dispatch:n=>{u.dispatch(n);},getSnapshot:n=>u.getDistributableSnapshot(n),inspect:()=>u.inspect(),settle:n=>u.settle(n)}}export{H as createWorkerClient,b as getWorkerModuleRegistry,U as handleWorkerMessages,L as registerWorkerModule};//# sourceMappingURL=worker.js.map | ||
| //# sourceMappingURL=worker.js.map |
+1
-1
| { | ||
| "name": "@directive-run/core", | ||
| "version": "1.21.0", | ||
| "version": "1.22.0", | ||
| "imports": { | ||
@@ -5,0 +5,0 @@ "#is-development": { |
+2
-2
@@ -189,3 +189,3 @@ # @directive-run/core | ||
| Every system exposes a typed `system.observe(observer)` stream — one listener receives every observation event with full TypeScript narrowing on `event.type`. Source-publish, source-drop, fact-change, constraint evaluation, requirement lifecycle, resolver lifecycle, and effect runs all flow through the same channel. | ||
| Every system exposes a typed `system.observe(observer)` stream – one listener receives every observation event with full TypeScript narrowing on `event.type`. Source-publish, source-drop, fact-change, constraint evaluation, requirement lifecycle, resolver lifecycle, and effect runs all flow through the same channel. | ||
@@ -219,3 +219,3 @@ ```ts | ||
| The `SourceDropReason` union is the single source of truth for drop reasons — `SystemInspection.sources[i].lastDropReason`, the `Plugin.onSourceDrop` hook signature, and the `source.drop` observation-event variant all reference the same type. Adding a new reason in one place flows to all three at compile time. | ||
| The `SourceDropReason` union is the single source of truth for drop reasons – `SystemInspection.sources[i].lastDropReason`, the `Plugin.onSourceDrop` hook signature, and the `source.drop` observation-event variant all reference the same type. Adding a new reason in one place flows to all three at compile time. | ||
@@ -222,0 +222,0 @@ ## Why Directive? |
| 'use strict';var chunkM5PEB553_cjs=require('./chunk-M5PEB553.cjs'),chunkGACC2DMS_cjs=require('./chunk-GACC2DMS.cjs'),chunkGKMJ7NMP_cjs=require('./chunk-GKMJ7NMP.cjs'),chunkGBCWXTXW_cjs=require('./chunk-GBCWXTXW.cjs');var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function $(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!chunkGKMJ7NMP_cjs.k.has(t))return e.get(t)},set(n,t,i){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.set?e.set(t,i):false},has(n,t){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||chunkGKMJ7NMP_cjs.k.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function j(e,n){let t=Z.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,Z.set(e,t);let i=$({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n}${m}${r}`],set:(r,u)=>{if(chunkGBCWXTXW_cjs.a){let s=chunkGKMJ7NMP_cjs.l(u);s&&chunkGKMJ7NMP_cjs.m(`${n}.${r}`,s);}return e[`${n}${m}${r}`]=u,true},has:r=>`${n}${m}${r}`in e,delete:r=>(delete e[`${n}${m}${r}`],true)});return t.set(n,i),i}function re(e,n,t){let i=Q.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return j(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let i=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(i);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),s=["self",...t],c=$({get:o=>{if(o==="self")return j(e,n);if(u.has(o))return j(e,o);chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>s});return r.set(i,c),c}function K(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let i=$({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,i),i}function se(e,n,t){let i=X.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return K(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let i=te.get(e);return i||(i=new Map,te.set(e,i)),$({get:r=>{if(!Object.hasOwn(n,r))return;let u=i.get(r);if(u)return u;let s=$({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return i.set(r,s),s},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function S(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function B(e){let n={};for(let[t,i]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),s=t.slice(r+m.length);n[u]||(n[u]={}),n[u][s]=i;}else n._root||(n._root={}),n._root[t]=i;}return n}function A(e,n,t,i){return t?oe(e,n,i):j(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let s=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return chunkGBCWXTXW_cjs.b(s),s}if(!e||typeof e!="object")return e;let i=e;if("$all"in i||"$any"in i){let s="$all"in i?"$all":"$any",c=i[s],o={[s]:c.map(f=>E(f,n,t))};return chunkGBCWXTXW_cjs.b(o),o}if("$not"in i){let s={$not:E(i.$not,n,t)};return chunkGBCWXTXW_cjs.b(s),s}function r(s,c){return E(s,c,ce)}let u={};for(let s of Object.keys(i)){if(s.startsWith("$")||ae(s)){u[s]=i[s];continue}if(s==="self"){let c=i[s];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(s)){let c=i[s];if(c&&typeof c=="object"){let o=r(c,s);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,s)]=i[s];}return chunkGBCWXTXW_cjs.b(u),u}var ce=new Set;function me(e,n){let t=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,i=e.constraints;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t)},c=true;continue}o[f]=l;}c&&(i=o);}let r=e.derive;if(r){let c=false,o={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o[f]=l;continue}let h=d.compute;if(typeof h=="function"){o[f]=l;continue}if(chunkGACC2DMS_cjs.k(h)){chunkGBCWXTXW_cjs.b(h);let k=g=>chunkGACC2DMS_cjs.s(h,g);o[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(chunkGACC2DMS_cjs.h(h)){chunkGBCWXTXW_cjs.b(h);let k=chunkGACC2DMS_cjs.q(h),g=P=>k(P);o[f]=d.meta?{compute:g,meta:d.meta}:g,c=true;continue}o[f]=l;}c&&(r=o);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),h=Object.hasOwn(l,"patch");if(d&&h&&chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),h&&!d){let k=l;chunkGBCWXTXW_cjs.b(k.patch);let g=(P,x)=>chunkGACC2DMS_cjs.v(k.patch,P,x??{});o[f]=k.meta?{handler:g,meta:k.meta}:g,c=true;continue}}o[f]=l;}c&&(u=o);}let s=e.effects;if(s){let c=false,o={};for(let[f,l]of Object.entries(s)){let d=l;if(d.on!==void 0&&chunkGACC2DMS_cjs.h(d.on)){o[f]={...d,on:E(d.on,n,t)},c=true;continue}o[f]=l;}c&&(s=o);}return i===e.constraints&&r===e.derive&&u===e.events&&s===e.effects?e:{...e,constraints:i,derive:r,events:u,effects:s}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[i,r]of Object.entries(e.schema.facts))t[b(n,i)]=r;return t}function pe(e,n){if(e.init)return t=>{let i=j(t,n);e.init(i);}}function ve(e,n,t,i){if(!e.derive)return;let r={};for(let[u,s]of Object.entries(e.derive)){let c=chunkM5PEB553_cjs.a(s),o=c?s.compute:s,f=c?s.meta:void 0,l=(d,h)=>{let k=A(d,n,t,i),g=K(h,n);return o(k,g)};r[b(n,u)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[i,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),s=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=j(f,n);s(d,l);};t[b(n,i)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,i){if(!e.constraints)return;let r={};for(let[u,s]of Object.entries(e.constraints)){let c=s,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),owns:c.owns?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=A(f,n,t,i);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=A(f,n,t,i);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,i){if(!e.resolvers)return;let r={};for(let[s,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:A(l.facts,n,t,i),signal:l.signal}};let o=c;r[b(n,s)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,i){if(!e.effects)return;let r={};for(let[u,s]of Object.entries(e.effects)){let c=s;r[b(n,u)]={...c,run:(o,f)=>{let l=A(o,n,t,i),d=f?A(f,n,t,i):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(i=>b(n,i))}}function H(e){let{mod:n,namespace:t,snapshotModulesSet:i}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),s=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,s),events:be(r,t),effects:Se(r,t,u,s),sources:r.sources,constraints:Me(r,t,u,s),resolvers:Re(r,t,u,s),hooks:r.hooks,meta:r.meta,history:Oe(r,t,i)}}function xe(e){let n=Object.keys(e),t=new Set(n),i=new Set,r=new Set,u=[],s=[];function c(o){if(i.has(o))return;if(r.has(o)){let l=s.indexOf(o),d=[...s.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),s.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);s.pop(),r.delete(o),i.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let i of Object.keys(n.schema.facts))t.push(`${e}${m}${i}`);if(n.schema.derivations)for(let i of Object.keys(n.schema.derivations))t.push(`${e}${m}${i}`);return t}function ze(e){if(!e||!("module"in e)&&!("modules"in e))throw new Error("[Directive] createSystem requires either `{ module }` (single-module form) or `{ modules: { name: module } }` (namespaced form). Got an options object with neither.");if("module"in e){if(!e.module)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof e.module}`);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array. | ||
| Instead of: | ||
| createSystem({ modules: [authModule, dataModule] }) | ||
| Use: | ||
| createSystem({ modules: { auth: authModule, data: dataModule } }) | ||
| Or for a single module: | ||
| createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead: | ||
| createSystem({ module: myModule }) | ||
| For multiple modules, wrap in an object: | ||
| createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e){let n=e.modules,t=new Set(Object.keys(n)),i=typeof e.history=="object"?e.history:null,r=i?.snapshotModules?new Set(i.snapshotModules):null;if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(chunkGBCWXTXW_cjs.a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let w of Object.keys(y.crossModuleDeps))w===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(w)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${w}, but no module with namespace "${w}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(chunkGBCWXTXW_cjs.a&&i?.snapshotModules)for(let a of i.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,s=e.initOrder??"auto";if(Array.isArray(s)){let a=s,y=Object.keys(n).filter(w=>!a.includes(w));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else s==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f}=de(e);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let w of Object.keys(y.schema.facts))if(w.includes(m))throw new Error(`[Directive] Schema key "${w}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l={names:null};function d(){return l.names===null&&(l.names=Object.keys(n)),l.names}let h=u.map(a=>{let y=n[a];return y?H({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);chunkGBCWXTXW_cjs.a&&e.tickMs&&e.tickMs>0&&(h.some(y=>y.events&&Object.keys(y.events).some(w=>w.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but no module defines a "tick" event handler.`));let k=null,g=null;function P(a){for(let[y,w]of Object.entries(a)){if(chunkGKMJ7NMP_cjs.k.has(y)){chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(w&&typeof w=="object"&&!chunkGBCWXTXW_cjs.f(w))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,D]of Object.entries(w))chunkGKMJ7NMP_cjs.k.has(M)||(g.facts[`${y}${m}${M}`]=D);}}g=chunkM5PEB553_cjs.A({modules:h,plugins:e.plugins,history:c,trace:o,errorBoundary:f,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{e.initialFacts&&P(e.initialFacts),k&&(P(k),k=null);}});let x=new Map;for(let a of Object.keys(n)){let y=n[a];y&&x.set(a,ue(a,y));}let q=re(g.facts,n,d),ye=se(g.derive,n,d),ge=ie(g,n,d),R=null,F=e.tickMs,_={_mode:"namespaced",facts:q,history:g.history,derive:ye,events:ge,constraints:g.constraints,effects:g.effects,resolvers:g.resolvers,async hydrate(a){if(g.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k=y);},initialize(){g.initialize();},start(){if(g.start(),F&&F>0){let a;for(let y of h)if(y?.events&&(a=Object.keys(y.events).find(w=>w.endsWith(`${m}tick`)),a))break;if(a){let y=a;R=setInterval(()=>{g.dispatch({type:y});},F);}}},stop(){R&&(clearInterval(R),R=null),g.stop();},async stopAsync(){R&&(clearInterval(R),R=null),await g.stopAsync();},destroy(){this.stop(),g.destroy();},async destroyAsync(){await this.stopAsync(),await g.destroyAsync();},async evict(a){R&&(clearInterval(R),R=null),await g.evict(a);},dispatch(a){g.dispatch(a);},read(a){return g.read(S(a))},subscribe(a,y){let w=[];for(let M of a)if(M.endsWith(".*")){let D=M.slice(0,-2),W=x.get(D);W?w.push(...W):chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${D}" not found.`);}else w.push(S(M));return g.subscribe(w,y)},subscribeModule(a,y){let w=x.get(a);return !w||w.length===0?(chunkGBCWXTXW_cjs.a&&console.warn(`[Directive] subscribeModule("${a}") \u2014 namespace not found. Available: ${[...x.keys()].join(", ")}`),()=>{}):g.subscribe(w,y)},watch(a,y,w){return g.watch(S(a),y,w)},when(a,y){return g.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)},w=g.getDistributableSnapshot(y);return {...w,data:B(w.data)}},watchDistributableSnapshot(a,y){let w={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)};return g.watchDistributableSnapshot(w,M=>{y({...M,data:B(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(chunkGKMJ7NMP_cjs.k.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let D of Object.keys(y.schema.facts))if(D.includes(m))throw new Error(`[Directive] Schema key "${D}" in module "${a}" contains the reserved separator "${m}".`);let w=y,M=H({mod:w,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=w,l.names=null,x.set(a,ue(a,w)),g.registerModule(M);}};return le(_,g),fe(_),_}function de(e){let n=e.history,t=e.trace,i=e.errorBoundary;return e.zeroConfig&&(n=n??chunkGBCWXTXW_cjs.a,i={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:i}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n),n.notify&&(e.notify=n.notify);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let i of t)i in e||(e[i]=n[i].bind(n));}function fe(e){chunkGBCWXTXW_cjs.a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e){let n=e.module;if(!n)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof n}`);if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e.initialFacts&&!chunkGBCWXTXW_cjs.f(e.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");chunkGBCWXTXW_cjs.a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e.tickMs&&e.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but module has no "tick" event handler.`)),(typeof e.history=="object"?e.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:i,errorBoundary:r}=de(e),u=null,s=null;s=chunkM5PEB553_cjs.A({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,sources:n.sources,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e.plugins,history:t,trace:i,errorBoundary:r,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{if(e.initialFacts)for(let[d,h]of Object.entries(e.initialFacts))chunkGKMJ7NMP_cjs.k.has(d)||(s.facts[d]=h);if(u){if(!chunkGBCWXTXW_cjs.f(u))chunkGBCWXTXW_cjs.a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,h]of Object.entries(u))chunkGKMJ7NMP_cjs.k.has(d)||(s.facts[d]=h);u=null;}}});let c=new Proxy({},{get(d,h){if(typeof h!="symbol"&&!chunkGKMJ7NMP_cjs.k.has(h))return k=>{s.dispatch({type:h,...k});}},has(d,h){return typeof h=="symbol"||chunkGKMJ7NMP_cjs.k.has(h)?false:n.events?h in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,h){if(typeof h!="symbol"&&!chunkGKMJ7NMP_cjs.k.has(h)&&n.events&&h in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f=e.tickMs,l={_mode:"single",facts:s.facts,history:s.history,derive:s.derive,events:c,constraints:s.constraints,effects:s.effects,resolvers:s.resolvers,async hydrate(d){if(s.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let h=await d();h&&typeof h=="object"&&(u=h);},initialize(){s.initialize();},start(){s.start(),f&&f>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{s.dispatch({type:"tick"});},f));},stop(){o&&(clearInterval(o),o=null),s.stop();},async stopAsync(){o&&(clearInterval(o),o=null),await s.stopAsync();},destroy(){this.stop(),s.destroy();},async destroyAsync(){await this.stopAsync(),await s.destroyAsync();},async evict(d){o&&(clearInterval(o),o=null),await s.evict(d);},registerModule(d){s.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,sources:d.sources,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l,s),fe(l),l}exports.a=ze;//# sourceMappingURL=chunk-4OXCKDKS.cjs.map | ||
| //# sourceMappingURL=chunk-4OXCKDKS.cjs.map |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import {A as A$1,a as a$1}from'./chunk-6QAUJFQH.js';import {k as k$1,h,q,s,v}from'./chunk-RBF653NR.js';import {k,l,m as m$1}from'./chunk-6PF2FRBG.js';import {a,f,b as b$1}from'./chunk-SFUVPP4L.js';var m="::",he=Symbol.for("nodejs.util.inspect.custom");function we(e){if(!e.ownKeys)return {};let n={};for(let t of e.ownKeys())n[t]=e.get(t);return n}function $(e){return new Proxy({},{get(n,t){if(typeof t=="symbol")return t===he?()=>we(e):void 0;if(!k.has(t))return e.get(t)},set(n,t,i){return typeof t=="symbol"||k.has(t)?false:e.set?e.set(t,i):false},has(n,t){return typeof t=="symbol"||k.has(t)?false:e.has?e.has(t):false},deleteProperty(n,t){return typeof t=="symbol"||k.has(t)?false:e.delete?e.delete(t):false},ownKeys(){return e.ownKeys?e.ownKeys():[]},getOwnPropertyDescriptor(n,t){if(typeof t!="symbol"&&e.has&&typeof t=="string"&&e.has(t))return {configurable:true,enumerable:true}},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}})}var Z=new WeakMap,Q=new WeakMap,X=new WeakMap,ee=new WeakMap,ne=new WeakMap,te=new WeakMap;function j(e,n){let t=Z.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,Z.set(e,t);let i=$({get:r=>r==="$store"||r==="$snapshot"?e[r]:e[`${n}${m}${r}`],set:(r,u)=>{if(a){let s=l(u);s&&m$1(`${n}.${r}`,s);}return e[`${n}${m}${r}`]=u,true},has:r=>`${n}${m}${r}`in e,delete:r=>(delete e[`${n}${m}${r}`],true)});return t.set(n,i),i}function re(e,n,t){let i=Q.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return j(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return Q.set(e,r),r}function oe(e,n,t){let i=`${n}|${t.join(",")}`,r=ne.get(e);if(r){let o=r.get(i);if(o)return o}else r=new Map,ne.set(e,r);let u=new Set(t),s=["self",...t],c=$({get:o=>{if(o==="self")return j(e,n);if(u.has(o))return j(e,o);a&&console.warn(`[Directive] Module "${n}" accessed undeclared cross-module property "${o}". Add it to crossModuleDeps or use "facts.self.${o}" for own module facts.`);},has:o=>o==="self"||u.has(o),ownKeys:()=>s});return r.set(i,c),c}function K(e,n){let t=ee.get(e);if(t){let r=t.get(n);if(r)return r}else t=new Map,ee.set(e,t);let i=$({get:r=>e[`${n}${m}${r}`],has:r=>`${n}${m}${r}`in e});return t.set(n,i),i}function se(e,n,t){let i=X.get(e);if(i)return i;let r=$({get:u=>{if(Object.hasOwn(n,u))return K(e,u)},has:u=>Object.hasOwn(n,u),ownKeys:()=>t()});return X.set(e,r),r}function ie(e,n,t){let i=te.get(e);return i||(i=new Map,te.set(e,i)),$({get:r=>{if(!Object.hasOwn(n,r))return;let u=i.get(r);if(u)return u;let s=$({get:c=>o=>{e.dispatch({type:`${r}${m}${c}`,...o});}});return i.set(r,s),s},has:r=>Object.hasOwn(n,r),ownKeys:()=>t()})}function S(e){if(e.includes(".")){let[n,...t]=e.split(".");return `${n}${m}${t.join(m)}`}return e}function B(e){let n={};for(let[t,i]of Object.entries(e)){let r=t.indexOf(m);if(r>0){let u=t.slice(0,r),s=t.slice(r+m.length);n[u]||(n[u]={}),n[u][s]=i;}else n._root||(n._root={}),n._root[t]=i;}return n}function A(e,n,t,i){return t?oe(e,n,i):j(e,n)}function b(e,n){return `${e}${m}${n}`}function ae(e){return e.includes(m)}function E(e,n,t){if(Array.isArray(e)){let s=e.map(c=>{if(c&&typeof c=="object"&&typeof c.fact=="string"){let o=c.fact;return ae(o)?c:{...c,fact:b(n,o)}}return c});return b$1(s),s}if(!e||typeof e!="object")return e;let i=e;if("$all"in i||"$any"in i){let s="$all"in i?"$all":"$any",c=i[s],o={[s]:c.map(f=>E(f,n,t))};return b$1(o),o}if("$not"in i){let s={$not:E(i.$not,n,t)};return b$1(s),s}function r(s,c){return E(s,c,ce)}let u={};for(let s of Object.keys(i)){if(s.startsWith("$")||ae(s)){u[s]=i[s];continue}if(s==="self"){let c=i[s];if(c&&typeof c=="object"){let o=r(c,n);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}if(t.has(s)){let c=i[s];if(c&&typeof c=="object"){let o=r(c,s);if(o&&typeof o=="object"&&!Array.isArray(o)){for(let[f,l]of Object.entries(o))u[f]=l;continue}}}u[b(n,s)]=i[s];}return b$1(u),u}var ce=new Set;function me(e,n){let t=e.crossModuleDeps?new Set(Object.keys(e.crossModuleDeps)):ce,i=e.constraints;if(i){let c=false,o={};for(let[f,l]of Object.entries(i)){let d=l;if(d.when!==void 0&&typeof d.when!="function"){o[f]={...d,when:E(d.when,n,t)},c=true;continue}o[f]=l;}c&&(i=o);}let r=e.derive;if(r){let c=false,o={};for(let[f,l]of Object.entries(r)){let d=l&&typeof l=="object"&&Object.hasOwn(l,"compute")?l:null;if(!d){o[f]=l;continue}let h$1=d.compute;if(typeof h$1=="function"){o[f]=l;continue}if(k$1(h$1)){b$1(h$1);let k=g=>s(h$1,g);o[f]=d.meta?{compute:k,meta:d.meta}:k,c=true;continue}if(h(h$1)){b$1(h$1);let k=q(h$1),g=P=>k(P);o[f]=d.meta?{compute:g,meta:d.meta}:g,c=true;continue}o[f]=l;}c&&(r=o);}let u=e.events;if(u){let c=false,o={};for(let[f,l]of Object.entries(u)){if(l&&typeof l=="object"){let d=Object.hasOwn(l,"handler"),h=Object.hasOwn(l,"patch");if(d&&h&&a&&console.warn(`[Directive] event "${f}": both \`handler\` and \`patch\` provided \u2014 using \`handler\` (patch is ignored).`),h&&!d){let k=l;b$1(k.patch);let g=(P,x)=>v(k.patch,P,x??{});o[f]=k.meta?{handler:g,meta:k.meta}:g,c=true;continue}}o[f]=l;}c&&(u=o);}let s$1=e.effects;if(s$1){let c=false,o={};for(let[f,l]of Object.entries(s$1)){let d=l;if(d.on!==void 0&&h(d.on)){o[f]={...d,on:E(d.on,n,t)},c=true;continue}o[f]=l;}c&&(s$1=o);}return i===e.constraints&&r===e.derive&&u===e.events&&s$1===e.effects?e:{...e,constraints:i,derive:r,events:u,effects:s$1}}function C(e){return Object.keys(e).length>0?e:void 0}function ke(e,n){let t={};for(let[i,r]of Object.entries(e.schema.facts))t[b(n,i)]=r;return t}function pe(e,n){if(e.init)return t=>{let i=j(t,n);e.init(i);}}function ve(e,n,t,i){if(!e.derive)return;let r={};for(let[u,s]of Object.entries(e.derive)){let c=a$1(s),o=c?s.compute:s,f=c?s.meta:void 0,l=(d,h)=>{let k=A(d,n,t,i),g=K(h,n);return o(k,g)};r[b(n,u)]=f?{compute:l,meta:f}:l;}return C(r)}function be(e,n){if(!e.events)return;let t={};for(let[i,r]of Object.entries(e.events)){let u=typeof r=="object"&&r!==null&&Object.hasOwn(r,"handler"),s=u?r.handler:r,c=u?r.meta:void 0,o=(f,l)=>{let d=j(f,n);s(d,l);};t[b(n,i)]=c?{handler:o,meta:c}:o;}return C(t)}function Me(e,n,t,i){if(!e.constraints)return;let r={};for(let[u,s]of Object.entries(e.constraints)){let c=s,o=typeof c.when=="function";r[b(n,u)]={...c,deps:c.deps?.map(f=>b(n,f)),after:c.after?.map(f=>f.includes(m)?f:b(n,f)),owns:c.owns?.map(f=>f.includes(m)?f:b(n,f)),when:o?f=>{let l=A(f,n,t,i);return c.when(l)}:c.when,require:typeof c.require=="function"?f=>{let l=A(f,n,t,i);return c.require(l)}:c.require};}return C(r)}function Re(e,n,t,i){if(!e.resolvers)return;let r={};for(let[s,c]of Object.entries(e.resolvers)){let f=function(l){return {facts:A(l.facts,n,t,i),signal:l.signal}};let o=c;r[b(n,s)]={...o,...o.resolve&&{resolve:async(l,d)=>{await o.resolve(l,f(d));}},...o.resolveBatch&&{resolveBatch:async(l,d)=>{await o.resolveBatch(l,f(d));}},...o.resolveBatchWithResults&&{resolveBatchWithResults:async(l,d)=>o.resolveBatchWithResults(l,f(d))}};}return C(r)}function Se(e,n,t,i){if(!e.effects)return;let r={};for(let[u,s]of Object.entries(e.effects)){let c=s;r[b(n,u)]={...c,run:(o,f)=>{let l=A(o,n,t,i),d=f?A(f,n,t,i):void 0;return c.run(l,d)},deps:c.deps?.map(o=>b(n,o))};}return C(r)}function Oe(e,n,t){return {snapshotEvents:t&&!t.has(n)?[]:e.history?.snapshotEvents?.map(i=>b(n,i))}}function H(e){let{mod:n,namespace:t,snapshotModulesSet:i}=e,r=me(n,t),u=!!(r.crossModuleDeps&&Object.keys(r.crossModuleDeps).length>0),s=u?Object.keys(r.crossModuleDeps):[];return {id:r.id,schema:ke(r,t),requirements:r.schema.requirements??{},init:pe(r,t),derive:ve(r,t,u,s),events:be(r,t),effects:Se(r,t,u,s),sources:r.sources,constraints:Me(r,t,u,s),resolvers:Re(r,t,u,s),hooks:r.hooks,meta:r.meta,history:Oe(r,t,i)}}function xe(e){let n=Object.keys(e),t=new Set(n),i=new Set,r=new Set,u=[],s=[];function c(o){if(i.has(o))return;if(r.has(o)){let l=s.indexOf(o),d=[...s.slice(l),o].join(" \u2192 ");throw new Error(`[Directive] Circular dependency detected: ${d}. Modules cannot have circular crossModuleDeps. Break the cycle by removing one of the cross-module references.`)}r.add(o),s.push(o);let f=e[o];if(f?.crossModuleDeps)for(let l of Object.keys(f.crossModuleDeps))t.has(l)&&c(l);s.pop(),r.delete(o),i.add(o),u.push(o);}for(let o of n)c(o);return u}function ue(e,n){let t=[];for(let i of Object.keys(n.schema.facts))t.push(`${e}${m}${i}`);if(n.schema.derivations)for(let i of Object.keys(n.schema.derivations))t.push(`${e}${m}${i}`);return t}function ze(e){if(!e||!("module"in e)&&!("modules"in e))throw new Error("[Directive] createSystem requires either `{ module }` (single-module form) or `{ modules: { name: module } }` (namespaced form). Got an options object with neither.");if("module"in e){if(!e.module)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof e.module}`);return $e(e)}let n=e;if(Array.isArray(n.modules))throw new Error(`[Directive] createSystem expects modules as an object, not an array. | ||
| Instead of: | ||
| createSystem({ modules: [authModule, dataModule] }) | ||
| Use: | ||
| createSystem({ modules: { auth: authModule, data: dataModule } }) | ||
| Or for a single module: | ||
| createSystem({ module: counterModule })`);let t=n.modules;if(t&&typeof t=="object"&&"id"in t&&"schema"in t)throw new Error(`[Directive] A single module was passed to \`modules:\`. For a single module, use \`module:\` instead: | ||
| createSystem({ module: myModule }) | ||
| For multiple modules, wrap in an object: | ||
| createSystem({ modules: { myName: myModule } })`);return De(n)}function De(e){let n=e.modules,t=new Set(Object.keys(n)),i=typeof e.history=="object"?e.history:null,r=i?.snapshotModules?new Set(i.snapshotModules):null;if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(a){for(let[a,y]of Object.entries(n))if(y.crossModuleDeps)for(let w of Object.keys(y.crossModuleDeps))w===a?console.warn(`[Directive] Module "${a}" references itself in crossModuleDeps. Use "facts.self" to access own module's facts instead.`):t.has(w)||console.warn(`[Directive] Module "${a}" declares crossModuleDeps.${w}, but no module with namespace "${w}" exists in the system. Available modules: ${[...t].join(", ")}`);}if(a&&i?.snapshotModules)for(let a of i.snapshotModules)t.has(a)||console.warn(`[Directive] history.snapshotModules entry "${a}" doesn't match any module. Available modules: ${[...t].join(", ")}`);let u,s=e.initOrder??"auto";if(Array.isArray(s)){let a=s,y=Object.keys(n).filter(w=>!a.includes(w));if(y.length>0)throw new Error(`[Directive] initOrder is missing modules: ${y.join(", ")}. All modules must be included in the explicit order.`);u=a;}else s==="declaration"?u=Object.keys(n):u=xe(n);let{history:c,trace:o,errorBoundary:f$1}=de(e);for(let a of Object.keys(n)){if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}". Module names cannot contain "${m}".`);let y=n[a];if(y){for(let w of Object.keys(y.schema.facts))if(w.includes(m))throw new Error(`[Directive] Schema key "${w}" in module "${a}" contains the reserved separator "${m}". Schema keys cannot contain "${m}".`)}}let l={names:null};function d(){return l.names===null&&(l.names=Object.keys(n)),l.names}let h=u.map(a=>{let y=n[a];return y?H({mod:y,namespace:a,snapshotModulesSet:r}):null}).filter(a=>a!==null);a&&e.tickMs&&e.tickMs>0&&(h.some(y=>y.events&&Object.keys(y.events).some(w=>w.endsWith(`${m}tick`)))||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but no module defines a "tick" event handler.`));let k$1=null,g=null;function P(a$1){for(let[y,w]of Object.entries(a$1)){if(k.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains blocked namespace "${y}". Skipping.`);continue}if(!t.has(y)){a&&console.warn(`[Directive] initialFacts/hydrate contains unknown namespace "${y}". Available modules: ${[...t].join(", ")}`);continue}if(w&&typeof w=="object"&&!f(w))throw new Error(`[Directive] initialFacts/hydrate for namespace "${y}" contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.`);for(let[M,D]of Object.entries(w))k.has(M)||(g.facts[`${y}${m}${M}`]=D);}}g=A$1({modules:h,plugins:e.plugins,history:c,trace:o,errorBoundary:f$1,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{e.initialFacts&&P(e.initialFacts),k$1&&(P(k$1),k$1=null);}});let x=new Map;for(let a of Object.keys(n)){let y=n[a];y&&x.set(a,ue(a,y));}let q=re(g.facts,n,d),ye=se(g.derive,n,d),ge=ie(g,n,d),R=null,F=e.tickMs,_={_mode:"namespaced",facts:q,history:g.history,derive:ye,events:ge,constraints:g.constraints,effects:g.effects,resolvers:g.resolvers,async hydrate(a){if(g.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let y=await a();y&&typeof y=="object"&&(k$1=y);},initialize(){g.initialize();},start(){if(g.start(),F&&F>0){let a;for(let y of h)if(y?.events&&(a=Object.keys(y.events).find(w=>w.endsWith(`${m}tick`)),a))break;if(a){let y=a;R=setInterval(()=>{g.dispatch({type:y});},F);}}},stop(){R&&(clearInterval(R),R=null),g.stop();},async stopAsync(){R&&(clearInterval(R),R=null),await g.stopAsync();},destroy(){this.stop(),g.destroy();},async destroyAsync(){await this.stopAsync(),await g.destroyAsync();},async evict(a){R&&(clearInterval(R),R=null),await g.evict(a);},dispatch(a){g.dispatch(a);},read(a){return g.read(S(a))},subscribe(a$1,y){let w=[];for(let M of a$1)if(M.endsWith(".*")){let D=M.slice(0,-2),W=x.get(D);W?w.push(...W):a&&console.warn(`[Directive] subscribe wildcard "${M}" \u2014 namespace "${D}" not found.`);}else w.push(S(M));return g.subscribe(w,y)},subscribeModule(a$1,y){let w=x.get(a$1);return !w||w.length===0?(a&&console.warn(`[Directive] subscribeModule("${a$1}") \u2014 namespace not found. Available: ${[...x.keys()].join(", ")}`),()=>{}):g.subscribe(w,y)},watch(a,y,w){return g.watch(S(a),y,w)},when(a,y){return g.when(()=>a(q),y)},getDistributableSnapshot(a){let y={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)},w=g.getDistributableSnapshot(y);return {...w,data:B(w.data)}},watchDistributableSnapshot(a,y){let w={...a,includeDerivations:a?.includeDerivations?.map(S),excludeDerivations:a?.excludeDerivations?.map(S),includeFacts:a?.includeFacts?.map(S)};return g.watchDistributableSnapshot(w,M=>{y({...M,data:B(M.data)});})},registerModule(a,y){if(t.has(a))throw new Error(`[Directive] Module namespace "${a}" already exists. Cannot register a duplicate namespace.`);if(a.includes(m))throw new Error(`[Directive] Module name "${a}" contains the reserved separator "${m}".`);if(k.has(a))throw new Error(`[Directive] Module name "${a}" is a blocked property.`);for(let D of Object.keys(y.schema.facts))if(D.includes(m))throw new Error(`[Directive] Schema key "${D}" in module "${a}" contains the reserved separator "${m}".`);let w=y,M=H({mod:w,namespace:a,snapshotModulesSet:r});t.add(a),n[a]=w,l.names=null,x.set(a,ue(a,w)),g.registerModule(M);}};return le(_,g),fe(_),_}function de(e){let n=e.history,t=e.trace,i=e.errorBoundary;return e.zeroConfig&&(n=n??a,i={onConstraintError:"skip",onResolverError:"skip",onEffectError:"skip",onDerivationError:"skip",...e.errorBoundary}),{history:n,trace:t,errorBoundary:i}}function le(e,n){Object.defineProperties(e,{trace:{get(){return n.trace},enumerable:true,configurable:true},meta:{value:n.meta,enumerable:true,configurable:true},isRunning:{get(){return n.isRunning},enumerable:true,configurable:true},isSettled:{get(){return n.isSettled},enumerable:true,configurable:true},isInitialized:{get(){return n.isInitialized},enumerable:true,configurable:true},isReady:{get(){return n.isReady},enumerable:true,configurable:true}}),e.whenReady=n.whenReady.bind(n),e.batch=n.batch.bind(n),e.onSettledChange=n.onSettledChange.bind(n),e.onHistoryChange=n.onHistoryChange.bind(n),e.inspect=n.inspect.bind(n),e.settle=n.settle.bind(n),e.explain=n.explain.bind(n),e.getSnapshot=n.getSnapshot.bind(n),e.restore=n.restore.bind(n),e.observe=n.observe.bind(n),n.notify&&(e.notify=n.notify);let t=["dispatch","read","subscribe","watch","when","getDistributableSnapshot","watchDistributableSnapshot"];for(let i of t)i in e||(e[i]=n[i].bind(n));}function fe(e){a&&(typeof process>"u"||process.env?.NODE_ENV!=="test")&&setTimeout(()=>{!e.isRunning&&!e.isInitialized&&console.warn("[Directive] System created but start() was never called. Constraints, resolvers, and effects will not run until you call system.start().");},0);}function $e(e){let n=e.module;if(!n)throw new Error(`[Directive] createSystem requires a module. Got: ${typeof n}`);if(e.tickMs!==void 0&&e.tickMs<=0)throw new Error("[Directive] tickMs must be a positive number");if(e.initialFacts&&!f(e.initialFacts))throw new Error("[Directive] initialFacts contains potentially dangerous keys (__proto__, constructor, or prototype). This may indicate a prototype pollution attack.");a&&(n.crossModuleDeps&&Object.keys(n.crossModuleDeps).length>0&&console.warn("[Directive] Single module mode ignores crossModuleDeps. Use multiple modules if cross-module access is needed: createSystem({ modules: { ... } })"),e.tickMs&&e.tickMs>0&&(n.events&&"tick"in n.events||console.warn(`[Directive] tickMs is set to ${e.tickMs}ms but module has no "tick" event handler.`)),(typeof e.history=="object"?e.history:null)?.snapshotModules&&console.warn("[Directive] history.snapshotModules has no effect in single-module mode. Use history.snapshotEvents on the module definition instead, or switch to createSystem({ modules: { ... } }) for multi-module filtering."));let{history:t,trace:i,errorBoundary:r}=de(e),u=null,s=null;s=A$1({modules:[{id:n.id,schema:n.schema.facts,requirements:n.schema.requirements,init:n.init,derive:n.derive,events:n.events,effects:n.effects,sources:n.sources,constraints:n.constraints,resolvers:n.resolvers,hooks:n.hooks,meta:n.meta,history:n.history}],plugins:e.plugins,history:t,trace:i,errorBoundary:r,tickMs:e.tickMs,cloud:e.cloud,onAfterModuleInit:()=>{if(e.initialFacts)for(let[d,h]of Object.entries(e.initialFacts))k.has(d)||(s.facts[d]=h);if(u){if(!f(u))a&&console.warn("[Directive] hydrate() data contains potentially dangerous keys. Skipping.");else for(let[d,h]of Object.entries(u))k.has(d)||(s.facts[d]=h);u=null;}}});let c=new Proxy({},{get(d,h){if(typeof h!="symbol"&&!k.has(h))return k=>{s.dispatch({type:h,...k});}},has(d,h){return typeof h=="symbol"||k.has(h)?false:n.events?h in n.events:false},ownKeys(){return n.events?Object.keys(n.events):[]},getOwnPropertyDescriptor(d,h){if(typeof h!="symbol"&&!k.has(h)&&n.events&&h in n.events)return {configurable:true,enumerable:true}},set(){return false},deleteProperty(){return false},defineProperty(){return false},getPrototypeOf(){return null},setPrototypeOf(){return false}}),o=null,f$1=e.tickMs,l={_mode:"single",facts:s.facts,history:s.history,derive:s.derive,events:c,constraints:s.constraints,effects:s.effects,resolvers:s.resolvers,async hydrate(d){if(s.isRunning)throw new Error("[Directive] hydrate() must be called before start(). The system is already running.");let h=await d();h&&typeof h=="object"&&(u=h);},initialize(){s.initialize();},start(){s.start(),f$1&&f$1>0&&n.events&&"tick"in n.events&&(o=setInterval(()=>{s.dispatch({type:"tick"});},f$1));},stop(){o&&(clearInterval(o),o=null),s.stop();},async stopAsync(){o&&(clearInterval(o),o=null),await s.stopAsync();},destroy(){this.stop(),s.destroy();},async destroyAsync(){await this.stopAsync(),await s.destroyAsync();},async evict(d){o&&(clearInterval(o),o=null),await s.evict(d);},registerModule(d){s.registerModule({id:d.id,schema:d.schema.facts,requirements:d.schema.requirements,init:d.init,derive:d.derive,events:d.events,effects:d.effects,sources:d.sources,constraints:d.constraints,resolvers:d.resolvers,hooks:d.hooks,history:d.history});}};return le(l,s),fe(l),l}export{ze as a};//# sourceMappingURL=chunk-E53A4NHM.js.map | ||
| //# sourceMappingURL=chunk-E53A4NHM.js.map |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { F as FactPredicate, C as ClauseResult, P as Plugin, M as ModuleSchema } from './plugins-4IfhJV32.cjs'; | ||
| /** | ||
| * Audit-ledger type definitions — entry shapes, sink interface, query | ||
| * filter, verify result, and plugin options. Pure types + the two | ||
| * schema-version constants (`HASH_ALGO`, `SCHEMA_VERSION`) that are | ||
| * referenced by the entry shape. | ||
| * | ||
| * Kept free of runtime imports so the hash/freeze/sink modules can pull | ||
| * types from here without a cycle. | ||
| */ | ||
| /** Hash algorithm tag — bumped if canonicalization or hash function changes. */ | ||
| declare const HASH_ALGO: "djb2-1"; | ||
| /** | ||
| * Entry schema version. Bumped if `AuditEntry` field shape changes in | ||
| * a way that breaks back-compat parsers. Persisted on every entry so | ||
| * exports remain self-describing across library upgrades. (F-5) | ||
| */ | ||
| declare const SCHEMA_VERSION: 1; | ||
| type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "source.attach" | "source.detach" | "source.error" | "system.init" | "system.start" | "system.stop" | "system.destroy" | "system.snapshot" | "system.history.navigate" | "system.truncated" | "system.entry-erased" | "system.subject-erased"; | ||
| /** | ||
| * Internal sentinel symbol type. The actual symbol VALUE lives in | ||
| * `hash.ts` and is never exported from this folder's public surface — | ||
| * but the TYPE must be referenceable here so `AuditEntryBase` can | ||
| * declare the optional `__internal` field. | ||
| * | ||
| * We use `symbol` rather than `typeof LEDGER_INTERNAL_TOKEN` because | ||
| * importing the symbol value into types.ts would either re-export it | ||
| * (defeating the defense) or create a circular import. The runtime | ||
| * check in `verify()` compares against the actual symbol reference. | ||
| */ | ||
| type LedgerInternalSentinel = symbol; | ||
| interface AuditEntryBase { | ||
| /** Monotonic sequence number, starting at 0. */ | ||
| readonly seq: number; | ||
| /** Wall-clock timestamp (ms epoch). */ | ||
| readonly ts: number; | ||
| /** Discriminator. */ | ||
| readonly kind: AuditEntryKind; | ||
| /** Hash of the previous entry's full payload. null on the genesis entry. */ | ||
| readonly prevHash: string | null; | ||
| /** | ||
| * Hash algorithm tag identifying the canonicalization + hash | ||
| * function in use. Bumped if the algorithm or canonical form | ||
| * changes, so exports remain verifiable across versions. | ||
| */ | ||
| readonly hashAlgo: typeof HASH_ALGO; | ||
| /** | ||
| * Entry schema version — bumped if any `AuditEntry` field shape | ||
| * changes in a way that breaks back-compat. Pair with `hashAlgo` | ||
| * when migrating older exports. (F-5) | ||
| */ | ||
| readonly schemaVersion: typeof SCHEMA_VERSION; | ||
| /** | ||
| * Private sentinel — present (and equal to the in-module token) only | ||
| * on legitimate tombstones minted by `ledger.erase()`. Filtered out | ||
| * of all public read paths (`query`, `recent`, `toJSON`, etc.) so | ||
| * consumers never see or copy it. (N7) | ||
| * | ||
| * NOT serialized. NOT exported. Forging this from outside the module | ||
| * is impossible without the symbol reference; `verify()` rejects any | ||
| * `system.entry-erased` entry that lacks it. | ||
| * | ||
| * @internal | ||
| */ | ||
| readonly __internal?: LedgerInternalSentinel; | ||
| } | ||
| type AuditEntry = (AuditEntryBase & { | ||
| kind: "constraint.evaluate"; | ||
| constraintId: string; | ||
| active: boolean; | ||
| /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. Refreshed on `register()`/`assign()`/`unregister()`. May be undefined for function-form constraints (see `whenSource`). PII operands redacted unless `capturePII: true`. */ | ||
| whenSpec?: FactPredicate<unknown>; | ||
| whenExplain?: readonly ClauseResult[]; | ||
| /** | ||
| * For function-form constraints (no `whenSpec`), a tamper-evident | ||
| * identity for the function. We DO NOT capture the raw source — | ||
| * closures routinely reference secrets, API keys, or PII (e.g. | ||
| * `if (apiKey === "sk-live-xxx")`) and a preview would leak them | ||
| * into the audit log. Instead, we capture a djb2 hash of the | ||
| * stringified function (`hashObject(String(fn))`). Auditors can | ||
| * detect "the function changed between deploys" by comparing | ||
| * hashes across entries, without ever seeing the function body. | ||
| * | ||
| * Informational only — NOT replayable. (N5, M22) | ||
| */ | ||
| whenSource?: { | ||
| kind: "function"; | ||
| sourceHash: string; | ||
| }; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.write.rejected"; | ||
| rejection: "rejection" | "summary"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| reason: string; | ||
| fact?: string; | ||
| expected?: unknown; | ||
| actual?: unknown; | ||
| dropped?: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "fact.change"; | ||
| key: string; | ||
| prior: unknown; | ||
| next: unknown; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.complete"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| duration: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.error"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.attach" | "source.detach"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.error"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| /** | ||
| * `phase: "runtime"` (RFC 0008) flags errors the source reported | ||
| * mid-flight via the `reportError` callback `attach` receives as | ||
| * its second argument — distinct from lifecycle `"attach"` / | ||
| * `"cleanup"` failures. | ||
| */ | ||
| phase: "attach" | "cleanup" | "runtime"; | ||
| /** | ||
| * Truncated error message — capped at a fixed length by the source | ||
| * manager before it reaches the ledger. Source authors who embed | ||
| * payloads in error messages get a bounded leak surface rather than | ||
| * an unbounded one. Pair with the matching `source.attach` / | ||
| * `source.detach` entries for full lifecycle context. | ||
| */ | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.init" | "system.start" | "system.stop" | "system.destroy"; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.snapshot"; | ||
| snapshotId: number; | ||
| trigger: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.history.navigate"; | ||
| from: number; | ||
| to: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.truncated"; | ||
| droppedSeq: number; | ||
| droppedCount: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.entry-erased"; | ||
| originalKind: AuditEntryKind; | ||
| erasedAt: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.subject-erased"; | ||
| /** | ||
| * djb2 hash of the filter (via `hashObject(filter)`). PII-safe — | ||
| * the raw filter values never land in the ledger. Pair with | ||
| * `filterShape` to see which filter fields were used. (N2) | ||
| */ | ||
| filterHash: string; | ||
| /** | ||
| * Stripped-values shape of the filter — captures WHICH fields were | ||
| * present without recording their values. (N2) | ||
| */ | ||
| filterShape: { | ||
| factPath: boolean; | ||
| constraintId: boolean; | ||
| kind: AuditEntryKind | readonly AuditEntryKind[] | undefined; | ||
| changedBetween: "[range]" | undefined; | ||
| }; | ||
| erased: number; | ||
| }); | ||
| interface QueryFilter { | ||
| /** Exact-match fact path. */ | ||
| factPath?: string; | ||
| /** Filter by constraint id. */ | ||
| constraintId?: string; | ||
| /** Filter by entry kind. */ | ||
| kind?: AuditEntryKind | readonly AuditEntryKind[]; | ||
| /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */ | ||
| changedBetween?: [string | number | Date, string | number | Date]; | ||
| /** Maximum entries returned. Default 1000. */ | ||
| limit?: number; | ||
| } | ||
| /** | ||
| * Verify result — chain valid OR a break with full context for tamper visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain breaks — | ||
| * `verify()` reports them in `erasedSeqs` and continues the walk from the | ||
| * tombstone's own hash. Real tamper still surfaces as `valid: false`. | ||
| * | ||
| * Forged tombstones (a caller writes `kind: "system.entry-erased"` | ||
| * directly via `sink.write()` to mask tamper as erasure) are detected: | ||
| * legitimate tombstones carry an in-module sentinel that forgeries | ||
| * cannot mint, so `verify()` reports them as tamper. (N7) | ||
| */ | ||
| type VerifyResult = { | ||
| valid: true; | ||
| entryCount: number; | ||
| /** | ||
| * Seq numbers of entries legitimately broken by `erase()` | ||
| * tombstones. NOT timestamps — each entry pairs this seq with | ||
| * the per-entry `system.entry-erased.erasedAt` (ms epoch) for | ||
| * the timestamp. Empty unless the chain contains erasures. | ||
| * (N1 + M1; renamed from `erasedAt` in R3) | ||
| */ | ||
| erasedSeqs?: number[]; | ||
| } | { | ||
| valid: false; | ||
| brokenAt: number; | ||
| expectedHash: string; | ||
| actualHash: string; | ||
| entry: AuditEntry; | ||
| /** | ||
| * Human-readable reason for the break — populated for cases | ||
| * where the cause is more specific than "hash mismatch" (e.g. | ||
| * tombstone forgery detected via missing sentinel). | ||
| */ | ||
| reason?: string; | ||
| }; | ||
| interface AuditLedgerSink { | ||
| write(entry: AuditEntry): void; | ||
| query(filter: QueryFilter): readonly AuditEntry[]; | ||
| recent(n: number): readonly AuditEntry[]; | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| clear(): void; | ||
| destroy(): void; | ||
| /** | ||
| * Replace matching entries with marker entries IN PLACE (preserving seq + | ||
| * prevHash so the hash chain still verifies — the marker is a | ||
| * tombstone in chain terms; the chain break is what makes erasure | ||
| * visible to `verify()`). v1 implementation matches on the same | ||
| * `QueryFilter` shape used by `query()`. Returns the count of entries | ||
| * replaced. | ||
| * | ||
| * WARNING: erases only from this sink. Any external copies (toJSON | ||
| * exports, downstream pipelines) must be erased separately. | ||
| */ | ||
| erase?(filter: QueryFilter, markerEntryFactory: (e: AuditEntry) => AuditEntry): number; | ||
| /** | ||
| * Optional hook fired by the sink BEFORE shifting the oldest entry | ||
| * out of a bounded ring buffer. The ledger plugin uses this to emit | ||
| * a `system.truncated` marker so an auditor sees that the log was | ||
| * truncated and where. (M23) | ||
| */ | ||
| onTruncate?(handler: (droppedSeq: number, droppedCount: number) => void): void; | ||
| } | ||
| interface AuditLedgerOptions { | ||
| /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */ | ||
| sink?: AuditLedgerSink; | ||
| /** | ||
| * Whether to capture raw fact values (`prior`/`next` on fact.change, | ||
| * `actual` in whenExplain). Default `false` — PII-tagged facts are | ||
| * redacted by default. Set `true` to opt out of redaction. | ||
| */ | ||
| capturePII?: boolean; | ||
| /** | ||
| * Optional caller-supplied redactor. Runs AFTER the default | ||
| * pii-tag-based redaction. Useful for additional sanitization. | ||
| */ | ||
| redact?: (entry: AuditEntry) => AuditEntry; | ||
| } | ||
| interface AuditLedger { | ||
| /** The plugin to pass to `createSystem({ plugins: [...] })`. */ | ||
| readonly plugin: Plugin<ModuleSchema>; | ||
| /** Query entries matching the filter. */ | ||
| query(filter?: QueryFilter): readonly AuditEntry[]; | ||
| /** Most recent N entries (chronological). */ | ||
| recent(n: number): readonly AuditEntry[]; | ||
| /** All entries that touch this fact path (exact match). */ | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** All entries for this constraint id. */ | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** Full ledger snapshot for export / serialization. */ | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| /** | ||
| * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff | ||
| * every entry's `prevHash` matches the (sync, djb2-based) hash of | ||
| * the previous entry. On break, returns the index of the first | ||
| * broken link plus the expected vs actual hashes — feed into a | ||
| * "TAMPERED" visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain | ||
| * breaks — `verify()` reports them in `erasedSeqs` and continues | ||
| * the walk from the tombstone's actual hash. Real tamper still | ||
| * surfaces as `valid: false`. (N1 + M1) | ||
| * | ||
| * Forged tombstones — `kind: "system.entry-erased"` entries written | ||
| * directly via `sink.write()` to mask tamper — are detected as | ||
| * forgery. Legitimate tombstones carry an in-module sentinel that | ||
| * forgeries cannot mint. (N7) | ||
| * | ||
| * v1 ships sync djb2 only. `verify({ strong: true })` is reserved | ||
| * for v2 (SHA-256) and THROWS today — there is no silent fallback. | ||
| * Call `verify()` (no args) for tamper detection. | ||
| */ | ||
| verify(opts?: { | ||
| strong?: boolean; | ||
| }): VerifyResult; | ||
| /** | ||
| * Per-subject erasure (GDPR Art. 17 stub). Replaces matching entries | ||
| * in this sink with `system.entry-erased` tombstones (preserving | ||
| * seq + prevHash so verify() can resync), then appends a chained | ||
| * `system.subject-erased` marker entry that summarises the erasure. | ||
| * | ||
| * Returns `{ erased, markerEntry }` — `markerEntry` is the chained | ||
| * `system.subject-erased` summary (the N per-entry tombstones live | ||
| * in the sink, not on the return value). (M7) | ||
| * | ||
| * When `erased === 0` (filter matched nothing), `markerEntry` is | ||
| * `null` and no marker is emitted into the chain — avoids polluting | ||
| * the audit trail with empty "erased: 0" records. (MAJOR-3) | ||
| * | ||
| * WARNING: v1 erases only from THIS sink. External copies (toJSON | ||
| * exports, downstream pipelines, persisted backups) must be erased | ||
| * separately. (C8) | ||
| */ | ||
| erase(filter: QueryFilter): { | ||
| erased: number; | ||
| markerEntry: AuditEntry | null; | ||
| }; | ||
| /** Empty the sink. */ | ||
| clear(): void; | ||
| /** Unsubscribe + drop the sink. */ | ||
| destroy(): void; | ||
| } | ||
| /** | ||
| * `memorySink()` — bounded ring-buffer implementation of | ||
| * `AuditLedgerSink`. Drops the oldest entry past `capacity` | ||
| * (default 10,000), exposes a truncation hook so the ledger plugin | ||
| * can emit a `system.truncated` marker before the shift, and | ||
| * supports in-place tombstone erasure for GDPR Art. 17. | ||
| * | ||
| * Pure storage layer — no hash chain awareness, no PII redaction. | ||
| * The plugin in `./index.ts` owns those concerns and routes them | ||
| * through this sink via `write()` / `erase()`. | ||
| */ | ||
| /** | ||
| * In-memory bounded ring-buffer sink. Drops oldest entries past | ||
| * `capacity` (default 10,000). Use this as the default sink for dev, | ||
| * tests, and StackBlitz demos. | ||
| */ | ||
| declare function memorySink(opts?: { | ||
| capacity?: number; | ||
| }): AuditLedgerSink; | ||
| /** | ||
| * createAuditLedger — append-only, queryable, hash-chained | ||
| * (djb2; SHA-256 reserved for v2) audit of every state change. For | ||
| * forensics and "show me why this user got that decision." | ||
| * | ||
| * Captures (per observation event): | ||
| * | ||
| * - `constraint.evaluate` → { whenSpec, whenExplain, active, whenSource? } | ||
| * - `resolver.write.rejected` (rejection + summary kinds) | ||
| * - `fact.change` → { key, prior, next } | ||
| * - `resolver.complete` → { resolverId, requirementId, duration } | ||
| * - `system.init` / `system.start` / `system.stop` / `system.destroy` | ||
| * - `system.snapshot` / `system.history.navigate` (lifecycle markers) | ||
| * - `system.truncated` (ring-buffer overflow marker) | ||
| * - `system.entry-erased` / `system.subject-erased` (GDPR Art.17 stub) | ||
| * | ||
| * PII redaction: by default, fact keys whose meta carries the `pii` | ||
| * tag (via `system.meta.byTag("pii")`) have their values replaced with | ||
| * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, | ||
| * `fact.change.next`, and the cached `whenSpec` operands. Opt out with | ||
| * `capturePII: true`. | ||
| * | ||
| * Folder layout: | ||
| * types.ts — public type surface + version stamps | ||
| * hash.ts — djb2 dispatch + freeze helper + INTERNAL TOKEN | ||
| * sink.ts — memorySink() ring buffer | ||
| * predicate-redact.ts — PII-aware redactWhenSpec | ||
| * verify.ts — tombstone-aware chain walk | ||
| * index.ts (this) — createAuditLedger factory + plugin wiring | ||
| */ | ||
| /** | ||
| * Create an audit ledger that subscribes to the given system's | ||
| * observation stream. Returns a `Plugin` to install + a query/verify | ||
| * API for the ledger. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createAuditLedger } from "@directive-run/core/plugins"; | ||
| * | ||
| * const ledger = createAuditLedger(); | ||
| * const system = createSystem({ module, plugins: [ledger.plugin] }); | ||
| * system.start(); | ||
| * | ||
| * // Six months later — auditor asks "what changed cart-total in March?" | ||
| * ledger.query({ | ||
| * factPath: "cartTotal", | ||
| * changedBetween: ["2026-03-01", "2026-04-01"], | ||
| * }); | ||
| * | ||
| * // Verify nobody tampered with the ledger | ||
| * const verdict = await ledger.verify(); | ||
| * if (!verdict.valid) { | ||
| * console.error("Tamper at entry", verdict.brokenAt); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger; | ||
| export { type AuditEntry as A, type QueryFilter as Q, type VerifyResult as V, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m }; |
| import { F as FactPredicate, C as ClauseResult, P as Plugin, M as ModuleSchema } from './plugins-4IfhJV32.js'; | ||
| /** | ||
| * Audit-ledger type definitions — entry shapes, sink interface, query | ||
| * filter, verify result, and plugin options. Pure types + the two | ||
| * schema-version constants (`HASH_ALGO`, `SCHEMA_VERSION`) that are | ||
| * referenced by the entry shape. | ||
| * | ||
| * Kept free of runtime imports so the hash/freeze/sink modules can pull | ||
| * types from here without a cycle. | ||
| */ | ||
| /** Hash algorithm tag — bumped if canonicalization or hash function changes. */ | ||
| declare const HASH_ALGO: "djb2-1"; | ||
| /** | ||
| * Entry schema version. Bumped if `AuditEntry` field shape changes in | ||
| * a way that breaks back-compat parsers. Persisted on every entry so | ||
| * exports remain self-describing across library upgrades. (F-5) | ||
| */ | ||
| declare const SCHEMA_VERSION: 1; | ||
| type AuditEntryKind = "constraint.evaluate" | "resolver.write.rejected" | "fact.change" | "resolver.complete" | "resolver.error" | "source.attach" | "source.detach" | "source.error" | "system.init" | "system.start" | "system.stop" | "system.destroy" | "system.snapshot" | "system.history.navigate" | "system.truncated" | "system.entry-erased" | "system.subject-erased"; | ||
| /** | ||
| * Internal sentinel symbol type. The actual symbol VALUE lives in | ||
| * `hash.ts` and is never exported from this folder's public surface — | ||
| * but the TYPE must be referenceable here so `AuditEntryBase` can | ||
| * declare the optional `__internal` field. | ||
| * | ||
| * We use `symbol` rather than `typeof LEDGER_INTERNAL_TOKEN` because | ||
| * importing the symbol value into types.ts would either re-export it | ||
| * (defeating the defense) or create a circular import. The runtime | ||
| * check in `verify()` compares against the actual symbol reference. | ||
| */ | ||
| type LedgerInternalSentinel = symbol; | ||
| interface AuditEntryBase { | ||
| /** Monotonic sequence number, starting at 0. */ | ||
| readonly seq: number; | ||
| /** Wall-clock timestamp (ms epoch). */ | ||
| readonly ts: number; | ||
| /** Discriminator. */ | ||
| readonly kind: AuditEntryKind; | ||
| /** Hash of the previous entry's full payload. null on the genesis entry. */ | ||
| readonly prevHash: string | null; | ||
| /** | ||
| * Hash algorithm tag identifying the canonicalization + hash | ||
| * function in use. Bumped if the algorithm or canonical form | ||
| * changes, so exports remain verifiable across versions. | ||
| */ | ||
| readonly hashAlgo: typeof HASH_ALGO; | ||
| /** | ||
| * Entry schema version — bumped if any `AuditEntry` field shape | ||
| * changes in a way that breaks back-compat. Pair with `hashAlgo` | ||
| * when migrating older exports. (F-5) | ||
| */ | ||
| readonly schemaVersion: typeof SCHEMA_VERSION; | ||
| /** | ||
| * Private sentinel — present (and equal to the in-module token) only | ||
| * on legitimate tombstones minted by `ledger.erase()`. Filtered out | ||
| * of all public read paths (`query`, `recent`, `toJSON`, etc.) so | ||
| * consumers never see or copy it. (N7) | ||
| * | ||
| * NOT serialized. NOT exported. Forging this from outside the module | ||
| * is impossible without the symbol reference; `verify()` rejects any | ||
| * `system.entry-erased` entry that lacks it. | ||
| * | ||
| * @internal | ||
| */ | ||
| readonly __internal?: LedgerInternalSentinel; | ||
| } | ||
| type AuditEntry = (AuditEntryBase & { | ||
| kind: "constraint.evaluate"; | ||
| constraintId: string; | ||
| active: boolean; | ||
| /** Cached at ledger start from `system.inspect().constraints[].whenSpec`. Refreshed on `register()`/`assign()`/`unregister()`. May be undefined for function-form constraints (see `whenSource`). PII operands redacted unless `capturePII: true`. */ | ||
| whenSpec?: FactPredicate<unknown>; | ||
| whenExplain?: readonly ClauseResult[]; | ||
| /** | ||
| * For function-form constraints (no `whenSpec`), a tamper-evident | ||
| * identity for the function. We DO NOT capture the raw source — | ||
| * closures routinely reference secrets, API keys, or PII (e.g. | ||
| * `if (apiKey === "sk-live-xxx")`) and a preview would leak them | ||
| * into the audit log. Instead, we capture a djb2 hash of the | ||
| * stringified function (`hashObject(String(fn))`). Auditors can | ||
| * detect "the function changed between deploys" by comparing | ||
| * hashes across entries, without ever seeing the function body. | ||
| * | ||
| * Informational only — NOT replayable. (N5, M22) | ||
| */ | ||
| whenSource?: { | ||
| kind: "function"; | ||
| sourceHash: string; | ||
| }; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.write.rejected"; | ||
| rejection: "rejection" | "summary"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| reason: string; | ||
| fact?: string; | ||
| expected?: unknown; | ||
| actual?: unknown; | ||
| dropped?: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "fact.change"; | ||
| key: string; | ||
| prior: unknown; | ||
| next: unknown; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.complete"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| duration: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "resolver.error"; | ||
| resolverId: string; | ||
| requirementId: string; | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.attach" | "source.detach"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "source.error"; | ||
| sourceId: string; | ||
| moduleId: string; | ||
| /** | ||
| * `phase: "runtime"` (RFC 0008) flags errors the source reported | ||
| * mid-flight via the `reportError` callback `attach` receives as | ||
| * its second argument — distinct from lifecycle `"attach"` / | ||
| * `"cleanup"` failures. | ||
| */ | ||
| phase: "attach" | "cleanup" | "runtime"; | ||
| /** | ||
| * Truncated error message — capped at a fixed length by the source | ||
| * manager before it reaches the ledger. Source authors who embed | ||
| * payloads in error messages get a bounded leak surface rather than | ||
| * an unbounded one. Pair with the matching `source.attach` / | ||
| * `source.detach` entries for full lifecycle context. | ||
| */ | ||
| error: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.init" | "system.start" | "system.stop" | "system.destroy"; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.snapshot"; | ||
| snapshotId: number; | ||
| trigger: string; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.history.navigate"; | ||
| from: number; | ||
| to: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.truncated"; | ||
| droppedSeq: number; | ||
| droppedCount: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.entry-erased"; | ||
| originalKind: AuditEntryKind; | ||
| erasedAt: number; | ||
| }) | (AuditEntryBase & { | ||
| kind: "system.subject-erased"; | ||
| /** | ||
| * djb2 hash of the filter (via `hashObject(filter)`). PII-safe — | ||
| * the raw filter values never land in the ledger. Pair with | ||
| * `filterShape` to see which filter fields were used. (N2) | ||
| */ | ||
| filterHash: string; | ||
| /** | ||
| * Stripped-values shape of the filter — captures WHICH fields were | ||
| * present without recording their values. (N2) | ||
| */ | ||
| filterShape: { | ||
| factPath: boolean; | ||
| constraintId: boolean; | ||
| kind: AuditEntryKind | readonly AuditEntryKind[] | undefined; | ||
| changedBetween: "[range]" | undefined; | ||
| }; | ||
| erased: number; | ||
| }); | ||
| interface QueryFilter { | ||
| /** Exact-match fact path. */ | ||
| factPath?: string; | ||
| /** Filter by constraint id. */ | ||
| constraintId?: string; | ||
| /** Filter by entry kind. */ | ||
| kind?: AuditEntryKind | readonly AuditEntryKind[]; | ||
| /** Time range as `[startMs, endMs]`, ISO strings, or epoch numbers. */ | ||
| changedBetween?: [string | number | Date, string | number | Date]; | ||
| /** Maximum entries returned. Default 1000. */ | ||
| limit?: number; | ||
| } | ||
| /** | ||
| * Verify result — chain valid OR a break with full context for tamper visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain breaks — | ||
| * `verify()` reports them in `erasedSeqs` and continues the walk from the | ||
| * tombstone's own hash. Real tamper still surfaces as `valid: false`. | ||
| * | ||
| * Forged tombstones (a caller writes `kind: "system.entry-erased"` | ||
| * directly via `sink.write()` to mask tamper as erasure) are detected: | ||
| * legitimate tombstones carry an in-module sentinel that forgeries | ||
| * cannot mint, so `verify()` reports them as tamper. (N7) | ||
| */ | ||
| type VerifyResult = { | ||
| valid: true; | ||
| entryCount: number; | ||
| /** | ||
| * Seq numbers of entries legitimately broken by `erase()` | ||
| * tombstones. NOT timestamps — each entry pairs this seq with | ||
| * the per-entry `system.entry-erased.erasedAt` (ms epoch) for | ||
| * the timestamp. Empty unless the chain contains erasures. | ||
| * (N1 + M1; renamed from `erasedAt` in R3) | ||
| */ | ||
| erasedSeqs?: number[]; | ||
| } | { | ||
| valid: false; | ||
| brokenAt: number; | ||
| expectedHash: string; | ||
| actualHash: string; | ||
| entry: AuditEntry; | ||
| /** | ||
| * Human-readable reason for the break — populated for cases | ||
| * where the cause is more specific than "hash mismatch" (e.g. | ||
| * tombstone forgery detected via missing sentinel). | ||
| */ | ||
| reason?: string; | ||
| }; | ||
| interface AuditLedgerSink { | ||
| write(entry: AuditEntry): void; | ||
| query(filter: QueryFilter): readonly AuditEntry[]; | ||
| recent(n: number): readonly AuditEntry[]; | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| clear(): void; | ||
| destroy(): void; | ||
| /** | ||
| * Replace matching entries with marker entries IN PLACE (preserving seq + | ||
| * prevHash so the hash chain still verifies — the marker is a | ||
| * tombstone in chain terms; the chain break is what makes erasure | ||
| * visible to `verify()`). v1 implementation matches on the same | ||
| * `QueryFilter` shape used by `query()`. Returns the count of entries | ||
| * replaced. | ||
| * | ||
| * WARNING: erases only from this sink. Any external copies (toJSON | ||
| * exports, downstream pipelines) must be erased separately. | ||
| */ | ||
| erase?(filter: QueryFilter, markerEntryFactory: (e: AuditEntry) => AuditEntry): number; | ||
| /** | ||
| * Optional hook fired by the sink BEFORE shifting the oldest entry | ||
| * out of a bounded ring buffer. The ledger plugin uses this to emit | ||
| * a `system.truncated` marker so an auditor sees that the log was | ||
| * truncated and where. (M23) | ||
| */ | ||
| onTruncate?(handler: (droppedSeq: number, droppedCount: number) => void): void; | ||
| } | ||
| interface AuditLedgerOptions { | ||
| /** Sink to write entries to. Default: in-memory ring buffer (capacity 10k). */ | ||
| sink?: AuditLedgerSink; | ||
| /** | ||
| * Whether to capture raw fact values (`prior`/`next` on fact.change, | ||
| * `actual` in whenExplain). Default `false` — PII-tagged facts are | ||
| * redacted by default. Set `true` to opt out of redaction. | ||
| */ | ||
| capturePII?: boolean; | ||
| /** | ||
| * Optional caller-supplied redactor. Runs AFTER the default | ||
| * pii-tag-based redaction. Useful for additional sanitization. | ||
| */ | ||
| redact?: (entry: AuditEntry) => AuditEntry; | ||
| } | ||
| interface AuditLedger { | ||
| /** The plugin to pass to `createSystem({ plugins: [...] })`. */ | ||
| readonly plugin: Plugin<ModuleSchema>; | ||
| /** Query entries matching the filter. */ | ||
| query(filter?: QueryFilter): readonly AuditEntry[]; | ||
| /** Most recent N entries (chronological). */ | ||
| recent(n: number): readonly AuditEntry[]; | ||
| /** All entries that touch this fact path (exact match). */ | ||
| forFact(path: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** All entries for this constraint id. */ | ||
| forConstraint(id: string, opts?: { | ||
| limit?: number; | ||
| }): readonly AuditEntry[]; | ||
| /** Full ledger snapshot for export / serialization. */ | ||
| toJSON(): { | ||
| entries: readonly AuditEntry[]; | ||
| capturedAt: number; | ||
| }; | ||
| /** | ||
| * Walk the hash chain genesis → tip. Returns `{ valid: true }` iff | ||
| * every entry's `prevHash` matches the (sync, djb2-based) hash of | ||
| * the previous entry. On break, returns the index of the first | ||
| * broken link plus the expected vs actual hashes — feed into a | ||
| * "TAMPERED" visualization. | ||
| * | ||
| * Erased entries (via `ledger.erase()`) appear as legitimate chain | ||
| * breaks — `verify()` reports them in `erasedSeqs` and continues | ||
| * the walk from the tombstone's actual hash. Real tamper still | ||
| * surfaces as `valid: false`. (N1 + M1) | ||
| * | ||
| * Forged tombstones — `kind: "system.entry-erased"` entries written | ||
| * directly via `sink.write()` to mask tamper — are detected as | ||
| * forgery. Legitimate tombstones carry an in-module sentinel that | ||
| * forgeries cannot mint. (N7) | ||
| * | ||
| * v1 ships sync djb2 only. `verify({ strong: true })` is reserved | ||
| * for v2 (SHA-256) and THROWS today — there is no silent fallback. | ||
| * Call `verify()` (no args) for tamper detection. | ||
| */ | ||
| verify(opts?: { | ||
| strong?: boolean; | ||
| }): VerifyResult; | ||
| /** | ||
| * Per-subject erasure (GDPR Art. 17 stub). Replaces matching entries | ||
| * in this sink with `system.entry-erased` tombstones (preserving | ||
| * seq + prevHash so verify() can resync), then appends a chained | ||
| * `system.subject-erased` marker entry that summarises the erasure. | ||
| * | ||
| * Returns `{ erased, markerEntry }` — `markerEntry` is the chained | ||
| * `system.subject-erased` summary (the N per-entry tombstones live | ||
| * in the sink, not on the return value). (M7) | ||
| * | ||
| * When `erased === 0` (filter matched nothing), `markerEntry` is | ||
| * `null` and no marker is emitted into the chain — avoids polluting | ||
| * the audit trail with empty "erased: 0" records. (MAJOR-3) | ||
| * | ||
| * WARNING: v1 erases only from THIS sink. External copies (toJSON | ||
| * exports, downstream pipelines, persisted backups) must be erased | ||
| * separately. (C8) | ||
| */ | ||
| erase(filter: QueryFilter): { | ||
| erased: number; | ||
| markerEntry: AuditEntry | null; | ||
| }; | ||
| /** Empty the sink. */ | ||
| clear(): void; | ||
| /** Unsubscribe + drop the sink. */ | ||
| destroy(): void; | ||
| } | ||
| /** | ||
| * `memorySink()` — bounded ring-buffer implementation of | ||
| * `AuditLedgerSink`. Drops the oldest entry past `capacity` | ||
| * (default 10,000), exposes a truncation hook so the ledger plugin | ||
| * can emit a `system.truncated` marker before the shift, and | ||
| * supports in-place tombstone erasure for GDPR Art. 17. | ||
| * | ||
| * Pure storage layer — no hash chain awareness, no PII redaction. | ||
| * The plugin in `./index.ts` owns those concerns and routes them | ||
| * through this sink via `write()` / `erase()`. | ||
| */ | ||
| /** | ||
| * In-memory bounded ring-buffer sink. Drops oldest entries past | ||
| * `capacity` (default 10,000). Use this as the default sink for dev, | ||
| * tests, and StackBlitz demos. | ||
| */ | ||
| declare function memorySink(opts?: { | ||
| capacity?: number; | ||
| }): AuditLedgerSink; | ||
| /** | ||
| * createAuditLedger — append-only, queryable, hash-chained | ||
| * (djb2; SHA-256 reserved for v2) audit of every state change. For | ||
| * forensics and "show me why this user got that decision." | ||
| * | ||
| * Captures (per observation event): | ||
| * | ||
| * - `constraint.evaluate` → { whenSpec, whenExplain, active, whenSource? } | ||
| * - `resolver.write.rejected` (rejection + summary kinds) | ||
| * - `fact.change` → { key, prior, next } | ||
| * - `resolver.complete` → { resolverId, requirementId, duration } | ||
| * - `system.init` / `system.start` / `system.stop` / `system.destroy` | ||
| * - `system.snapshot` / `system.history.navigate` (lifecycle markers) | ||
| * - `system.truncated` (ring-buffer overflow marker) | ||
| * - `system.entry-erased` / `system.subject-erased` (GDPR Art.17 stub) | ||
| * | ||
| * PII redaction: by default, fact keys whose meta carries the `pii` | ||
| * tag (via `system.meta.byTag("pii")`) have their values replaced with | ||
| * `"[redacted]"` in `whenExplain.actual`, `fact.change.prior`, | ||
| * `fact.change.next`, and the cached `whenSpec` operands. Opt out with | ||
| * `capturePII: true`. | ||
| * | ||
| * Folder layout: | ||
| * types.ts — public type surface + version stamps | ||
| * hash.ts — djb2 dispatch + freeze helper + INTERNAL TOKEN | ||
| * sink.ts — memorySink() ring buffer | ||
| * predicate-redact.ts — PII-aware redactWhenSpec | ||
| * verify.ts — tombstone-aware chain walk | ||
| * index.ts (this) — createAuditLedger factory + plugin wiring | ||
| */ | ||
| /** | ||
| * Create an audit ledger that subscribes to the given system's | ||
| * observation stream. Returns a `Plugin` to install + a query/verify | ||
| * API for the ledger. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createAuditLedger } from "@directive-run/core/plugins"; | ||
| * | ||
| * const ledger = createAuditLedger(); | ||
| * const system = createSystem({ module, plugins: [ledger.plugin] }); | ||
| * system.start(); | ||
| * | ||
| * // Six months later — auditor asks "what changed cart-total in March?" | ||
| * ledger.query({ | ||
| * factPath: "cartTotal", | ||
| * changedBetween: ["2026-03-01", "2026-04-01"], | ||
| * }); | ||
| * | ||
| * // Verify nobody tampered with the ledger | ||
| * const verdict = await ledger.verify(); | ||
| * if (!verdict.valid) { | ||
| * console.error("Tamper at entry", verdict.brokenAt); | ||
| * } | ||
| * ``` | ||
| */ | ||
| declare function createAuditLedger(opts?: AuditLedgerOptions): AuditLedger; | ||
| export { type AuditEntry as A, type QueryFilter as Q, type VerifyResult as V, type AuditEntryKind as a, type AuditLedger as b, type AuditLedgerOptions as c, type AuditLedgerSink as d, createAuditLedger as e, memorySink as m }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
| import { ah as Schema, a as Facts, F as FactPredicate, b4 as InferSchema, L as FactTemplate, D as DefinitionMeta, r as Requirement, bl as RequirementOutput, ag as RetryPolicy, B as BatchConfig, be as ResolverContext, ad as PredicateOp, a6 as PatchSpec, C as ClauseResult } from './plugins-4IfhJV32.js'; | ||
| /** | ||
| * Derivation Types - Type definitions for derivations | ||
| */ | ||
| /** Derivation definition function signature. */ | ||
| interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| (facts: Facts<S>, derived: DerivedValues<S, D>): T; | ||
| } | ||
| /** | ||
| * Derivation definition with metadata (object form). | ||
| * Use this when you want to attach debugging metadata to a derivation. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * derive: { | ||
| * displayName: { | ||
| * compute: (facts) => `${facts.firstName} ${facts.lastName}`, | ||
| * meta: { label: "Display Name", description: "Full name for UI" }, | ||
| * }, | ||
| * }, | ||
| * ``` | ||
| */ | ||
| interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| /** | ||
| * The derivation body. Either: | ||
| * - a function `(facts, derived) => T` (original form), or | ||
| * - a {@link FactPredicate} data spec — boolean derivations only, or | ||
| * - a {@link FactTemplate} `{ $template: "..." }` — string derivations only. | ||
| * | ||
| * Data forms are normalized to a wrapper function at registration; the | ||
| * wrapper reads through the facts proxy so existing auto-tracking | ||
| * captures dependencies. | ||
| */ | ||
| compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never); | ||
| meta?: DefinitionMeta; | ||
| } | ||
| /** Map of derivation definitions (internal — always bare functions after unwrap). */ | ||
| type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>; | ||
| /** Computed derived values. */ | ||
| type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = { | ||
| readonly [K in keyof D]: ReturnType<D[K]>; | ||
| }; | ||
| /** Internal derivation state */ | ||
| interface DerivationState<T> { | ||
| id: string; | ||
| compute: () => T; | ||
| cachedValue: T | undefined; | ||
| dependencies: Set<string>; | ||
| isStale: boolean; | ||
| isComputing: boolean; | ||
| /** Consecutive runs producing the same deps (auto-tracked only) */ | ||
| stableRunCount: number; | ||
| /** Once true, skip withTracking() overhead until a tracked fact mutates */ | ||
| depsStable: boolean; | ||
| } | ||
| /** | ||
| * Type Helpers - External typed constraint and resolver definitions | ||
| * | ||
| * These types enable defining constraints and resolvers with full type safety | ||
| * outside of module definitions, while maintaining proper type inference. | ||
| */ | ||
| /** | ||
| * External constraint definition with full typing. | ||
| * Use this when defining constraints outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed constraint factory | ||
| * const createMaxCountConstraint = <S extends Schema>( | ||
| * maxCount: number | ||
| * ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({ | ||
| * priority: 10, | ||
| * when: (facts) => (facts as { count: number }).count > maxCount, | ||
| * require: { type: "RESET_COUNT" }, | ||
| * }); | ||
| * | ||
| * // Use in module | ||
| * const module = createModule("counter", { | ||
| * schema: { count: t.number() }, | ||
| * constraints: { | ||
| * maxCount: createMaxCountConstraint(100), | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> { | ||
| /** Priority for ordering (higher runs first) */ | ||
| priority?: number; | ||
| /** Mark this constraint as async (avoids runtime detection) */ | ||
| async?: boolean; | ||
| /** Condition function (sync or async) */ | ||
| when: (facts: Facts<S>) => boolean | Promise<boolean>; | ||
| /** | ||
| * Requirement(s) to produce when condition is met. | ||
| */ | ||
| require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>); | ||
| /** Timeout for async constraints (ms) */ | ||
| timeout?: number; | ||
| /** | ||
| * Constraint IDs whose resolvers must complete before this constraint is evaluated. | ||
| * - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for) | ||
| * - If dependency's resolver fails, this constraint remains blocked until it succeeds | ||
| * - Cross-module: use the constraint ID as it appears in the merged system | ||
| */ | ||
| after?: string[]; | ||
| } | ||
| /** | ||
| * External resolver definition with full typing. | ||
| * Use this when defining resolvers outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed resolver factory | ||
| * interface FetchUserReq extends Requirement { | ||
| * type: "FETCH_USER"; | ||
| * userId: string; | ||
| * } | ||
| * | ||
| * const createFetchUserResolver = <S extends Schema>( | ||
| * fetchFn: (userId: string) => Promise<User> | ||
| * ): TypedResolver<S, FetchUserReq> => ({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * key: (req) => `fetch-user-${req.userId}`, | ||
| * retry: { attempts: 3, backoff: "exponential" }, | ||
| * resolve: async (req, ctx) => { | ||
| * const user = await fetchFn(req.userId); | ||
| * (ctx.facts as { user: User }).user = user; | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedResolver<S extends Schema, R extends Requirement = Requirement> { | ||
| /** | ||
| * Requirement type to handle. | ||
| * - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`) | ||
| * - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`) | ||
| */ | ||
| requirement: R["type"] | ((req: Requirement) => req is R); | ||
| /** Custom key function for deduplication */ | ||
| key?: (req: R) => string; | ||
| /** Retry policy */ | ||
| retry?: RetryPolicy; | ||
| /** Timeout for resolver execution (ms) */ | ||
| timeout?: number; | ||
| /** Batch configuration */ | ||
| batch?: BatchConfig; | ||
| /** Resolve function for single requirement */ | ||
| resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>; | ||
| /** Resolve function for batched requirements */ | ||
| resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>; | ||
| } | ||
| /** | ||
| * Create a typed constraint factory for a specific schema. | ||
| * This enables creating reusable constraint definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { count: t.number(), threshold: t.number() }; | ||
| * const factory = createConstraintFactory<typeof schema>(); | ||
| * | ||
| * const maxCountConstraint = factory.create({ | ||
| * when: (facts) => facts.count > facts.threshold, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createConstraintFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed constraint | ||
| */ | ||
| create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| }; | ||
| /** | ||
| * Create a typed resolver factory for a specific schema. | ||
| * This enables creating reusable resolver definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { user: t.object<User>() }; | ||
| * const factory = createResolverFactory<typeof schema>(); | ||
| * | ||
| * const fetchUserResolver = factory.create<FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createResolverFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed resolver | ||
| */ | ||
| create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| }; | ||
| /** | ||
| * Type-safe constraint creator. | ||
| * Simpler alternative to createConstraintFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const constraint = typedConstraint<typeof schema, { type: "RESET" }>({ | ||
| * when: (facts) => facts.count > 100, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| /** | ||
| * Type-safe resolver creator. | ||
| * Simpler alternative to createResolverFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const resolver = typedResolver<typeof schema, FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| /** | ||
| * Schema Introspection | ||
| * | ||
| * A runtime discriminant for every `t.*()` builder result, so downstream | ||
| * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`) | ||
| * can ask "what kind is this fact?" without grepping the source. | ||
| * | ||
| * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`. | ||
| * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.) | ||
| * preserve / decorate it. When `_kind` is absent (legacy or third-party | ||
| * builder), the parser falls back to reading the freeform `_typeName` | ||
| * string. When even that fails: `{ kind: "unknown" }` — graceful close. | ||
| * | ||
| * This module has zero hot-path cost; it is only invoked when an | ||
| * introspecting caller asks for it. | ||
| */ | ||
| /** | ||
| * The closed set of kinds a Directive schema field can be. | ||
| * | ||
| * Drives operator availability via {@link getOperatorsForKind}: e.g. | ||
| * `"number"` gets the orderable operators (`$gte`, `$lte`); `"boolean"` | ||
| * does not. | ||
| */ | ||
| type SchemaKind = "number" | "string" | "boolean" | "bigint" | "date" | "array" | "object" | "record" | "tuple" | "enum" | "literal" | "union" | "branded" | "unknown"; | ||
| /** | ||
| * A tree-shaped discriminator for a schema field. Composite kinds | ||
| * (array, object, tuple, etc.) carry their element / shape information | ||
| * so an LLM-prompt builder can show "cartTotal is a number" AND | ||
| * "items is an array of { sku: string, qty: number }". | ||
| * | ||
| * `nullable` / `hasDefault` flags appear on the inner node (NOT a | ||
| * wrapping kind) so operator-lookup on `t.number().nullable()` returns | ||
| * the number's operators unchanged — `$gte` works on the non-null arm. | ||
| */ | ||
| type SchemaKindNode = ({ | ||
| kind: "number" | "string" | "boolean" | "bigint" | "date" | "unknown"; | ||
| } | { | ||
| kind: "literal"; | ||
| value: string | number | boolean | null; | ||
| primitive: "string" | "number" | "boolean" | "null"; | ||
| } | { | ||
| kind: "enum"; | ||
| values: readonly (string | number)[]; | ||
| primitive: "string" | "number"; | ||
| } | { | ||
| kind: "array"; | ||
| element: SchemaKindNode; | ||
| } | { | ||
| kind: "tuple"; | ||
| elements: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "object"; | ||
| shape: Record<string, SchemaKindNode>; | ||
| } | { | ||
| kind: "record"; | ||
| value: SchemaKindNode; | ||
| } | { | ||
| kind: "union"; | ||
| members: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "branded"; | ||
| inner: SchemaKindNode; | ||
| }) & { | ||
| /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */ | ||
| nullable?: boolean; | ||
| /** True if the schema has a `.default()`. */ | ||
| hasDefault?: boolean; | ||
| }; | ||
| /** | ||
| * Return the {@link SchemaKindNode} for a schema field. Prefers the | ||
| * explicit `_kind` discriminant set by the builder; falls back to | ||
| * parsing the freeform `_typeName` string for legacy / third-party | ||
| * builders that don't set `_kind`. | ||
| * | ||
| * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder | ||
| * that throws on property access returns `{ kind: "unknown" }` instead of | ||
| * propagating the throw to introspecting callers. | ||
| * | ||
| * In dev mode, a function input (`typeof schema === "function"`) emits a | ||
| * warning — common foot-gun where the caller forgot to invoke a builder | ||
| * factory (e.g. wrote `t.number` instead of `t.number()`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * getKind(t.number()) // → { kind: "number" } | ||
| * getKind(t.string().nullable()) // → { kind: "string", nullable: true } | ||
| * getKind(t.array(t.number())) // → { kind: "array", element: { kind: "number" } } | ||
| * ``` | ||
| */ | ||
| declare function getKind(schema: unknown): SchemaKindNode; | ||
| /** | ||
| * Walk the `facts` block of a module schema and emit a flat map from | ||
| * dotted path → kind node. Nested `t.object()` shapes flatten using | ||
| * `.` as the separator, matching the convention used by | ||
| * `OperatorObject<V>`'s nested-path support. | ||
| * | ||
| * Passing a top-level schema directly (without the `facts:` wrapper) | ||
| * also works — anything iterable as `Record<string, ExtendedSchemaType>` | ||
| * is acceptable. | ||
| * | ||
| * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is | ||
| * silently skipped (treated as `{ kind: "unknown" }` for that field) | ||
| * rather than aborting the whole walk. | ||
| * | ||
| * In dev mode, a top-level schema that yields an empty map (no | ||
| * introspectable keys) emits a warning — common foot-gun where the | ||
| * caller passed `myModule` instead of `myModule.schema`. | ||
| */ | ||
| declare function getSchemaFieldKinds(schema: unknown): Map<string, SchemaKindNode>; | ||
| /** | ||
| * Return the set of `PredicateOp` strings that are valid against a | ||
| * given {@link SchemaKindNode}. | ||
| * | ||
| * Mirrors the type-level matrix encoded in `OperatorObject<V>` in | ||
| * `types/predicate.ts` — drift between the two is enforced by the | ||
| * compile-time conformance test | ||
| * (`schema-introspection-conformance.test-d.ts`). | ||
| * | ||
| * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists` | ||
| * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`, | ||
| * `$lt`, `$lte`, `$between` | ||
| * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains` | ||
| * - **Array:** + `$contains` (over the element type) | ||
| * - **Union:** *intersection* across members (the operand must be valid | ||
| * for every branch). | ||
| * - **Branded:** delegates to the inner kind. | ||
| * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in` | ||
| * operand restricted at the LLM-prompt layer (not enforced here). | ||
| * | ||
| * `nullable` does not change operator availability — `$gte` on a | ||
| * nullable number is fine on the non-null arm; `$exists` handles null. | ||
| */ | ||
| declare function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[]; | ||
| /** | ||
| * Return all known predicate operators — convenience for prompt builders | ||
| * that need to show the LLM the full set. | ||
| */ | ||
| declare function listAllPredicateOperators(): readonly PredicateOp[]; | ||
| /** | ||
| * Runtime for data-configuration predicates and templates. | ||
| * | ||
| * Pure module — imports only its own types. Reads facts through whatever | ||
| * object it is handed (the reactive `Facts` proxy in production, a plain | ||
| * snapshot in tests), so it never depends on the engine, store, or tracking. | ||
| */ | ||
| /** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */ | ||
| type Scope = Record<string, unknown>; | ||
| /** | ||
| * True when `v` is a data-form spec (predicate object/array) rather than a | ||
| * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.) | ||
| * — only plain `{}` literals and arrays of plain clause shapes qualify. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isPredicate({ phase: "red" }); // true | ||
| * isPredicate((f) => f.phase === "red"); // false | ||
| * isPredicate([{ fact: "phase", op: "$eq", value: "red" }]); // true | ||
| * ``` | ||
| */ | ||
| declare function isPredicate(v: unknown): boolean; | ||
| /** | ||
| * True when `v` is a {@link FactTemplate} (`{ $template: string }`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isTemplate({ $template: "Hi ${name}" }); // true | ||
| * isTemplate({ $set: { name: "x" } }); // false | ||
| * ``` | ||
| */ | ||
| declare function isTemplate(v: unknown): v is FactTemplate; | ||
| /** | ||
| * Throw when a predicate spec contains an operand that cannot survive a | ||
| * JSON round-trip — i.e. that would silently mis-evaluate if the spec was | ||
| * loaded from `JSON.parse`. | ||
| * | ||
| * Three failure classes are detected: | ||
| * | ||
| * - **Lost `RegExp` operand.** A `$matches` operand that is not a | ||
| * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as | ||
| * `{}`, so a `$matches` clause with an empty-object operand is the | ||
| * signature of a regex that did not survive serialization. Reify it | ||
| * with `new RegExp(pattern, flags)` before installing the predicate. | ||
| * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a | ||
| * `bigint` operand cannot have been produced by a JSON pipeline and | ||
| * cannot be persisted by one either. | ||
| * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all | ||
| * members; a predicate carrying one is not JSON-safe. | ||
| * | ||
| * This is an opt-in helper — the engine does not call it automatically. | ||
| * Users who load predicates from JSON should call it after `JSON.parse` | ||
| * to fail loud rather than silently mis-evaluate. See the | ||
| * "Serialization" section of RFC-0004. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * validatePredicate({ phase: { $matches: {} } }); | ||
| * // throws — empty object where a RegExp is required | ||
| * | ||
| * validatePredicate({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // ok — JSON-clean operands | ||
| * ``` | ||
| */ | ||
| declare function validatePredicate(spec: unknown, path?: string): void; | ||
| interface SchemaValidationError { | ||
| /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */ | ||
| readonly path: string; | ||
| /** The operator that failed (or the literal-equality marker `$eq`). */ | ||
| readonly op: string; | ||
| /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */ | ||
| readonly kind?: SchemaKindNode; | ||
| /** The operators that ARE allowed for this fact's kind. */ | ||
| readonly allowedOps?: readonly string[]; | ||
| /** Human-readable failure reason (suitable for feeding back to an LLM). */ | ||
| readonly reason: string; | ||
| } | ||
| interface SchemaValidationOptions { | ||
| /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */ | ||
| readonly maxOperatorCount?: number; | ||
| /** | ||
| * Reject `$in` / `$nin` operands that contain more than this many elements | ||
| * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000 | ||
| * — beyond that, a downstream query compiler may degrade quadratically. | ||
| */ | ||
| readonly maxArrayOperandLength?: number; | ||
| } | ||
| /** | ||
| * Heuristic: flag a regex source string that has obvious nested quantifiers | ||
| * (e.g. `(.+)+`, `(.*)*`, `(\w+)+`, `(a|a)+`) — the classic ReDoS shapes. | ||
| * Not a full ReDoS prover; intentionally conservative so a string-rehydrated | ||
| * `$matches` operand can be rejected before it ever reaches `RegExp.test`. | ||
| * | ||
| * Callers MUST NOT treat a `false` result as "safe" — a determined adversary | ||
| * can craft patterns this heuristic misses. The right answer for untrusted | ||
| * regex is "don't accept untrusted regex"; this helper exists to catch the | ||
| * obvious foot-guns. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * dangerousRegex("(a+)+"); // → true | ||
| * dangerousRegex("(.*)*"); // → true | ||
| * dangerousRegex("(\\w+)+"); // → true | ||
| * dangerousRegex("^[a-z]+$"); // → false | ||
| * ``` | ||
| */ | ||
| declare function dangerousRegex(source: string): boolean; | ||
| type SchemaValidationResult = { | ||
| ok: true; | ||
| operatorCount: number; | ||
| } | { | ||
| ok: false; | ||
| errors: readonly SchemaValidationError[]; | ||
| operatorCount: number; | ||
| }; | ||
| /** | ||
| * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate | ||
| * against a schema's runtime kind map. Catches errors that | ||
| * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a | ||
| * boolean fact), unknown fact paths, and (optionally) operator-count | ||
| * exhaustion DoS attempts. | ||
| * | ||
| * Pair with {@link validatePredicate} (structural / JSON safety) for full | ||
| * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a | ||
| * module schema. | ||
| * | ||
| * Designed for the LLM-emit retry loop: returns a list of errors with | ||
| * structured `{path, op, kind, allowedOps, reason}` rather than throwing, | ||
| * so the caller can feed the errors back to the model. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } }); | ||
| * const result = validatePredicateAgainstSchema( | ||
| * { cartTotal: { $gte: 50 }, active: { $gte: true } }, | ||
| * kindMap, | ||
| * ); | ||
| * // → { ok: false, errors: [{ path: "active", op: "$gte", reason: "..." }], operatorCount: 2 } | ||
| * ``` | ||
| */ | ||
| declare function validatePredicateAgainstSchema(spec: unknown, kindMap: Map<string, SchemaKindNode>, opts?: SchemaValidationOptions): SchemaValidationResult; | ||
| /** | ||
| * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous | ||
| * snapshot) is consulted only by the `$changed` operator. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicate({ phase: "red", elapsed: { $gte: 30 } }, { phase: "red", elapsed: 45 }); | ||
| * // → true | ||
| * evaluatePredicate({ $any: [{ phase: "red" }, { phase: "yellow" }] }, { phase: "green" }); | ||
| * // → false | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicate(spec: unknown, facts: Scope, prev?: Scope, depth?: number): boolean; | ||
| /** | ||
| * Evaluate a predicate and return a per-clause breakdown — the data feed for | ||
| * devtools, `system.explain()`, and `directive explain`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicateExplained( | ||
| * { phase: "red", elapsed: { $gte: 30 } }, | ||
| * { phase: "red", elapsed: 20 }, | ||
| * ); | ||
| * // → [ | ||
| * // { path: "phase", op: "$eq", expected: "red", actual: "red", pass: true }, | ||
| * // { path: "elapsed", op: "$gte", expected: 30, actual: 20, pass: false }, | ||
| * // ] | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicateExplained(spec: unknown, facts: Scope, prev?: Scope, pathPrefix?: string): ClauseResult[]; | ||
| /** | ||
| * Memoize a predicate as a reusable evaluation closure. | ||
| * | ||
| * The returned function accepts any `facts` scope (the reactive proxy in | ||
| * production, a plain object in tests) plus an optional `prev` snapshot for | ||
| * `$changed`. The closure is cached **by predicate identity** in a | ||
| * `WeakMap`, so passing the same `predicate` reference repeatedly is | ||
| * allocation-free; cleanup is automatic once the predicate is no longer | ||
| * reachable. | ||
| * | ||
| * Note: no actual compilation happens — the returned closure re-walks the | ||
| * spec on every call via `evaluatePredicate`. The name reflects what the | ||
| * function does (closure memoization keyed by predicate identity), not a | ||
| * bytecode/AST compile step. | ||
| * | ||
| * Intended for advanced users who want a stable function reference per | ||
| * predicate (custom devtools, batched analyses). Regular module code does | ||
| * not need to call this — the engine wraps data-form `when` / `on` specs | ||
| * automatically at registration. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const predicate = { phase: "red", elapsed: { $gte: 30 } }; | ||
| * const check = memoizePredicate(predicate); | ||
| * check({ phase: "red", elapsed: 45 }); // → true | ||
| * check({ phase: "red", elapsed: 5 }); // → false | ||
| * ``` | ||
| */ | ||
| declare function memoizePredicate(predicate: object): (facts: Scope, prev?: Scope) => boolean; | ||
| /** | ||
| * Collect the fact keys a predicate references. Used for static analysis, | ||
| * devtools, and effect `on` dependency wiring. Nested predicates contribute | ||
| * dotted keys (`auth.token`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractDeps({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // → Set { "phase", "elapsed" } | ||
| * extractDeps({ self: { phase: "red" }, auth: { token: { $exists: true } } }); | ||
| * // → Set { "self.phase", "auth.token" } | ||
| * ``` | ||
| */ | ||
| declare function extractDeps(spec: unknown, prefix?: string): Set<string>; | ||
| /** | ||
| * Interpolate a {@link FactTemplate} against a scope. Single-pass character | ||
| * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal | ||
| * `${`; unknown keys dev-warn and yield an empty string. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateTemplate({ $template: "Hi ${name}!" }, { name: "Ada" }); | ||
| * // → "Hi Ada!" | ||
| * evaluateTemplate({ $template: "$${price}" }, {}); | ||
| * // → "${price}" | ||
| * ``` | ||
| */ | ||
| declare function evaluateTemplate(spec: FactTemplate, scope: Scope): string; | ||
| /** | ||
| * Collect the placeholder keys referenced by a template. The static-analysis | ||
| * counterpart to {@link extractDeps} — useful for devtools, codegen, and | ||
| * "which facts does this template read" inspections. Only valid identifier | ||
| * placeholders are collected; malformed ones are ignored. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractTemplateKeys({ $template: "${firstName} ${lastName}" }); | ||
| * // → Set { "firstName", "lastName" } | ||
| * extractTemplateKeys({ $template: "$${literal}" }); | ||
| * // → Set {} (escaped — not a placeholder) | ||
| * ``` | ||
| */ | ||
| declare function extractTemplateKeys(spec: FactTemplate): Set<string>; | ||
| /** | ||
| * Build a stable dedup key by selecting fields from a requirement payload. | ||
| * Order-as-declared; values are stable-stringified (keys sorted recursively) | ||
| * so two payloads with the same fields in different orders dedupe to the | ||
| * same key. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateKeySelector(["url", "method"], { url: "/a", method: "GET" }); | ||
| * // → '"/a"|"GET"' | ||
| * evaluateKeySelector(["id"], { id: 42 }); | ||
| * // → '42' | ||
| * ``` | ||
| */ | ||
| declare function evaluateKeySelector(selector: readonly string[], source: Record<string, unknown>): string; | ||
| /** | ||
| * Apply a {@link PatchSpec} — assign facts from literals, payload copies | ||
| * (`$ref`), or interpolated strings (`$template`). Mutates through the passed | ||
| * `facts` proxy so change-tracking and downstream invalidation fire. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spec = { | ||
| * $set: { | ||
| * active: true, | ||
| * userId: { $ref: "id" }, | ||
| * label: { $template: "user ${name}" }, | ||
| * }, | ||
| * }; | ||
| * applyPatch(spec, facts, { id: "u_1", name: "Ada" }); | ||
| * // facts.active = true; facts.userId = "u_1"; facts.label = "user Ada" | ||
| * ``` | ||
| */ | ||
| declare function applyPatch(spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>, facts: Record<string, unknown>, payload: Record<string, unknown>): void; | ||
| export { type TypedResolver as A, createConstraintFactory as B, createResolverFactory as C, type DerivationDefWithMeta as D, dangerousRegex as E, type SchemaKindNode as S, type TypedConstraint as T, type DerivationDef as a, type DerivationsDef as b, type SchemaKind as c, type SchemaValidationError as d, type SchemaValidationOptions as e, type SchemaValidationResult as f, applyPatch as g, evaluateKeySelector as h, evaluatePredicate as i, evaluatePredicateExplained as j, evaluateTemplate as k, extractDeps as l, extractTemplateKeys as m, getKind as n, getOperatorsForKind as o, getSchemaFieldKinds as p, isPredicate as q, isTemplate as r, listAllPredicateOperators as s, memoizePredicate as t, typedConstraint as u, typedResolver as v, validatePredicate as w, validatePredicateAgainstSchema as x, type DerivedValues as y, type DerivationState as z }; |
| import { ah as Schema, a as Facts, F as FactPredicate, b4 as InferSchema, L as FactTemplate, D as DefinitionMeta, r as Requirement, bl as RequirementOutput, ag as RetryPolicy, B as BatchConfig, be as ResolverContext, ad as PredicateOp, a6 as PatchSpec, C as ClauseResult } from './plugins-4IfhJV32.cjs'; | ||
| /** | ||
| * Derivation Types - Type definitions for derivations | ||
| */ | ||
| /** Derivation definition function signature. */ | ||
| interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| (facts: Facts<S>, derived: DerivedValues<S, D>): T; | ||
| } | ||
| /** | ||
| * Derivation definition with metadata (object form). | ||
| * Use this when you want to attach debugging metadata to a derivation. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * derive: { | ||
| * displayName: { | ||
| * compute: (facts) => `${facts.firstName} ${facts.lastName}`, | ||
| * meta: { label: "Display Name", description: "Full name for UI" }, | ||
| * }, | ||
| * }, | ||
| * ``` | ||
| */ | ||
| interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> { | ||
| /** | ||
| * The derivation body. Either: | ||
| * - a function `(facts, derived) => T` (original form), or | ||
| * - a {@link FactPredicate} data spec — boolean derivations only, or | ||
| * - a {@link FactTemplate} `{ $template: "..." }` — string derivations only. | ||
| * | ||
| * Data forms are normalized to a wrapper function at registration; the | ||
| * wrapper reads through the facts proxy so existing auto-tracking | ||
| * captures dependencies. | ||
| */ | ||
| compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never); | ||
| meta?: DefinitionMeta; | ||
| } | ||
| /** Map of derivation definitions (internal — always bare functions after unwrap). */ | ||
| type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>; | ||
| /** Computed derived values. */ | ||
| type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = { | ||
| readonly [K in keyof D]: ReturnType<D[K]>; | ||
| }; | ||
| /** Internal derivation state */ | ||
| interface DerivationState<T> { | ||
| id: string; | ||
| compute: () => T; | ||
| cachedValue: T | undefined; | ||
| dependencies: Set<string>; | ||
| isStale: boolean; | ||
| isComputing: boolean; | ||
| /** Consecutive runs producing the same deps (auto-tracked only) */ | ||
| stableRunCount: number; | ||
| /** Once true, skip withTracking() overhead until a tracked fact mutates */ | ||
| depsStable: boolean; | ||
| } | ||
| /** | ||
| * Type Helpers - External typed constraint and resolver definitions | ||
| * | ||
| * These types enable defining constraints and resolvers with full type safety | ||
| * outside of module definitions, while maintaining proper type inference. | ||
| */ | ||
| /** | ||
| * External constraint definition with full typing. | ||
| * Use this when defining constraints outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed constraint factory | ||
| * const createMaxCountConstraint = <S extends Schema>( | ||
| * maxCount: number | ||
| * ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({ | ||
| * priority: 10, | ||
| * when: (facts) => (facts as { count: number }).count > maxCount, | ||
| * require: { type: "RESET_COUNT" }, | ||
| * }); | ||
| * | ||
| * // Use in module | ||
| * const module = createModule("counter", { | ||
| * schema: { count: t.number() }, | ||
| * constraints: { | ||
| * maxCount: createMaxCountConstraint(100), | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> { | ||
| /** Priority for ordering (higher runs first) */ | ||
| priority?: number; | ||
| /** Mark this constraint as async (avoids runtime detection) */ | ||
| async?: boolean; | ||
| /** Condition function (sync or async) */ | ||
| when: (facts: Facts<S>) => boolean | Promise<boolean>; | ||
| /** | ||
| * Requirement(s) to produce when condition is met. | ||
| */ | ||
| require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>); | ||
| /** Timeout for async constraints (ms) */ | ||
| timeout?: number; | ||
| /** | ||
| * Constraint IDs whose resolvers must complete before this constraint is evaluated. | ||
| * - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for) | ||
| * - If dependency's resolver fails, this constraint remains blocked until it succeeds | ||
| * - Cross-module: use the constraint ID as it appears in the merged system | ||
| */ | ||
| after?: string[]; | ||
| } | ||
| /** | ||
| * External resolver definition with full typing. | ||
| * Use this when defining resolvers outside of createModule(). | ||
| * | ||
| * @typeParam S - The schema type | ||
| * @typeParam R - The requirement type (defaults to Requirement) | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Define a typed resolver factory | ||
| * interface FetchUserReq extends Requirement { | ||
| * type: "FETCH_USER"; | ||
| * userId: string; | ||
| * } | ||
| * | ||
| * const createFetchUserResolver = <S extends Schema>( | ||
| * fetchFn: (userId: string) => Promise<User> | ||
| * ): TypedResolver<S, FetchUserReq> => ({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * key: (req) => `fetch-user-${req.userId}`, | ||
| * retry: { attempts: 3, backoff: "exponential" }, | ||
| * resolve: async (req, ctx) => { | ||
| * const user = await fetchFn(req.userId); | ||
| * (ctx.facts as { user: User }).user = user; | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| interface TypedResolver<S extends Schema, R extends Requirement = Requirement> { | ||
| /** | ||
| * Requirement type to handle. | ||
| * - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`) | ||
| * - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`) | ||
| */ | ||
| requirement: R["type"] | ((req: Requirement) => req is R); | ||
| /** Custom key function for deduplication */ | ||
| key?: (req: R) => string; | ||
| /** Retry policy */ | ||
| retry?: RetryPolicy; | ||
| /** Timeout for resolver execution (ms) */ | ||
| timeout?: number; | ||
| /** Batch configuration */ | ||
| batch?: BatchConfig; | ||
| /** Resolve function for single requirement */ | ||
| resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>; | ||
| /** Resolve function for batched requirements */ | ||
| resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>; | ||
| } | ||
| /** | ||
| * Create a typed constraint factory for a specific schema. | ||
| * This enables creating reusable constraint definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { count: t.number(), threshold: t.number() }; | ||
| * const factory = createConstraintFactory<typeof schema>(); | ||
| * | ||
| * const maxCountConstraint = factory.create({ | ||
| * when: (facts) => facts.count > facts.threshold, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createConstraintFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed constraint | ||
| */ | ||
| create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| }; | ||
| /** | ||
| * Create a typed resolver factory for a specific schema. | ||
| * This enables creating reusable resolver definitions with proper typing. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const schema = { user: t.object<User>() }; | ||
| * const factory = createResolverFactory<typeof schema>(); | ||
| * | ||
| * const fetchUserResolver = factory.create<FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createResolverFactory<S extends Schema>(): { | ||
| /** | ||
| * Create a typed resolver | ||
| */ | ||
| create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| }; | ||
| /** | ||
| * Type-safe constraint creator. | ||
| * Simpler alternative to createConstraintFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const constraint = typedConstraint<typeof schema, { type: "RESET" }>({ | ||
| * when: (facts) => facts.count > 100, | ||
| * require: { type: "RESET" }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>; | ||
| /** | ||
| * Type-safe resolver creator. | ||
| * Simpler alternative to createResolverFactory when you don't need a factory pattern. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const resolver = typedResolver<typeof schema, FetchUserReq>({ | ||
| * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER", | ||
| * resolve: async (req, ctx) => { | ||
| * ctx.facts.user = await fetchUser(req.userId); | ||
| * }, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>; | ||
| /** | ||
| * Schema Introspection | ||
| * | ||
| * A runtime discriminant for every `t.*()` builder result, so downstream | ||
| * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`) | ||
| * can ask "what kind is this fact?" without grepping the source. | ||
| * | ||
| * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`. | ||
| * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.) | ||
| * preserve / decorate it. When `_kind` is absent (legacy or third-party | ||
| * builder), the parser falls back to reading the freeform `_typeName` | ||
| * string. When even that fails: `{ kind: "unknown" }` — graceful close. | ||
| * | ||
| * This module has zero hot-path cost; it is only invoked when an | ||
| * introspecting caller asks for it. | ||
| */ | ||
| /** | ||
| * The closed set of kinds a Directive schema field can be. | ||
| * | ||
| * Drives operator availability via {@link getOperatorsForKind}: e.g. | ||
| * `"number"` gets the orderable operators (`$gte`, `$lte`); `"boolean"` | ||
| * does not. | ||
| */ | ||
| type SchemaKind = "number" | "string" | "boolean" | "bigint" | "date" | "array" | "object" | "record" | "tuple" | "enum" | "literal" | "union" | "branded" | "unknown"; | ||
| /** | ||
| * A tree-shaped discriminator for a schema field. Composite kinds | ||
| * (array, object, tuple, etc.) carry their element / shape information | ||
| * so an LLM-prompt builder can show "cartTotal is a number" AND | ||
| * "items is an array of { sku: string, qty: number }". | ||
| * | ||
| * `nullable` / `hasDefault` flags appear on the inner node (NOT a | ||
| * wrapping kind) so operator-lookup on `t.number().nullable()` returns | ||
| * the number's operators unchanged — `$gte` works on the non-null arm. | ||
| */ | ||
| type SchemaKindNode = ({ | ||
| kind: "number" | "string" | "boolean" | "bigint" | "date" | "unknown"; | ||
| } | { | ||
| kind: "literal"; | ||
| value: string | number | boolean | null; | ||
| primitive: "string" | "number" | "boolean" | "null"; | ||
| } | { | ||
| kind: "enum"; | ||
| values: readonly (string | number)[]; | ||
| primitive: "string" | "number"; | ||
| } | { | ||
| kind: "array"; | ||
| element: SchemaKindNode; | ||
| } | { | ||
| kind: "tuple"; | ||
| elements: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "object"; | ||
| shape: Record<string, SchemaKindNode>; | ||
| } | { | ||
| kind: "record"; | ||
| value: SchemaKindNode; | ||
| } | { | ||
| kind: "union"; | ||
| members: readonly SchemaKindNode[]; | ||
| } | { | ||
| kind: "branded"; | ||
| inner: SchemaKindNode; | ||
| }) & { | ||
| /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */ | ||
| nullable?: boolean; | ||
| /** True if the schema has a `.default()`. */ | ||
| hasDefault?: boolean; | ||
| }; | ||
| /** | ||
| * Return the {@link SchemaKindNode} for a schema field. Prefers the | ||
| * explicit `_kind` discriminant set by the builder; falls back to | ||
| * parsing the freeform `_typeName` string for legacy / third-party | ||
| * builders that don't set `_kind`. | ||
| * | ||
| * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder | ||
| * that throws on property access returns `{ kind: "unknown" }` instead of | ||
| * propagating the throw to introspecting callers. | ||
| * | ||
| * In dev mode, a function input (`typeof schema === "function"`) emits a | ||
| * warning — common foot-gun where the caller forgot to invoke a builder | ||
| * factory (e.g. wrote `t.number` instead of `t.number()`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * getKind(t.number()) // → { kind: "number" } | ||
| * getKind(t.string().nullable()) // → { kind: "string", nullable: true } | ||
| * getKind(t.array(t.number())) // → { kind: "array", element: { kind: "number" } } | ||
| * ``` | ||
| */ | ||
| declare function getKind(schema: unknown): SchemaKindNode; | ||
| /** | ||
| * Walk the `facts` block of a module schema and emit a flat map from | ||
| * dotted path → kind node. Nested `t.object()` shapes flatten using | ||
| * `.` as the separator, matching the convention used by | ||
| * `OperatorObject<V>`'s nested-path support. | ||
| * | ||
| * Passing a top-level schema directly (without the `facts:` wrapper) | ||
| * also works — anything iterable as `Record<string, ExtendedSchemaType>` | ||
| * is acceptable. | ||
| * | ||
| * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is | ||
| * silently skipped (treated as `{ kind: "unknown" }` for that field) | ||
| * rather than aborting the whole walk. | ||
| * | ||
| * In dev mode, a top-level schema that yields an empty map (no | ||
| * introspectable keys) emits a warning — common foot-gun where the | ||
| * caller passed `myModule` instead of `myModule.schema`. | ||
| */ | ||
| declare function getSchemaFieldKinds(schema: unknown): Map<string, SchemaKindNode>; | ||
| /** | ||
| * Return the set of `PredicateOp` strings that are valid against a | ||
| * given {@link SchemaKindNode}. | ||
| * | ||
| * Mirrors the type-level matrix encoded in `OperatorObject<V>` in | ||
| * `types/predicate.ts` — drift between the two is enforced by the | ||
| * compile-time conformance test | ||
| * (`schema-introspection-conformance.test-d.ts`). | ||
| * | ||
| * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists` | ||
| * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`, | ||
| * `$lt`, `$lte`, `$between` | ||
| * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains` | ||
| * - **Array:** + `$contains` (over the element type) | ||
| * - **Union:** *intersection* across members (the operand must be valid | ||
| * for every branch). | ||
| * - **Branded:** delegates to the inner kind. | ||
| * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in` | ||
| * operand restricted at the LLM-prompt layer (not enforced here). | ||
| * | ||
| * `nullable` does not change operator availability — `$gte` on a | ||
| * nullable number is fine on the non-null arm; `$exists` handles null. | ||
| */ | ||
| declare function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[]; | ||
| /** | ||
| * Return all known predicate operators — convenience for prompt builders | ||
| * that need to show the LLM the full set. | ||
| */ | ||
| declare function listAllPredicateOperators(): readonly PredicateOp[]; | ||
| /** | ||
| * Runtime for data-configuration predicates and templates. | ||
| * | ||
| * Pure module — imports only its own types. Reads facts through whatever | ||
| * object it is handed (the reactive `Facts` proxy in production, a plain | ||
| * snapshot in tests), so it never depends on the engine, store, or tracking. | ||
| */ | ||
| /** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */ | ||
| type Scope = Record<string, unknown>; | ||
| /** | ||
| * True when `v` is a data-form spec (predicate object/array) rather than a | ||
| * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.) | ||
| * — only plain `{}` literals and arrays of plain clause shapes qualify. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isPredicate({ phase: "red" }); // true | ||
| * isPredicate((f) => f.phase === "red"); // false | ||
| * isPredicate([{ fact: "phase", op: "$eq", value: "red" }]); // true | ||
| * ``` | ||
| */ | ||
| declare function isPredicate(v: unknown): boolean; | ||
| /** | ||
| * True when `v` is a {@link FactTemplate} (`{ $template: string }`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isTemplate({ $template: "Hi ${name}" }); // true | ||
| * isTemplate({ $set: { name: "x" } }); // false | ||
| * ``` | ||
| */ | ||
| declare function isTemplate(v: unknown): v is FactTemplate; | ||
| /** | ||
| * Throw when a predicate spec contains an operand that cannot survive a | ||
| * JSON round-trip — i.e. that would silently mis-evaluate if the spec was | ||
| * loaded from `JSON.parse`. | ||
| * | ||
| * Three failure classes are detected: | ||
| * | ||
| * - **Lost `RegExp` operand.** A `$matches` operand that is not a | ||
| * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as | ||
| * `{}`, so a `$matches` clause with an empty-object operand is the | ||
| * signature of a regex that did not survive serialization. Reify it | ||
| * with `new RegExp(pattern, flags)` before installing the predicate. | ||
| * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a | ||
| * `bigint` operand cannot have been produced by a JSON pipeline and | ||
| * cannot be persisted by one either. | ||
| * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all | ||
| * members; a predicate carrying one is not JSON-safe. | ||
| * | ||
| * This is an opt-in helper — the engine does not call it automatically. | ||
| * Users who load predicates from JSON should call it after `JSON.parse` | ||
| * to fail loud rather than silently mis-evaluate. See the | ||
| * "Serialization" section of RFC-0004. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * validatePredicate({ phase: { $matches: {} } }); | ||
| * // throws — empty object where a RegExp is required | ||
| * | ||
| * validatePredicate({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // ok — JSON-clean operands | ||
| * ``` | ||
| */ | ||
| declare function validatePredicate(spec: unknown, path?: string): void; | ||
| interface SchemaValidationError { | ||
| /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */ | ||
| readonly path: string; | ||
| /** The operator that failed (or the literal-equality marker `$eq`). */ | ||
| readonly op: string; | ||
| /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */ | ||
| readonly kind?: SchemaKindNode; | ||
| /** The operators that ARE allowed for this fact's kind. */ | ||
| readonly allowedOps?: readonly string[]; | ||
| /** Human-readable failure reason (suitable for feeding back to an LLM). */ | ||
| readonly reason: string; | ||
| } | ||
| interface SchemaValidationOptions { | ||
| /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */ | ||
| readonly maxOperatorCount?: number; | ||
| /** | ||
| * Reject `$in` / `$nin` operands that contain more than this many elements | ||
| * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000 | ||
| * — beyond that, a downstream query compiler may degrade quadratically. | ||
| */ | ||
| readonly maxArrayOperandLength?: number; | ||
| } | ||
| /** | ||
| * Heuristic: flag a regex source string that has obvious nested quantifiers | ||
| * (e.g. `(.+)+`, `(.*)*`, `(\w+)+`, `(a|a)+`) — the classic ReDoS shapes. | ||
| * Not a full ReDoS prover; intentionally conservative so a string-rehydrated | ||
| * `$matches` operand can be rejected before it ever reaches `RegExp.test`. | ||
| * | ||
| * Callers MUST NOT treat a `false` result as "safe" — a determined adversary | ||
| * can craft patterns this heuristic misses. The right answer for untrusted | ||
| * regex is "don't accept untrusted regex"; this helper exists to catch the | ||
| * obvious foot-guns. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * dangerousRegex("(a+)+"); // → true | ||
| * dangerousRegex("(.*)*"); // → true | ||
| * dangerousRegex("(\\w+)+"); // → true | ||
| * dangerousRegex("^[a-z]+$"); // → false | ||
| * ``` | ||
| */ | ||
| declare function dangerousRegex(source: string): boolean; | ||
| type SchemaValidationResult = { | ||
| ok: true; | ||
| operatorCount: number; | ||
| } | { | ||
| ok: false; | ||
| errors: readonly SchemaValidationError[]; | ||
| operatorCount: number; | ||
| }; | ||
| /** | ||
| * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate | ||
| * against a schema's runtime kind map. Catches errors that | ||
| * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a | ||
| * boolean fact), unknown fact paths, and (optionally) operator-count | ||
| * exhaustion DoS attempts. | ||
| * | ||
| * Pair with {@link validatePredicate} (structural / JSON safety) for full | ||
| * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a | ||
| * module schema. | ||
| * | ||
| * Designed for the LLM-emit retry loop: returns a list of errors with | ||
| * structured `{path, op, kind, allowedOps, reason}` rather than throwing, | ||
| * so the caller can feed the errors back to the model. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } }); | ||
| * const result = validatePredicateAgainstSchema( | ||
| * { cartTotal: { $gte: 50 }, active: { $gte: true } }, | ||
| * kindMap, | ||
| * ); | ||
| * // → { ok: false, errors: [{ path: "active", op: "$gte", reason: "..." }], operatorCount: 2 } | ||
| * ``` | ||
| */ | ||
| declare function validatePredicateAgainstSchema(spec: unknown, kindMap: Map<string, SchemaKindNode>, opts?: SchemaValidationOptions): SchemaValidationResult; | ||
| /** | ||
| * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous | ||
| * snapshot) is consulted only by the `$changed` operator. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicate({ phase: "red", elapsed: { $gte: 30 } }, { phase: "red", elapsed: 45 }); | ||
| * // → true | ||
| * evaluatePredicate({ $any: [{ phase: "red" }, { phase: "yellow" }] }, { phase: "green" }); | ||
| * // → false | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicate(spec: unknown, facts: Scope, prev?: Scope, depth?: number): boolean; | ||
| /** | ||
| * Evaluate a predicate and return a per-clause breakdown — the data feed for | ||
| * devtools, `system.explain()`, and `directive explain`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluatePredicateExplained( | ||
| * { phase: "red", elapsed: { $gte: 30 } }, | ||
| * { phase: "red", elapsed: 20 }, | ||
| * ); | ||
| * // → [ | ||
| * // { path: "phase", op: "$eq", expected: "red", actual: "red", pass: true }, | ||
| * // { path: "elapsed", op: "$gte", expected: 30, actual: 20, pass: false }, | ||
| * // ] | ||
| * ``` | ||
| */ | ||
| declare function evaluatePredicateExplained(spec: unknown, facts: Scope, prev?: Scope, pathPrefix?: string): ClauseResult[]; | ||
| /** | ||
| * Memoize a predicate as a reusable evaluation closure. | ||
| * | ||
| * The returned function accepts any `facts` scope (the reactive proxy in | ||
| * production, a plain object in tests) plus an optional `prev` snapshot for | ||
| * `$changed`. The closure is cached **by predicate identity** in a | ||
| * `WeakMap`, so passing the same `predicate` reference repeatedly is | ||
| * allocation-free; cleanup is automatic once the predicate is no longer | ||
| * reachable. | ||
| * | ||
| * Note: no actual compilation happens — the returned closure re-walks the | ||
| * spec on every call via `evaluatePredicate`. The name reflects what the | ||
| * function does (closure memoization keyed by predicate identity), not a | ||
| * bytecode/AST compile step. | ||
| * | ||
| * Intended for advanced users who want a stable function reference per | ||
| * predicate (custom devtools, batched analyses). Regular module code does | ||
| * not need to call this — the engine wraps data-form `when` / `on` specs | ||
| * automatically at registration. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const predicate = { phase: "red", elapsed: { $gte: 30 } }; | ||
| * const check = memoizePredicate(predicate); | ||
| * check({ phase: "red", elapsed: 45 }); // → true | ||
| * check({ phase: "red", elapsed: 5 }); // → false | ||
| * ``` | ||
| */ | ||
| declare function memoizePredicate(predicate: object): (facts: Scope, prev?: Scope) => boolean; | ||
| /** | ||
| * Collect the fact keys a predicate references. Used for static analysis, | ||
| * devtools, and effect `on` dependency wiring. Nested predicates contribute | ||
| * dotted keys (`auth.token`). | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractDeps({ phase: "red", elapsed: { $gte: 30 } }); | ||
| * // → Set { "phase", "elapsed" } | ||
| * extractDeps({ self: { phase: "red" }, auth: { token: { $exists: true } } }); | ||
| * // → Set { "self.phase", "auth.token" } | ||
| * ``` | ||
| */ | ||
| declare function extractDeps(spec: unknown, prefix?: string): Set<string>; | ||
| /** | ||
| * Interpolate a {@link FactTemplate} against a scope. Single-pass character | ||
| * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal | ||
| * `${`; unknown keys dev-warn and yield an empty string. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateTemplate({ $template: "Hi ${name}!" }, { name: "Ada" }); | ||
| * // → "Hi Ada!" | ||
| * evaluateTemplate({ $template: "$${price}" }, {}); | ||
| * // → "${price}" | ||
| * ``` | ||
| */ | ||
| declare function evaluateTemplate(spec: FactTemplate, scope: Scope): string; | ||
| /** | ||
| * Collect the placeholder keys referenced by a template. The static-analysis | ||
| * counterpart to {@link extractDeps} — useful for devtools, codegen, and | ||
| * "which facts does this template read" inspections. Only valid identifier | ||
| * placeholders are collected; malformed ones are ignored. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * extractTemplateKeys({ $template: "${firstName} ${lastName}" }); | ||
| * // → Set { "firstName", "lastName" } | ||
| * extractTemplateKeys({ $template: "$${literal}" }); | ||
| * // → Set {} (escaped — not a placeholder) | ||
| * ``` | ||
| */ | ||
| declare function extractTemplateKeys(spec: FactTemplate): Set<string>; | ||
| /** | ||
| * Build a stable dedup key by selecting fields from a requirement payload. | ||
| * Order-as-declared; values are stable-stringified (keys sorted recursively) | ||
| * so two payloads with the same fields in different orders dedupe to the | ||
| * same key. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * evaluateKeySelector(["url", "method"], { url: "/a", method: "GET" }); | ||
| * // → '"/a"|"GET"' | ||
| * evaluateKeySelector(["id"], { id: 42 }); | ||
| * // → '42' | ||
| * ``` | ||
| */ | ||
| declare function evaluateKeySelector(selector: readonly string[], source: Record<string, unknown>): string; | ||
| /** | ||
| * Apply a {@link PatchSpec} — assign facts from literals, payload copies | ||
| * (`$ref`), or interpolated strings (`$template`). Mutates through the passed | ||
| * `facts` proxy so change-tracking and downstream invalidation fire. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spec = { | ||
| * $set: { | ||
| * active: true, | ||
| * userId: { $ref: "id" }, | ||
| * label: { $template: "user ${name}" }, | ||
| * }, | ||
| * }; | ||
| * applyPatch(spec, facts, { id: "u_1", name: "Ada" }); | ||
| * // facts.active = true; facts.userId = "u_1"; facts.label = "user Ada" | ||
| * ``` | ||
| */ | ||
| declare function applyPatch(spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>, facts: Record<string, unknown>, payload: Record<string, unknown>): void; | ||
| export { type TypedResolver as A, createConstraintFactory as B, createResolverFactory as C, type DerivationDefWithMeta as D, dangerousRegex as E, type SchemaKindNode as S, type TypedConstraint as T, type DerivationDef as a, type DerivationsDef as b, type SchemaKind as c, type SchemaValidationError as d, type SchemaValidationOptions as e, type SchemaValidationResult as f, applyPatch as g, evaluateKeySelector as h, evaluatePredicate as i, evaluatePredicateExplained as j, evaluateTemplate as k, extractDeps as l, extractTemplateKeys as m, getKind as n, getOperatorsForKind as o, getSchemaFieldKinds as p, isPredicate as q, isTemplate as r, listAllPredicateOperators as s, memoizePredicate as t, typedConstraint as u, typedResolver as v, validatePredicate as w, validatePredicateAgainstSchema as x, type DerivedValues as y, type DerivationState as z }; |
| 'use strict';var chunk4OXCKDKS_cjs=require('./chunk-4OXCKDKS.cjs');require('./chunk-M5PEB553.cjs'),require('./chunk-GACC2DMS.cjs'),require('./chunk-GKMJ7NMP.cjs'),require('./chunk-GBCWXTXW.cjs');Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunk4OXCKDKS_cjs.a}});//# sourceMappingURL=system-SB7JYMRB.cjs.map | ||
| //# sourceMappingURL=system-SB7JYMRB.cjs.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"system-SB7JYMRB.cjs"} |
| export{a as createSystem}from'./chunk-E53A4NHM.js';import'./chunk-6QAUJFQH.js';import'./chunk-RBF653NR.js';import'./chunk-6PF2FRBG.js';import'./chunk-SFUVPP4L.js';//# sourceMappingURL=system-SJBP4TO5.js.map | ||
| //# sourceMappingURL=system-SJBP4TO5.js.map |
| {"version":3,"sources":[],"names":[],"mappings":"","file":"system-SJBP4TO5.js"} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 2 instances
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 2 instances
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
5166591
1.38%13323
1.83%8
-11.11%