@directive-run/core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/dist/adapter-utils.cjs +2 -0
  4. package/dist/adapter-utils.cjs.map +1 -0
  5. package/dist/adapter-utils.d.cts +230 -0
  6. package/dist/adapter-utils.d.ts +230 -0
  7. package/dist/adapter-utils.js +2 -0
  8. package/dist/adapter-utils.js.map +1 -0
  9. package/dist/index.cjs +35 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +2016 -0
  12. package/dist/index.d.ts +2016 -0
  13. package/dist/index.js +35 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/migration.cjs +25 -0
  16. package/dist/migration.cjs.map +1 -0
  17. package/dist/migration.d.cts +109 -0
  18. package/dist/migration.d.ts +109 -0
  19. package/dist/migration.js +25 -0
  20. package/dist/migration.js.map +1 -0
  21. package/dist/plugins/index.cjs +3 -0
  22. package/dist/plugins/index.cjs.map +1 -0
  23. package/dist/plugins/index.d.cts +697 -0
  24. package/dist/plugins/index.d.ts +697 -0
  25. package/dist/plugins/index.js +3 -0
  26. package/dist/plugins/index.js.map +1 -0
  27. package/dist/plugins-CcwEXXMS.d.cts +1876 -0
  28. package/dist/plugins-CcwEXXMS.d.ts +1876 -0
  29. package/dist/testing.cjs +12 -0
  30. package/dist/testing.cjs.map +1 -0
  31. package/dist/testing.d.cts +235 -0
  32. package/dist/testing.d.ts +235 -0
  33. package/dist/testing.js +12 -0
  34. package/dist/testing.js.map +1 -0
  35. package/dist/utils-4JrY5fk9.d.cts +198 -0
  36. package/dist/utils-4JrY5fk9.d.ts +198 -0
  37. package/dist/worker.cjs +12 -0
  38. package/dist/worker.cjs.map +1 -0
  39. package/dist/worker.d.cts +241 -0
  40. package/dist/worker.d.ts +241 -0
  41. package/dist/worker.js +12 -0
  42. package/dist/worker.js.map +1 -0
  43. package/package.json +85 -0
@@ -0,0 +1,2016 @@
1
+ import { S as Schema, F as Facts, R as Requirement, a as RequirementOutput, b as RetryPolicy, B as BatchConfig, c as ResolverContext, d as SchemaType, e as FactsStore, M as ModuleSchema, T as TypedDerivationsDef, f as TypedEventsDef, E as EffectsDef, g as TypedConstraintsDef, h as TypedResolversDef, i as ModuleHooks, C as CrossModuleDeps, j as CrossModuleDerivationsDef, k as CrossModuleEffectsDef, l as CrossModuleConstraintsDef, m as ModuleDef, n as CreateSystemOptionsSingle, o as SingleModuleSystem, p as ModulesMap, q as CreateSystemOptionsNamed, N as NamespacedSystem, D as DerivationsSchema, r as TypedConstraintDef, s as RequirementOutput$1, I as InferRequirements, P as Plugin, t as DebugConfig, u as ErrorBoundaryConfig, v as InferFacts, w as ExtractSchema, x as RequirementWithId, y as RequirementKeyFn, z as ConstraintsDef, A as ConstraintState, G as ResolversDef, H as ResolverStatus, J as System, K as FactChange, L as FactsSnapshot, O as ReconcileResult, Q as Snapshot, U as DirectiveError, V as RecoveryStrategy, W as ErrorSource, X as RetryLaterConfig, Y as TimeTravelAPI, Z as SystemConfig } from './plugins-CcwEXXMS.cjs';
2
+ export { _ as AnySystem, $ as BatchItemResult, a0 as BatchResolveResults, a1 as CircuitBreakerConfig, a2 as CircuitBreakerState, a3 as CrossModuleConstraintDef, a4 as CrossModuleDerivationFn, a5 as CrossModuleEffectDef, a6 as CrossModuleFactsWithSelf, a7 as DerivationKeys, a8 as DerivationReturnType, a9 as DeriveAccessor, aa as DispatchEventsFromSchema, ab as DistributableSnapshot, ac as DistributableSnapshotOptions, ad as EffectCleanup, ae as EventPayloadSchema, af as EventsAccessor, ag as EventsAccessorFromSchema, ah as EventsDef, ai as EventsSchema, aj as FactKeys, ak as FactReturnType, al as FlexibleEventHandler, am as InferDerivations, an as InferEventPayloadFromSchema, ao as InferEvents, ap as InferRequirementPayloadFromSchema, aq as InferRequirementTypes, ar as InferSchema, as as InferSchemaType, at as InferSelectorState, au as MutableNamespacedFacts, av as NamespacedDerivations, aw as NamespacedEventsAccessor, ax as NamespacedFacts, ay as ObservableKeys, az as RequirementExplanation, aA as RequirementPayloadSchema, aB as RequirementsSchema, aC as SnapshotMeta, aD as SystemEvent, aE as SystemInspection, aF as SystemMode, aG as SystemSnapshot, aH as TimeTravelState, aI as TypedResolverContext, aJ as TypedResolverDef, aK as UnionEvents, aL as isNamespacedSystem, aM as isSingleModuleSystem } from './plugins-CcwEXXMS.cjs';
3
+ export { D as DistributableSnapshotLike, S as SignedSnapshot, a as SnapshotDiff, b as SnapshotDiffEntry, d as diffSnapshots, i as isSignedSnapshot, c as isSnapshotExpired, s as shallowEqual, e as signSnapshot, v as validateSnapshot, f as verifySnapshotSignature } from './utils-4JrY5fk9.cjs';
4
+ export { DirectiveModuleStructure, ReduxSliceConfig, XStateMachineConfig, ZustandStoreConfig, analyzeReduxSlice, analyzeXStateMachine, analyzeZustandStore, generateMigrationChecklist, generateModuleCode } from './migration.cjs';
5
+
6
+ /**
7
+ * Derivation Types - Type definitions for derivations
8
+ */
9
+
10
+ /** Tracking context for auto-dependency detection */
11
+ interface TrackingContext {
12
+ readonly isTracking: boolean;
13
+ track(key: string): void;
14
+ getDependencies(): Set<string>;
15
+ }
16
+ /**
17
+ * Legacy derivation definition function signature.
18
+ * Used internally by the engine.
19
+ *
20
+ * @deprecated For typed derivations, use TypedDerivationsDef from module.ts
21
+ */
22
+ interface DerivationDef<S extends Schema, T, D extends DerivationsDef<S>> {
23
+ (facts: Facts<S>, derive: DerivedValues<S, D>): T;
24
+ }
25
+ /**
26
+ * Legacy map of derivation definitions.
27
+ * Used internally by the engine.
28
+ *
29
+ * @deprecated For typed derivations, use TypedDerivationsDef from module.ts
30
+ */
31
+ type DerivationsDef<S extends Schema> = Record<string, DerivationDef<S, unknown, DerivationsDef<S>>>;
32
+ /**
33
+ * Legacy computed derived values.
34
+ * Used internally by the engine.
35
+ *
36
+ * @deprecated For typed derivations, use InferDerivations from schema.ts
37
+ */
38
+ type DerivedValues<S extends Schema, D extends DerivationsDef<S>> = {
39
+ readonly [K in keyof D]: ReturnType<D[K]>;
40
+ };
41
+ /** Internal derivation state */
42
+ interface DerivationState<T> {
43
+ id: string;
44
+ compute: () => T;
45
+ cachedValue: T | undefined;
46
+ dependencies: Set<string>;
47
+ isStale: boolean;
48
+ isComputing: boolean;
49
+ }
50
+
51
+ /**
52
+ * Type Helpers - External typed constraint and resolver definitions
53
+ *
54
+ * These types enable defining constraints and resolvers with full type safety
55
+ * outside of module definitions, while maintaining proper type inference.
56
+ */
57
+
58
+ /**
59
+ * External constraint definition with full typing.
60
+ * Use this when defining constraints outside of createModule().
61
+ *
62
+ * @typeParam S - The schema type
63
+ * @typeParam R - The requirement type (defaults to Requirement)
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Define a typed constraint factory
68
+ * const createMaxCountConstraint = <S extends Schema>(
69
+ * maxCount: number
70
+ * ): TypedConstraint<S, { type: "RESET_COUNT" }> => ({
71
+ * priority: 10,
72
+ * when: (facts) => (facts as { count: number }).count > maxCount,
73
+ * require: { type: "RESET_COUNT" },
74
+ * });
75
+ *
76
+ * // Use in module
77
+ * const module = createModule("counter", {
78
+ * schema: { count: t.number() },
79
+ * constraints: {
80
+ * maxCount: createMaxCountConstraint(100),
81
+ * },
82
+ * });
83
+ * ```
84
+ */
85
+ interface TypedConstraint<S extends Schema, R extends Requirement = Requirement> {
86
+ /** Priority for ordering (higher runs first) */
87
+ priority?: number;
88
+ /** Mark this constraint as async (avoids runtime detection) */
89
+ async?: boolean;
90
+ /** Condition function (sync or async) */
91
+ when: (facts: Facts<S>) => boolean | Promise<boolean>;
92
+ /**
93
+ * Requirement(s) to produce when condition is met.
94
+ */
95
+ require: RequirementOutput<R> | ((facts: Facts<S>) => RequirementOutput<R>);
96
+ /** Timeout for async constraints (ms) */
97
+ timeout?: number;
98
+ /**
99
+ * Constraint IDs whose resolvers must complete before this constraint is evaluated.
100
+ * - If dependency's `when()` returns false, this constraint proceeds (nothing to wait for)
101
+ * - If dependency's resolver fails, this constraint remains blocked until it succeeds
102
+ * - Cross-module: use the constraint ID as it appears in the merged system
103
+ */
104
+ after?: string[];
105
+ }
106
+ /**
107
+ * External resolver definition with full typing.
108
+ * Use this when defining resolvers outside of createModule().
109
+ *
110
+ * @typeParam S - The schema type
111
+ * @typeParam R - The requirement type (defaults to Requirement)
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * // Define a typed resolver factory
116
+ * interface FetchUserReq extends Requirement {
117
+ * type: "FETCH_USER";
118
+ * userId: string;
119
+ * }
120
+ *
121
+ * const createFetchUserResolver = <S extends Schema>(
122
+ * fetchFn: (userId: string) => Promise<User>
123
+ * ): TypedResolver<S, FetchUserReq> => ({
124
+ * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
125
+ * key: (req) => `fetch-user-${req.userId}`,
126
+ * retry: { attempts: 3, backoff: "exponential" },
127
+ * resolve: async (req, ctx) => {
128
+ * const user = await fetchFn(req.userId);
129
+ * (ctx.facts as { user: User }).user = user;
130
+ * },
131
+ * });
132
+ * ```
133
+ */
134
+ interface TypedResolver<S extends Schema, R extends Requirement = Requirement> {
135
+ /**
136
+ * Requirement type to handle.
137
+ * - String: matches `req.type` directly (e.g., `requirement: "FETCH_USER"`)
138
+ * - Function: type guard predicate (e.g., `requirement: (req) => req.type === "FETCH_USER"`)
139
+ */
140
+ requirement: R["type"] | ((req: Requirement) => req is R);
141
+ /** Custom key function for deduplication */
142
+ key?: (req: R) => string;
143
+ /** Retry policy */
144
+ retry?: RetryPolicy;
145
+ /** Timeout for resolver execution (ms) */
146
+ timeout?: number;
147
+ /** Batch configuration */
148
+ batch?: BatchConfig;
149
+ /** Resolve function for single requirement */
150
+ resolve?: (req: R, ctx: ResolverContext<S>) => Promise<void>;
151
+ /** Resolve function for batched requirements */
152
+ resolveBatch?: (reqs: R[], ctx: ResolverContext<S>) => Promise<void>;
153
+ }
154
+ /**
155
+ * Create a typed constraint factory for a specific schema.
156
+ * This enables creating reusable constraint definitions with proper typing.
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const schema = { count: t.number(), threshold: t.number() };
161
+ * const factory = constraintFactory<typeof schema>();
162
+ *
163
+ * const maxCountConstraint = factory.create({
164
+ * when: (facts) => facts.count > facts.threshold,
165
+ * require: { type: "RESET" },
166
+ * });
167
+ * ```
168
+ */
169
+ declare function constraintFactory<S extends Schema>(): {
170
+ /**
171
+ * Create a typed constraint
172
+ */
173
+ create<R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
174
+ };
175
+ /**
176
+ * Create a typed resolver factory for a specific schema.
177
+ * This enables creating reusable resolver definitions with proper typing.
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const schema = { user: t.object<User>() };
182
+ * const factory = resolverFactory<typeof schema>();
183
+ *
184
+ * const fetchUserResolver = factory.create<FetchUserReq>({
185
+ * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
186
+ * resolve: async (req, ctx) => {
187
+ * ctx.facts.user = await fetchUser(req.userId);
188
+ * },
189
+ * });
190
+ * ```
191
+ */
192
+ declare function resolverFactory<S extends Schema>(): {
193
+ /**
194
+ * Create a typed resolver
195
+ */
196
+ create<R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
197
+ };
198
+ /**
199
+ * Type-safe constraint creator.
200
+ * Simpler alternative to constraintFactory when you don't need a factory pattern.
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const constraint = typedConstraint<typeof schema, { type: "RESET" }>({
205
+ * when: (facts) => facts.count > 100,
206
+ * require: { type: "RESET" },
207
+ * });
208
+ * ```
209
+ */
210
+ declare function typedConstraint<S extends Schema, R extends Requirement = Requirement>(constraint: TypedConstraint<S, R>): TypedConstraint<S, R>;
211
+ /**
212
+ * Type-safe resolver creator.
213
+ * Simpler alternative to resolverFactory when you don't need a factory pattern.
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const resolver = typedResolver<typeof schema, FetchUserReq>({
218
+ * requirement: (req): req is FetchUserReq => req.type === "FETCH_USER",
219
+ * resolve: async (req, ctx) => {
220
+ * ctx.facts.user = await fetchUser(req.userId);
221
+ * },
222
+ * });
223
+ * ```
224
+ */
225
+ declare function typedResolver<S extends Schema, R extends Requirement = Requirement>(resolver: TypedResolver<S, R>): TypedResolver<S, R>;
226
+
227
+ /**
228
+ * Facts Store - Proxy-based reactive state with auto-tracking
229
+ *
230
+ * Features:
231
+ * - Proxy-based access (facts.phase instead of facts.get("phase"))
232
+ * - Automatic dependency tracking via tracking context
233
+ * - Batched updates with coalesced notifications
234
+ * - Granular subscriptions by key
235
+ * - Schema validation in development mode
236
+ */
237
+
238
+ /** Brand symbol for branded types */
239
+ declare const Brand: unique symbol;
240
+ /** Branded type - adds a unique brand to a base type */
241
+ type Branded<T, B extends string> = T & {
242
+ readonly [Brand]: B;
243
+ };
244
+ /** Extended SchemaType with type name for better error messages */
245
+ interface ExtendedSchemaType<T> extends SchemaType<T> {
246
+ readonly _typeName?: string;
247
+ readonly _default?: T | (() => T);
248
+ readonly _transform?: (value: unknown) => T;
249
+ readonly _description?: string;
250
+ readonly _refinements?: Array<{
251
+ predicate: (value: T) => boolean;
252
+ message: string;
253
+ }>;
254
+ /** Mutable - set by array validators to indicate which element failed */
255
+ _lastFailedIndex?: number;
256
+ }
257
+ /** Chainable schema type with all common methods */
258
+ interface ChainableSchemaType<T> extends ExtendedSchemaType<T> {
259
+ default(value: T | (() => T)): ChainableSchemaType<T>;
260
+ transform<U>(fn: (value: T) => U): ChainableSchemaType<U>;
261
+ brand<B extends string>(): ChainableSchemaType<Branded<T, B>>;
262
+ describe(description: string): ChainableSchemaType<T>;
263
+ refine(predicate: (value: T) => boolean, message: string): ChainableSchemaType<T>;
264
+ nullable(): ChainableSchemaType<T | null>;
265
+ optional(): ChainableSchemaType<T | undefined>;
266
+ }
267
+ /**
268
+ * Schema type builders for defining fact types.
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * const module = createModule("example", {
273
+ * schema: {
274
+ * name: t.string(),
275
+ * age: t.number().min(0).max(150),
276
+ * active: t.boolean(),
277
+ * tags: t.array<string>().of(t.string()),
278
+ * user: t.object<{ id: string; email: string }>(),
279
+ * },
280
+ * });
281
+ * ```
282
+ */
283
+ declare const t: {
284
+ /**
285
+ * Create a string schema type.
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * // Basic string
290
+ * schema: { name: t.string() }
291
+ *
292
+ * // String literal union (for type safety)
293
+ * schema: { phase: t.string<"red" | "green" | "yellow">() }
294
+ *
295
+ * // With custom validation
296
+ * schema: { email: t.string().validate(s => s.includes("@")) }
297
+ *
298
+ * // With transform
299
+ * schema: { trimmed: t.string().transform(s => s.trim()) }
300
+ *
301
+ * // With brand
302
+ * schema: { userId: t.string().brand<"UserId">() }
303
+ * ```
304
+ */
305
+ string<T extends string = string>(): ChainableSchemaType<T>;
306
+ /**
307
+ * Create a number schema type with optional min/max constraints.
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * // Basic number
312
+ * schema: { count: t.number() }
313
+ *
314
+ * // With range constraints
315
+ * schema: { age: t.number().min(0).max(150) }
316
+ *
317
+ * // With custom validation
318
+ * schema: { even: t.number().validate(n => n % 2 === 0) }
319
+ *
320
+ * // With default
321
+ * schema: { count: t.number().default(0) }
322
+ *
323
+ * // With transform (from string)
324
+ * schema: { age: t.number().transform(v => parseInt(String(v), 10)) }
325
+ * ```
326
+ */
327
+ number(): ChainableSchemaType<number> & {
328
+ min(n: number): ChainableSchemaType<number> & /*elided*/ any;
329
+ max(n: number): ChainableSchemaType<number> & /*elided*/ any;
330
+ };
331
+ /**
332
+ * Create a boolean schema type.
333
+ *
334
+ * @example
335
+ * ```typescript
336
+ * schema: {
337
+ * active: t.boolean(),
338
+ * verified: t.boolean().default(false),
339
+ * }
340
+ * ```
341
+ */
342
+ boolean(): ChainableSchemaType<boolean>;
343
+ /**
344
+ * Create an array schema type.
345
+ * Can be used with or without element validation:
346
+ * - `t.array<string>()` - Type-only, no element validation
347
+ * - `t.array<string>().of(t.string())` - With element validation
348
+ */
349
+ array<T>(): ChainableSchemaType<T[]> & {
350
+ of(elementType: SchemaType<T>): ChainableSchemaType<T[]> & /*elided*/ any;
351
+ nonEmpty(): ChainableSchemaType<T[]> & /*elided*/ any;
352
+ maxLength(n: number): ChainableSchemaType<T[]> & /*elided*/ any;
353
+ minLength(n: number): ChainableSchemaType<T[]> & /*elided*/ any;
354
+ _lastFailedIndex?: number;
355
+ };
356
+ /**
357
+ * Create an object schema type.
358
+ * Can be used with or without shape validation:
359
+ * - `t.object<User>()` - Type-only, no property validation
360
+ * - `t.object<User>().shape({ name: t.string(), age: t.number() })` - With property validation
361
+ */
362
+ object<T extends Record<string, unknown>>(): ChainableSchemaType<T> & {
363
+ shape(schema: { [K in keyof T]?: SchemaType<T[K]>; }): ChainableSchemaType<T> & /*elided*/ any;
364
+ nonNull(): ChainableSchemaType<T> & /*elided*/ any;
365
+ hasKeys(...keys: string[]): ChainableSchemaType<T> & /*elided*/ any;
366
+ };
367
+ /**
368
+ * Create an any-typed schema (bypasses all validation).
369
+ *
370
+ * @deprecated Use specific types (`t.string()`, `t.object()`, `t.union()`) for type safety.
371
+ * This bypasses all runtime validation.
372
+ *
373
+ * @example
374
+ * ```typescript
375
+ * // Use when type is complex or external
376
+ * schema: {
377
+ * externalApiResponse: t.any<ExternalAPIResponse>(),
378
+ * }
379
+ * ```
380
+ */
381
+ any<T>(): ExtendedSchemaType<T>;
382
+ /**
383
+ * Create an enum schema type for string literal unions.
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * // Define allowed values
388
+ * schema: { status: t.enum("idle", "loading", "success", "error") }
389
+ *
390
+ * // Type is inferred as "idle" | "loading" | "success" | "error"
391
+ * ```
392
+ */
393
+ enum<T extends string>(...values: T[]): ChainableSchemaType<T>;
394
+ /**
395
+ * Create a literal schema type for exact value matching.
396
+ *
397
+ * @example
398
+ * ```typescript
399
+ * // Exact string match
400
+ * schema: { type: t.literal("user") }
401
+ *
402
+ * // Exact number match
403
+ * schema: { version: t.literal(1) }
404
+ *
405
+ * // Exact boolean
406
+ * schema: { enabled: t.literal(true) }
407
+ * ```
408
+ */
409
+ literal<T extends string | number | boolean>(value: T): ChainableSchemaType<T>;
410
+ /**
411
+ * Create a nullable schema type (T | null).
412
+ *
413
+ * @example
414
+ * ```typescript
415
+ * // Nullable string
416
+ * schema: { name: t.nullable(t.string()) }
417
+ *
418
+ * // Nullable object
419
+ * schema: { user: t.nullable(t.object<User>()) }
420
+ * ```
421
+ */
422
+ nullable<T>(innerType: SchemaType<T>): SchemaType<T | null>;
423
+ /**
424
+ * Create an optional schema type (T | undefined).
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * // Optional string
429
+ * schema: { nickname: t.optional(t.string()) }
430
+ *
431
+ * // Optional number
432
+ * schema: { age: t.optional(t.number()) }
433
+ * ```
434
+ */
435
+ optional<T>(innerType: SchemaType<T>): SchemaType<T | undefined>;
436
+ /**
437
+ * Create a union schema type.
438
+ *
439
+ * @example
440
+ * ```typescript
441
+ * // String or number
442
+ * schema: { value: t.union(t.string(), t.number()) }
443
+ *
444
+ * // Multiple types
445
+ * schema: { data: t.union(t.string(), t.number(), t.boolean()) }
446
+ * ```
447
+ */
448
+ union<T extends SchemaType<unknown>[]>(...types: T): ChainableSchemaType<T[number] extends SchemaType<infer U> ? U : never>;
449
+ /**
450
+ * Create a record schema type for dynamic key-value maps.
451
+ *
452
+ * @example
453
+ * ```typescript
454
+ * // Record with string values
455
+ * schema: { metadata: t.record(t.string()) }
456
+ *
457
+ * // Record with number values
458
+ * schema: { scores: t.record(t.number()) }
459
+ * ```
460
+ */
461
+ record<V>(valueType: SchemaType<V>): ChainableSchemaType<Record<string, V>>;
462
+ /**
463
+ * Create a tuple schema type for fixed-length arrays with specific types.
464
+ *
465
+ * @example
466
+ * ```typescript
467
+ * // [string, number] tuple
468
+ * schema: { coord: t.tuple(t.string(), t.number()) }
469
+ *
470
+ * // [x, y, z] coordinates
471
+ * schema: { position: t.tuple(t.number(), t.number(), t.number()) }
472
+ * ```
473
+ */
474
+ tuple<T extends SchemaType<unknown>[]>(...types: T): ChainableSchemaType<{ [K in keyof T]: T[K] extends SchemaType<infer U> ? U : never; }>;
475
+ /**
476
+ * Create a date schema type.
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * schema: { createdAt: t.date() }
481
+ * ```
482
+ */
483
+ date(): ChainableSchemaType<Date>;
484
+ /**
485
+ * Create a UUID schema type.
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * schema: { id: t.uuid() }
490
+ * ```
491
+ */
492
+ uuid(): ChainableSchemaType<string>;
493
+ /**
494
+ * Create an email schema type.
495
+ *
496
+ * @example
497
+ * ```typescript
498
+ * schema: { email: t.email() }
499
+ * ```
500
+ */
501
+ email(): ChainableSchemaType<string>;
502
+ /**
503
+ * Create a URL schema type.
504
+ *
505
+ * @example
506
+ * ```typescript
507
+ * schema: { website: t.url() }
508
+ * ```
509
+ */
510
+ url(): ChainableSchemaType<string>;
511
+ /**
512
+ * Create a bigint schema type.
513
+ *
514
+ * @example
515
+ * ```typescript
516
+ * schema: { largeNumber: t.bigint() }
517
+ * ```
518
+ */
519
+ bigint(): ChainableSchemaType<bigint>;
520
+ };
521
+ /** Options for creating a facts store */
522
+ interface CreateFactsStoreOptions<S extends Schema> {
523
+ schema: S;
524
+ /** Validate values against schema (default: process.env.NODE_ENV !== 'production') */
525
+ validate?: boolean;
526
+ /** Throw on unknown schema keys (default: true in dev mode) */
527
+ strictKeys?: boolean;
528
+ /** Redact sensitive values in error messages */
529
+ redactErrors?: boolean;
530
+ /** Callback when facts change (for plugin hooks) */
531
+ onChange?: (key: string, value: unknown, prev: unknown) => void;
532
+ /** Callback for batch changes */
533
+ onBatch?: (changes: Array<{
534
+ key: string;
535
+ value: unknown;
536
+ prev: unknown;
537
+ type: "set" | "delete";
538
+ }>) => void;
539
+ }
540
+ /**
541
+ * Create a reactive facts store backed by a Map with schema validation,
542
+ * batched mutations, and granular key-level subscriptions.
543
+ *
544
+ * The store is the low-level primitive that powers the `facts` proxy.
545
+ * Most users should use {@link createFacts} or `createModule` instead.
546
+ *
547
+ * @param options - Store configuration including schema, validation settings, and change callbacks
548
+ * @returns A `FactsStore<S>` with get/set/batch/subscribe methods and automatic schema validation
549
+ *
550
+ * @example
551
+ * ```ts
552
+ * const store = createFactsStore({
553
+ * schema: { count: t.number(), name: t.string() },
554
+ * });
555
+ *
556
+ * store.set("count", 1);
557
+ * store.get("count"); // 1
558
+ *
559
+ * store.batch(() => {
560
+ * store.set("count", 2);
561
+ * store.set("name", "hello");
562
+ * }); // listeners fire once after batch completes
563
+ * ```
564
+ */
565
+ declare function createFactsStore<S extends Schema>(options: CreateFactsStoreOptions<S>): FactsStore<S>;
566
+ /**
567
+ * Create a Proxy wrapper around a {@link FactsStore} for clean property-style
568
+ * access (`facts.phase`) with automatic dependency tracking.
569
+ *
570
+ * Reading a property calls `store.get()` (which tracks the access for
571
+ * auto-tracked derivations). Writing a property calls `store.set()` (which
572
+ * validates against the schema). The proxy also exposes `$store` for direct
573
+ * store access and `$snapshot()` for untracked reads.
574
+ *
575
+ * @param store - The underlying facts store to wrap
576
+ * @param schema - The schema definition (used for `ownKeys` enumeration)
577
+ * @returns A `Facts<S>` proxy with property-style get/set and prototype pollution guards
578
+ */
579
+ declare function createFactsProxy<S extends Schema>(store: FactsStore<S>, schema: S): Facts<S>;
580
+ /**
581
+ * Convenience factory that creates both a {@link FactsStore} and its
582
+ * {@link createFactsProxy | proxy wrapper} in a single call.
583
+ *
584
+ * This is the recommended entry point when you need low-level store access
585
+ * outside of `createModule` / `createSystem`.
586
+ *
587
+ * @param options - Same options as {@link createFactsStore}
588
+ * @returns An object with `store` (the reactive Map-backed store) and `facts` (the Proxy accessor)
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * const { store, facts } = createFacts({
593
+ * schema: { phase: t.string<"red" | "green">() },
594
+ * });
595
+ *
596
+ * facts.phase = "red";
597
+ * console.log(facts.phase); // "red"
598
+ * store.subscribe(["phase"], () => console.log("phase changed"));
599
+ * ```
600
+ */
601
+ declare function createFacts<S extends Schema>(options: CreateFactsStoreOptions<S>): {
602
+ store: FactsStore<S>;
603
+ facts: Facts<S>;
604
+ };
605
+
606
+ /**
607
+ * Module - The declarative API for defining Directive modules
608
+ *
609
+ * Modules group related facts, constraints, resolvers, effects, and derivations.
610
+ */
611
+
612
+ /**
613
+ * Module configuration with consolidated schema.
614
+ *
615
+ * derive and events are optional - omit them if your schema has empty derivations/events.
616
+ */
617
+ interface ModuleConfig<M extends ModuleSchema> {
618
+ schema: M;
619
+ init?: (facts: Facts<M["facts"]>) => void;
620
+ derive?: TypedDerivationsDef<M>;
621
+ events?: TypedEventsDef<M>;
622
+ effects?: EffectsDef<M["facts"]>;
623
+ constraints?: TypedConstraintsDef<M>;
624
+ resolvers?: TypedResolversDef<M>;
625
+ hooks?: ModuleHooks<M>;
626
+ }
627
+ /**
628
+ * Module configuration with cross-module dependencies for type-safe access
629
+ * to other modules' facts in effects and constraints.
630
+ *
631
+ * When crossModuleDeps is provided:
632
+ * - Own module facts: `facts.self.*`
633
+ * - Cross-module facts: `facts.{dep}.*`
634
+ *
635
+ * @example
636
+ * ```typescript
637
+ * import { authSchema } from './auth';
638
+ * import { dataSchema } from './data';
639
+ *
640
+ * const uiModule = createModule("ui", {
641
+ * schema: uiSchema,
642
+ * crossModuleDeps: { auth: authSchema, data: dataSchema },
643
+ * effects: {
644
+ * onAuthChange: {
645
+ * run: (facts) => {
646
+ * facts.self.notifications // ✅ own module via "self"
647
+ * facts.auth.isAuthenticated // ✅ cross-module (namespaced)
648
+ * facts.data.users // ✅ cross-module (namespaced)
649
+ * }
650
+ * }
651
+ * },
652
+ * constraints: {
653
+ * fetchWhenAuth: {
654
+ * when: (facts) => facts.auth.isAuthenticated && facts.self.users.length === 0,
655
+ * require: { type: "FETCH_USERS" },
656
+ * }
657
+ * }
658
+ * });
659
+ * ```
660
+ */
661
+ interface ModuleConfigWithDeps<M extends ModuleSchema, Deps extends CrossModuleDeps> {
662
+ schema: M;
663
+ /**
664
+ * Cross-module dependencies for type-safe access in derive/effects/constraints.
665
+ *
666
+ * **Access patterns by context:**
667
+ * - `derive`, `effects`, `constraints`: Use `facts.self.*` for own module, `facts.{dep}.*` for cross-module
668
+ * - `init`, `events`, `resolvers`: Use flat access (`facts.myFact`) - no cross-module access
669
+ *
670
+ * This separation ensures initialization and event handling stay scoped to own module,
671
+ * while observers (derive/effects/constraints) can see across modules.
672
+ *
673
+ * @example
674
+ * ```typescript
675
+ * crossModuleDeps: { auth: authSchema },
676
+ * init: (facts) => { facts.users = []; }, // flat access
677
+ * derive: { count: (facts) => facts.self.users.length }, // facts.self.*
678
+ * effects: { log: { run: (facts) => console.log(facts.auth.token) } }, // facts.{dep}.*
679
+ * ```
680
+ */
681
+ crossModuleDeps: Deps;
682
+ /** Initialize module facts. Uses flat access (`facts.myFact`) to ensure modules initialize independently. */
683
+ init?: (facts: Facts<M["facts"]>) => void;
684
+ /** Derivations with cross-module facts access (`facts.self.*` + `facts.{dep}.*`) */
685
+ derive?: CrossModuleDerivationsDef<M, Deps>;
686
+ /** Event handlers. Uses flat access (`facts.myFact`) to keep mutations scoped to own module. */
687
+ events?: TypedEventsDef<M>;
688
+ /** Effects with cross-module facts access (`facts.self.*` + `facts.{dep}.*`) */
689
+ effects?: CrossModuleEffectsDef<M, Deps>;
690
+ /** Constraints with cross-module facts access (`facts.self.*` + `facts.{dep}.*`) */
691
+ constraints?: CrossModuleConstraintsDef<M, Deps>;
692
+ /** Resolvers. Uses flat access (`ctx.facts.myFact`) to keep async mutations scoped to own module. */
693
+ resolvers?: TypedResolversDef<M>;
694
+ hooks?: ModuleHooks<M>;
695
+ }
696
+ /**
697
+ * Create a module definition with full type inference.
698
+ *
699
+ * The consolidated schema provides:
700
+ * - Derivation composition (`derive.otherDerivation` is typed)
701
+ * - Event dispatch (`system.dispatch({ type: "..." })` has autocomplete)
702
+ * - Resolver requirements (`req.payload` is typed based on requirement type)
703
+ *
704
+ * @example
705
+ * ```ts
706
+ * const trafficLight = createModule("traffic-light", {
707
+ * schema: {
708
+ * facts: {
709
+ * phase: t.string<"red" | "green" | "yellow">(),
710
+ * elapsed: t.number(),
711
+ * },
712
+ * derivations: {
713
+ * isRed: t.boolean(),
714
+ * timeRemaining: t.number(),
715
+ * },
716
+ * events: {
717
+ * tick: {},
718
+ * setPhase: { phase: t.string<"red" | "green" | "yellow">() },
719
+ * },
720
+ * requirements: {
721
+ * TRANSITION: { to: t.string<"red" | "green" | "yellow">() },
722
+ * },
723
+ * },
724
+ * init: (facts) => {
725
+ * facts.phase = "red";
726
+ * facts.elapsed = 0;
727
+ * },
728
+ * derive: {
729
+ * isRed: (facts) => facts.phase === "red",
730
+ * timeRemaining: (facts, derive) => {
731
+ * // derive.isRed is typed as boolean!
732
+ * return derive.isRed ? 30 - facts.elapsed : 0;
733
+ * },
734
+ * },
735
+ * events: {
736
+ * tick: (facts) => { facts.elapsed += 1; },
737
+ * setPhase: (facts, { phase }) => { facts.phase = phase; }, // phase is typed!
738
+ * },
739
+ * constraints: {
740
+ * shouldTransition: {
741
+ * when: (facts) => facts.phase === "red" && facts.elapsed > 30,
742
+ * require: { type: "TRANSITION", to: "green" },
743
+ * },
744
+ * },
745
+ * resolvers: {
746
+ * transition: {
747
+ * requirement: "TRANSITION",
748
+ * resolve: async (req, ctx) => {
749
+ * ctx.facts.phase = req.to; // req.to is typed!
750
+ * ctx.facts.elapsed = 0;
751
+ * },
752
+ * },
753
+ * },
754
+ * });
755
+ * ```
756
+ *
757
+ * @example With cross-module dependencies
758
+ * ```ts
759
+ * import { authSchema } from './auth';
760
+ *
761
+ * const dataModule = createModule("data", {
762
+ * schema: dataSchema,
763
+ * crossModuleDeps: { auth: authSchema },
764
+ * constraints: {
765
+ * fetchWhenAuth: {
766
+ * when: (facts) => {
767
+ * // facts.self.* for own module, facts.auth.* for cross-module
768
+ * return facts.auth.isAuthenticated && facts.self.users.length === 0;
769
+ * },
770
+ * require: { type: "FETCH_USERS" },
771
+ * },
772
+ * },
773
+ * derive: {
774
+ * canFetch: (facts) => facts.auth.isAuthenticated && facts.self.users.length === 0,
775
+ * },
776
+ * });
777
+ * ```
778
+ */
779
+ declare function createModule<const M extends ModuleSchema, const Deps extends CrossModuleDeps>(id: string, config: ModuleConfigWithDeps<M, Deps>): ModuleDef<M>;
780
+ declare function createModule<const M extends ModuleSchema>(id: string, config: ModuleConfig<M>): ModuleDef<M>;
781
+ declare function createModule<const M extends ModuleSchema>(id: string, config: ModuleConfigWithDeps<M, CrossModuleDeps> | ModuleConfig<M>): ModuleDef<M>;
782
+ /**
783
+ * Create a module factory that produces named instances from a single definition.
784
+ * Useful for multi-instance UIs (tabs, panels, multi-tenant) where you need
785
+ * isolated state from the same schema.
786
+ *
787
+ * @example
788
+ * ```typescript
789
+ * const chatRoom = createModuleFactory({
790
+ * schema: {
791
+ * facts: { messages: t.array<string>(), users: t.array<string>() },
792
+ * derivations: { count: t.number() },
793
+ * },
794
+ * init: (facts) => { facts.messages = []; facts.users = []; },
795
+ * derive: { count: (facts) => facts.messages.length },
796
+ * });
797
+ *
798
+ * const system = createSystem({
799
+ * modules: {
800
+ * lobby: chatRoom("lobby"),
801
+ * support: chatRoom("support"),
802
+ * },
803
+ * });
804
+ * ```
805
+ */
806
+ declare function createModuleFactory<const M extends ModuleSchema>(config: ModuleConfig<M>): (name: string) => ModuleDef<M>;
807
+ declare function createModuleFactory<const M extends ModuleSchema, const Deps extends CrossModuleDeps>(config: ModuleConfigWithDeps<M, Deps>): (name: string) => ModuleDef<M>;
808
+
809
+ /**
810
+ * System - The top-level API for creating a Directive runtime
811
+ *
812
+ * A system combines modules with plugins and configuration.
813
+ * Modules are passed as an object with namespaced access:
814
+ *
815
+ * @example
816
+ * ```typescript
817
+ * const system = createSystem({
818
+ * modules: { auth: authModule, data: dataModule },
819
+ * });
820
+ *
821
+ * system.facts.auth.token // Namespaced facts
822
+ * system.derive.data.userCount // Namespaced derivations
823
+ * system.events.auth.login() // Namespaced events
824
+ * ```
825
+ */
826
+
827
+ /**
828
+ * Create a Directive system.
829
+ *
830
+ * Supports two modes:
831
+ * - **Single module**: Use `module` prop for direct access without namespace
832
+ * - **Multiple modules**: Use `modules` prop for namespaced access
833
+ *
834
+ * @example Single module (direct access)
835
+ * ```ts
836
+ * const system = createSystem({ module: counterModule });
837
+ * system.facts.count // Direct access
838
+ * system.events.increment() // Direct events
839
+ * ```
840
+ *
841
+ * @example Multiple modules (namespaced access)
842
+ * ```ts
843
+ * const system = createSystem({
844
+ * modules: { auth: authModule, data: dataModule },
845
+ * });
846
+ * system.facts.auth.token // Namespaced access
847
+ * system.events.auth.login() // Namespaced events
848
+ * ```
849
+ */
850
+ declare function createSystem<S extends ModuleSchema>(options: CreateSystemOptionsSingle<S>): SingleModuleSystem<S>;
851
+ declare function createSystem<const Modules extends ModulesMap>(options: CreateSystemOptionsNamed<Modules>): NamespacedSystem<Modules>;
852
+
853
+ /**
854
+ * Builder Pattern API for Directive Modules
855
+ *
856
+ * An alternative, fluent API for creating modules that provides
857
+ * a more declarative style for module definition.
858
+ *
859
+ * @example
860
+ * ```typescript
861
+ * import { module, t } from '@directive-run/core';
862
+ *
863
+ * const counter = module("counter")
864
+ * .schema({
865
+ * facts: { count: t.number(), lastAction: t.string() },
866
+ * derivations: { doubled: t.number(), isPositive: t.boolean() },
867
+ * events: { increment: {}, decrement: {} },
868
+ * requirements: {},
869
+ * })
870
+ * .init((facts) => {
871
+ * facts.count = 0;
872
+ * facts.lastAction = "";
873
+ * })
874
+ * .derive({
875
+ * doubled: (facts) => facts.count * 2,
876
+ * isPositive: (facts) => facts.count > 0,
877
+ * })
878
+ * .events({
879
+ * increment: (facts) => {
880
+ * facts.count += 1;
881
+ * facts.lastAction = "increment";
882
+ * },
883
+ * decrement: (facts) => {
884
+ * facts.count -= 1;
885
+ * facts.lastAction = "decrement";
886
+ * },
887
+ * })
888
+ * .build();
889
+ * ```
890
+ */
891
+
892
+ /**
893
+ * Module builder interface - provides fluent API for building modules.
894
+ *
895
+ * @typeParam M - The module schema type (set after calling `.schema()`)
896
+ */
897
+ interface ModuleBuilder<M extends ModuleSchema = ModuleSchema> {
898
+ /**
899
+ * Define the schema for this module (facts, derivations, events, requirements).
900
+ */
901
+ schema<NewM extends ModuleSchema>(schema: NewM): ModuleBuilder<NewM>;
902
+ /**
903
+ * Define the initialization function for this module.
904
+ */
905
+ init(initFn: (facts: Facts<M["facts"]>) => void): ModuleBuilder<M>;
906
+ /**
907
+ * Define derivation implementations for this module.
908
+ * Keys must match those declared in schema.derivations.
909
+ */
910
+ derive<D extends Record<string, (facts: Facts<M["facts"]>, derive: DeriveAccessor<M>) => unknown>>(derivations: D): ModuleBuilder<M>;
911
+ /**
912
+ * Define event handler implementations for this module.
913
+ * Keys must match those declared in schema.events.
914
+ */
915
+ events<E extends Record<string, (facts: Facts<M["facts"]>, payload: unknown) => void>>(events: E): ModuleBuilder<M>;
916
+ /**
917
+ * Define effects (side effects) for this module.
918
+ */
919
+ effects(effects: EffectsDef<M["facts"]>): ModuleBuilder<M>;
920
+ /**
921
+ * Define constraints for this module.
922
+ */
923
+ constraints<C extends Record<string, ConstraintDef<M>>>(constraints: C): ModuleBuilder<M>;
924
+ /**
925
+ * Define resolvers for this module.
926
+ */
927
+ resolvers<R extends Record<string, ResolverDef<M>>>(resolvers: R): ModuleBuilder<M>;
928
+ /**
929
+ * Define lifecycle hooks for this module.
930
+ */
931
+ hooks(hooks: ModuleHooks<M>): ModuleBuilder<M>;
932
+ /**
933
+ * Build the module definition.
934
+ */
935
+ build(): ModuleDef<M>;
936
+ }
937
+ /**
938
+ * Accessor for reading other derivations within a derivation function.
939
+ */
940
+ type DeriveAccessor<M extends ModuleSchema> = M["derivations"] extends DerivationsSchema ? {
941
+ readonly [K in keyof M["derivations"]]: InferSchemaType<M["derivations"][K]>;
942
+ } : Record<string, never>;
943
+ /**
944
+ * Infer the TypeScript type from a schema type definition.
945
+ */
946
+ type InferSchemaType<T> = T extends {
947
+ _type: infer U;
948
+ } ? U : any;
949
+ /**
950
+ * Constraint definition for the builder.
951
+ */
952
+ interface ConstraintDef<M extends ModuleSchema> {
953
+ when: (facts: Facts<M["facts"]>) => boolean;
954
+ require: {
955
+ type: string;
956
+ [key: string]: unknown;
957
+ } | ((facts: Facts<M["facts"]>) => {
958
+ type: string;
959
+ [key: string]: unknown;
960
+ } | null);
961
+ priority?: number;
962
+ }
963
+ /**
964
+ * Resolver definition for the builder.
965
+ */
966
+ interface ResolverDef<M extends ModuleSchema> {
967
+ requirement: string | ((req: {
968
+ type: string;
969
+ [key: string]: unknown;
970
+ }) => boolean);
971
+ resolve: (req: {
972
+ type: string;
973
+ [key: string]: unknown;
974
+ }, ctx: {
975
+ facts: Facts<M["facts"]>;
976
+ signal?: AbortSignal;
977
+ }) => void | Promise<void>;
978
+ retry?: {
979
+ attempts?: number;
980
+ backoff?: "linear" | "exponential";
981
+ delay?: number;
982
+ };
983
+ timeout?: number;
984
+ key?: (req: {
985
+ type: string;
986
+ [key: string]: unknown;
987
+ }) => string;
988
+ }
989
+ /**
990
+ * Create a new module builder.
991
+ *
992
+ * @param id - The unique identifier for this module
993
+ * @returns A module builder
994
+ */
995
+ declare function module$1(id: string): ModuleBuilder<ModuleSchema>;
996
+
997
+ /**
998
+ * Constraint Builder API
999
+ *
1000
+ * Fluent builders for creating typed constraint definitions.
1001
+ *
1002
+ * @example Full builder
1003
+ * ```typescript
1004
+ * import { constraint } from '@directive-run/core';
1005
+ *
1006
+ * const escalate = constraint<typeof schema>()
1007
+ * .when(f => f.confidence < 0.7)
1008
+ * .require({ type: 'ESCALATE' })
1009
+ * .priority(50)
1010
+ * .build();
1011
+ * ```
1012
+ *
1013
+ * @example Quick shorthand
1014
+ * ```typescript
1015
+ * import { when } from '@directive-run/core';
1016
+ *
1017
+ * const pause = when<typeof schema>(f => f.errors > 3)
1018
+ * .require({ type: 'PAUSE' });
1019
+ * ```
1020
+ */
1021
+
1022
+ type WhenFn<M extends ModuleSchema> = (facts: Facts<M["facts"]>) => boolean | Promise<boolean>;
1023
+ type RequireValue<M extends ModuleSchema> = RequirementOutput$1<InferRequirements<M>> | ((facts: Facts<M["facts"]>) => RequirementOutput$1<InferRequirements<M>>);
1024
+ /** Builder after constraint() — must call .when() first */
1025
+ interface ConstraintBuilderStart<M extends ModuleSchema> {
1026
+ when(condition: WhenFn<M>): ConstraintBuilderWithWhen<M>;
1027
+ }
1028
+ /** Builder after .when() — must call .require() next */
1029
+ interface ConstraintBuilderWithWhen<M extends ModuleSchema> {
1030
+ require(req: RequireValue<M>): ConstraintBuilderComplete<M>;
1031
+ }
1032
+ /** Builder after .require() — optional chaining + .build() */
1033
+ interface ConstraintBuilderComplete<M extends ModuleSchema> {
1034
+ priority(n: number): ConstraintBuilderComplete<M>;
1035
+ after(...ids: string[]): ConstraintBuilderComplete<M>;
1036
+ deps(...keys: string[]): ConstraintBuilderComplete<M>;
1037
+ timeout(ms: number): ConstraintBuilderComplete<M>;
1038
+ async(value: boolean): ConstraintBuilderComplete<M>;
1039
+ build(): TypedConstraintDef<M>;
1040
+ }
1041
+ /** Result from when().require() — a valid constraint with optional immutable chaining */
1042
+ type WhenConstraint<M extends ModuleSchema> = TypedConstraintDef<M> & {
1043
+ withPriority(n: number): WhenConstraint<M>;
1044
+ withAfter(...ids: string[]): WhenConstraint<M>;
1045
+ withDeps(...keys: string[]): WhenConstraint<M>;
1046
+ withTimeout(ms: number): WhenConstraint<M>;
1047
+ withAsync(value: boolean): WhenConstraint<M>;
1048
+ };
1049
+ /** Result from when() — must call .require() */
1050
+ interface WhenBuilder<M extends ModuleSchema> {
1051
+ require(req: RequireValue<M>): WhenConstraint<M>;
1052
+ }
1053
+ /**
1054
+ * Create a constraint using the full builder pattern.
1055
+ * Requires `.when()`, `.require()`, and `.build()`.
1056
+ *
1057
+ * @example
1058
+ * ```typescript
1059
+ * const c = constraint<typeof schema>()
1060
+ * .when(f => f.phase === "red")
1061
+ * .require({ type: "TRANSITION", to: "green" })
1062
+ * .priority(50)
1063
+ * .after("healthCheck")
1064
+ * .build();
1065
+ * ```
1066
+ */
1067
+ declare function constraint<M extends ModuleSchema>(): ConstraintBuilderStart<M>;
1068
+ /**
1069
+ * Quick shorthand for creating constraints.
1070
+ * Returns a valid constraint directly (no `.build()` needed).
1071
+ *
1072
+ * @example
1073
+ * ```typescript
1074
+ * const pause = when<typeof schema>(f => f.errors > 3)
1075
+ * .require({ type: 'PAUSE' });
1076
+ *
1077
+ * // With optional chaining (immutable — returns new constraint)
1078
+ * const halt = when<typeof schema>(f => f.errors > 10)
1079
+ * .require({ type: 'HALT' })
1080
+ * .withPriority(100)
1081
+ * .withAfter('healthCheck');
1082
+ * ```
1083
+ */
1084
+ declare function when<M extends ModuleSchema>(condition: WhenFn<M>): WhenBuilder<M>;
1085
+
1086
+ /**
1087
+ * System Builder API
1088
+ *
1089
+ * Fluent builder for creating Directive systems.
1090
+ *
1091
+ * @example Single module
1092
+ * ```typescript
1093
+ * import { system } from '@directive-run/core';
1094
+ *
1095
+ * const sys = system()
1096
+ * .module(counterModule)
1097
+ * .plugins([loggingPlugin()])
1098
+ * .debug({ timeTravel: true })
1099
+ * .build();
1100
+ * ```
1101
+ *
1102
+ * @example Multiple modules
1103
+ * ```typescript
1104
+ * const sys = system()
1105
+ * .modules({ auth: authModule, cart: cartModule })
1106
+ * .plugins([loggingPlugin()])
1107
+ * .build();
1108
+ * ```
1109
+ */
1110
+
1111
+ /** Initial builder — must choose .module() or .modules() */
1112
+ interface SystemBuilderStart {
1113
+ module<S extends ModuleSchema>(mod: ModuleDef<S>): SingleModuleSystemBuilder<S>;
1114
+ modules<const Modules extends ModulesMap>(mods: Modules): NamespacedSystemBuilder<Modules>;
1115
+ }
1116
+ /** Builder for single-module system */
1117
+ interface SingleModuleSystemBuilder<S extends ModuleSchema> {
1118
+ plugins(plugins: Array<Plugin<ModuleSchema>>): SingleModuleSystemBuilder<S>;
1119
+ debug(config: DebugConfig): SingleModuleSystemBuilder<S>;
1120
+ errorBoundary(config: ErrorBoundaryConfig): SingleModuleSystemBuilder<S>;
1121
+ tickMs(ms: number): SingleModuleSystemBuilder<S>;
1122
+ zeroConfig(enabled?: boolean): SingleModuleSystemBuilder<S>;
1123
+ initialFacts(facts: Partial<InferFacts<S>>): SingleModuleSystemBuilder<S>;
1124
+ build(): SingleModuleSystem<S>;
1125
+ }
1126
+ /** Builder for namespaced multi-module system */
1127
+ interface NamespacedSystemBuilder<Modules extends ModulesMap> {
1128
+ plugins(plugins: Array<Plugin<ModuleSchema>>): NamespacedSystemBuilder<Modules>;
1129
+ debug(config: DebugConfig): NamespacedSystemBuilder<Modules>;
1130
+ errorBoundary(config: ErrorBoundaryConfig): NamespacedSystemBuilder<Modules>;
1131
+ tickMs(ms: number): NamespacedSystemBuilder<Modules>;
1132
+ zeroConfig(enabled?: boolean): NamespacedSystemBuilder<Modules>;
1133
+ initialFacts(facts: Partial<{
1134
+ [K in keyof Modules]: Partial<InferFacts<ExtractSchema<Modules[K]>>>;
1135
+ }>): NamespacedSystemBuilder<Modules>;
1136
+ initOrder(order: "auto" | "declaration" | Array<keyof Modules & string>): NamespacedSystemBuilder<Modules>;
1137
+ build(): NamespacedSystem<Modules>;
1138
+ }
1139
+ /**
1140
+ * Create a system using the fluent builder pattern.
1141
+ * Choose `.module()` for single-module or `.modules()` for namespaced.
1142
+ *
1143
+ * @example
1144
+ * ```typescript
1145
+ * const sys = system()
1146
+ * .module(counterModule)
1147
+ * .plugins([loggingPlugin()])
1148
+ * .build();
1149
+ * ```
1150
+ */
1151
+ declare function system(): SystemBuilderStart;
1152
+
1153
+ /**
1154
+ * Requirement Status Utilities
1155
+ *
1156
+ * Provides reactive tracking of requirement status for UI feedback.
1157
+ */
1158
+
1159
+ /** Status of a requirement type */
1160
+ interface RequirementTypeStatus {
1161
+ /** Number of pending (unmet) requirements of this type */
1162
+ pending: number;
1163
+ /** Number of inflight (being resolved) requirements of this type */
1164
+ inflight: number;
1165
+ /** Number of failed requirements of this type */
1166
+ failed: number;
1167
+ /** Whether any requirements of this type are loading (pending or inflight) */
1168
+ isLoading: boolean;
1169
+ /** Whether any requirements of this type have failed */
1170
+ hasError: boolean;
1171
+ /** Last error for this type (if any) */
1172
+ lastError: Error | null;
1173
+ }
1174
+ /**
1175
+ * Create a plugin that tracks requirement status for reactive UI updates.
1176
+ *
1177
+ * @example
1178
+ * ```typescript
1179
+ * import { createRequirementStatusPlugin } from '@directive-run/core';
1180
+ *
1181
+ * const statusPlugin = createRequirementStatusPlugin();
1182
+ *
1183
+ * const system = createSystem({
1184
+ * modules: [myModule],
1185
+ * plugins: [statusPlugin.plugin],
1186
+ * });
1187
+ *
1188
+ * // Get status for a requirement type
1189
+ * const status = statusPlugin.getStatus("FETCH_USER");
1190
+ * console.log(status.isLoading, status.hasError);
1191
+ *
1192
+ * // Subscribe to status changes
1193
+ * const unsubscribe = statusPlugin.subscribe(() => {
1194
+ * console.log("Status changed:", statusPlugin.getStatus("FETCH_USER"));
1195
+ * });
1196
+ * ```
1197
+ */
1198
+ declare function createRequirementStatusPlugin(): {
1199
+ plugin: Plugin<never>;
1200
+ getStatus: (type: string) => RequirementTypeStatus;
1201
+ getAllStatus: () => Map<string, RequirementTypeStatus>;
1202
+ subscribe: (listener: () => void) => () => void;
1203
+ reset: () => void;
1204
+ };
1205
+ /**
1206
+ * Create a hook factory for requirement status.
1207
+ * This is designed to be used with React's useSyncExternalStore.
1208
+ *
1209
+ * @example
1210
+ * ```typescript
1211
+ * import { useSyncExternalStore } from 'react';
1212
+ * import { createRequirementStatusPlugin, createStatusHook } from '@directive-run/core';
1213
+ *
1214
+ * const statusPlugin = createRequirementStatusPlugin();
1215
+ * const useRequirementStatus = createStatusHook(statusPlugin);
1216
+ *
1217
+ * function MyComponent() {
1218
+ * const status = useRequirementStatus("FETCH_USER");
1219
+ * if (status.isLoading) return <Spinner />;
1220
+ * if (status.hasError) return <Error error={status.lastError} />;
1221
+ * return <Content />;
1222
+ * }
1223
+ * ```
1224
+ */
1225
+ declare function createStatusHook(statusPlugin: ReturnType<typeof createRequirementStatusPlugin>): (type: string) => RequirementTypeStatus;
1226
+
1227
+ /**
1228
+ * System with Status Plugin Helper
1229
+ *
1230
+ * Convenience function for creating a system with status tracking enabled.
1231
+ */
1232
+
1233
+ /** Options for createSystemWithStatus */
1234
+ interface CreateSystemWithStatusOptions<M extends ModuleSchema> {
1235
+ /** The module to use for the system */
1236
+ module: ModuleDef<M>;
1237
+ /** Additional plugins to include alongside the status plugin */
1238
+ plugins?: Plugin<any>[];
1239
+ /** Debug configuration */
1240
+ debug?: DebugConfig;
1241
+ /** Error boundary configuration */
1242
+ errorBoundary?: ErrorBoundaryConfig;
1243
+ /** Tick interval in milliseconds */
1244
+ tickMs?: number;
1245
+ /** Enable zero-config mode */
1246
+ zeroConfig?: boolean;
1247
+ /** Initial facts to set on the system */
1248
+ initialFacts?: Record<string, any>;
1249
+ }
1250
+ /** Return type for createSystemWithStatus */
1251
+ interface SystemWithStatus<M extends ModuleSchema> {
1252
+ /**
1253
+ * The Directive system instance.
1254
+ * This is a SingleModuleSystem - use system.facts, system.dispatch(), etc.
1255
+ */
1256
+ system: SingleModuleSystem<M>;
1257
+ /** The status plugin for use with useRequirementStatus hooks */
1258
+ statusPlugin: ReturnType<typeof createRequirementStatusPlugin>;
1259
+ }
1260
+ /**
1261
+ * Create a Directive system with a status plugin pre-configured.
1262
+ *
1263
+ * This is a convenience wrapper around `createSystem` and `createRequirementStatusPlugin`
1264
+ * that handles the wiring automatically. The status plugin is added to the system's
1265
+ * plugins array so it receives lifecycle events.
1266
+ *
1267
+ * @param options - System configuration options
1268
+ * @returns An object containing both the system and the statusPlugin
1269
+ *
1270
+ * @example
1271
+ * ```tsx
1272
+ * import { createSystemWithStatus } from '@directive-run/core';
1273
+ * import { useRequirementStatus, useFact } from '@directive-run/react';
1274
+ *
1275
+ * // Simple setup - no provider needed
1276
+ * const { system, statusPlugin } = createSystemWithStatus({
1277
+ * module: myModule,
1278
+ * });
1279
+ * system.start();
1280
+ *
1281
+ * function App() {
1282
+ * const data = useFact(system, "data");
1283
+ * return <LoadingIndicator />;
1284
+ * }
1285
+ *
1286
+ * function LoadingIndicator() {
1287
+ * const status = useRequirementStatus(statusPlugin, "FETCH_DATA");
1288
+ * if (status.isLoading) return <Spinner />;
1289
+ * if (status.hasError) return <Error message={status.lastError?.message} />;
1290
+ * return <Content />;
1291
+ * }
1292
+ * ```
1293
+ */
1294
+ declare function createSystemWithStatus<M extends ModuleSchema>(options: CreateSystemWithStatusOptions<M>): SystemWithStatus<M>;
1295
+
1296
+ /**
1297
+ * Requirements - Typed requirement identity with custom dedupe keys
1298
+ *
1299
+ * Features:
1300
+ * - Type-safe requirement definitions
1301
+ * - Stable identity generation
1302
+ * - Custom key functions for deduplication control
1303
+ * - Requirement comparison and hashing
1304
+ */
1305
+
1306
+ /**
1307
+ * Generate a stable ID for a requirement.
1308
+ * Uses type + sorted properties by default.
1309
+ */
1310
+ declare function generateRequirementId(req: Requirement, keyFn?: RequirementKeyFn): string;
1311
+ /**
1312
+ * Helper to create typed requirements with a fluent API.
1313
+ *
1314
+ * Creates a factory function that produces requirements with a specific type.
1315
+ * Useful for creating requirements in constraint definitions.
1316
+ *
1317
+ * @param type - The requirement type string
1318
+ * @returns A factory function that creates requirements with the given type
1319
+ *
1320
+ * @example
1321
+ * ```typescript
1322
+ * // Create a requirement factory
1323
+ * const fetchUser = req("FETCH_USER");
1324
+ *
1325
+ * // Use in constraint definition
1326
+ * constraints: {
1327
+ * needsUser: {
1328
+ * when: (facts) => facts.userId && !facts.user,
1329
+ * require: fetchUser({ userId: 123, priority: "high" }),
1330
+ * },
1331
+ * }
1332
+ *
1333
+ * // Results in: { type: "FETCH_USER", userId: 123, priority: "high" }
1334
+ * ```
1335
+ */
1336
+ declare function req<T extends string>(type: T): <P extends Record<string, unknown>>(props: P) => Requirement & {
1337
+ type: T;
1338
+ } & P;
1339
+ /**
1340
+ * Check if a requirement matches a type.
1341
+ */
1342
+ declare function isRequirementType<T extends string>(req: Requirement, type: T): req is Requirement & {
1343
+ type: T;
1344
+ };
1345
+ /**
1346
+ * Create a type guard for resolver `requirement` predicate.
1347
+ * Cleaner alternative to writing verbose type guards.
1348
+ *
1349
+ * @example
1350
+ * ```typescript
1351
+ * // With explicit requirement type (recommended for complex types)
1352
+ * interface FetchUserRequirement { type: "FETCH_USER"; userId: string }
1353
+ * requirement: forType<FetchUserRequirement>("FETCH_USER"),
1354
+ * key: (req) => req.userId, // req is FetchUserRequirement
1355
+ *
1356
+ * // Or simple string literal (for basic types)
1357
+ * requirement: forType("FETCH_USER"),
1358
+ * key: (req) => req.type, // req is Requirement & { type: "FETCH_USER" }
1359
+ * ```
1360
+ */
1361
+ declare function forType<R extends Requirement>(type: R["type"]): (req: Requirement) => req is R;
1362
+ declare function forType<T extends string>(type: T): (req: Requirement) => req is Requirement & {
1363
+ type: T;
1364
+ };
1365
+ /**
1366
+ * A set of requirements with automatic deduplication by ID.
1367
+ *
1368
+ * Requirements are uniquely identified by their ID (generated from type + properties).
1369
+ * When adding a requirement with a duplicate ID, the first one wins.
1370
+ *
1371
+ * @example
1372
+ * ```typescript
1373
+ * const set = new RequirementSet();
1374
+ *
1375
+ * // Add requirements
1376
+ * set.add(createRequirementWithId({ type: "FETCH_USER", userId: 1 }, "constraint1"));
1377
+ * set.add(createRequirementWithId({ type: "FETCH_USER", userId: 1 }, "constraint2")); // Ignored (duplicate)
1378
+ *
1379
+ * // Check and retrieve
1380
+ * console.log(set.size); // 1
1381
+ * console.log(set.has("FETCH_USER:{\"userId\":1}")); // true
1382
+ *
1383
+ * // Diff with another set
1384
+ * const newSet = new RequirementSet();
1385
+ * newSet.add(createRequirementWithId({ type: "FETCH_USER", userId: 2 }, "constraint1"));
1386
+ * const { added, removed } = newSet.diff(set);
1387
+ * // added: [{ type: "FETCH_USER", userId: 2 }]
1388
+ * // removed: [{ type: "FETCH_USER", userId: 1 }]
1389
+ * ```
1390
+ */
1391
+ declare class RequirementSet {
1392
+ private map;
1393
+ /**
1394
+ * Add a requirement to the set.
1395
+ * If a requirement with the same ID already exists, it is ignored (first wins).
1396
+ * @param req - The requirement with its computed ID
1397
+ */
1398
+ add(req: RequirementWithId): void;
1399
+ /** Remove a requirement by ID */
1400
+ remove(id: string): boolean;
1401
+ /** Check if a requirement exists */
1402
+ has(id: string): boolean;
1403
+ /** Get a requirement by ID */
1404
+ get(id: string): RequirementWithId | undefined;
1405
+ /** Get all requirements */
1406
+ all(): RequirementWithId[];
1407
+ /** Get all requirement IDs */
1408
+ ids(): string[];
1409
+ /** Get the count of requirements */
1410
+ get size(): number;
1411
+ /** Clear all requirements */
1412
+ clear(): void;
1413
+ /** Create a copy */
1414
+ clone(): RequirementSet;
1415
+ /** Diff with another set - returns added and removed */
1416
+ diff(other: RequirementSet): {
1417
+ added: RequirementWithId[];
1418
+ removed: RequirementWithId[];
1419
+ unchanged: RequirementWithId[];
1420
+ };
1421
+ }
1422
+
1423
+ /**
1424
+ * Derivations - Auto-tracked computed values with composition
1425
+ *
1426
+ * Features:
1427
+ * - Automatic dependency tracking (no manual deps arrays)
1428
+ * - Memoization with smart invalidation
1429
+ * - Derivation composition (derivations can depend on other derivations)
1430
+ * - Circular dependency detection
1431
+ * - Lazy evaluation
1432
+ */
1433
+
1434
+ interface DerivationsManager<S extends Schema, D extends DerivationsDef<S>> {
1435
+ /** Get a derived value (computes if stale) */
1436
+ get<K extends keyof D>(id: K): ReturnType<D[K]>;
1437
+ /** Check if a derivation is stale */
1438
+ isStale(id: keyof D): boolean;
1439
+ /** Invalidate derivations that depend on a fact key */
1440
+ invalidate(factKey: string): void;
1441
+ /** Invalidate derivations for multiple fact keys, notifying listeners once at the end */
1442
+ invalidateMany(factKeys: Iterable<string>): void;
1443
+ /** Invalidate all derivations */
1444
+ invalidateAll(): void;
1445
+ /** Subscribe to derivation changes */
1446
+ subscribe(ids: Array<keyof D>, listener: () => void): () => void;
1447
+ /** Get the proxy for composition */
1448
+ getProxy(): DerivedValues<S, D>;
1449
+ /** Get dependencies for a derivation */
1450
+ getDependencies(id: keyof D): Set<string>;
1451
+ /** Register new derivation definitions (for dynamic module registration) */
1452
+ registerDefinitions(newDefs: DerivationsDef<S>): void;
1453
+ }
1454
+ /** Options for creating a derivations manager */
1455
+ interface CreateDerivationsOptions<S extends Schema, D extends DerivationsDef<S>> {
1456
+ definitions: D;
1457
+ facts: Facts<S>;
1458
+ store: FactsStore<S>;
1459
+ /** Callback when a derivation is computed */
1460
+ onCompute?: (id: string, value: unknown, deps: string[]) => void;
1461
+ /** Callback when a derivation is invalidated */
1462
+ onInvalidate?: (id: string) => void;
1463
+ /** Callback when a derivation errors */
1464
+ onError?: (id: string, error: unknown) => void;
1465
+ }
1466
+ /**
1467
+ * Create a manager for lazily-evaluated, auto-tracked derived values.
1468
+ *
1469
+ * Derivations are memoized computations that automatically track which facts
1470
+ * they read. When a tracked fact changes, the derivation is invalidated and
1471
+ * recomputed on next access. Derivations can depend on other derivations
1472
+ * (composition), and circular dependencies are detected at compute time.
1473
+ *
1474
+ * Notifications are deferred during invalidation so listeners always see
1475
+ * consistent state across multiple simultaneous fact changes.
1476
+ *
1477
+ * @param options - Derivation definitions, facts proxy, store, and optional lifecycle callbacks
1478
+ * @returns A `DerivationsManager` with get/invalidate/subscribe/getProxy methods
1479
+ */
1480
+ declare function createDerivationsManager<S extends Schema, D extends DerivationsDef<S>>(options: CreateDerivationsOptions<S, D>): DerivationsManager<S, D>;
1481
+
1482
+ /**
1483
+ * Effects - Fire-and-forget side effects
1484
+ *
1485
+ * Features:
1486
+ * - Separate from requirement resolution
1487
+ * - Error isolation (never breaks reconciliation)
1488
+ * - Optional explicit dependencies for optimization
1489
+ * - Runs after facts stabilize
1490
+ *
1491
+ * IMPORTANT: Auto-tracking limitations
1492
+ * ------------------------------------
1493
+ * When using auto-tracking (no explicit `deps`), only SYNCHRONOUS fact accesses
1494
+ * are tracked. If your effect reads facts after an `await`, those reads are NOT
1495
+ * tracked and won't trigger the effect on future changes.
1496
+ *
1497
+ * For async effects, always use explicit `deps`:
1498
+ * @example
1499
+ * ```typescript
1500
+ * effects: {
1501
+ * // BAD: fetchData is async, facts.userId read after await won't be tracked
1502
+ * badEffect: {
1503
+ * run: async (facts) => {
1504
+ * await someAsyncOp();
1505
+ * console.log(facts.userId); // NOT tracked!
1506
+ * },
1507
+ * },
1508
+ * // GOOD: explicit deps for async effects
1509
+ * goodEffect: {
1510
+ * deps: ["userId"],
1511
+ * run: async (facts) => {
1512
+ * await someAsyncOp();
1513
+ * console.log(facts.userId); // Works because we declared the dep
1514
+ * },
1515
+ * },
1516
+ * }
1517
+ * ```
1518
+ */
1519
+
1520
+ interface EffectsManager<_S extends Schema = Schema> {
1521
+ /** Run all effects that should trigger based on changes */
1522
+ runEffects(changedKeys: Set<string>): Promise<void>;
1523
+ /** Run all effects unconditionally */
1524
+ runAll(): Promise<void>;
1525
+ /** Disable an effect */
1526
+ disable(id: string): void;
1527
+ /** Enable an effect */
1528
+ enable(id: string): void;
1529
+ /** Check if an effect is enabled */
1530
+ isEnabled(id: string): boolean;
1531
+ /** Run all stored cleanup functions (called on system stop/destroy) */
1532
+ cleanupAll(): void;
1533
+ /** Register new effect definitions (for dynamic module registration) */
1534
+ registerDefinitions(newDefs: EffectsDef<Schema>): void;
1535
+ }
1536
+ /** Options for creating an effects manager */
1537
+ interface CreateEffectsOptions<S extends Schema> {
1538
+ definitions: EffectsDef<S>;
1539
+ facts: Facts<S>;
1540
+ store: FactsStore<S>;
1541
+ /** Callback when an effect runs */
1542
+ onRun?: (id: string) => void;
1543
+ /** Callback when an effect errors */
1544
+ onError?: (id: string, error: unknown) => void;
1545
+ }
1546
+ /**
1547
+ * Create a manager for fire-and-forget side effects that run after facts
1548
+ * stabilize.
1549
+ *
1550
+ * Effects support auto-tracked dependencies (re-tracked on every run to
1551
+ * capture conditional reads) or explicit `deps` arrays. Each effect can
1552
+ * return a cleanup function that runs before the next execution or on
1553
+ * system stop. Errors in effects are isolated and never break the
1554
+ * reconciliation loop.
1555
+ *
1556
+ * @param options - Effect definitions, facts proxy, store, and optional lifecycle callbacks
1557
+ * @returns An `EffectsManager` with runEffects/runAll/enable/disable/cleanupAll methods
1558
+ */
1559
+ declare function createEffectsManager<S extends Schema>(options: CreateEffectsOptions<S>): EffectsManager<S>;
1560
+
1561
+ /**
1562
+ * Constraints - Rules that produce requirements when conditions aren't met
1563
+ *
1564
+ * Features:
1565
+ * - Sync and async constraint evaluation
1566
+ * - Priority ordering (higher runs first)
1567
+ * - Timeout handling for async constraints
1568
+ * - Error isolation
1569
+ */
1570
+
1571
+ interface ConstraintsManager<_S extends Schema> {
1572
+ /** Evaluate all constraints and return unmet requirements */
1573
+ evaluate(changedKeys?: Set<string>): Promise<RequirementWithId[]>;
1574
+ /** Get the current state of a constraint */
1575
+ getState(id: string): ConstraintState | undefined;
1576
+ /** Get all constraint states */
1577
+ getAllStates(): ConstraintState[];
1578
+ /** Disable a constraint */
1579
+ disable(id: string): void;
1580
+ /** Enable a constraint */
1581
+ enable(id: string): void;
1582
+ /** Invalidate constraints that depend on the given fact key */
1583
+ invalidate(factKey: string): void;
1584
+ /** Mark a constraint's resolver as completed (for `after` ordering) */
1585
+ markResolved(constraintId: string): void;
1586
+ /** Check if a constraint has been resolved (for `after` ordering) */
1587
+ isResolved(constraintId: string): boolean;
1588
+ /** Register new constraint definitions (for dynamic module registration) */
1589
+ registerDefinitions(newDefs: ConstraintsDef<Schema>): void;
1590
+ }
1591
+ /** Options for creating a constraints manager */
1592
+ interface CreateConstraintsOptions<S extends Schema> {
1593
+ definitions: ConstraintsDef<S>;
1594
+ facts: Facts<S>;
1595
+ /** Custom key functions for requirements (by constraint ID) */
1596
+ requirementKeys?: Record<string, RequirementKeyFn>;
1597
+ /** Default timeout for async constraints (ms) */
1598
+ defaultTimeout?: number;
1599
+ /** Callback when a constraint is evaluated */
1600
+ onEvaluate?: (id: string, active: boolean) => void;
1601
+ /** Callback when a constraint errors */
1602
+ onError?: (id: string, error: unknown) => void;
1603
+ }
1604
+ /**
1605
+ * Create a manager that evaluates constraint rules and produces unmet
1606
+ * requirements.
1607
+ *
1608
+ * Constraints are evaluated in priority order (higher first), with
1609
+ * topological ordering for same-priority constraints connected by `after`
1610
+ * dependencies. Supports sync and async `when()` predicates, incremental
1611
+ * evaluation based on changed fact keys, and per-constraint enable/disable.
1612
+ *
1613
+ * @param options - Constraint definitions, facts proxy, custom requirement key functions, and lifecycle callbacks
1614
+ * @returns A `ConstraintsManager` with evaluate/invalidate/enable/disable/markResolved methods
1615
+ */
1616
+ declare function createConstraintsManager<S extends Schema>(options: CreateConstraintsOptions<S>): ConstraintsManager<S>;
1617
+
1618
+ /**
1619
+ * Resolvers - Capability-based handlers for requirements
1620
+ *
1621
+ * Features:
1622
+ * - Capability matching (handles predicate)
1623
+ * - Custom dedupe keys
1624
+ * - Retry policies with exponential backoff
1625
+ * - Batched resolution for similar requirements
1626
+ * - Cancellation via AbortController
1627
+ */
1628
+
1629
+ /** Inflight resolver info */
1630
+ interface InflightInfo {
1631
+ id: string;
1632
+ resolverId: string;
1633
+ startedAt: number;
1634
+ }
1635
+ interface ResolversManager<_S extends Schema> {
1636
+ /** Start resolving a requirement */
1637
+ resolve(req: RequirementWithId): void;
1638
+ /** Cancel a resolver by requirement ID */
1639
+ cancel(requirementId: string): void;
1640
+ /** Cancel all inflight resolvers */
1641
+ cancelAll(): void;
1642
+ /** Get status of a resolver by requirement ID */
1643
+ getStatus(requirementId: string): ResolverStatus;
1644
+ /** Get all inflight requirement IDs */
1645
+ getInflight(): string[];
1646
+ /** Get full info for all inflight resolvers */
1647
+ getInflightInfo(): InflightInfo[];
1648
+ /** Check if a requirement is being resolved */
1649
+ isResolving(requirementId: string): boolean;
1650
+ /** Process batched requirements (called periodically) */
1651
+ processBatches(): void;
1652
+ /** Register new resolver definitions (for dynamic module registration) */
1653
+ registerDefinitions(newDefs: ResolversDef<Schema>): void;
1654
+ }
1655
+ /** Options for creating a resolvers manager */
1656
+ interface CreateResolversOptions<S extends Schema> {
1657
+ definitions: ResolversDef<S>;
1658
+ facts: Facts<S>;
1659
+ store: FactsStore<S>;
1660
+ /** Callback when a resolver starts */
1661
+ onStart?: (resolver: string, req: RequirementWithId) => void;
1662
+ /** Callback when a resolver completes */
1663
+ onComplete?: (resolver: string, req: RequirementWithId, duration: number) => void;
1664
+ /** Callback when a resolver errors */
1665
+ onError?: (resolver: string, req: RequirementWithId, error: unknown) => void;
1666
+ /** Callback when a resolver retries */
1667
+ onRetry?: (resolver: string, req: RequirementWithId, attempt: number) => void;
1668
+ /** Callback when a resolver is canceled */
1669
+ onCancel?: (resolver: string, req: RequirementWithId) => void;
1670
+ /** Callback when resolution cycle completes (for reconciliation) */
1671
+ onResolutionComplete?: () => void;
1672
+ }
1673
+ /**
1674
+ * Create a manager that fulfills requirements by matching them to resolver
1675
+ * handlers.
1676
+ *
1677
+ * Resolvers are matched by requirement type (string or predicate). Each
1678
+ * resolution runs with an `AbortController` for cancellation, configurable
1679
+ * retry policies (none/linear/exponential backoff), and optional batching
1680
+ * for grouping similar requirements. Duplicate in-flight requirements are
1681
+ * automatically deduplicated.
1682
+ *
1683
+ * @param options - Resolver definitions, facts proxy, store, and lifecycle callbacks (onStart/onComplete/onError/onRetry/onCancel/onResolutionComplete)
1684
+ * @returns A `ResolversManager` with resolve/cancel/cancelAll/getStatus/processBatches methods
1685
+ */
1686
+ declare function createResolversManager<S extends Schema>(options: CreateResolversOptions<S>): ResolversManager<S>;
1687
+
1688
+ /**
1689
+ * Plugin Architecture - Extensible middleware for Directive
1690
+ *
1691
+ * Features:
1692
+ * - Lifecycle hooks for all engine events
1693
+ * - Multiple plugins can be composed
1694
+ * - Plugins execute in registration order
1695
+ */
1696
+
1697
+ interface PluginManager<_S extends Schema = any> {
1698
+ /** Register a plugin */
1699
+ register(plugin: Plugin<any>): void;
1700
+ /** Unregister a plugin by name */
1701
+ unregister(name: string): void;
1702
+ /** Get all registered plugins */
1703
+ getPlugins(): Plugin<any>[];
1704
+ emitInit(system: System<any>): Promise<void>;
1705
+ emitStart(system: System<any>): void;
1706
+ emitStop(system: System<any>): void;
1707
+ emitDestroy(system: System<any>): void;
1708
+ emitFactSet(key: string, value: unknown, prev: unknown): void;
1709
+ emitFactDelete(key: string, prev: unknown): void;
1710
+ emitFactsBatch(changes: FactChange[]): void;
1711
+ emitDerivationCompute(id: string, value: unknown, deps: string[]): void;
1712
+ emitDerivationInvalidate(id: string): void;
1713
+ emitReconcileStart(snapshot: FactsSnapshot<any>): void;
1714
+ emitReconcileEnd(result: ReconcileResult): void;
1715
+ emitConstraintEvaluate(id: string, active: boolean): void;
1716
+ emitConstraintError(id: string, error: unknown): void;
1717
+ emitRequirementCreated(req: RequirementWithId): void;
1718
+ emitRequirementMet(req: RequirementWithId, byResolver: string): void;
1719
+ emitRequirementCanceled(req: RequirementWithId): void;
1720
+ emitResolverStart(resolver: string, req: RequirementWithId): void;
1721
+ emitResolverComplete(resolver: string, req: RequirementWithId, duration: number): void;
1722
+ emitResolverError(resolver: string, req: RequirementWithId, error: unknown): void;
1723
+ emitResolverRetry(resolver: string, req: RequirementWithId, attempt: number): void;
1724
+ emitResolverCancel(resolver: string, req: RequirementWithId): void;
1725
+ emitEffectRun(id: string): void;
1726
+ emitEffectError(id: string, error: unknown): void;
1727
+ emitSnapshot(snapshot: Snapshot): void;
1728
+ emitTimeTravel(from: number, to: number): void;
1729
+ emitError(error: DirectiveError): void;
1730
+ emitErrorRecovery(error: DirectiveError, strategy: RecoveryStrategy): void;
1731
+ }
1732
+ /**
1733
+ * Create a manager that broadcasts lifecycle events to registered plugins.
1734
+ *
1735
+ * Plugins are called in registration order. All hook invocations are
1736
+ * wrapped in try-catch so a misbehaving plugin never breaks the engine.
1737
+ * Duplicate plugin names are detected and the older registration is
1738
+ * replaced with a warning.
1739
+ *
1740
+ * @returns A `PluginManager` with register/unregister/getPlugins and emit* methods for every lifecycle event
1741
+ */
1742
+ declare function createPluginManager<S extends Schema = any>(): PluginManager<S>;
1743
+
1744
+ /**
1745
+ * Error Boundaries - Configurable error handling and recovery
1746
+ *
1747
+ * Features:
1748
+ * - Catch errors in constraints/resolvers/effects/derivations
1749
+ * - Configurable recovery strategies (skip, retry, retry-later, disable, throw)
1750
+ * - Circuit breaker pattern for automatic failure protection
1751
+ * - Error reporting to plugins
1752
+ */
1753
+
1754
+ /**
1755
+ * Pending retry entry.
1756
+ */
1757
+ interface PendingRetry {
1758
+ source: ErrorSource;
1759
+ sourceId: string;
1760
+ context: unknown;
1761
+ attempt: number;
1762
+ nextRetryTime: number;
1763
+ callback?: () => void;
1764
+ }
1765
+ /**
1766
+ * Create a manager for deferred retry scheduling with exponential backoff.
1767
+ *
1768
+ * Retries are stored in a Map keyed by source ID. Each retry tracks its
1769
+ * attempt number and next retry time. When `processDueRetries()` is called
1770
+ * (typically during reconciliation), entries whose time has elapsed are
1771
+ * returned and removed from the queue.
1772
+ *
1773
+ * @param config - Backoff configuration: `delayMs`, `maxRetries`, `backoffMultiplier`, `maxDelayMs`
1774
+ * @returns A manager with `scheduleRetry`, `getPendingRetries`, `processDueRetries`, `cancelRetry`, and `clearAll` methods
1775
+ */
1776
+ declare function createRetryLaterManager(config?: RetryLaterConfig): {
1777
+ /** Schedule a retry */
1778
+ scheduleRetry: (source: ErrorSource, sourceId: string, context: unknown, attempt: number, callback?: () => void) => PendingRetry | null;
1779
+ /** Get pending retries */
1780
+ getPendingRetries: () => PendingRetry[];
1781
+ /** Process due retries */
1782
+ processDueRetries: () => PendingRetry[];
1783
+ /** Cancel a retry */
1784
+ cancelRetry: (sourceId: string) => void;
1785
+ /** Clear all pending retries */
1786
+ clearAll: () => void;
1787
+ };
1788
+ interface ErrorBoundaryManager {
1789
+ /** Handle an error from a specific source */
1790
+ handleError(source: ErrorSource, sourceId: string, error: unknown, context?: unknown): RecoveryStrategy;
1791
+ /** Get the last error */
1792
+ getLastError(): DirectiveError | null;
1793
+ /** Get all errors */
1794
+ getAllErrors(): DirectiveError[];
1795
+ /** Clear all errors */
1796
+ clearErrors(): void;
1797
+ /** Get retry-later manager */
1798
+ getRetryLaterManager(): ReturnType<typeof createRetryLaterManager>;
1799
+ /** Process due retries (call periodically or on reconcile) */
1800
+ processDueRetries(): PendingRetry[];
1801
+ /** Clear retry attempts for a source ID (call on success) */
1802
+ clearRetryAttempts(sourceId: string): void;
1803
+ }
1804
+ /** Options for creating an error boundary manager */
1805
+ interface CreateErrorBoundaryOptions {
1806
+ config?: ErrorBoundaryConfig;
1807
+ /** Callback when an error occurs */
1808
+ onError?: (error: DirectiveError) => void;
1809
+ /** Callback when recovery is attempted */
1810
+ onRecovery?: (error: DirectiveError, strategy: RecoveryStrategy) => void;
1811
+ }
1812
+ /**
1813
+ * Create a manager that handles errors from constraints, resolvers, effects,
1814
+ * and derivations with configurable per-source recovery strategies.
1815
+ *
1816
+ * Supported strategies: `"skip"` (ignore), `"retry"` (immediate),
1817
+ * `"retry-later"` (deferred with backoff), `"disable"` (turn off source),
1818
+ * and `"throw"` (re-throw). Recent errors are kept in a ring buffer
1819
+ * (last 100) for inspection. The retry-later strategy delegates to an
1820
+ * internal {@link createRetryLaterManager}.
1821
+ *
1822
+ * @param options - Error boundary configuration, plus `onError` and `onRecovery` callbacks for plugin integration
1823
+ * @returns An `ErrorBoundaryManager` with handleError/getLastError/getAllErrors/clearErrors/processDueRetries methods
1824
+ *
1825
+ * @example
1826
+ * ```ts
1827
+ * const boundary = createErrorBoundaryManager({
1828
+ * config: {
1829
+ * onResolverError: "retry-later",
1830
+ * onEffectError: "skip",
1831
+ * retryLater: { maxRetries: 5, delayMs: 500 },
1832
+ * },
1833
+ * onError: (err) => console.error(err.source, err.message),
1834
+ * });
1835
+ *
1836
+ * const strategy = boundary.handleError("resolver", "fetchUser", new Error("timeout"));
1837
+ * // strategy === "retry-later"
1838
+ * ```
1839
+ */
1840
+ declare function createErrorBoundaryManager(options?: CreateErrorBoundaryOptions): ErrorBoundaryManager;
1841
+
1842
+ /**
1843
+ * Time-Travel Debugging - Snapshot-based state history
1844
+ *
1845
+ * Features:
1846
+ * - Ring buffer of state snapshots
1847
+ * - Go back/forward through history
1848
+ * - Replay from any snapshot
1849
+ * - Export/import state history
1850
+ */
1851
+
1852
+ interface TimeTravelManager<_S extends Schema> extends TimeTravelAPI {
1853
+ /** Take a snapshot of current state */
1854
+ takeSnapshot(trigger: string): Snapshot;
1855
+ /** Restore facts from a snapshot */
1856
+ restore(snapshot: Snapshot): void;
1857
+ /** Check if time-travel is enabled */
1858
+ readonly isEnabled: boolean;
1859
+ /** True while restoring a snapshot (engine should skip reconciliation) */
1860
+ readonly isRestoring: boolean;
1861
+ /** Pause snapshot taking */
1862
+ pause(): void;
1863
+ /** Resume snapshot taking */
1864
+ resume(): void;
1865
+ }
1866
+ /** Options for creating a time-travel manager */
1867
+ interface CreateTimeTravelOptions<S extends Schema> {
1868
+ config: DebugConfig;
1869
+ facts: Facts<S>;
1870
+ store: FactsStore<S>;
1871
+ /** Callback when a snapshot is taken */
1872
+ onSnapshot?: (snapshot: Snapshot) => void;
1873
+ /** Callback when time-travel occurs */
1874
+ onTimeTravel?: (from: number, to: number) => void;
1875
+ }
1876
+ /**
1877
+ * Create a snapshot-based time-travel debugger with a ring buffer of state
1878
+ * history.
1879
+ *
1880
+ * Snapshots are taken automatically after fact changes (during
1881
+ * reconciliation) and can be navigated with `goBack`/`goForward`/`goTo`.
1882
+ * Changesets group multiple snapshots into a single undo/redo unit.
1883
+ * The entire history can be exported to JSON and re-imported for
1884
+ * cross-session debugging.
1885
+ *
1886
+ * @param options - Debug config (maxSnapshots, timeTravel flag), facts proxy, store, and snapshot/time-travel callbacks
1887
+ * @returns A `TimeTravelManager` with takeSnapshot/restore/goBack/goForward/goTo/replay/export/import and changeset methods
1888
+ */
1889
+ declare function createTimeTravelManager<S extends Schema>(options: CreateTimeTravelOptions<S>): TimeTravelManager<S>;
1890
+ /**
1891
+ * Create a no-op time-travel manager used when `debug.timeTravel` is
1892
+ * disabled. All methods are safe to call but perform no work.
1893
+ *
1894
+ * @returns A `TimeTravelManager` where every method is a no-op and `isEnabled` is `false`
1895
+ */
1896
+ declare function createDisabledTimeTravel<S extends Schema>(): TimeTravelManager<S>;
1897
+
1898
+ /**
1899
+ * Engine - The core reconciliation loop
1900
+ *
1901
+ * The engine orchestrates:
1902
+ * 1. Fact changes trigger reconciliation
1903
+ * 2. Constraints produce requirements
1904
+ * 3. Resolvers fulfill requirements
1905
+ * 4. Effects run after stabilization
1906
+ * 5. Derivations are invalidated and recomputed
1907
+ */
1908
+
1909
+ /**
1910
+ * Create the core Directive reconciliation engine that wires facts, derivations,
1911
+ * effects, constraints, resolvers, plugins, error boundaries, and time-travel
1912
+ * into a single reactive system.
1913
+ *
1914
+ * This is the internal factory used by `createSystem`. Most users should call
1915
+ * `createSystem` instead, which provides a friendlier API and handles module
1916
+ * composition.
1917
+ *
1918
+ * @param config - Full system configuration: modules, plugins, error boundary settings, and debug options
1919
+ * @returns A `System` instance with facts, derive, events, dispatch, subscribe, watch, settle, and lifecycle methods
1920
+ *
1921
+ * @example
1922
+ * ```ts
1923
+ * // Prefer createSystem for most use cases:
1924
+ * import { createSystem, createModule, t } from "@directive-run/core";
1925
+ *
1926
+ * const counter = createModule("counter", {
1927
+ * schema: { count: t.number() },
1928
+ * init: (facts) => { facts.count = 0; },
1929
+ * });
1930
+ *
1931
+ * const system = createSystem({ module: counter });
1932
+ * system.start();
1933
+ * system.facts.count = 42;
1934
+ * ```
1935
+ */
1936
+ declare function createEngine<S extends Schema>(config: SystemConfig<any>): System<any>;
1937
+
1938
+ /**
1939
+ * Dependency tracking context for auto-tracking derivations
1940
+ *
1941
+ * Uses a stack-based approach to handle nested derivation computations.
1942
+ * When a derivation accesses a fact, the tracking context records it.
1943
+ */
1944
+
1945
+ /**
1946
+ * Get the current tracking context.
1947
+ * Returns null context if no tracking is active.
1948
+ */
1949
+ declare function getCurrentTracker(): TrackingContext;
1950
+ /**
1951
+ * Check if we're currently tracking dependencies.
1952
+ */
1953
+ declare function isTracking(): boolean;
1954
+ /**
1955
+ * Run a function with dependency tracking.
1956
+ * Returns the computed value and the set of dependencies accessed.
1957
+ */
1958
+ declare function withTracking<T>(fn: () => T): {
1959
+ value: T;
1960
+ deps: Set<string>;
1961
+ };
1962
+ /**
1963
+ * Run a function without tracking.
1964
+ * Useful for reading facts without creating dependencies.
1965
+ */
1966
+ declare function withoutTracking<T>(fn: () => T): T;
1967
+ /**
1968
+ * Track a specific key in the current context.
1969
+ * No-op if not currently tracking.
1970
+ */
1971
+ declare function trackAccess(key: string): void;
1972
+
1973
+ /**
1974
+ * @directive-run/core
1975
+ *
1976
+ * Constraint-driven runtime for TypeScript.
1977
+ *
1978
+ * Also available:
1979
+ * - `@directive-run/core/plugins` – Logging, devtools, persistence, observability, circuit breaker
1980
+ * - `@directive-run/core/testing` – Mock resolvers, fake timers, assertion helpers
1981
+ * - `@directive-run/core/migration` – Redux/Zustand/XState migration codemods
1982
+ * - `@directive-run/core/adapter-utils` – Shared framework adapter utilities
1983
+ * - `@directive-run/core/worker` – Web Worker support
1984
+ *
1985
+ * @packageDocumentation
1986
+ */
1987
+
1988
+ /**
1989
+ * Backoff strategy constants for retry policies.
1990
+ * Use for autocomplete when configuring resolver retry policies.
1991
+ *
1992
+ * @example
1993
+ * ```ts
1994
+ * import { Backoff } from '@directive-run/core';
1995
+ *
1996
+ * const resolver = {
1997
+ * requirement: "FETCH_DATA",
1998
+ * retry: {
1999
+ * attempts: 3,
2000
+ * backoff: Backoff.Exponential, // Autocomplete-friendly!
2001
+ * initialDelay: 100,
2002
+ * },
2003
+ * resolve: async (req, ctx) => { ... },
2004
+ * };
2005
+ * ```
2006
+ */
2007
+ declare const Backoff: {
2008
+ /** No delay between retries */
2009
+ readonly None: "none";
2010
+ /** Linear delay increase (initialDelay * attempt) */
2011
+ readonly Linear: "linear";
2012
+ /** Exponential delay increase (initialDelay * 2^attempt) */
2013
+ readonly Exponential: "exponential";
2014
+ };
2015
+
2016
+ export { Backoff, BatchConfig, type Branded, type ChainableSchemaType, type ConstraintBuilderComplete, type ConstraintBuilderStart, type ConstraintBuilderWithWhen, ConstraintState, ConstraintsDef, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleConstraintsDef, CrossModuleDeps, CrossModuleDerivationsDef, CrossModuleEffectsDef, DebugConfig, type DerivationState, type DerivationsDef, DerivationsSchema, type DerivedValues, DirectiveError, EffectsDef, ErrorBoundaryConfig, ErrorSource, type ExtendedSchemaType, FactChange, Facts, FactsSnapshot, FactsStore, InferFacts, InferRequirements, type InflightInfo, type ModuleBuilder, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, type NamespacedSystemBuilder, type PendingRetry, Plugin, ReconcileResult, RecoveryStrategy, Requirement, RequirementKeyFn, RequirementOutput$1 as RequirementOutput, RequirementSet, type RequirementTypeStatus, RequirementWithId, ResolverContext, ResolverStatus, ResolversDef, RetryLaterConfig, RetryPolicy, Schema, SchemaType, SingleModuleSystem, type SingleModuleSystemBuilder, Snapshot, System, type SystemBuilderStart, SystemConfig, TimeTravelAPI, type TypedConstraint, TypedConstraintDef, TypedConstraintsDef, TypedDerivationsDef, TypedEventsDef, type TypedResolver, TypedResolversDef, type WhenBuilder, type WhenConstraint, constraint, constraintFactory, createConstraintsManager, createDerivationsManager, createDisabledTimeTravel, createEffectsManager, createEngine, createErrorBoundaryManager, createFacts, createFactsProxy, createFactsStore, createModule, createModuleFactory, createPluginManager, createRequirementStatusPlugin, createResolversManager, createRetryLaterManager, createStatusHook, createSystem, createSystemWithStatus, createTimeTravelManager, forType, generateRequirementId, getCurrentTracker, isRequirementType, isTracking, module$1 as module, req, resolverFactory, system, t, trackAccess, typedConstraint, typedResolver, when, withTracking, withoutTracking };