@directive-run/core 1.12.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-utils.cjs +1 -1
- package/dist/adapter-utils.d.cts +2 -2
- package/dist/adapter-utils.d.ts +2 -2
- package/dist/adapter-utils.js +1 -1
- package/dist/adapter-utils.js.map +1 -1
- package/dist/audit-ledger-Dc6hAXam.d.cts +378 -0
- package/dist/audit-ledger-dxvslGi3.d.ts +378 -0
- package/dist/chunk-2FF6QGOA.js +2 -0
- package/dist/chunk-2FF6QGOA.js.map +1 -0
- package/dist/chunk-4MNQDXH7.cjs +3 -0
- package/dist/chunk-4MNQDXH7.cjs.map +1 -0
- package/dist/chunk-644QZVTT.js +16 -0
- package/dist/{chunk-26Z5VNPZ.js.map → chunk-644QZVTT.js.map} +1 -1
- package/dist/chunk-ENZEHIL7.cjs +3 -0
- package/dist/chunk-ENZEHIL7.cjs.map +1 -0
- package/dist/chunk-I722BZA5.js +7 -0
- package/dist/chunk-I722BZA5.js.map +1 -0
- package/dist/chunk-IXRS4LM4.cjs +2 -0
- package/dist/chunk-IXRS4LM4.cjs.map +1 -0
- package/dist/chunk-NPX5EKPP.cjs +16 -0
- package/dist/{chunk-EX3XG667.cjs.map → chunk-NPX5EKPP.cjs.map} +1 -1
- package/dist/chunk-PA6VC32N.js +2 -0
- package/dist/chunk-PA6VC32N.js.map +1 -0
- package/dist/chunk-PXRV64PA.js +3 -0
- package/dist/chunk-PXRV64PA.js.map +1 -0
- package/dist/chunk-R2GHSCTR.js +3 -0
- package/dist/chunk-R2GHSCTR.js.map +1 -0
- package/dist/chunk-T4TRJEJN.cjs +2 -0
- package/dist/chunk-T4TRJEJN.cjs.map +1 -0
- package/dist/chunk-X7G7UBXU.cjs +7 -0
- package/dist/chunk-X7G7UBXU.cjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +214 -391
- package/dist/index.d.ts +214 -391
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +1 -1
- package/dist/internals.d.cts +5 -5
- package/dist/internals.d.ts +5 -5
- package/dist/internals.js +1 -1
- package/dist/plugins/index.cjs +2 -2
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.d.cts +2 -2
- package/dist/plugins/index.d.ts +2 -2
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/{plugins-Ykl_sAPE.d.ts → plugins-BIzXaYbg.d.cts} +15 -1
- package/dist/{plugins-Ykl_sAPE.d.cts → plugins-BIzXaYbg.d.ts} +15 -1
- package/dist/predicate-Bnx3LN7P.d.cts +655 -0
- package/dist/predicate-BxQVf0ug.d.ts +655 -0
- package/dist/system-A6VYKLVF.js +2 -0
- package/dist/{system-VZWB6WXX.js.map → system-A6VYKLVF.js.map} +1 -1
- package/dist/system-CDJMD5O5.cjs +2 -0
- package/dist/{system-GK3NSFQH.cjs.map → system-CDJMD5O5.cjs.map} +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/{utils-BnQajqPu.d.cts → utils-Mg55IerF.d.cts} +27 -1
- package/dist/{utils-BnQajqPu.d.ts → utils-Mg55IerF.d.ts} +27 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/audit-ledger-9IElAHH9.d.ts +0 -205
- package/dist/audit-ledger-qMjEBqiP.d.cts +0 -205
- package/dist/chunk-26Z5VNPZ.js +0 -16
- package/dist/chunk-4VZOZWXM.cjs +0 -2
- package/dist/chunk-4VZOZWXM.cjs.map +0 -1
- package/dist/chunk-7NMXRATK.cjs +0 -3
- package/dist/chunk-7NMXRATK.cjs.map +0 -1
- package/dist/chunk-7TSYQEN3.js +0 -2
- package/dist/chunk-7TSYQEN3.js.map +0 -1
- package/dist/chunk-EOLY64E6.cjs +0 -3
- package/dist/chunk-EOLY64E6.cjs.map +0 -1
- package/dist/chunk-EX3XG667.cjs +0 -16
- package/dist/chunk-N4KTCKOI.cjs +0 -7
- package/dist/chunk-N4KTCKOI.cjs.map +0 -1
- package/dist/chunk-T6IJUWYR.js +0 -3
- package/dist/chunk-T6IJUWYR.js.map +0 -1
- package/dist/chunk-TPOKS4RY.js +0 -3
- package/dist/chunk-TPOKS4RY.js.map +0 -1
- package/dist/chunk-TZHC4E6S.js +0 -7
- package/dist/chunk-TZHC4E6S.js.map +0 -1
- package/dist/helpers-D2pfb6vT.d.ts +0 -235
- package/dist/helpers-hh6UanB1.d.cts +0 -235
- package/dist/system-GK3NSFQH.cjs +0 -2
- package/dist/system-VZWB6WXX.js +0 -2
package/dist/chunk-TZHC4E6S.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
var a=typeof process<"u"&&process.env?.NODE_ENV!=="production";function u(e,t,r){e[t]=r;}function d(e,t){return e[t]}function p(e,t){return {name:e,onRequirementCreated:t.onRequirementCreated?r=>t.onRequirementCreated(r.requirement):void 0,onRequirementMet:t.onRequirementResolved?r=>t.onRequirementResolved(r.requirement):void 0,onError:t.onError}}function f(e){return t=>t.type===e}function m(e){let t=new Set(e);return r=>t.has(r.type)}var n=[];function R(){let e=n.length;return e===0?null:n[e-1]}function S(){return n.length>0}function g(e){let t=new Set;n.push(t);try{return {value:e(),deps:t}}finally{n.pop();}}function x(e){let t=n.splice(0,n.length);try{return e()}finally{for(let r of t)n.push(r);}}function q(e){let t=n.length;t!==0&&n[t-1].add(e);}var y=Object.freeze(new Set(["__proto__","constructor","prototype"]));function h(e){if(e===null||typeof e!="object")return null;if(e instanceof Date)return "Date";if(e instanceof Set)return "Set";if(e instanceof Map)return "Map";if(typeof File<"u"&&e instanceof File)return "File";if(Array.isArray(e))return null;let t=Object.getPrototypeOf(e);return t!==null&&t!==Object.prototype?"ClassInstance":null}var o=new Set,s={Date:".getTime() for timestamps",Set:"[...set] for arrays",Map:"Object.fromEntries(map) for plain objects",File:"{ name, size, type, lastModified } for metadata",ClassInstance:"a plain-object snapshot"};function C(e,t){let r=`${e}|${t}`;if(o.has(r))return;o.add(r);let i=s[t]??"a JSON-roundtrippable value";console.warn(`[Directive] Fact "${e}" assigned a ${t} instance.
|
|
2
|
-
Facts must be JSON-roundtrippable for reactivity to work correctly.
|
|
3
|
-
${t} mutations are not tracked.
|
|
4
|
-
Use ${i} instead.
|
|
5
|
-
See: https://directive.run/docs/facts#json-rule`);}
|
|
6
|
-
export{a,u as b,d as c,p as d,f as e,m as f,R as g,S as h,g as i,x as j,q as k,y as l,h as m,C as n};//# sourceMappingURL=chunk-TZHC4E6S.js.map
|
|
7
|
-
//# sourceMappingURL=chunk-TZHC4E6S.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev-true.ts","../src/core/types/adapter-utils.ts","../src/core/tracking.ts"],"names":["dev_true_default","setBridgeFact","facts","key","value","getBridgeFact","createCallbackPlugin","name","callbacks","req","requirementGuard","type","requirementGuardMultiple","types","typeSet","depStack","getCurrentDeps","len","isTracking","withTracking","fn","deps","withoutTracking","saved","ctx","trackAccess","BLOCKED_PROPS","detectNonJsonValueType","proto","nonJsonWarningCache","nonJsonHints","warnNonJsonFactAssignment","factPath","valueType","cacheKey","hint"],"mappings":"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","file":"chunk-TZHC4E6S.js","sourcesContent":["// Runtime check that bundlers (webpack, esbuild, turbopack, rollup) inline\n// based on the consumer's NODE_ENV. Without this, the published bundle bakes\n// in `true` and dev-mode validation runs in every consumer's production\n// build — a real footgun the v1.5/v1.6 release hit.\nexport default typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n","/**\n * Adapter Type Utilities - Shared types and helpers for framework adapters\n *\n * These utilities reduce type assertions in adapters by providing:\n * - Schema composition types\n * - Constraint/resolver converters\n * - Plugin factory helpers\n */\n\nimport type { Facts } from \"./facts.js\";\nimport type { Plugin } from \"./plugins.js\";\nimport type { ConstraintDef, Requirement } from \"./requirements.js\";\nimport type { ResolverContext, ResolverDef } from \"./resolvers.js\";\nimport type { InferSchema, Schema } from \"./schema.js\";\n\n// ============================================================================\n// Schema Composition Types\n// ============================================================================\n\n/**\n * Merge two schemas into one.\n * Useful for adapters that add bridge-specific facts to user schemas.\n *\n * @example\n * ```typescript\n * type BridgeFields = { __state: SchemaType<Record<string, unknown>> };\n * type Combined = MergedSchema<UserSchema, BridgeFields>;\n * ```\n */\nexport type MergedSchema<Base extends Schema, Extra extends Schema> = Base &\n Extra;\n\n/**\n * Create a schema type from a fields definition.\n * Helper for defining adapter bridge schemas.\n *\n * @example\n * ```typescript\n * type AdapterBridgeSchema = BridgeSchema<{\n * __adapterState: SchemaType<Record<string, unknown>>;\n * }>;\n * ```\n */\nexport type BridgeSchema<Fields extends Schema> = Fields;\n\n// ============================================================================\n// Bridge Schema Helper\n// ============================================================================\n\n/**\n * Create a bridge schema definition for adapters.\n * Returns a schema object compatible with createModule().\n *\n * @example\n * ```typescript\n * const bridgeSchema = createBridgeSchema({\n * __state: t.object<Record<string, unknown>>(),\n * });\n * ```\n */\nexport function createBridgeSchema<S extends Schema>(schema: S): S {\n return schema;\n}\n\n// ============================================================================\n// Type-Safe Fact Mutation\n// ============================================================================\n\n/**\n * Type-safe fact setter for known schema keys.\n * Use when you have a typed schema and want to set a specific fact.\n *\n * @example\n * ```typescript\n * setFact(facts, \"count\", 10); // Type-checked\n * ```\n */\nexport function setFact<S extends Schema, K extends keyof InferSchema<S>>(\n facts: Facts<S>,\n key: K,\n value: InferSchema<S>[K],\n): void {\n (facts as Record<string, unknown>)[key as string] = value;\n}\n\n/**\n * Set a bridge fact without strict typing.\n * Use for adapter-internal bridge fields like `__adapterState`.\n *\n * @example\n * ```typescript\n * setBridgeFact(facts, \"__adapterState\", currentState);\n * ```\n */\nexport function setBridgeFact<V>(\n facts: Facts<Schema>,\n key: string,\n value: V,\n): void {\n (facts as Record<string, unknown>)[key] = value;\n}\n\n/**\n * Get a bridge fact without strict typing.\n * Use for adapter-internal bridge fields.\n *\n * @example\n * ```typescript\n * const state = getBridgeFact<MyState>(facts, \"__adapterState\");\n * ```\n */\nexport function getBridgeFact<V>(facts: Facts<Schema>, key: string): V {\n return (facts as Record<string, unknown>)[key] as V;\n}\n\n// ============================================================================\n// Constraint Converters\n// ============================================================================\n\n/**\n * Adapter constraint definition (generic form used by adapters).\n */\nexport interface AdapterConstraint<TState> {\n when: (state: TState) => boolean | Promise<boolean>;\n require: Requirement | ((state: TState) => Requirement | null);\n priority?: number;\n}\n\n/**\n * Convert adapter-style constraints to Directive format.\n * Maps adapter constraints that work with external state (TState) to\n * Directive constraints that work with Facts<Schema>.\n *\n * @param constraints - Adapter constraints keyed by name\n * @param extractState - Function to extract adapter state from facts\n *\n * @example\n * ```typescript\n * const directiveConstraints = convertConstraints<MyState, BridgeSchema>(\n * adapterConstraints,\n * (facts) => getBridgeFact<MyState>(facts, \"__state\"),\n * );\n * ```\n */\nexport function convertConstraints<TState, S extends Schema>(\n constraints: Record<string, AdapterConstraint<TState>>,\n extractState: (facts: Facts<S>) => TState,\n): Record<string, ConstraintDef<S, Requirement>> {\n const result: Record<string, ConstraintDef<S, Requirement>> = {};\n\n for (const [id, constraint] of Object.entries(constraints)) {\n result[id] = {\n priority: constraint.priority ?? 0,\n when: (facts) => constraint.when(extractState(facts)),\n require: (facts) => {\n const req =\n typeof constraint.require === \"function\"\n ? constraint.require(extractState(facts))\n : constraint.require;\n return req;\n },\n };\n }\n\n return result;\n}\n\n// ============================================================================\n// Resolver Converters\n// ============================================================================\n\n/**\n * Adapter resolver context (generic form used by adapters).\n */\nexport interface AdapterResolverContext<TContext> {\n context: TContext;\n signal: AbortSignal;\n}\n\n/**\n * Adapter resolver definition (generic form used by adapters).\n */\nexport interface AdapterResolver<\n TContext,\n R extends Requirement = Requirement,\n> {\n requirement: (req: Requirement) => req is R;\n key?: (req: R) => string;\n resolve: (\n req: R,\n ctx: AdapterResolverContext<TContext>,\n ) => void | Promise<void>;\n}\n\n/**\n * Convert adapter-style resolvers to Directive format.\n * Maps adapter resolvers that work with external context (TContext) to\n * Directive resolvers that work with ResolverContext<Schema>.\n *\n * @param resolvers - Adapter resolvers keyed by name\n * @param createContext - Function to create adapter context from Directive context\n *\n * @example\n * ```typescript\n * const directiveResolvers = convertResolvers<MyContext, BridgeSchema>(\n * adapterResolvers,\n * (ctx) => ({\n * getState: () => getBridgeFact<MyState>(ctx.facts, \"__state\"),\n * setState: (update) => setBridgeFact(ctx.facts, \"__state\", update),\n * signal: ctx.signal,\n * }),\n * );\n * ```\n */\nexport function convertResolvers<TContext, S extends Schema>(\n resolvers: Record<string, AdapterResolver<TContext, Requirement>>,\n createContext: (ctx: ResolverContext<S>) => TContext,\n): Record<string, ResolverDef<S, Requirement>> {\n const result: Record<string, ResolverDef<S, Requirement>> = {};\n\n for (const [id, resolver] of Object.entries(resolvers)) {\n result[id] = {\n requirement: resolver.requirement,\n key: resolver.key,\n resolve: async (req, ctx) => {\n const adapterCtx = createContext(ctx);\n await resolver.resolve(req, {\n context: adapterCtx,\n signal: ctx.signal,\n });\n },\n };\n }\n\n return result;\n}\n\n// ============================================================================\n// Plugin Factory\n// ============================================================================\n\n/**\n * Callback definitions for adapter plugins.\n */\nexport interface AdapterCallbacks {\n onRequirementCreated?: (req: Requirement) => void;\n onRequirementResolved?: (req: Requirement) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Create a callback plugin for adapter events.\n * Wraps adapter callbacks in a Directive plugin.\n *\n * @param name - Plugin name (for debugging)\n * @param callbacks - Callback functions to invoke\n *\n * @example\n * ```typescript\n * const callbackPlugin = createCallbackPlugin(\"adapter-callbacks\", {\n * onRequirementCreated: (req) => console.log(\"Created:\", req),\n * onRequirementResolved: (req) => console.log(\"Resolved:\", req),\n * });\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: Plugins work with any schema type\nexport function createCallbackPlugin(\n name: string,\n callbacks: AdapterCallbacks,\n): Plugin<any> {\n return {\n name,\n onRequirementCreated: callbacks.onRequirementCreated\n ? (req) => callbacks.onRequirementCreated!(req.requirement)\n : undefined,\n onRequirementMet: callbacks.onRequirementResolved\n ? (req) => callbacks.onRequirementResolved!(req.requirement)\n : undefined,\n onError: callbacks.onError,\n };\n}\n\n// ============================================================================\n// Module Config Helpers\n// ============================================================================\n\n/**\n * Cast constraints to the correct type for createModule.\n * Use this when TypeScript can't infer the constraint types correctly.\n */\nexport function asConstraints<S extends Schema>(\n constraints: Record<string, ConstraintDef<S, Requirement>>,\n): Record<string, ConstraintDef<S, Requirement>> {\n return constraints;\n}\n\n/**\n * Cast resolvers to the correct type for createModule.\n * Use this when TypeScript can't infer the resolver types correctly.\n */\nexport function asResolvers<S extends Schema>(\n resolvers: Record<string, ResolverDef<S, Requirement>>,\n): Record<string, ResolverDef<S, Requirement>> {\n return resolvers;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Create a type guard for a specific requirement type.\n * Simplifies the common pattern of checking req.type.\n *\n * @example\n * ```typescript\n * const isResetReq = requirementGuard<ResetReq>(\"RESET\");\n * // Use in resolver:\n * { requirement: isResetReq, resolve: ... }\n * ```\n */\nexport function requirementGuard<R extends Requirement>(\n type: R[\"type\"],\n): (req: Requirement) => req is R {\n return (req): req is R => req.type === type;\n}\n\n/**\n * Create a type guard that matches multiple requirement types.\n *\n * @example\n * ```typescript\n * const isDataReq = requirementGuardMultiple<FetchReq | RefreshReq>([\"FETCH\", \"REFRESH\"]);\n * ```\n */\nexport function requirementGuardMultiple<R extends Requirement>(\n types: Array<R[\"type\"]>,\n): (req: Requirement) => req is R {\n const typeSet = new Set(types);\n return (req): req is R => typeSet.has(req.type);\n}\n","/**\n * Dependency tracking context for auto-tracking derivations\n *\n * Uses a stack-based approach to handle nested derivation computations.\n * When a derivation accesses a fact, the tracking context records it.\n */\n\n/** Stack of active dependency sets (bare Sets for zero-allocation hot path) */\nconst depStack: Set<string>[] = [];\n\n/**\n * Get the current dependency set, or null if not tracking.\n *\n * @returns The active dependency Set, or `null` if no tracking is active.\n *\n * @internal\n */\nexport function getCurrentDeps(): Set<string> | null {\n const len = depStack.length;\n return len === 0 ? null : depStack[len - 1]!;\n}\n\n/**\n * Check if dependency tracking is currently active.\n *\n * @returns `true` if inside a {@link withTracking} call, `false` otherwise.\n *\n * @internal\n */\nexport function isTracking(): boolean {\n return depStack.length > 0;\n}\n\n/**\n * Run a function with dependency tracking.\n *\n * @remarks\n * Pushes a fresh Set onto the stack, executes `fn`, then pops it.\n * Any fact reads inside `fn` are recorded as dependencies.\n * Nesting is supported — inner calls get their own independent Set.\n *\n * @param fn - The function to execute under tracking.\n * @returns An object with the computed `value` and a `deps` Set of accessed\n * fact keys.\n *\n * @internal\n */\nexport function withTracking<T>(fn: () => T): { value: T; deps: Set<string> } {\n const deps = new Set<string>();\n depStack.push(deps);\n\n try {\n const value = fn();\n return { value, deps };\n } finally {\n depStack.pop();\n }\n}\n\n/**\n * Run a function without tracking.\n *\n * @remarks\n * Temporarily clears the tracking stack so that fact reads inside `fn` do\n * not register as dependencies. The stack is restored after `fn` returns\n * (even on error). Useful for side-effect reads that should not trigger\n * derivation invalidation.\n *\n * @param fn - The function to execute without tracking.\n * @returns The return value of `fn`.\n *\n * @internal\n */\nexport function withoutTracking<T>(fn: () => T): T {\n const saved = depStack.splice(0, depStack.length);\n\n try {\n return fn();\n } finally {\n for (const ctx of saved) {\n depStack.push(ctx);\n }\n }\n}\n\n/**\n * Track a specific key in the current context.\n *\n * @remarks\n * No-op if no tracking context is active.\n *\n * @param key - The fact key to record as a dependency.\n *\n * @internal\n */\nexport function trackAccess(key: string): void {\n const len = depStack.length;\n if (len === 0) {\n return;\n }\n depStack[len - 1]!.add(key);\n}\n\n/**\n * Prototype pollution guard — shared across all proxy handlers.\n *\n * @remarks\n * Contains `__proto__`, `constructor`, and `prototype`. Every proxy `get`\n * and `has` trap checks this set and returns `undefined` / `false` for\n * matching keys, preventing prototype pollution via proxy-based objects.\n *\n * @internal\n */\nexport const BLOCKED_PROPS: ReadonlySet<string> = Object.freeze(\n new Set([\"__proto__\", \"constructor\", \"prototype\"]),\n);\n\n// ============================================================================\n// Non-JSON value-type detection (MIGRATION_FEEDBACK item 20)\n// ============================================================================\n\n/**\n * Detect whether `value` is a non-JSON-roundtrippable type whose mutations\n * the facts proxy cannot track for reactivity.\n *\n * Returns the kind label (`\"Date\"`, `\"Set\"`, `\"Map\"`, `\"File\"`, or\n * `\"ClassInstance\"`) when one is detected, or `null` for plain objects,\n * arrays, primitives, and `null`/`undefined`.\n *\n * The `File` check is SSR-safe: if the runtime has no `File` global the\n * branch is skipped without throwing.\n *\n * The `ClassInstance` check fires for any object whose prototype is not\n * `Object.prototype` and which is not an array — e.g. instances of user\n * classes whose mutations bypass reactivity.\n *\n * @internal\n */\nexport function detectNonJsonValueType(value: unknown): string | null {\n if (value === null || typeof value !== \"object\") {\n return null;\n }\n if (value instanceof Date) {\n return \"Date\";\n }\n if (value instanceof Set) {\n return \"Set\";\n }\n if (value instanceof Map) {\n return \"Map\";\n }\n if (typeof File !== \"undefined\" && value instanceof File) {\n return \"File\";\n }\n // Plain objects and arrays are JSON-friendly.\n if (Array.isArray(value)) {\n return null;\n }\n // Class instances: prototype is not Object.prototype.\n // Plain `{}` literals have prototype `Object.prototype`; objects created\n // via `Object.create(null)` have a `null` prototype which we treat as\n // \"plain\" (it's still JSON-roundtrippable).\n const proto = Object.getPrototypeOf(value);\n if (proto !== null && proto !== Object.prototype) {\n return \"ClassInstance\";\n }\n\n return null;\n}\n\n/**\n * Per-(path, valueType) dedupe cache — once a warning fires for a given\n * combo we never re-emit. Keeps the dev console quiet under loops that\n * assign the same Date 100 times in a row.\n *\n * @internal\n */\nconst nonJsonWarningCache = new Set<string>();\n\nconst nonJsonHints: Record<string, string> = {\n Date: \".getTime() for timestamps\",\n Set: \"[...set] for arrays\",\n Map: \"Object.fromEntries(map) for plain objects\",\n File: \"{ name, size, type, lastModified } for metadata\",\n ClassInstance: \"a plain-object snapshot\",\n};\n\n/**\n * Emit a one-time dev-mode warning when a non-JSON value is assigned to a\n * fact. Called from the proxy `set` traps in both `createFactsProxy`\n * (single-module / standalone facts) and `createModuleFactsProxy`\n * (system-namespaced facts). No-ops in production builds — the call sites\n * are gated on `isDevelopment` so this entire helper is tree-shakable.\n *\n * @param factPath - Display path for the warning (e.g. `auth.token` or\n * bare `token` for non-namespaced stores).\n * @param valueType - The label returned from {@link detectNonJsonValueType}.\n *\n * @internal\n */\nexport function warnNonJsonFactAssignment(\n factPath: string,\n valueType: string,\n): void {\n const cacheKey = `${factPath}|${valueType}`;\n if (nonJsonWarningCache.has(cacheKey)) {\n return;\n }\n nonJsonWarningCache.add(cacheKey);\n\n const hint = nonJsonHints[valueType] ?? \"a JSON-roundtrippable value\";\n console.warn(\n `[Directive] Fact \"${factPath}\" assigned a ${valueType} instance.\\n` +\n `Facts must be JSON-roundtrippable for reactivity to work correctly.\\n` +\n `${valueType} mutations are not tracked.\\n` +\n `Use ${hint} instead.\\n` +\n `See: https://directive.run/docs/facts#json-rule`,\n );\n}\n\n/**\n * Reset the warning dedupe cache. Test-only — exported via internals for\n * vitest spec setup. Not part of the public API.\n *\n * @internal\n */\nexport function _resetNonJsonWarningCache(): void {\n nonJsonWarningCache.clear();\n}\n"]}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { a8 as Schema, c as Facts, b as FactPredicate, aS as InferSchema, F as FactTemplate, D as DefinitionMeta, t as Requirement, b9 as RequirementOutput, a7 as RetryPolicy, B as BatchConfig, b0 as ResolverContext } from './plugins-Ykl_sAPE.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Derivation Types - Type definitions for derivations
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Derivation definition function signature. */
|
|
8
|
-
interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> {
|
|
9
|
-
(facts: Facts<S>, derived: DerivedValues<S, D>): T;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Derivation definition with metadata (object form).
|
|
13
|
-
* Use this when you want to attach debugging metadata to a derivation.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* derive: {
|
|
18
|
-
* displayName: {
|
|
19
|
-
* compute: (facts) => `${facts.firstName} ${facts.lastName}`,
|
|
20
|
-
* meta: { label: "Display Name", description: "Full name for UI" },
|
|
21
|
-
* },
|
|
22
|
-
* },
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> {
|
|
26
|
-
/**
|
|
27
|
-
* The derivation body. Either:
|
|
28
|
-
* - a function `(facts, derived) => T` (original form), or
|
|
29
|
-
* - a {@link FactPredicate} data spec — boolean derivations only, or
|
|
30
|
-
* - a {@link FactTemplate} `{ $template: "..." }` — string derivations only.
|
|
31
|
-
*
|
|
32
|
-
* Data forms are normalized to a wrapper function at registration; the
|
|
33
|
-
* wrapper reads through the facts proxy so existing auto-tracking
|
|
34
|
-
* captures dependencies.
|
|
35
|
-
*/
|
|
36
|
-
compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never);
|
|
37
|
-
meta?: DefinitionMeta;
|
|
38
|
-
}
|
|
39
|
-
/** Map of derivation definitions (internal — always bare functions after unwrap). */
|
|
40
|
-
type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>;
|
|
41
|
-
/** Computed derived values. */
|
|
42
|
-
type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = {
|
|
43
|
-
readonly [K in keyof D]: ReturnType<D[K]>;
|
|
44
|
-
};
|
|
45
|
-
/** Internal derivation state */
|
|
46
|
-
interface DerivationState<T> {
|
|
47
|
-
id: string;
|
|
48
|
-
compute: () => T;
|
|
49
|
-
cachedValue: T | undefined;
|
|
50
|
-
dependencies: Set<string>;
|
|
51
|
-
isStale: boolean;
|
|
52
|
-
isComputing: boolean;
|
|
53
|
-
/** Consecutive runs producing the same deps (auto-tracked only) */
|
|
54
|
-
stableRunCount: number;
|
|
55
|
-
/** Once true, skip withTracking() overhead until a tracked fact mutates */
|
|
56
|
-
depsStable: boolean;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Type Helpers - External typed constraint and resolver definitions
|
|
61
|
-
*
|
|
62
|
-
* These types enable defining constraints and resolvers with full type safety
|
|
63
|
-
* outside of module definitions, while maintaining proper type inference.
|
|
64
|
-
*/
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* External constraint definition with full typing.
|
|
68
|
-
* Use this when defining constraints outside of createModule().
|
|
69
|
-
*
|
|
70
|
-
* @typeParam S - The schema type
|
|
71
|
-
* @typeParam R - The requirement type (defaults to Requirement)
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* // Define a typed constraint factory
|
|
76
|
-
* const createMaxCountConstraint = <S extends Schema>(
|
|
77
|
-
* maxCount: number
|
|
78
|
-
* ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({
|
|
79
|
-
* priority: 10,
|
|
80
|
-
* when: (facts) => (facts as { count: number }).count > maxCount,
|
|
81
|
-
* require: { type: "RESET_COUNT" },
|
|
82
|
-
* });
|
|
83
|
-
*
|
|
84
|
-
* // Use in module
|
|
85
|
-
* const module = createModule("counter", {
|
|
86
|
-
* schema: { count: t.number() },
|
|
87
|
-
* constraints: {
|
|
88
|
-
* maxCount: createMaxCountConstraint(100),
|
|
89
|
-
* },
|
|
90
|
-
* });
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
|
-
interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> {
|
|
94
|
-
/** Priority for ordering (higher runs first) */
|
|
95
|
-
priority?: number;
|
|
96
|
-
/** Mark this constraint as async (avoids runtime detection) */
|
|
97
|
-
async?: boolean;
|
|
98
|
-
/** Condition function (sync or async) */
|
|
99
|
-
when: (facts: Facts<S>) => boolean | Promise<boolean>;
|
|
100
|
-
/**
|
|
101
|
-
* Requirement(s) to produce when condition is met.
|
|
102
|
-
*/
|
|
103
|
-
require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>);
|
|
104
|
-
/** Timeout for async constraints (ms) */
|
|
105
|
-
timeout?: number;
|
|
106
|
-
/**
|
|
107
|
-
* Constraint IDs whose resolvers must complete before this constraint is evaluated.
|
|
108
|
-
* - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for)
|
|
109
|
-
* - If dependency's resolver fails, this constraint remains blocked until it succeeds
|
|
110
|
-
* - Cross-module: use the constraint ID as it appears in the merged system
|
|
111
|
-
*/
|
|
112
|
-
after?: string[];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* External resolver definition with full typing.
|
|
116
|
-
* Use this when defining resolvers outside of createModule().
|
|
117
|
-
*
|
|
118
|
-
* @typeParam S - The schema type
|
|
119
|
-
* @typeParam R - The requirement type (defaults to Requirement)
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```typescript
|
|
123
|
-
* // Define a typed resolver factory
|
|
124
|
-
* interface FetchUserReq extends Requirement {
|
|
125
|
-
* type: "FETCH_USER";
|
|
126
|
-
* userId: string;
|
|
127
|
-
* }
|
|
128
|
-
*
|
|
129
|
-
* const createFetchUserResolver = <S extends Schema>(
|
|
130
|
-
* fetchFn: (userId: string) => Promise<User>
|
|
131
|
-
* ): TypedResolver<S, FetchUserReq> => ({
|
|
132
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
133
|
-
* key: (req) => `fetch-user-${req.userId}`,
|
|
134
|
-
* retry: { attempts: 3, backoff: "exponential" },
|
|
135
|
-
* resolve: async (req, ctx) => {
|
|
136
|
-
* const user = await fetchFn(req.userId);
|
|
137
|
-
* (ctx.facts as { user: User }).user = user;
|
|
138
|
-
* },
|
|
139
|
-
* });
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
interface TypedResolver<S extends Schema, R extends Requirement = Requirement> {
|
|
143
|
-
/**
|
|
144
|
-
* Requirement type to handle.
|
|
145
|
-
* - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`)
|
|
146
|
-
* - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`)
|
|
147
|
-
*/
|
|
148
|
-
requirement: R["type"] | ((req: Requirement) => req is R);
|
|
149
|
-
/** Custom key function for deduplication */
|
|
150
|
-
key?: (req: R) => string;
|
|
151
|
-
/** Retry policy */
|
|
152
|
-
retry?: RetryPolicy;
|
|
153
|
-
/** Timeout for resolver execution (ms) */
|
|
154
|
-
timeout?: number;
|
|
155
|
-
/** Batch configuration */
|
|
156
|
-
batch?: BatchConfig;
|
|
157
|
-
/** Resolve function for single requirement */
|
|
158
|
-
resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>;
|
|
159
|
-
/** Resolve function for batched requirements */
|
|
160
|
-
resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Create a typed constraint factory for a specific schema.
|
|
164
|
-
* This enables creating reusable constraint definitions with proper typing.
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```typescript
|
|
168
|
-
* const schema = { count: t.number(), threshold: t.number() };
|
|
169
|
-
* const factory = createConstraintFactory<typeof schema>();
|
|
170
|
-
*
|
|
171
|
-
* const maxCountConstraint = factory.create({
|
|
172
|
-
* when: (facts) => facts.count > facts.threshold,
|
|
173
|
-
* require: { type: "RESET" },
|
|
174
|
-
* });
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
declare function createConstraintFactory<S extends Schema>(): {
|
|
178
|
-
/**
|
|
179
|
-
* Create a typed constraint
|
|
180
|
-
*/
|
|
181
|
-
create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
|
|
182
|
-
};
|
|
183
|
-
/**
|
|
184
|
-
* Create a typed resolver factory for a specific schema.
|
|
185
|
-
* This enables creating reusable resolver definitions with proper typing.
|
|
186
|
-
*
|
|
187
|
-
* @example
|
|
188
|
-
* ```typescript
|
|
189
|
-
* const schema = { user: t.object<User>() };
|
|
190
|
-
* const factory = createResolverFactory<typeof schema>();
|
|
191
|
-
*
|
|
192
|
-
* const fetchUserResolver = factory.create<FetchUserReq>({
|
|
193
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
194
|
-
* resolve: async (req, ctx) => {
|
|
195
|
-
* ctx.facts.user = await fetchUser(req.userId);
|
|
196
|
-
* },
|
|
197
|
-
* });
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
declare function createResolverFactory<S extends Schema>(): {
|
|
201
|
-
/**
|
|
202
|
-
* Create a typed resolver
|
|
203
|
-
*/
|
|
204
|
-
create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
|
|
205
|
-
};
|
|
206
|
-
/**
|
|
207
|
-
* Type-safe constraint creator.
|
|
208
|
-
* Simpler alternative to createConstraintFactory when you don't need a factory pattern.
|
|
209
|
-
*
|
|
210
|
-
* @example
|
|
211
|
-
* ```typescript
|
|
212
|
-
* const constraint = typedConstraint<typeof schema, { type: "RESET" }>({
|
|
213
|
-
* when: (facts) => facts.count > 100,
|
|
214
|
-
* require: { type: "RESET" },
|
|
215
|
-
* });
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
|
|
219
|
-
/**
|
|
220
|
-
* Type-safe resolver creator.
|
|
221
|
-
* Simpler alternative to createResolverFactory when you don't need a factory pattern.
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const resolver = typedResolver<typeof schema, FetchUserReq>({
|
|
226
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
227
|
-
* resolve: async (req, ctx) => {
|
|
228
|
-
* ctx.facts.user = await fetchUser(req.userId);
|
|
229
|
-
* },
|
|
230
|
-
* });
|
|
231
|
-
* ```
|
|
232
|
-
*/
|
|
233
|
-
declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
|
|
234
|
-
|
|
235
|
-
export { type DerivationDefWithMeta as D, type TypedConstraint as T, typedResolver as a, type DerivationsDef as b, type DerivedValues as c, type DerivationState as d, type TypedResolver as e, createConstraintFactory as f, createResolverFactory as g, typedConstraint as t };
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { a8 as Schema, c as Facts, b as FactPredicate, aS as InferSchema, F as FactTemplate, D as DefinitionMeta, t as Requirement, b9 as RequirementOutput, a7 as RetryPolicy, B as BatchConfig, b0 as ResolverContext } from './plugins-Ykl_sAPE.cjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Derivation Types - Type definitions for derivations
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Derivation definition function signature. */
|
|
8
|
-
interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> {
|
|
9
|
-
(facts: Facts<S>, derived: DerivedValues<S, D>): T;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Derivation definition with metadata (object form).
|
|
13
|
-
* Use this when you want to attach debugging metadata to a derivation.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* derive: {
|
|
18
|
-
* displayName: {
|
|
19
|
-
* compute: (facts) => `${facts.firstName} ${facts.lastName}`,
|
|
20
|
-
* meta: { label: "Display Name", description: "Full name for UI" },
|
|
21
|
-
* },
|
|
22
|
-
* },
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
interface DerivationDefWithMeta<S extends Schema, T, D extends DerivationsDef<S>> {
|
|
26
|
-
/**
|
|
27
|
-
* The derivation body. Either:
|
|
28
|
-
* - a function `(facts, derived) => T` (original form), or
|
|
29
|
-
* - a {@link FactPredicate} data spec — boolean derivations only, or
|
|
30
|
-
* - a {@link FactTemplate} `{ $template: "..." }` — string derivations only.
|
|
31
|
-
*
|
|
32
|
-
* Data forms are normalized to a wrapper function at registration; the
|
|
33
|
-
* wrapper reads through the facts proxy so existing auto-tracking
|
|
34
|
-
* captures dependencies.
|
|
35
|
-
*/
|
|
36
|
-
compute: DerivationDef<S, T, D> | ([T] extends [boolean] ? FactPredicate<InferSchema<S>> : never) | ([T] extends [string] ? FactTemplate : never);
|
|
37
|
-
meta?: DefinitionMeta;
|
|
38
|
-
}
|
|
39
|
-
/** Map of derivation definitions (internal — always bare functions after unwrap). */
|
|
40
|
-
type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>;
|
|
41
|
-
/** Computed derived values. */
|
|
42
|
-
type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = {
|
|
43
|
-
readonly [K in keyof D]: ReturnType<D[K]>;
|
|
44
|
-
};
|
|
45
|
-
/** Internal derivation state */
|
|
46
|
-
interface DerivationState<T> {
|
|
47
|
-
id: string;
|
|
48
|
-
compute: () => T;
|
|
49
|
-
cachedValue: T | undefined;
|
|
50
|
-
dependencies: Set<string>;
|
|
51
|
-
isStale: boolean;
|
|
52
|
-
isComputing: boolean;
|
|
53
|
-
/** Consecutive runs producing the same deps (auto-tracked only) */
|
|
54
|
-
stableRunCount: number;
|
|
55
|
-
/** Once true, skip withTracking() overhead until a tracked fact mutates */
|
|
56
|
-
depsStable: boolean;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Type Helpers - External typed constraint and resolver definitions
|
|
61
|
-
*
|
|
62
|
-
* These types enable defining constraints and resolvers with full type safety
|
|
63
|
-
* outside of module definitions, while maintaining proper type inference.
|
|
64
|
-
*/
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* External constraint definition with full typing.
|
|
68
|
-
* Use this when defining constraints outside of createModule().
|
|
69
|
-
*
|
|
70
|
-
* @typeParam S - The schema type
|
|
71
|
-
* @typeParam R - The requirement type (defaults to Requirement)
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* // Define a typed constraint factory
|
|
76
|
-
* const createMaxCountConstraint = <S extends Schema>(
|
|
77
|
-
* maxCount: number
|
|
78
|
-
* ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({
|
|
79
|
-
* priority: 10,
|
|
80
|
-
* when: (facts) => (facts as { count: number }).count > maxCount,
|
|
81
|
-
* require: { type: "RESET_COUNT" },
|
|
82
|
-
* });
|
|
83
|
-
*
|
|
84
|
-
* // Use in module
|
|
85
|
-
* const module = createModule("counter", {
|
|
86
|
-
* schema: { count: t.number() },
|
|
87
|
-
* constraints: {
|
|
88
|
-
* maxCount: createMaxCountConstraint(100),
|
|
89
|
-
* },
|
|
90
|
-
* });
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
|
-
interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> {
|
|
94
|
-
/** Priority for ordering (higher runs first) */
|
|
95
|
-
priority?: number;
|
|
96
|
-
/** Mark this constraint as async (avoids runtime detection) */
|
|
97
|
-
async?: boolean;
|
|
98
|
-
/** Condition function (sync or async) */
|
|
99
|
-
when: (facts: Facts<S>) => boolean | Promise<boolean>;
|
|
100
|
-
/**
|
|
101
|
-
* Requirement(s) to produce when condition is met.
|
|
102
|
-
*/
|
|
103
|
-
require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>);
|
|
104
|
-
/** Timeout for async constraints (ms) */
|
|
105
|
-
timeout?: number;
|
|
106
|
-
/**
|
|
107
|
-
* Constraint IDs whose resolvers must complete before this constraint is evaluated.
|
|
108
|
-
* - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for)
|
|
109
|
-
* - If dependency's resolver fails, this constraint remains blocked until it succeeds
|
|
110
|
-
* - Cross-module: use the constraint ID as it appears in the merged system
|
|
111
|
-
*/
|
|
112
|
-
after?: string[];
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* External resolver definition with full typing.
|
|
116
|
-
* Use this when defining resolvers outside of createModule().
|
|
117
|
-
*
|
|
118
|
-
* @typeParam S - The schema type
|
|
119
|
-
* @typeParam R - The requirement type (defaults to Requirement)
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```typescript
|
|
123
|
-
* // Define a typed resolver factory
|
|
124
|
-
* interface FetchUserReq extends Requirement {
|
|
125
|
-
* type: "FETCH_USER";
|
|
126
|
-
* userId: string;
|
|
127
|
-
* }
|
|
128
|
-
*
|
|
129
|
-
* const createFetchUserResolver = <S extends Schema>(
|
|
130
|
-
* fetchFn: (userId: string) => Promise<User>
|
|
131
|
-
* ): TypedResolver<S, FetchUserReq> => ({
|
|
132
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
133
|
-
* key: (req) => `fetch-user-${req.userId}`,
|
|
134
|
-
* retry: { attempts: 3, backoff: "exponential" },
|
|
135
|
-
* resolve: async (req, ctx) => {
|
|
136
|
-
* const user = await fetchFn(req.userId);
|
|
137
|
-
* (ctx.facts as { user: User }).user = user;
|
|
138
|
-
* },
|
|
139
|
-
* });
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
interface TypedResolver<S extends Schema, R extends Requirement = Requirement> {
|
|
143
|
-
/**
|
|
144
|
-
* Requirement type to handle.
|
|
145
|
-
* - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`)
|
|
146
|
-
* - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`)
|
|
147
|
-
*/
|
|
148
|
-
requirement: R["type"] | ((req: Requirement) => req is R);
|
|
149
|
-
/** Custom key function for deduplication */
|
|
150
|
-
key?: (req: R) => string;
|
|
151
|
-
/** Retry policy */
|
|
152
|
-
retry?: RetryPolicy;
|
|
153
|
-
/** Timeout for resolver execution (ms) */
|
|
154
|
-
timeout?: number;
|
|
155
|
-
/** Batch configuration */
|
|
156
|
-
batch?: BatchConfig;
|
|
157
|
-
/** Resolve function for single requirement */
|
|
158
|
-
resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>;
|
|
159
|
-
/** Resolve function for batched requirements */
|
|
160
|
-
resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Create a typed constraint factory for a specific schema.
|
|
164
|
-
* This enables creating reusable constraint definitions with proper typing.
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```typescript
|
|
168
|
-
* const schema = { count: t.number(), threshold: t.number() };
|
|
169
|
-
* const factory = createConstraintFactory<typeof schema>();
|
|
170
|
-
*
|
|
171
|
-
* const maxCountConstraint = factory.create({
|
|
172
|
-
* when: (facts) => facts.count > facts.threshold,
|
|
173
|
-
* require: { type: "RESET" },
|
|
174
|
-
* });
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
declare function createConstraintFactory<S extends Schema>(): {
|
|
178
|
-
/**
|
|
179
|
-
* Create a typed constraint
|
|
180
|
-
*/
|
|
181
|
-
create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
|
|
182
|
-
};
|
|
183
|
-
/**
|
|
184
|
-
* Create a typed resolver factory for a specific schema.
|
|
185
|
-
* This enables creating reusable resolver definitions with proper typing.
|
|
186
|
-
*
|
|
187
|
-
* @example
|
|
188
|
-
* ```typescript
|
|
189
|
-
* const schema = { user: t.object<User>() };
|
|
190
|
-
* const factory = createResolverFactory<typeof schema>();
|
|
191
|
-
*
|
|
192
|
-
* const fetchUserResolver = factory.create<FetchUserReq>({
|
|
193
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
194
|
-
* resolve: async (req, ctx) => {
|
|
195
|
-
* ctx.facts.user = await fetchUser(req.userId);
|
|
196
|
-
* },
|
|
197
|
-
* });
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
declare function createResolverFactory<S extends Schema>(): {
|
|
201
|
-
/**
|
|
202
|
-
* Create a typed resolver
|
|
203
|
-
*/
|
|
204
|
-
create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
|
|
205
|
-
};
|
|
206
|
-
/**
|
|
207
|
-
* Type-safe constraint creator.
|
|
208
|
-
* Simpler alternative to createConstraintFactory when you don't need a factory pattern.
|
|
209
|
-
*
|
|
210
|
-
* @example
|
|
211
|
-
* ```typescript
|
|
212
|
-
* const constraint = typedConstraint<typeof schema, { type: "RESET" }>({
|
|
213
|
-
* when: (facts) => facts.count > 100,
|
|
214
|
-
* require: { type: "RESET" },
|
|
215
|
-
* });
|
|
216
|
-
* ```
|
|
217
|
-
*/
|
|
218
|
-
declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
|
|
219
|
-
/**
|
|
220
|
-
* Type-safe resolver creator.
|
|
221
|
-
* Simpler alternative to createResolverFactory when you don't need a factory pattern.
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const resolver = typedResolver<typeof schema, FetchUserReq>({
|
|
226
|
-
* requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
|
|
227
|
-
* resolve: async (req, ctx) => {
|
|
228
|
-
* ctx.facts.user = await fetchUser(req.userId);
|
|
229
|
-
* },
|
|
230
|
-
* });
|
|
231
|
-
* ```
|
|
232
|
-
*/
|
|
233
|
-
declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
|
|
234
|
-
|
|
235
|
-
export { type DerivationDefWithMeta as D, type TypedConstraint as T, typedResolver as a, type DerivationsDef as b, type DerivedValues as c, type DerivationState as d, type TypedResolver as e, createConstraintFactory as f, createResolverFactory as g, typedConstraint as t };
|
package/dist/system-GK3NSFQH.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
'use strict';var chunkEX3XG667_cjs=require('./chunk-EX3XG667.cjs');require('./chunk-7NMXRATK.cjs'),require('./chunk-N4KTCKOI.cjs'),require('./chunk-EOLY64E6.cjs');Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunkEX3XG667_cjs.a}});//# sourceMappingURL=system-GK3NSFQH.cjs.map
|
|
2
|
-
//# sourceMappingURL=system-GK3NSFQH.cjs.map
|
package/dist/system-VZWB6WXX.js
DELETED