@directive-run/core 0.8.1 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/dist/adapter-utils.cjs +1 -1
- package/dist/adapter-utils.cjs.map +1 -1
- package/dist/adapter-utils.d.cts +1 -1
- package/dist/adapter-utils.d.ts +1 -1
- package/dist/adapter-utils.js +1 -1
- package/dist/adapter-utils.js.map +1 -1
- package/dist/chunk-6WG7FPH7.cjs +3 -0
- package/dist/chunk-6WG7FPH7.cjs.map +1 -0
- package/dist/chunk-DIK3SZBM.js +3 -0
- package/dist/chunk-DIK3SZBM.js.map +1 -0
- package/dist/chunk-GO63IIN5.js +2 -0
- package/dist/chunk-GO63IIN5.js.map +1 -0
- package/dist/chunk-KQKNE23L.cjs +2 -0
- package/dist/chunk-KQKNE23L.cjs.map +1 -0
- package/dist/chunk-LAH2FMON.cjs +16 -0
- package/dist/chunk-LAH2FMON.cjs.map +1 -0
- package/dist/chunk-MAARYRI4.js +16 -0
- package/dist/chunk-MAARYRI4.js.map +1 -0
- package/dist/chunk-O75OISQ2.js +2 -0
- package/dist/chunk-O75OISQ2.js.map +1 -0
- package/dist/chunk-PK2EH26L.cjs +2 -0
- package/dist/chunk-PK2EH26L.cjs.map +1 -0
- package/dist/helpers-50q7yhA9.d.ts +179 -0
- package/dist/helpers-B6SkcKCD.d.cts +179 -0
- package/dist/index.cjs +1 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -1421
- package/dist/index.d.ts +42 -1421
- package/dist/index.js +1 -16
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +2 -0
- package/dist/internals.cjs.map +1 -0
- package/dist/internals.d.cts +1176 -0
- package/dist/internals.d.ts +1176 -0
- package/dist/internals.js +2 -0
- package/dist/internals.js.map +1 -0
- package/dist/plugins/index.cjs +2 -2
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.d.cts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/index.js +2 -2
- package/dist/plugins/index.js.map +1 -1
- package/dist/{plugins-DaglUQVX.d.cts → plugins-Bg_oq2sO.d.cts} +22 -2
- package/dist/{plugins-DaglUQVX.d.ts → plugins-Bg_oq2sO.d.ts} +22 -2
- package/dist/system-L2FVVUSN.js +2 -0
- package/dist/system-L2FVVUSN.js.map +1 -0
- package/dist/system-L45Z2N4U.cjs +2 -0
- package/dist/system-L45Z2N4U.cjs.map +1 -0
- package/dist/testing.cjs +1 -16
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +54 -16
- package/dist/testing.d.ts +54 -16
- package/dist/testing.js +1 -16
- package/dist/testing.js.map +1 -1
- package/dist/worker.cjs +1 -16
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -16
- package/dist/worker.js.map +1 -1
- package/package.json +13 -4
|
@@ -0,0 +1,1176 @@
|
|
|
1
|
+
import { Q as Schema, F as Facts, a1 as FactsStore, E as EffectsDef, a2 as ConstraintsDef, p as RequirementKeyFn, R as RequirementWithId, a3 as ConstraintState, a4 as ResolversDef, a5 as ResolverStatus, o as Requirement, P as Plugin, V as System, a6 as FactChange, v as FactsSnapshot, a7 as ReconcileResult, U as Snapshot, D as DirectiveError, a8 as RecoveryStrategy, _ as TraceEntry, a9 as ErrorSource, n as ErrorBoundaryConfig, aa as RetryLaterConfig, H as HistoryAPI, w as HistoryOption, W as SystemConfig } from './plugins-Bg_oq2sO.cjs';
|
|
2
|
+
export { ab as BatchItemResult, ac as BatchResolveResults, ad as ConstraintsControl, ae as CrossModuleConstraintDef, g as CrossModuleConstraintsDef, af as CrossModuleDerivationFn, e as CrossModuleDerivationsDef, ag as CrossModuleEffectDef, f as CrossModuleEffectsDef, ah as CrossModuleFactsWithSelf, ai as DerivationKeys, aj as DerivationReturnType, ak as DerivationsControl, al as DerivationsSchema, am as DeriveAccessor, an as DispatchEventsFromSchema, q as DistributableSnapshot, r as DistributableSnapshotOptions, ao as EffectCleanup, ap as EffectsControl, aq as EventPayloadSchema, ar as EventsAccessor, as as EventsAccessorFromSchema, at as EventsDef, au as EventsSchema, av as FactKeys, aw as FactReturnType, ax as FlexibleEventHandler, ay as HistoryConfig, az as InferEventPayloadFromSchema, aA as InferRequirementPayloadFromSchema, aB as InferSchema, aC as MutableNamespacedFacts, aD as NamespacedDerivations, aE as NamespacedEventsAccessor, aF as NamespacedFacts, aG as ObservableKeys, aH as RequirementExplanation, aI as RequirementOutput, aJ as RequirementPayloadSchema, aK as RequirementsSchema, aL as ResolverContext, aM as ResolversControl, aN as SnapshotMeta, aO as SystemEvent, aP as TraceConfig, aQ as TypedConstraintDef, b as TypedConstraintsDef, T as TypedDerivationsDef, a as TypedEventsDef, aR as TypedResolverContext, aS as TypedResolverDef, c as TypedResolversDef, aT as UnionEvents } from './plugins-Bg_oq2sO.cjs';
|
|
3
|
+
export { T as TypedConstraint, b as TypedResolver, c as createConstraintFactory, d as createResolverFactory } from './helpers-B6SkcKCD.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Derivation Types - Type definitions for derivations
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Tracking context for auto-dependency detection */
|
|
10
|
+
interface TrackingContext {
|
|
11
|
+
readonly isTracking: boolean;
|
|
12
|
+
track(key: string): void;
|
|
13
|
+
getDependencies(): Set<string>;
|
|
14
|
+
}
|
|
15
|
+
/** Derivation definition function signature. */
|
|
16
|
+
interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> {
|
|
17
|
+
(facts: Facts<S>, derived: DerivedValues<S, D>): T;
|
|
18
|
+
}
|
|
19
|
+
/** Map of derivation definitions. */
|
|
20
|
+
type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>;
|
|
21
|
+
/** Computed derived values. */
|
|
22
|
+
type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = {
|
|
23
|
+
readonly [K in keyof D]: ReturnType<D[K]>;
|
|
24
|
+
};
|
|
25
|
+
/** Internal derivation state */
|
|
26
|
+
interface DerivationState<T> {
|
|
27
|
+
id: string;
|
|
28
|
+
compute: () => T;
|
|
29
|
+
cachedValue: T | undefined;
|
|
30
|
+
dependencies: Set<string>;
|
|
31
|
+
isStale: boolean;
|
|
32
|
+
isComputing: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Facts Store - Proxy-based reactive state with auto-tracking
|
|
37
|
+
*
|
|
38
|
+
* Features:
|
|
39
|
+
* - Proxy-based access (facts.phase instead of facts.get("phase"))
|
|
40
|
+
* - Automatic dependency tracking via tracking context
|
|
41
|
+
* - Batched updates with coalesced notifications
|
|
42
|
+
* - Granular subscriptions by key
|
|
43
|
+
* - Schema validation in development mode
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/** Options for creating a facts store */
|
|
47
|
+
interface CreateFactsStoreOptions<S extends Schema> {
|
|
48
|
+
schema: S;
|
|
49
|
+
/** Validate values against schema (default: process.env.NODE_ENV !== 'production') */
|
|
50
|
+
validate?: boolean;
|
|
51
|
+
/** Throw on unknown schema keys (default: true in dev mode) */
|
|
52
|
+
strictKeys?: boolean;
|
|
53
|
+
/** Redact sensitive values in error messages */
|
|
54
|
+
redactErrors?: boolean;
|
|
55
|
+
/** Callback when facts change (for plugin hooks) */
|
|
56
|
+
onChange?: (key: string, value: unknown, prev: unknown) => void;
|
|
57
|
+
/** Callback for batch changes */
|
|
58
|
+
onBatch?: (changes: Array<{
|
|
59
|
+
key: string;
|
|
60
|
+
value: unknown;
|
|
61
|
+
prev: unknown;
|
|
62
|
+
type: "set" | "delete";
|
|
63
|
+
}>) => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a reactive facts store backed by a Map with schema validation,
|
|
67
|
+
* batched mutations, and granular key-level subscriptions.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* The store is the low-level primitive that powers the `facts` proxy.
|
|
71
|
+
* Most users should use {@link createFacts} or `createModule` instead.
|
|
72
|
+
*
|
|
73
|
+
* @param options - Store configuration including schema, validation settings, and change callbacks
|
|
74
|
+
* @returns A {@link FactsStore} with get/set/batch/subscribe methods and automatic schema validation
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const store = createFactsStore({
|
|
79
|
+
* schema: { count: t.number(), name: t.string() },
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* store.set("count", 1);
|
|
83
|
+
* store.get("count"); // 1
|
|
84
|
+
*
|
|
85
|
+
* store.batch(() => {
|
|
86
|
+
* store.set("count", 2);
|
|
87
|
+
* store.set("name", "hello");
|
|
88
|
+
* }); // listeners fire once after batch completes
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
declare function createFactsStore<S extends Schema>(options: CreateFactsStoreOptions<S>): FactsStore<S>;
|
|
94
|
+
/**
|
|
95
|
+
* Create a Proxy wrapper around a {@link FactsStore} for clean property-style
|
|
96
|
+
* access (`facts.phase`) with automatic dependency tracking.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* Reading a property calls `store.get()` (which tracks the access for
|
|
100
|
+
* auto-tracked derivations). Writing a property calls `store.set()` (which
|
|
101
|
+
* validates against the schema). The proxy also exposes `$store` for direct
|
|
102
|
+
* store access and `$snapshot()` for untracked reads.
|
|
103
|
+
*
|
|
104
|
+
* @param store - The underlying facts store to wrap
|
|
105
|
+
* @param schema - The schema definition used for `ownKeys` enumeration
|
|
106
|
+
* @returns A {@link Facts} proxy with property-style get/set and prototype pollution guards
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const store = createFactsStore({ schema: { phase: t.string() } });
|
|
111
|
+
* const facts = createFactsProxy(store, { phase: t.string() });
|
|
112
|
+
*
|
|
113
|
+
* facts.phase = "red";
|
|
114
|
+
* console.log(facts.phase); // "red"
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
declare function createFactsProxy<S extends Schema>(store: FactsStore<S>, schema: S): Facts<S>;
|
|
120
|
+
/**
|
|
121
|
+
* Convenience factory that creates both a {@link FactsStore} and its
|
|
122
|
+
* {@link createFactsProxy | proxy wrapper} in a single call.
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* This is the recommended entry point when you need low-level store access
|
|
126
|
+
* outside of `createModule` / `createSystem`.
|
|
127
|
+
*
|
|
128
|
+
* @param options - Same options as {@link createFactsStore}
|
|
129
|
+
* @returns An object with `store` (the reactive Map-backed store) and `facts` (the Proxy accessor)
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const { store, facts } = createFacts({
|
|
134
|
+
* schema: { phase: t.string<"red" | "green">() },
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* facts.phase = "red";
|
|
138
|
+
* console.log(facts.phase); // "red"
|
|
139
|
+
* store.subscribe(["phase"], () => console.log("phase changed"));
|
|
140
|
+
* ```
|
|
141
|
+
*
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
declare function createFacts<S extends Schema>(options: CreateFactsStoreOptions<S>): {
|
|
145
|
+
store: FactsStore<S>;
|
|
146
|
+
facts: Facts<S>;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Derivations - Auto-tracked computed values with composition
|
|
151
|
+
*
|
|
152
|
+
* Features:
|
|
153
|
+
* - Automatic dependency tracking (no manual deps arrays)
|
|
154
|
+
* - Memoization with smart invalidation
|
|
155
|
+
* - Derivation composition (derivations can depend on other derivations)
|
|
156
|
+
* - Circular dependency detection
|
|
157
|
+
* - Lazy evaluation
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
interface DerivationsManager<S extends Schema, D extends DerivationsDef<S>> {
|
|
161
|
+
/** Get a derived value (computes if stale) */
|
|
162
|
+
get<K extends keyof D>(id: K): ReturnType<D[K]>;
|
|
163
|
+
/** Check if a derivation is stale */
|
|
164
|
+
isStale(id: keyof D): boolean;
|
|
165
|
+
/** Invalidate derivations that depend on a fact key */
|
|
166
|
+
invalidate(factKey: string): void;
|
|
167
|
+
/** Invalidate derivations for multiple fact keys, notifying listeners once at the end */
|
|
168
|
+
invalidateMany(factKeys: Iterable<string>): void;
|
|
169
|
+
/** Invalidate all derivations */
|
|
170
|
+
invalidateAll(): void;
|
|
171
|
+
/** Subscribe to derivation changes */
|
|
172
|
+
subscribe(ids: Array<keyof D>, listener: () => void): () => void;
|
|
173
|
+
/** Get the proxy for composition */
|
|
174
|
+
getProxy(): DerivedValues<S, D>;
|
|
175
|
+
/** Get dependencies for a derivation */
|
|
176
|
+
getDependencies(id: keyof D): Set<string>;
|
|
177
|
+
/** Register new derivation definitions (for dynamic module registration) */
|
|
178
|
+
registerDefinitions(newDefs: DerivationsDef<S>): void;
|
|
179
|
+
/** Override an existing derivation function */
|
|
180
|
+
assignDefinition(id: string, fn: DerivationsDef<S>[keyof DerivationsDef<S>]): void;
|
|
181
|
+
/** Remove a derivation and clean up its state */
|
|
182
|
+
unregisterDefinition(id: string): void;
|
|
183
|
+
/** Compute a derivation immediately (ignores cache) */
|
|
184
|
+
callOne(id: string): unknown;
|
|
185
|
+
}
|
|
186
|
+
/** Options for creating a derivations manager */
|
|
187
|
+
interface CreateDerivationsOptions<S extends Schema, D extends DerivationsDef<S>> {
|
|
188
|
+
definitions: D;
|
|
189
|
+
facts: Facts<S>;
|
|
190
|
+
store: FactsStore<S>;
|
|
191
|
+
/** Callback when a derivation is computed */
|
|
192
|
+
onCompute?: (id: string, value: unknown, oldValue: unknown, deps: string[]) => void;
|
|
193
|
+
/** Callback when a derivation is invalidated */
|
|
194
|
+
onInvalidate?: (id: string) => void;
|
|
195
|
+
/** Callback when a derivation errors */
|
|
196
|
+
onError?: (id: string, error: unknown) => void;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Create a manager for lazily-evaluated, auto-tracked derived values.
|
|
200
|
+
*
|
|
201
|
+
* Derivations are memoized computations that automatically track which facts
|
|
202
|
+
* they read. When a tracked fact changes, the derivation is invalidated and
|
|
203
|
+
* recomputed on next access. Derivations can depend on other derivations
|
|
204
|
+
* (composition), and circular dependencies are detected at compute time.
|
|
205
|
+
*
|
|
206
|
+
* Notifications are deferred during invalidation so listeners always see
|
|
207
|
+
* consistent state across multiple simultaneous fact changes.
|
|
208
|
+
*
|
|
209
|
+
* @param options - Derivation definitions, facts proxy, store, and optional
|
|
210
|
+
* lifecycle callbacks.
|
|
211
|
+
* @returns A {@link DerivationsManager} for accessing, invalidating, and
|
|
212
|
+
* subscribing to derived values.
|
|
213
|
+
*
|
|
214
|
+
* @internal
|
|
215
|
+
*/
|
|
216
|
+
declare function createDerivationsManager<S extends Schema, D extends DerivationsDef<S>>(options: CreateDerivationsOptions<S, D>): DerivationsManager<S, D>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Effects - Fire-and-forget side effects
|
|
220
|
+
*
|
|
221
|
+
* Features:
|
|
222
|
+
* - Separate from requirement resolution
|
|
223
|
+
* - Error isolation (never breaks reconciliation)
|
|
224
|
+
* - Optional explicit dependencies for optimization
|
|
225
|
+
* - Runs after facts stabilize
|
|
226
|
+
*
|
|
227
|
+
* IMPORTANT: Auto-tracking limitations
|
|
228
|
+
* ------------------------------------
|
|
229
|
+
* When using auto-tracking (no explicit `deps`), only SYNCHRONOUS fact accesses
|
|
230
|
+
* are tracked. If your effect reads facts after an `await`, those reads are NOT
|
|
231
|
+
* tracked and won't trigger the effect on future changes.
|
|
232
|
+
*
|
|
233
|
+
* For async effects, always use explicit `deps`:
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* effects: {
|
|
237
|
+
* // BAD: fetchData is async, facts.userId read after await won't be tracked
|
|
238
|
+
* badEffect: {
|
|
239
|
+
* run: async (facts) => {
|
|
240
|
+
* await someAsyncOp();
|
|
241
|
+
* console.log(facts.userId); // NOT tracked!
|
|
242
|
+
* },
|
|
243
|
+
* },
|
|
244
|
+
* // GOOD: explicit deps for async effects
|
|
245
|
+
* goodEffect: {
|
|
246
|
+
* deps: ["userId"],
|
|
247
|
+
* run: async (facts) => {
|
|
248
|
+
* await someAsyncOp();
|
|
249
|
+
* console.log(facts.userId); // Works because we declared the dep
|
|
250
|
+
* },
|
|
251
|
+
* },
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Manager returned by {@link createEffectsManager} that runs fire-and-forget
|
|
258
|
+
* side effects after facts stabilize.
|
|
259
|
+
*
|
|
260
|
+
* @internal
|
|
261
|
+
*/
|
|
262
|
+
interface EffectsManager<_S extends Schema = Schema> {
|
|
263
|
+
/**
|
|
264
|
+
* Run all effects whose tracked dependencies overlap with `changedKeys`.
|
|
265
|
+
*
|
|
266
|
+
* @remarks
|
|
267
|
+
* Effects with no recorded dependencies (first run or auto-tracked with no
|
|
268
|
+
* reads) run on any change. After execution, a snapshot of current facts is
|
|
269
|
+
* stored for the `prev` parameter on the next invocation.
|
|
270
|
+
*
|
|
271
|
+
* @param changedKeys - Fact keys that changed since the last run.
|
|
272
|
+
*/
|
|
273
|
+
runEffects(changedKeys: Set<string>): Promise<void>;
|
|
274
|
+
/**
|
|
275
|
+
* Run every enabled effect unconditionally, regardless of dependencies.
|
|
276
|
+
*/
|
|
277
|
+
runAll(): Promise<void>;
|
|
278
|
+
/**
|
|
279
|
+
* Disable an effect so it is skipped during subsequent runs.
|
|
280
|
+
*
|
|
281
|
+
* @param id - The effect definition ID.
|
|
282
|
+
*/
|
|
283
|
+
disable(id: string): void;
|
|
284
|
+
/**
|
|
285
|
+
* Re-enable a previously disabled effect.
|
|
286
|
+
*
|
|
287
|
+
* @param id - The effect definition ID.
|
|
288
|
+
*/
|
|
289
|
+
enable(id: string): void;
|
|
290
|
+
/**
|
|
291
|
+
* Check whether an effect is currently enabled.
|
|
292
|
+
*
|
|
293
|
+
* @param id - The effect definition ID.
|
|
294
|
+
* @returns `true` if the effect has not been disabled.
|
|
295
|
+
*/
|
|
296
|
+
isEnabled(id: string): boolean;
|
|
297
|
+
/**
|
|
298
|
+
* Invoke every stored cleanup function and mark the manager as stopped.
|
|
299
|
+
*
|
|
300
|
+
* @remarks
|
|
301
|
+
* After this call, any cleanup functions returned by in-flight async effects
|
|
302
|
+
* will be invoked immediately rather than stored.
|
|
303
|
+
*/
|
|
304
|
+
cleanupAll(): void;
|
|
305
|
+
/**
|
|
306
|
+
* Register additional effect definitions at runtime (used for dynamic
|
|
307
|
+
* module registration).
|
|
308
|
+
*
|
|
309
|
+
* @param newDefs - New effect definitions to merge into the manager.
|
|
310
|
+
*/
|
|
311
|
+
registerDefinitions(newDefs: EffectsDef<Schema>): void;
|
|
312
|
+
/**
|
|
313
|
+
* Override an existing effect definition. Runs cleanup of the old effect first.
|
|
314
|
+
*
|
|
315
|
+
* @param id - The effect definition ID to override.
|
|
316
|
+
* @param def - The new effect definition.
|
|
317
|
+
* @throws If no effect with this ID exists.
|
|
318
|
+
*/
|
|
319
|
+
assignDefinition(id: string, def: EffectsDef<Schema>[string]): void;
|
|
320
|
+
/**
|
|
321
|
+
* Remove an effect definition. Runs cleanup (try-catch) and removes from state.
|
|
322
|
+
*
|
|
323
|
+
* @param id - The effect definition ID to remove.
|
|
324
|
+
*/
|
|
325
|
+
unregisterDefinition(id: string): void;
|
|
326
|
+
/**
|
|
327
|
+
* Execute an effect's `run()` function immediately.
|
|
328
|
+
*
|
|
329
|
+
* @param id - The effect definition ID.
|
|
330
|
+
*/
|
|
331
|
+
callOne(id: string): Promise<void>;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Configuration options accepted by {@link createEffectsManager}.
|
|
335
|
+
*
|
|
336
|
+
* @internal
|
|
337
|
+
*/
|
|
338
|
+
interface CreateEffectsOptions<S extends Schema> {
|
|
339
|
+
/** Effect definitions keyed by ID. */
|
|
340
|
+
definitions: EffectsDef<S>;
|
|
341
|
+
/** Proxy-based facts object passed to effect `run()` functions. */
|
|
342
|
+
facts: Facts<S>;
|
|
343
|
+
/** Underlying fact store used for `batch()` coalescing of mutations. */
|
|
344
|
+
store: FactsStore<S>;
|
|
345
|
+
/** Called when an effect executes, with the fact keys that triggered it. */
|
|
346
|
+
onRun?: (id: string, deps: string[]) => void;
|
|
347
|
+
/** Called when an effect's `run()` or cleanup function throws. */
|
|
348
|
+
onError?: (id: string, error: unknown) => void;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Create a manager for fire-and-forget side effects that run after facts
|
|
352
|
+
* stabilize.
|
|
353
|
+
*
|
|
354
|
+
* @remarks
|
|
355
|
+
* Effects support two dependency modes:
|
|
356
|
+
*
|
|
357
|
+
* - **Auto-tracked** (no `deps`): Dependencies are re-tracked on every run
|
|
358
|
+
* via {@link withTracking}, so conditional fact reads are always captured.
|
|
359
|
+
* Only synchronous reads are tracked; reads after an `await` are invisible.
|
|
360
|
+
*
|
|
361
|
+
* - **Explicit `deps`**: A fixed array of fact keys declared on the definition.
|
|
362
|
+
* Preferred for async effects where auto-tracking cannot cross `await`
|
|
363
|
+
* boundaries.
|
|
364
|
+
*
|
|
365
|
+
* Each effect can return a cleanup function that runs before the next
|
|
366
|
+
* execution or when {@link EffectsManager.cleanupAll | cleanupAll} is called.
|
|
367
|
+
* Errors in effects are isolated via try-catch and never break the
|
|
368
|
+
* reconciliation loop. Synchronous fact mutations inside effects are
|
|
369
|
+
* coalesced with `store.batch()`.
|
|
370
|
+
*
|
|
371
|
+
* @param options - Configuration including effect definitions, facts proxy,
|
|
372
|
+
* store, and lifecycle callbacks.
|
|
373
|
+
* @returns An {@link EffectsManager} for running, enabling/disabling, and
|
|
374
|
+
* cleaning up effects.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```typescript
|
|
378
|
+
* const effects = createEffectsManager({
|
|
379
|
+
* definitions: {
|
|
380
|
+
* logPhase: {
|
|
381
|
+
* run: (facts, prev) => {
|
|
382
|
+
* if (prev?.phase !== facts.phase) {
|
|
383
|
+
* console.log(`Phase changed to ${facts.phase}`);
|
|
384
|
+
* }
|
|
385
|
+
* },
|
|
386
|
+
* },
|
|
387
|
+
* },
|
|
388
|
+
* facts: factsProxy,
|
|
389
|
+
* store: factsStore,
|
|
390
|
+
* });
|
|
391
|
+
*
|
|
392
|
+
* await effects.runEffects(new Set(["phase"]));
|
|
393
|
+
* ```
|
|
394
|
+
*
|
|
395
|
+
* @internal
|
|
396
|
+
*/
|
|
397
|
+
declare function createEffectsManager<S extends Schema>(options: CreateEffectsOptions<S>): EffectsManager<S>;
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Constraints - Rules that produce requirements when conditions aren't met
|
|
401
|
+
*
|
|
402
|
+
* Features:
|
|
403
|
+
* - Sync and async constraint evaluation
|
|
404
|
+
* - Priority ordering (higher runs first)
|
|
405
|
+
* - Timeout handling for async constraints
|
|
406
|
+
* - Error isolation
|
|
407
|
+
*/
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Manager returned by {@link createConstraintsManager} that evaluates
|
|
411
|
+
* constraint rules against the current facts and produces unmet
|
|
412
|
+
* {@link RequirementWithId | requirements}.
|
|
413
|
+
*
|
|
414
|
+
* @internal
|
|
415
|
+
*/
|
|
416
|
+
interface ConstraintsManager<_S extends Schema> {
|
|
417
|
+
/**
|
|
418
|
+
* Evaluate all enabled constraints and return unmet requirements.
|
|
419
|
+
*
|
|
420
|
+
* @remarks
|
|
421
|
+
* On the first call (or when `changedKeys` is empty), every enabled
|
|
422
|
+
* constraint is evaluated. On subsequent calls, only constraints whose
|
|
423
|
+
* tracked dependencies overlap with `changedKeys` are re-evaluated.
|
|
424
|
+
* Sync constraints run first, async constraints run in parallel, and
|
|
425
|
+
* `after` ordering is respected across multiple passes.
|
|
426
|
+
*
|
|
427
|
+
* @param changedKeys - Fact keys that changed since the last evaluation.
|
|
428
|
+
* When omitted or empty, all constraints are evaluated.
|
|
429
|
+
* @returns An array of {@link RequirementWithId} representing unmet requirements.
|
|
430
|
+
*/
|
|
431
|
+
evaluate(changedKeys?: Set<string>): Promise<RequirementWithId[]>;
|
|
432
|
+
/**
|
|
433
|
+
* Get the current state of a constraint by its definition ID.
|
|
434
|
+
*
|
|
435
|
+
* @param id - The constraint definition ID.
|
|
436
|
+
* @returns The {@link ConstraintState}, or `undefined` if the ID is unknown.
|
|
437
|
+
*/
|
|
438
|
+
getState(id: string): ConstraintState | undefined;
|
|
439
|
+
/**
|
|
440
|
+
* Get the state of every registered constraint.
|
|
441
|
+
*
|
|
442
|
+
* @returns An array of all {@link ConstraintState} objects.
|
|
443
|
+
*/
|
|
444
|
+
getAllStates(): ConstraintState[];
|
|
445
|
+
/**
|
|
446
|
+
* Disable a constraint so it is skipped during evaluation.
|
|
447
|
+
*
|
|
448
|
+
* @param id - The constraint definition ID.
|
|
449
|
+
*/
|
|
450
|
+
disable(id: string): void;
|
|
451
|
+
/**
|
|
452
|
+
* Re-enable a previously disabled constraint.
|
|
453
|
+
*
|
|
454
|
+
* @param id - The constraint definition ID.
|
|
455
|
+
*/
|
|
456
|
+
enable(id: string): void;
|
|
457
|
+
/**
|
|
458
|
+
* Mark all constraints that depend on `factKey` as dirty so they are
|
|
459
|
+
* re-evaluated on the next {@link ConstraintsManager.evaluate | evaluate} call.
|
|
460
|
+
*
|
|
461
|
+
* @param factKey - The fact store key that changed.
|
|
462
|
+
*/
|
|
463
|
+
invalidate(factKey: string): void;
|
|
464
|
+
/**
|
|
465
|
+
* Get the auto-tracked or explicit dependency set for a constraint.
|
|
466
|
+
*
|
|
467
|
+
* @param id - The constraint definition ID.
|
|
468
|
+
* @returns A `Set` of fact keys, or `undefined` if no dependencies have been recorded.
|
|
469
|
+
*/
|
|
470
|
+
getDependencies(id: string): Set<string> | undefined;
|
|
471
|
+
/**
|
|
472
|
+
* Record that a constraint's resolver completed successfully, unblocking
|
|
473
|
+
* any constraints that list it in their `after` array.
|
|
474
|
+
*
|
|
475
|
+
* @param constraintId - The constraint definition ID whose resolver finished.
|
|
476
|
+
*/
|
|
477
|
+
markResolved(constraintId: string): void;
|
|
478
|
+
/**
|
|
479
|
+
* Check whether a constraint is currently disabled.
|
|
480
|
+
*
|
|
481
|
+
* @param id - The constraint definition ID.
|
|
482
|
+
* @returns `true` if the constraint has been disabled via {@link ConstraintsManager.disable | disable}.
|
|
483
|
+
*/
|
|
484
|
+
isDisabled(id: string): boolean;
|
|
485
|
+
/**
|
|
486
|
+
* Check whether a constraint has been marked as resolved.
|
|
487
|
+
*
|
|
488
|
+
* @param constraintId - The constraint definition ID.
|
|
489
|
+
* @returns `true` if {@link ConstraintsManager.markResolved | markResolved} was called for this constraint.
|
|
490
|
+
*/
|
|
491
|
+
isResolved(constraintId: string): boolean;
|
|
492
|
+
/**
|
|
493
|
+
* Register additional constraint definitions at runtime (used for dynamic
|
|
494
|
+
* module registration).
|
|
495
|
+
*
|
|
496
|
+
* @remarks
|
|
497
|
+
* Rebuilds the topological order and reverse dependency map so new `after`
|
|
498
|
+
* dependencies are validated for cycles and indexed.
|
|
499
|
+
*
|
|
500
|
+
* @param newDefs - New constraint definitions to merge into the manager.
|
|
501
|
+
*/
|
|
502
|
+
registerDefinitions(newDefs: ConstraintsDef<Schema>): void;
|
|
503
|
+
/**
|
|
504
|
+
* Override an existing constraint definition.
|
|
505
|
+
* Stores the original in an internal map for inspection.
|
|
506
|
+
*
|
|
507
|
+
* @param id - The constraint definition ID to override.
|
|
508
|
+
* @param def - The new constraint definition.
|
|
509
|
+
* @throws If no constraint with this ID exists.
|
|
510
|
+
*/
|
|
511
|
+
assignDefinition(id: string, def: ConstraintsDef<Schema>[string]): void;
|
|
512
|
+
/**
|
|
513
|
+
* Remove a constraint definition and all its internal state.
|
|
514
|
+
*
|
|
515
|
+
* @param id - The constraint definition ID to remove.
|
|
516
|
+
*/
|
|
517
|
+
unregisterDefinition(id: string): void;
|
|
518
|
+
/**
|
|
519
|
+
* Evaluate a single constraint and emit its requirement if active.
|
|
520
|
+
* Props are merged into the requirement object.
|
|
521
|
+
*
|
|
522
|
+
* @param id - The constraint definition ID.
|
|
523
|
+
* @param props - Optional properties to merge into the requirement.
|
|
524
|
+
* @returns The emitted requirements (if any).
|
|
525
|
+
*/
|
|
526
|
+
callOne(id: string, props?: Record<string, unknown>): Promise<RequirementWithId[]>;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Configuration options accepted by {@link createConstraintsManager}.
|
|
530
|
+
*
|
|
531
|
+
* @internal
|
|
532
|
+
*/
|
|
533
|
+
interface CreateConstraintsOptions<S extends Schema> {
|
|
534
|
+
/** Constraint definitions keyed by ID. */
|
|
535
|
+
definitions: ConstraintsDef<S>;
|
|
536
|
+
/** Proxy-based facts object used to evaluate `when()` predicates. */
|
|
537
|
+
facts: Facts<S>;
|
|
538
|
+
/** Custom key functions for requirement deduplication, keyed by constraint ID. */
|
|
539
|
+
requirementKeys?: Record<string, RequirementKeyFn>;
|
|
540
|
+
/** Default timeout in milliseconds for async constraint evaluation (defaults to 5 000). */
|
|
541
|
+
defaultTimeout?: number;
|
|
542
|
+
/** Called after each constraint evaluation with the constraint ID and whether `when()` was active. */
|
|
543
|
+
onEvaluate?: (id: string, active: boolean) => void;
|
|
544
|
+
/** Called when a constraint's `when()` or `require()` throws. */
|
|
545
|
+
onError?: (id: string, error: unknown) => void;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Create a manager that evaluates constraint rules and produces unmet
|
|
549
|
+
* requirements.
|
|
550
|
+
*
|
|
551
|
+
* @remarks
|
|
552
|
+
* Constraints are evaluated in priority order (higher priority first), with
|
|
553
|
+
* topological ordering for same-priority constraints connected by `after`
|
|
554
|
+
* dependencies. The manager supports sync and async `when()` predicates,
|
|
555
|
+
* incremental evaluation based on changed fact keys, and per-constraint
|
|
556
|
+
* enable/disable toggling. Cycle detection runs eagerly at construction time
|
|
557
|
+
* to prevent deadlocks in production.
|
|
558
|
+
*
|
|
559
|
+
* @param options - Configuration including constraint definitions, facts proxy,
|
|
560
|
+
* custom requirement key functions, and lifecycle callbacks.
|
|
561
|
+
* @returns A {@link ConstraintsManager} for evaluating, invalidating, and
|
|
562
|
+
* managing constraint lifecycle.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* const constraints = createConstraintsManager({
|
|
567
|
+
* definitions: {
|
|
568
|
+
* mustTransition: {
|
|
569
|
+
* priority: 50,
|
|
570
|
+
* when: (facts) => facts.phase === "red" && facts.elapsed > 30,
|
|
571
|
+
* require: { type: "TRANSITION", to: "green" },
|
|
572
|
+
* },
|
|
573
|
+
* },
|
|
574
|
+
* facts: factsProxy,
|
|
575
|
+
* onEvaluate: (id, active) => console.log(id, active),
|
|
576
|
+
* });
|
|
577
|
+
*
|
|
578
|
+
* const unmet = await constraints.evaluate();
|
|
579
|
+
* ```
|
|
580
|
+
*
|
|
581
|
+
* @internal
|
|
582
|
+
*/
|
|
583
|
+
declare function createConstraintsManager<S extends Schema>(options: CreateConstraintsOptions<S>): ConstraintsManager<S>;
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Resolvers - Capability-based handlers for requirements
|
|
587
|
+
*
|
|
588
|
+
* Features:
|
|
589
|
+
* - Capability matching (handles predicate)
|
|
590
|
+
* - Custom dedupe keys
|
|
591
|
+
* - Retry policies with exponential backoff
|
|
592
|
+
* - Batched resolution for similar requirements
|
|
593
|
+
* - Cancellation via AbortController
|
|
594
|
+
*/
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Summary of a resolver that is currently in flight.
|
|
598
|
+
*
|
|
599
|
+
* @internal
|
|
600
|
+
*/
|
|
601
|
+
interface InflightInfo {
|
|
602
|
+
/** The unique requirement ID being resolved. */
|
|
603
|
+
id: string;
|
|
604
|
+
/** The definition ID of the resolver handling this requirement. */
|
|
605
|
+
resolverId: string;
|
|
606
|
+
/** Epoch timestamp (ms) when resolution started. */
|
|
607
|
+
startedAt: number;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Manager returned by {@link createResolversManager} that matches
|
|
611
|
+
* requirements to resolver handlers and manages their execution lifecycle.
|
|
612
|
+
*
|
|
613
|
+
* @internal
|
|
614
|
+
*/
|
|
615
|
+
interface ResolversManager<_S extends Schema> {
|
|
616
|
+
/**
|
|
617
|
+
* Start resolving a requirement by matching it to a resolver handler.
|
|
618
|
+
*
|
|
619
|
+
* @remarks
|
|
620
|
+
* Duplicate in-flight requirements (same `req.id`) are silently ignored.
|
|
621
|
+
* If the matched resolver has `batch.enabled`, the requirement is queued
|
|
622
|
+
* for batch processing instead of being resolved immediately.
|
|
623
|
+
*
|
|
624
|
+
* @param req - The requirement (with a stable identity ID) to resolve.
|
|
625
|
+
*/
|
|
626
|
+
resolve(req: RequirementWithId): void;
|
|
627
|
+
/**
|
|
628
|
+
* Cancel an in-flight or batch-queued resolver by requirement ID.
|
|
629
|
+
*
|
|
630
|
+
* @remarks
|
|
631
|
+
* Aborts the `AbortController` for in-flight resolvers. For batch-queued
|
|
632
|
+
* requirements, removes the requirement from the pending batch.
|
|
633
|
+
*
|
|
634
|
+
* @param requirementId - The unique requirement ID to cancel.
|
|
635
|
+
*/
|
|
636
|
+
cancel(requirementId: string): void;
|
|
637
|
+
/**
|
|
638
|
+
* Cancel every in-flight resolver and flush all pending batch queues.
|
|
639
|
+
*/
|
|
640
|
+
cancelAll(): void;
|
|
641
|
+
/**
|
|
642
|
+
* Get the current status of a resolver by requirement ID.
|
|
643
|
+
*
|
|
644
|
+
* @param requirementId - The unique requirement ID to look up.
|
|
645
|
+
* @returns The {@link ResolverStatus} (idle, pending, running, success, error, or canceled).
|
|
646
|
+
*/
|
|
647
|
+
getStatus(requirementId: string): ResolverStatus;
|
|
648
|
+
/**
|
|
649
|
+
* Get the requirement IDs of all currently in-flight resolvers.
|
|
650
|
+
*
|
|
651
|
+
* @returns An array of requirement ID strings.
|
|
652
|
+
*/
|
|
653
|
+
getInflight(): string[];
|
|
654
|
+
/**
|
|
655
|
+
* Get detailed info for every in-flight resolver.
|
|
656
|
+
*
|
|
657
|
+
* @returns An array of {@link InflightInfo} objects.
|
|
658
|
+
*/
|
|
659
|
+
getInflightInfo(): InflightInfo[];
|
|
660
|
+
/**
|
|
661
|
+
* Check whether a requirement is currently being resolved.
|
|
662
|
+
*
|
|
663
|
+
* @param requirementId - The unique requirement ID to check.
|
|
664
|
+
* @returns `true` if the requirement has an active in-flight resolver.
|
|
665
|
+
*/
|
|
666
|
+
isResolving(requirementId: string): boolean;
|
|
667
|
+
/**
|
|
668
|
+
* Immediately flush all pending batch queues, executing their resolvers.
|
|
669
|
+
*/
|
|
670
|
+
processBatches(): void;
|
|
671
|
+
/**
|
|
672
|
+
* Check whether any batch queues have requirements waiting to be processed.
|
|
673
|
+
*
|
|
674
|
+
* @returns `true` if at least one batch queue is non-empty.
|
|
675
|
+
*/
|
|
676
|
+
hasPendingBatches(): boolean;
|
|
677
|
+
/**
|
|
678
|
+
* Register additional resolver definitions at runtime (used for dynamic
|
|
679
|
+
* module registration).
|
|
680
|
+
*
|
|
681
|
+
* @remarks
|
|
682
|
+
* Clears the resolver-by-type cache so newly registered resolvers are
|
|
683
|
+
* discoverable on the next {@link ResolversManager.resolve | resolve} call.
|
|
684
|
+
*
|
|
685
|
+
* @param newDefs - New resolver definitions to merge into the manager.
|
|
686
|
+
*/
|
|
687
|
+
registerDefinitions(newDefs: ResolversDef<Schema>): void;
|
|
688
|
+
/**
|
|
689
|
+
* Override an existing resolver definition.
|
|
690
|
+
*
|
|
691
|
+
* @param id - The resolver definition ID to override.
|
|
692
|
+
* @param def - The new resolver definition.
|
|
693
|
+
* @throws If no resolver with this ID exists.
|
|
694
|
+
*/
|
|
695
|
+
assignDefinition(id: string, def: ResolversDef<Schema>[string]): void;
|
|
696
|
+
/**
|
|
697
|
+
* Remove a resolver definition. Cancels any inflight resolution.
|
|
698
|
+
*
|
|
699
|
+
* @param id - The resolver definition ID to remove.
|
|
700
|
+
*/
|
|
701
|
+
unregisterDefinition(id: string): void;
|
|
702
|
+
/**
|
|
703
|
+
* Execute a resolver with a given requirement object.
|
|
704
|
+
*
|
|
705
|
+
* @param id - The resolver definition ID.
|
|
706
|
+
* @param requirement - The requirement to resolve.
|
|
707
|
+
*/
|
|
708
|
+
callOne(id: string, requirement: Requirement): Promise<void>;
|
|
709
|
+
/**
|
|
710
|
+
* Clean up all internal state. Called on system destroy.
|
|
711
|
+
*/
|
|
712
|
+
destroy(): void;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Configuration options accepted by {@link createResolversManager}.
|
|
716
|
+
*
|
|
717
|
+
* @internal
|
|
718
|
+
*/
|
|
719
|
+
interface CreateResolversOptions<S extends Schema> {
|
|
720
|
+
/** Resolver definitions keyed by ID. */
|
|
721
|
+
definitions: ResolversDef<S>;
|
|
722
|
+
/** Proxy-based facts object passed to resolver contexts. */
|
|
723
|
+
facts: Facts<S>;
|
|
724
|
+
/** Underlying fact store used for `batch()` coalescing of mutations. */
|
|
725
|
+
store: FactsStore<S>;
|
|
726
|
+
/** Called when a resolver begins execution. */
|
|
727
|
+
onStart?: (resolver: string, req: RequirementWithId) => void;
|
|
728
|
+
/** Called when a resolver completes successfully, with the wall-clock duration in ms. */
|
|
729
|
+
onComplete?: (resolver: string, req: RequirementWithId, duration: number) => void;
|
|
730
|
+
/** Called when a resolver exhausts all retry attempts. */
|
|
731
|
+
onError?: (resolver: string, req: RequirementWithId, error: unknown) => void;
|
|
732
|
+
/** Called before each retry attempt with the upcoming attempt number. */
|
|
733
|
+
onRetry?: (resolver: string, req: RequirementWithId, attempt: number) => void;
|
|
734
|
+
/** Called when a resolver is canceled via {@link ResolversManager.cancel | cancel}. */
|
|
735
|
+
onCancel?: (resolver: string, req: RequirementWithId) => void;
|
|
736
|
+
/** Called after any resolver finishes (success, error, or batch completion) to trigger reconciliation. */
|
|
737
|
+
onResolutionComplete?: () => void;
|
|
738
|
+
}
|
|
739
|
+
declare function createResolversManager<S extends Schema>(options: CreateResolversOptions<S>): ResolversManager<S>;
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Plugin Architecture - Extensible middleware for Directive
|
|
743
|
+
*
|
|
744
|
+
* Features:
|
|
745
|
+
* - Lifecycle hooks for all engine events
|
|
746
|
+
* - Multiple plugins can be composed
|
|
747
|
+
* - Plugins execute in registration order
|
|
748
|
+
*/
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Internal manager that broadcasts lifecycle events to registered {@link Plugin} instances.
|
|
752
|
+
*
|
|
753
|
+
* @remarks
|
|
754
|
+
* PluginManager uses `Schema` (flat) internally because the engine works with
|
|
755
|
+
* flat schemas. The public API uses `ModuleSchema` (consolidated), and the
|
|
756
|
+
* conversion happens in `createSystem`.
|
|
757
|
+
*
|
|
758
|
+
* Plugins execute in registration order. All hook invocations are wrapped in
|
|
759
|
+
* try-catch so a misbehaving plugin never breaks the engine. Duplicate plugin
|
|
760
|
+
* names are detected and the older registration is replaced with a warning.
|
|
761
|
+
*
|
|
762
|
+
* Lifecycle hook categories:
|
|
763
|
+
* - **System lifecycle:** `emitInit`, `emitStart`, `emitStop`, `emitDestroy`
|
|
764
|
+
* - **Facts:** `emitFactSet`, `emitFactDelete`, `emitFactsBatch`
|
|
765
|
+
* - **Derivations:** `emitDerivationCompute`, `emitDerivationInvalidate`
|
|
766
|
+
* - **Reconciliation:** `emitReconcileStart`, `emitReconcileEnd`
|
|
767
|
+
* - **Constraints:** `emitConstraintEvaluate`, `emitConstraintError`
|
|
768
|
+
* - **Requirements:** `emitRequirementCreated`, `emitRequirementMet`, `emitRequirementCanceled`
|
|
769
|
+
* - **Resolvers:** `emitResolverStart`, `emitResolverComplete`, `emitResolverError`, `emitResolverRetry`, `emitResolverCancel`
|
|
770
|
+
* - **Effects:** `emitEffectRun`, `emitEffectError`
|
|
771
|
+
* - **History:** `emitSnapshot`, `emitHistoryNavigate`
|
|
772
|
+
* - **Errors:** `emitError`, `emitErrorRecovery`
|
|
773
|
+
* - **Trace:** `emitTraceComplete`
|
|
774
|
+
*
|
|
775
|
+
* @typeParam _S - The flat schema type (unused at runtime).
|
|
776
|
+
*
|
|
777
|
+
* @internal
|
|
778
|
+
*/
|
|
779
|
+
interface PluginManager<_S extends Schema = any> {
|
|
780
|
+
/** Register a plugin */
|
|
781
|
+
register(plugin: Plugin<any>): void;
|
|
782
|
+
/** Unregister a plugin by name */
|
|
783
|
+
unregister(name: string): void;
|
|
784
|
+
/** Get all registered plugins */
|
|
785
|
+
getPlugins(): Plugin<any>[];
|
|
786
|
+
emitInit(system: System<any>): Promise<void>;
|
|
787
|
+
emitStart(system: System<any>): void;
|
|
788
|
+
emitStop(system: System<any>): void;
|
|
789
|
+
emitDestroy(system: System<any>): void;
|
|
790
|
+
emitFactSet(key: string, value: unknown, prev: unknown): void;
|
|
791
|
+
emitFactDelete(key: string, prev: unknown): void;
|
|
792
|
+
emitFactsBatch(changes: FactChange[]): void;
|
|
793
|
+
emitDerivationCompute(id: string, value: unknown, deps: string[]): void;
|
|
794
|
+
emitDerivationInvalidate(id: string): void;
|
|
795
|
+
emitReconcileStart(snapshot: FactsSnapshot<any>): void;
|
|
796
|
+
emitReconcileEnd(result: ReconcileResult): void;
|
|
797
|
+
emitConstraintEvaluate(id: string, active: boolean): void;
|
|
798
|
+
emitConstraintError(id: string, error: unknown): void;
|
|
799
|
+
emitRequirementCreated(req: RequirementWithId): void;
|
|
800
|
+
emitRequirementMet(req: RequirementWithId, byResolver: string): void;
|
|
801
|
+
emitRequirementCanceled(req: RequirementWithId): void;
|
|
802
|
+
emitResolverStart(resolver: string, req: RequirementWithId): void;
|
|
803
|
+
emitResolverComplete(resolver: string, req: RequirementWithId, duration: number): void;
|
|
804
|
+
emitResolverError(resolver: string, req: RequirementWithId, error: unknown): void;
|
|
805
|
+
emitResolverRetry(resolver: string, req: RequirementWithId, attempt: number): void;
|
|
806
|
+
emitResolverCancel(resolver: string, req: RequirementWithId): void;
|
|
807
|
+
emitEffectRun(id: string): void;
|
|
808
|
+
emitEffectError(id: string, error: unknown): void;
|
|
809
|
+
emitSnapshot(snapshot: Snapshot): void;
|
|
810
|
+
emitHistoryNavigate(from: number, to: number): void;
|
|
811
|
+
emitError(error: DirectiveError): void;
|
|
812
|
+
emitErrorRecovery(error: DirectiveError, strategy: RecoveryStrategy): void;
|
|
813
|
+
emitDefinitionRegister(type: string, id: string, def: unknown): void;
|
|
814
|
+
emitDefinitionAssign(type: string, id: string, def: unknown, original: unknown): void;
|
|
815
|
+
emitDefinitionUnregister(type: string, id: string): void;
|
|
816
|
+
emitDefinitionCall(type: string, id: string, props?: unknown): void;
|
|
817
|
+
emitTraceComplete(run: TraceEntry): void;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Create a {@link PluginManager} that broadcasts lifecycle events to registered plugins.
|
|
821
|
+
*
|
|
822
|
+
* @remarks
|
|
823
|
+
* Plugins are called in registration order. All hook invocations are wrapped
|
|
824
|
+
* in try-catch so a misbehaving plugin never breaks the engine. Duplicate
|
|
825
|
+
* plugin names are detected and the older registration is replaced with a
|
|
826
|
+
* console warning.
|
|
827
|
+
*
|
|
828
|
+
* @returns A {@link PluginManager} with `register`/`unregister`/`getPlugins` and `emit*` methods for every lifecycle event.
|
|
829
|
+
*
|
|
830
|
+
* @internal
|
|
831
|
+
*/
|
|
832
|
+
declare function createPluginManager<S extends Schema = any>(): PluginManager<S>;
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Error Boundaries - Configurable error handling and recovery
|
|
836
|
+
*
|
|
837
|
+
* Features:
|
|
838
|
+
* - Catch errors in constraints/resolvers/effects/derivations
|
|
839
|
+
* - Configurable recovery strategies (skip, retry, retry-later, disable, throw)
|
|
840
|
+
* - Circuit breaker pattern for automatic failure protection
|
|
841
|
+
* - Error reporting to plugins
|
|
842
|
+
*/
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* A queued retry entry tracking its source, attempt count, and scheduled time.
|
|
846
|
+
*
|
|
847
|
+
* @internal
|
|
848
|
+
*/
|
|
849
|
+
interface PendingRetry {
|
|
850
|
+
source: ErrorSource;
|
|
851
|
+
sourceId: string;
|
|
852
|
+
context: unknown;
|
|
853
|
+
attempt: number;
|
|
854
|
+
nextRetryTime: number;
|
|
855
|
+
callback?: () => void;
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Create a manager for deferred retry scheduling with exponential backoff.
|
|
859
|
+
*
|
|
860
|
+
* @remarks
|
|
861
|
+
* Retries are stored in a Map keyed by source ID. Each entry tracks its
|
|
862
|
+
* attempt number and the timestamp of the next eligible retry. When
|
|
863
|
+
* {@link createRetryLaterManager | processDueRetries} is called (typically
|
|
864
|
+
* during reconciliation), entries whose scheduled time has elapsed are
|
|
865
|
+
* returned and removed from the queue. The delay grows exponentially:
|
|
866
|
+
* `delayMs * backoffMultiplier^(attempt - 1)`, capped at `maxDelayMs`.
|
|
867
|
+
*
|
|
868
|
+
* @param config - Backoff configuration including `delayMs`, `maxRetries`, `backoffMultiplier`, and `maxDelayMs`.
|
|
869
|
+
* @returns A manager exposing `scheduleRetry`, `getPendingRetries`, `processDueRetries`, `cancelRetry`, and `clearAll` methods.
|
|
870
|
+
*
|
|
871
|
+
* @internal
|
|
872
|
+
*/
|
|
873
|
+
declare function createRetryLaterManager(config?: RetryLaterConfig): {
|
|
874
|
+
/** Schedule a retry */
|
|
875
|
+
scheduleRetry: (source: ErrorSource, sourceId: string, context: unknown, attempt: number, callback?: () => void) => PendingRetry | null;
|
|
876
|
+
/** Get pending retries */
|
|
877
|
+
getPendingRetries: () => PendingRetry[];
|
|
878
|
+
/** Process due retries */
|
|
879
|
+
processDueRetries: () => PendingRetry[];
|
|
880
|
+
/** Cancel a retry */
|
|
881
|
+
cancelRetry: (sourceId: string) => void;
|
|
882
|
+
/** Clear all pending retries */
|
|
883
|
+
clearAll: () => void;
|
|
884
|
+
};
|
|
885
|
+
/**
|
|
886
|
+
* Handle returned by {@link createErrorBoundaryManager} for routing errors
|
|
887
|
+
* through configurable recovery strategies.
|
|
888
|
+
*
|
|
889
|
+
* @internal
|
|
890
|
+
*/
|
|
891
|
+
interface ErrorBoundaryManager {
|
|
892
|
+
/**
|
|
893
|
+
* Route an error through the configured recovery strategy for its source.
|
|
894
|
+
*
|
|
895
|
+
* @param source - The subsystem that produced the error.
|
|
896
|
+
* @param sourceId - Identifier of the specific constraint, resolver, effect, or derivation.
|
|
897
|
+
* @param error - The thrown value (coerced to {@link DirectiveError} internally).
|
|
898
|
+
* @param context - Optional context forwarded to callbacks and retry entries.
|
|
899
|
+
* @returns The {@link RecoveryStrategy} that was applied.
|
|
900
|
+
*/
|
|
901
|
+
handleError(source: ErrorSource, sourceId: string, error: unknown, context?: unknown): RecoveryStrategy;
|
|
902
|
+
/**
|
|
903
|
+
* Return the most recently recorded error, or `null` if none exist.
|
|
904
|
+
*
|
|
905
|
+
* @returns The last {@link DirectiveError}, or `null`.
|
|
906
|
+
*/
|
|
907
|
+
getLastError(): DirectiveError | null;
|
|
908
|
+
/**
|
|
909
|
+
* Return a snapshot array of all recorded errors (up to the last 100).
|
|
910
|
+
*
|
|
911
|
+
* @returns A shallow copy of the internal error ring buffer.
|
|
912
|
+
*/
|
|
913
|
+
getAllErrors(): DirectiveError[];
|
|
914
|
+
/** Clear all recorded errors. */
|
|
915
|
+
clearErrors(): void;
|
|
916
|
+
/**
|
|
917
|
+
* Access the underlying retry-later manager for advanced scheduling.
|
|
918
|
+
*
|
|
919
|
+
* @returns The {@link createRetryLaterManager} instance used internally.
|
|
920
|
+
*/
|
|
921
|
+
getRetryLaterManager(): ReturnType<typeof createRetryLaterManager>;
|
|
922
|
+
/**
|
|
923
|
+
* Drain and return retry entries whose scheduled time has elapsed.
|
|
924
|
+
*
|
|
925
|
+
* @returns An array of {@link PendingRetry} entries that are now due.
|
|
926
|
+
*/
|
|
927
|
+
processDueRetries(): PendingRetry[];
|
|
928
|
+
/**
|
|
929
|
+
* Reset retry attempt tracking for a source, typically after a successful resolution.
|
|
930
|
+
*
|
|
931
|
+
* @param sourceId - The source identifier whose retry counter should be cleared.
|
|
932
|
+
*/
|
|
933
|
+
clearRetryAttempts(sourceId: string): void;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Options accepted by {@link createErrorBoundaryManager}.
|
|
937
|
+
*
|
|
938
|
+
* @internal
|
|
939
|
+
*/
|
|
940
|
+
interface CreateErrorBoundaryOptions {
|
|
941
|
+
/** Per-source recovery strategies and retry-later tuning. */
|
|
942
|
+
config?: ErrorBoundaryConfig;
|
|
943
|
+
/** Invoked every time an error is recorded, before the recovery strategy runs. */
|
|
944
|
+
onError?: (error: DirectiveError) => void;
|
|
945
|
+
/** Invoked after a recovery strategy has been selected for an error. */
|
|
946
|
+
onRecovery?: (error: DirectiveError, strategy: RecoveryStrategy) => void;
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Create a manager that handles errors from constraints, resolvers, effects,
|
|
950
|
+
* and derivations with configurable per-source recovery strategies.
|
|
951
|
+
*
|
|
952
|
+
* @remarks
|
|
953
|
+
* Five recovery strategies are available:
|
|
954
|
+
*
|
|
955
|
+
* - `"skip"` -- Swallow the error and continue.
|
|
956
|
+
* - `"retry"` -- Signal the caller to retry immediately.
|
|
957
|
+
* - `"retry-later"` -- Enqueue a deferred retry with exponential backoff
|
|
958
|
+
* (delegated to an internal {@link createRetryLaterManager}).
|
|
959
|
+
* - `"disable"` -- Permanently disable the failing source.
|
|
960
|
+
* - `"throw"` -- Re-throw the error as a {@link DirectiveError}.
|
|
961
|
+
*
|
|
962
|
+
* Recent errors are kept in a ring buffer (last 100) for inspection via
|
|
963
|
+
* {@link ErrorBoundaryManager.getAllErrors | getAllErrors}. Each strategy
|
|
964
|
+
* can be configured per source type (`onConstraintError`, `onResolverError`,
|
|
965
|
+
* etc.) or as a callback that dynamically selects a strategy.
|
|
966
|
+
*
|
|
967
|
+
* @param options - Error boundary configuration, plus `onError` and `onRecovery` callbacks for plugin integration.
|
|
968
|
+
* @returns An {@link ErrorBoundaryManager} for routing errors through the configured strategies.
|
|
969
|
+
*
|
|
970
|
+
* @internal
|
|
971
|
+
*/
|
|
972
|
+
declare function createErrorBoundaryManager(options?: CreateErrorBoundaryOptions): ErrorBoundaryManager;
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* History — Snapshot-based state history
|
|
976
|
+
*
|
|
977
|
+
* Features:
|
|
978
|
+
* - Ring buffer of state snapshots
|
|
979
|
+
* - Go back/forward through history
|
|
980
|
+
* - Replay from any snapshot
|
|
981
|
+
* - Export/import state history
|
|
982
|
+
*/
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Internal history manager that extends the public {@link HistoryAPI}
|
|
986
|
+
* with snapshot capture, restoration, and pause/resume controls.
|
|
987
|
+
*
|
|
988
|
+
* @remarks
|
|
989
|
+
* - `takeSnapshot(trigger)` records the current facts into the ring buffer.
|
|
990
|
+
* - `restore(snapshot)` deserializes a snapshot back into the facts store,
|
|
991
|
+
* setting `isRestoring = true` so the engine skips reconciliation.
|
|
992
|
+
* - `pause()` / `resume()` temporarily suspend snapshot recording (e.g.,
|
|
993
|
+
* during bulk imports or programmatic state resets).
|
|
994
|
+
* - `beginChangeset(label)` / `endChangeset()` group consecutive snapshots
|
|
995
|
+
* so `goBack`/`goForward` treat them as a single undo/redo unit.
|
|
996
|
+
*
|
|
997
|
+
* @typeParam _S - The schema type (unused at runtime but preserved for type safety).
|
|
998
|
+
*
|
|
999
|
+
* @internal
|
|
1000
|
+
*/
|
|
1001
|
+
interface HistoryManager<_S extends Schema> extends HistoryAPI {
|
|
1002
|
+
/** Take a snapshot of current state */
|
|
1003
|
+
takeSnapshot(trigger: string): Snapshot;
|
|
1004
|
+
/** Restore facts from a snapshot */
|
|
1005
|
+
restore(snapshot: Snapshot): void;
|
|
1006
|
+
/** Check if history is enabled */
|
|
1007
|
+
readonly isEnabled: boolean;
|
|
1008
|
+
/** True while restoring a snapshot (engine should skip reconciliation) */
|
|
1009
|
+
readonly isRestoring: boolean;
|
|
1010
|
+
/** Pause snapshot taking */
|
|
1011
|
+
pause(): void;
|
|
1012
|
+
/** Resume snapshot taking */
|
|
1013
|
+
resume(): void;
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Options for creating a history manager via {@link createHistoryManager}.
|
|
1017
|
+
*
|
|
1018
|
+
* @typeParam S - The facts schema type.
|
|
1019
|
+
*
|
|
1020
|
+
* @internal
|
|
1021
|
+
*/
|
|
1022
|
+
interface CreateHistoryOptions<S extends Schema> {
|
|
1023
|
+
historyOption: HistoryOption;
|
|
1024
|
+
facts: Facts<S>;
|
|
1025
|
+
store: FactsStore<S>;
|
|
1026
|
+
/** Callback when a snapshot is taken */
|
|
1027
|
+
onSnapshot?: (snapshot: Snapshot) => void;
|
|
1028
|
+
/** Callback when history navigation occurs */
|
|
1029
|
+
onHistoryChange?: (from: number, to: number) => void;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Create a snapshot-based history manager backed by a ring buffer.
|
|
1033
|
+
*
|
|
1034
|
+
* @remarks
|
|
1035
|
+
* Snapshots are taken automatically after fact changes (during reconciliation)
|
|
1036
|
+
* and can be navigated with `goBack`/`goForward`/`goTo`. Use
|
|
1037
|
+
* `beginChangeset(label)` and `endChangeset()` to group multiple snapshots
|
|
1038
|
+
* into a single undo/redo unit. The entire history can be exported to JSON
|
|
1039
|
+
* via `export()` and re-imported with `import()` for cross-session debugging.
|
|
1040
|
+
*
|
|
1041
|
+
* Call `pause()` to temporarily stop recording snapshots (e.g., during bulk
|
|
1042
|
+
* fact imports) and `resume()` to re-enable recording.
|
|
1043
|
+
*
|
|
1044
|
+
* @param options - History config, facts proxy, store, and optional snapshot/history callbacks.
|
|
1045
|
+
* @returns A {@link HistoryManager} with snapshot capture, navigation, changeset, and export/import methods.
|
|
1046
|
+
*
|
|
1047
|
+
* @internal
|
|
1048
|
+
*/
|
|
1049
|
+
declare function createHistoryManager<S extends Schema>(options: CreateHistoryOptions<S>): HistoryManager<S>;
|
|
1050
|
+
/**
|
|
1051
|
+
* Create a no-op history manager for use when history is disabled.
|
|
1052
|
+
*
|
|
1053
|
+
* @remarks
|
|
1054
|
+
* All methods are safe to call but perform no work. This avoids null-checks
|
|
1055
|
+
* throughout the engine -- callers can use the same {@link HistoryManager}
|
|
1056
|
+
* interface regardless of whether history is enabled.
|
|
1057
|
+
*
|
|
1058
|
+
* @returns A {@link HistoryManager} where every method is a no-op and `isEnabled` is `false`.
|
|
1059
|
+
*
|
|
1060
|
+
* @internal
|
|
1061
|
+
*/
|
|
1062
|
+
declare function createDisabledHistory<S extends Schema>(): HistoryManager<S>;
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Engine - The core reconciliation loop
|
|
1066
|
+
*
|
|
1067
|
+
* The engine orchestrates:
|
|
1068
|
+
* 1. Fact changes trigger reconciliation
|
|
1069
|
+
* 2. Constraints produce requirements
|
|
1070
|
+
* 3. Resolvers fulfill requirements
|
|
1071
|
+
* 4. Effects run after stabilization
|
|
1072
|
+
* 5. Derivations are invalidated and recomputed
|
|
1073
|
+
*/
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Create the core Directive reconciliation engine that wires facts, derivations,
|
|
1077
|
+
* effects, constraints, resolvers, plugins, error boundaries, and history
|
|
1078
|
+
* into a single reactive system.
|
|
1079
|
+
*
|
|
1080
|
+
* @remarks
|
|
1081
|
+
* This is the internal factory used by {@link createSystem}. Most users should
|
|
1082
|
+
* call `createSystem` instead, which provides a friendlier API and handles
|
|
1083
|
+
* module composition.
|
|
1084
|
+
*
|
|
1085
|
+
* @param config - Full system configuration including modules, plugins, error boundary settings, and debug options
|
|
1086
|
+
* @returns A {@link System} instance with facts, derive, events, dispatch, subscribe, watch, settle, and lifecycle methods
|
|
1087
|
+
*
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```ts
|
|
1090
|
+
* // Prefer createSystem for most use cases:
|
|
1091
|
+
* import { createSystem, createModule, t } from "@directive-run/core";
|
|
1092
|
+
*
|
|
1093
|
+
* const counter = createModule("counter", {
|
|
1094
|
+
* schema: { count: t.number() },
|
|
1095
|
+
* init: (facts) => { facts.count = 0; },
|
|
1096
|
+
* });
|
|
1097
|
+
*
|
|
1098
|
+
* const system = createSystem({ module: counter });
|
|
1099
|
+
* system.start();
|
|
1100
|
+
* system.facts.count = 42;
|
|
1101
|
+
* ```
|
|
1102
|
+
*
|
|
1103
|
+
* @internal
|
|
1104
|
+
*/
|
|
1105
|
+
declare function createEngine<S extends Schema>(config: SystemConfig<any>): System<any>;
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Dependency tracking context for auto-tracking derivations
|
|
1109
|
+
*
|
|
1110
|
+
* Uses a stack-based approach to handle nested derivation computations.
|
|
1111
|
+
* When a derivation accesses a fact, the tracking context records it.
|
|
1112
|
+
*/
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Get the current tracking context.
|
|
1116
|
+
*
|
|
1117
|
+
* @returns The active {@link TrackingContext}, or a null context (no-op) if
|
|
1118
|
+
* no tracking is active.
|
|
1119
|
+
*
|
|
1120
|
+
* @internal
|
|
1121
|
+
*/
|
|
1122
|
+
declare function getCurrentTracker(): TrackingContext;
|
|
1123
|
+
/**
|
|
1124
|
+
* Check if dependency tracking is currently active.
|
|
1125
|
+
*
|
|
1126
|
+
* @returns `true` if inside a {@link withTracking} call, `false` otherwise.
|
|
1127
|
+
*
|
|
1128
|
+
* @internal
|
|
1129
|
+
*/
|
|
1130
|
+
declare function isTracking(): boolean;
|
|
1131
|
+
/**
|
|
1132
|
+
* Run a function with dependency tracking.
|
|
1133
|
+
*
|
|
1134
|
+
* @remarks
|
|
1135
|
+
* Pushes a fresh tracking context onto the stack, executes `fn`, then pops
|
|
1136
|
+
* the context. Any fact reads inside `fn` are recorded as dependencies.
|
|
1137
|
+
* Nesting is supported — inner calls get their own independent context.
|
|
1138
|
+
*
|
|
1139
|
+
* @param fn - The function to execute under tracking.
|
|
1140
|
+
* @returns An object with the computed `value` and a `deps` Set of accessed
|
|
1141
|
+
* fact keys.
|
|
1142
|
+
*
|
|
1143
|
+
* @internal
|
|
1144
|
+
*/
|
|
1145
|
+
declare function withTracking<T>(fn: () => T): {
|
|
1146
|
+
value: T;
|
|
1147
|
+
deps: Set<string>;
|
|
1148
|
+
};
|
|
1149
|
+
/**
|
|
1150
|
+
* Run a function without tracking.
|
|
1151
|
+
*
|
|
1152
|
+
* @remarks
|
|
1153
|
+
* Temporarily clears the tracking stack so that fact reads inside `fn` do
|
|
1154
|
+
* not register as dependencies. The stack is restored after `fn` returns
|
|
1155
|
+
* (even on error). Useful for side-effect reads that should not trigger
|
|
1156
|
+
* derivation invalidation.
|
|
1157
|
+
*
|
|
1158
|
+
* @param fn - The function to execute without tracking.
|
|
1159
|
+
* @returns The return value of `fn`.
|
|
1160
|
+
*
|
|
1161
|
+
* @internal
|
|
1162
|
+
*/
|
|
1163
|
+
declare function withoutTracking<T>(fn: () => T): T;
|
|
1164
|
+
/**
|
|
1165
|
+
* Track a specific key in the current context.
|
|
1166
|
+
*
|
|
1167
|
+
* @remarks
|
|
1168
|
+
* No-op if no tracking context is active.
|
|
1169
|
+
*
|
|
1170
|
+
* @param key - The fact key to record as a dependency.
|
|
1171
|
+
*
|
|
1172
|
+
* @internal
|
|
1173
|
+
*/
|
|
1174
|
+
declare function trackAccess(key: string): void;
|
|
1175
|
+
|
|
1176
|
+
export { ConstraintState, ConstraintsDef, type DerivationState, type DerivationsDef, type DerivedValues, EffectsDef, ErrorSource, FactChange, FactsStore, type InflightInfo, type PendingRetry, ReconcileResult, RecoveryStrategy, RequirementKeyFn, ResolverStatus, ResolversDef, RetryLaterConfig, createConstraintsManager, createDerivationsManager, createDisabledHistory, createEffectsManager, createEngine, createErrorBoundaryManager, createFacts, createFactsProxy, createFactsStore, createHistoryManager, createPluginManager, createResolversManager, createRetryLaterManager, getCurrentTracker, isTracking, trackAccess, withTracking, withoutTracking };
|