@directive-run/core 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/adapter-utils.cjs +1 -1
  2. package/dist/adapter-utils.d.cts +1 -1
  3. package/dist/adapter-utils.d.ts +1 -1
  4. package/dist/adapter-utils.js +1 -1
  5. package/dist/chunk-DDUARSUH.cjs +7 -0
  6. package/dist/chunk-DDUARSUH.cjs.map +1 -0
  7. package/dist/chunk-FK7BD7XT.js +7 -0
  8. package/dist/chunk-FK7BD7XT.js.map +1 -0
  9. package/dist/chunk-GVVNFVEX.js +3 -0
  10. package/dist/chunk-GVVNFVEX.js.map +1 -0
  11. package/dist/chunk-JYGG4RIL.js +16 -0
  12. package/dist/chunk-JYGG4RIL.js.map +1 -0
  13. package/dist/chunk-RCCTZCZZ.cjs +3 -0
  14. package/dist/chunk-RCCTZCZZ.cjs.map +1 -0
  15. package/dist/chunk-U3DN2WML.cjs +16 -0
  16. package/dist/chunk-U3DN2WML.cjs.map +1 -0
  17. package/dist/{helpers-CroApnZa.d.cts → helpers-CCljEIsG.d.cts} +1 -1
  18. package/dist/{helpers-B8RS-sa_.d.ts → helpers-CfZCxxkR.d.ts} +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +307 -8
  22. package/dist/index.d.ts +307 -8
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/internals.cjs +1 -1
  26. package/dist/internals.d.cts +11 -4
  27. package/dist/internals.d.ts +11 -4
  28. package/dist/internals.js +1 -1
  29. package/dist/plugins/index.d.cts +1 -1
  30. package/dist/plugins/index.d.ts +1 -1
  31. package/dist/{plugins-day_qfBB.d.cts → plugins-CLZ3xci0.d.cts} +124 -3
  32. package/dist/{plugins-day_qfBB.d.ts → plugins-CLZ3xci0.d.ts} +124 -3
  33. package/dist/system-F2QGHEG7.js +2 -0
  34. package/dist/{system-5OAYXJIG.js.map → system-F2QGHEG7.js.map} +1 -1
  35. package/dist/system-LZMEZBOA.cjs +2 -0
  36. package/dist/{system-4J3B25OD.cjs.map → system-LZMEZBOA.cjs.map} +1 -1
  37. package/dist/testing.cjs +1 -1
  38. package/dist/testing.cjs.map +1 -1
  39. package/dist/testing.d.cts +37 -2
  40. package/dist/testing.d.ts +37 -2
  41. package/dist/testing.js +1 -1
  42. package/dist/testing.js.map +1 -1
  43. package/dist/worker.cjs +1 -1
  44. package/dist/worker.d.cts +1 -1
  45. package/dist/worker.d.ts +1 -1
  46. package/dist/worker.js +1 -1
  47. package/package.json +1 -1
  48. package/dist/chunk-2HKKISIL.js +0 -3
  49. package/dist/chunk-2HKKISIL.js.map +0 -1
  50. package/dist/chunk-4KFEHIIX.cjs +0 -3
  51. package/dist/chunk-4KFEHIIX.cjs.map +0 -1
  52. package/dist/chunk-KKHSUZA5.cjs +0 -2
  53. package/dist/chunk-KKHSUZA5.cjs.map +0 -1
  54. package/dist/chunk-L76IJROE.cjs +0 -16
  55. package/dist/chunk-L76IJROE.cjs.map +0 -1
  56. package/dist/chunk-LN4YQDLL.js +0 -2
  57. package/dist/chunk-LN4YQDLL.js.map +0 -1
  58. package/dist/chunk-WIMO6TQ3.js +0 -16
  59. package/dist/chunk-WIMO6TQ3.js.map +0 -1
  60. package/dist/system-4J3B25OD.cjs +0 -2
  61. package/dist/system-5OAYXJIG.js +0 -2
@@ -438,6 +438,28 @@ type EventsDef<S extends Schema> = Record<string, FlexibleEventHandler<S>>;
438
438
  * Resolver Types - Type definitions for resolvers
439
439
  */
440
440
 
441
+ /**
442
+ * Jitter strategy applied to the computed retry delay.
443
+ *
444
+ * Jitter spreads synchronized retries across a fleet of clients to
445
+ * prevent thundering-herd against shared services (e.g. Rekor, ACME,
446
+ * upstream APIs) when a regional outage causes every retry pass to
447
+ * wake at the same multiple of the initial delay.
448
+ *
449
+ * - `"none"` (default): no jitter; delay is exactly the computed value.
450
+ * - `"full"`: delay is uniformly distributed in `[0, computedDelay]`.
451
+ * AWS-style "full jitter" — best for thundering-herd protection
452
+ * against shared services at fleet scale.
453
+ * - `"equal"`: delay is `computedDelay/2 + uniform[0, computedDelay/2]`.
454
+ * Bounds the worst-case wait while still spreading retries.
455
+ * - `{ maxMs: number }`: adds `uniform[0, maxMs]` to the computed delay.
456
+ * Useful when bounded jitter is desired regardless of attempt number.
457
+ *
458
+ * Reference: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
459
+ */
460
+ type JitterStrategy = "none" | "full" | "equal" | {
461
+ maxMs: number;
462
+ };
441
463
  /** Retry policy configuration */
442
464
  interface RetryPolicy {
443
465
  /** Maximum number of attempts */
@@ -448,6 +470,17 @@ interface RetryPolicy {
448
470
  initialDelay?: number;
449
471
  /** Maximum delay in ms */
450
472
  maxDelay?: number;
473
+ /**
474
+ * Jitter strategy applied to the computed delay before each retry.
475
+ * Defaults to `"none"`. See {@link JitterStrategy} for options.
476
+ *
477
+ * Jitter is applied AFTER `maxDelay` clamping for `"full"` and `"equal"`
478
+ * strategies (so the jittered range respects `maxDelay`). For
479
+ * `{ maxMs }`, the additive jitter can push the final delay above
480
+ * `maxDelay` by up to `maxMs` — this is intentional, since `maxMs` is
481
+ * the operator's explicit upper bound on the jitter spread.
482
+ */
483
+ jitter?: JitterStrategy;
451
484
  /**
452
485
  * Optional predicate to decide whether to retry after an error.
453
486
  * Return `true` to retry, `false` to stop immediately.
@@ -491,6 +524,44 @@ interface ResolverContext<S extends Schema = Schema> {
491
524
  readonly signal: AbortSignal;
492
525
  /** Returns a read-only snapshot of the current facts state, useful for before/after comparisons inside resolvers. */
493
526
  readonly snapshot: () => FactsSnapshot<S>;
527
+ /**
528
+ * Mark this resolver's owning requirement(s) as eligible for re-evaluation
529
+ * in the next reconciliation pass — even if the constraint that produced
530
+ * them re-emits the same requirement ID.
531
+ *
532
+ * **Default behavior (no requeue):** When a resolver writes facts that
533
+ * cause its owning constraint's `when` to re-evaluate to true with the
534
+ * same requirement ID, Directive's diff logic recognizes the requirement
535
+ * as unchanged and does NOT re-fire the resolver. This is intentional:
536
+ * it prevents accidental infinite loops from resolvers that mutate facts
537
+ * read by their own constraint.
538
+ *
539
+ * **When to use `requeue()`:** Explicit chained pipelines where the
540
+ * resolver knowingly wants to be re-invoked with its updated facts (e.g.
541
+ * a multi-step state machine where each step writes the next pendingAction
542
+ * and requires the constraint to re-fire). Calling `requeue()` opts out of
543
+ * the suppression for *this* invocation only — the next reconcile will
544
+ * treat the still-emitted requirement as freshly added.
545
+ *
546
+ * **When NOT to use it:** Most resolvers. Prefer separate constraints
547
+ * keyed on different `when` predicates, or split mutation kinds so each
548
+ * step produces a distinct requirement ID.
549
+ *
550
+ * @example
551
+ * ```typescript
552
+ * resolve: async (req, ctx) => {
553
+ * if (ctx.facts.pendingAction?.kind === "first") {
554
+ * await doFirst();
555
+ * ctx.facts.pendingAction = { kind: "second" };
556
+ * ctx.requeue(); // re-fire the same constraint with updated state
557
+ * return;
558
+ * }
559
+ * await doSecond();
560
+ * ctx.facts.status = "done";
561
+ * }
562
+ * ```
563
+ */
564
+ readonly requeue: () => void;
494
565
  }
495
566
  /** Single resolver definition (untyped - use TypedResolversDef for type safety) */
496
567
  interface ResolverDef<S extends Schema, R extends Requirement = Requirement> {
@@ -1222,11 +1293,35 @@ declare function isNamespacedSystem(system: AnySystem): boolean;
1222
1293
  */
1223
1294
 
1224
1295
  /** Lifecycle hooks for modules */
1225
- interface ModuleHooks<_M extends ModuleSchema> {
1296
+ interface ModuleHooks<M extends ModuleSchema> {
1226
1297
  onInit?: (system: System<any>) => void;
1227
1298
  onStart?: (system: System<any>) => void;
1228
1299
  onStop?: (system: System<any>) => void;
1229
1300
  onError?: (error: DirectiveError, context: unknown) => void;
1301
+ /**
1302
+ * Called when a resolver owned by this module throws after all retries
1303
+ * have been exhausted. The hook fires *after* the engine's internal error
1304
+ * handling (error boundary, plugin notification, retry decision) so it is
1305
+ * a side-channel observer — not a recovery mechanism.
1306
+ *
1307
+ * Use it to forward resolver failures into module-local error sinks
1308
+ * (logging, telemetry, user-facing toast machines) without coupling those
1309
+ * sinks to the engine's plugin system.
1310
+ *
1311
+ * **Failure isolation:** Errors thrown from inside `onResolverError` are
1312
+ * caught by the engine and logged via `console.error`; they do not abort
1313
+ * the engine or other modules' hooks.
1314
+ *
1315
+ * @param error - The error the resolver threw (already normalized to `Error`).
1316
+ * @param requirement - The requirement object that the failing resolver was handling.
1317
+ * @param ctx - Hook context, including a typed snapshot of this module's facts.
1318
+ */
1319
+ onResolverError?: (error: Error, requirement: {
1320
+ type: string;
1321
+ [key: string]: unknown;
1322
+ }, ctx: {
1323
+ facts: Facts<M["facts"]>;
1324
+ }) => void;
1230
1325
  }
1231
1326
  /** Helper to get derivations schema, defaulting to empty */
1232
1327
  type GetDerivationsSchema<M extends ModuleSchema> = M["derivations"] extends DerivationsSchema ? M["derivations"] : Record<string, never>;
@@ -1390,6 +1485,32 @@ interface TypedResolverContext<M extends ModuleSchema> {
1390
1485
  readonly signal: AbortSignal;
1391
1486
  /** Returns a read-only snapshot of the current facts state, useful for before/after comparisons inside resolvers. */
1392
1487
  readonly snapshot: () => FactsSnapshot<M["facts"]>;
1488
+ /**
1489
+ * Mark this resolver's owning requirement(s) as eligible for re-evaluation
1490
+ * in the next reconciliation pass — even if the constraint that produced
1491
+ * them re-emits the same requirement ID.
1492
+ *
1493
+ * See {@link ResolverContext.requeue} for full semantics and guidance on
1494
+ * when (and when not) to use this. The default behavior — silently
1495
+ * suppressing same-constraint re-fires — is intentional and prevents
1496
+ * accidental loops; `requeue()` is the explicit opt-in for chained
1497
+ * pipelines.
1498
+ *
1499
+ * @example
1500
+ * ```typescript
1501
+ * resolve: async (req, ctx) => {
1502
+ * if (ctx.facts.pendingAction?.kind === "first") {
1503
+ * await doFirst();
1504
+ * ctx.facts.pendingAction = { kind: "second" };
1505
+ * ctx.requeue();
1506
+ * return;
1507
+ * }
1508
+ * await doSecond();
1509
+ * ctx.facts.status = "done";
1510
+ * }
1511
+ * ```
1512
+ */
1513
+ readonly requeue: () => void;
1393
1514
  }
1394
1515
  /**
1395
1516
  * Helper to extract a specific requirement type from the schema.
@@ -2049,8 +2170,8 @@ type ObservationEvent = {
2049
2170
  type: "reconcile.start";
2050
2171
  } | {
2051
2172
  type: "reconcile.end";
2052
- added: number;
2053
- removed: number;
2173
+ resolversCompleted: number;
2174
+ resolversCanceled: number;
2054
2175
  } | {
2055
2176
  type: "system.init";
2056
2177
  } | {
@@ -438,6 +438,28 @@ type EventsDef<S extends Schema> = Record<string, FlexibleEventHandler<S>>;
438
438
  * Resolver Types - Type definitions for resolvers
439
439
  */
440
440
 
441
+ /**
442
+ * Jitter strategy applied to the computed retry delay.
443
+ *
444
+ * Jitter spreads synchronized retries across a fleet of clients to
445
+ * prevent thundering-herd against shared services (e.g. Rekor, ACME,
446
+ * upstream APIs) when a regional outage causes every retry pass to
447
+ * wake at the same multiple of the initial delay.
448
+ *
449
+ * - `"none"` (default): no jitter; delay is exactly the computed value.
450
+ * - `"full"`: delay is uniformly distributed in `[0, computedDelay]`.
451
+ * AWS-style "full jitter" — best for thundering-herd protection
452
+ * against shared services at fleet scale.
453
+ * - `"equal"`: delay is `computedDelay/2 + uniform[0, computedDelay/2]`.
454
+ * Bounds the worst-case wait while still spreading retries.
455
+ * - `{ maxMs: number }`: adds `uniform[0, maxMs]` to the computed delay.
456
+ * Useful when bounded jitter is desired regardless of attempt number.
457
+ *
458
+ * Reference: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
459
+ */
460
+ type JitterStrategy = "none" | "full" | "equal" | {
461
+ maxMs: number;
462
+ };
441
463
  /** Retry policy configuration */
442
464
  interface RetryPolicy {
443
465
  /** Maximum number of attempts */
@@ -448,6 +470,17 @@ interface RetryPolicy {
448
470
  initialDelay?: number;
449
471
  /** Maximum delay in ms */
450
472
  maxDelay?: number;
473
+ /**
474
+ * Jitter strategy applied to the computed delay before each retry.
475
+ * Defaults to `"none"`. See {@link JitterStrategy} for options.
476
+ *
477
+ * Jitter is applied AFTER `maxDelay` clamping for `"full"` and `"equal"`
478
+ * strategies (so the jittered range respects `maxDelay`). For
479
+ * `{ maxMs }`, the additive jitter can push the final delay above
480
+ * `maxDelay` by up to `maxMs` — this is intentional, since `maxMs` is
481
+ * the operator's explicit upper bound on the jitter spread.
482
+ */
483
+ jitter?: JitterStrategy;
451
484
  /**
452
485
  * Optional predicate to decide whether to retry after an error.
453
486
  * Return `true` to retry, `false` to stop immediately.
@@ -491,6 +524,44 @@ interface ResolverContext<S extends Schema = Schema> {
491
524
  readonly signal: AbortSignal;
492
525
  /** Returns a read-only snapshot of the current facts state, useful for before/after comparisons inside resolvers. */
493
526
  readonly snapshot: () => FactsSnapshot<S>;
527
+ /**
528
+ * Mark this resolver's owning requirement(s) as eligible for re-evaluation
529
+ * in the next reconciliation pass — even if the constraint that produced
530
+ * them re-emits the same requirement ID.
531
+ *
532
+ * **Default behavior (no requeue):** When a resolver writes facts that
533
+ * cause its owning constraint's `when` to re-evaluate to true with the
534
+ * same requirement ID, Directive's diff logic recognizes the requirement
535
+ * as unchanged and does NOT re-fire the resolver. This is intentional:
536
+ * it prevents accidental infinite loops from resolvers that mutate facts
537
+ * read by their own constraint.
538
+ *
539
+ * **When to use `requeue()`:** Explicit chained pipelines where the
540
+ * resolver knowingly wants to be re-invoked with its updated facts (e.g.
541
+ * a multi-step state machine where each step writes the next pendingAction
542
+ * and requires the constraint to re-fire). Calling `requeue()` opts out of
543
+ * the suppression for *this* invocation only — the next reconcile will
544
+ * treat the still-emitted requirement as freshly added.
545
+ *
546
+ * **When NOT to use it:** Most resolvers. Prefer separate constraints
547
+ * keyed on different `when` predicates, or split mutation kinds so each
548
+ * step produces a distinct requirement ID.
549
+ *
550
+ * @example
551
+ * ```typescript
552
+ * resolve: async (req, ctx) => {
553
+ * if (ctx.facts.pendingAction?.kind === "first") {
554
+ * await doFirst();
555
+ * ctx.facts.pendingAction = { kind: "second" };
556
+ * ctx.requeue(); // re-fire the same constraint with updated state
557
+ * return;
558
+ * }
559
+ * await doSecond();
560
+ * ctx.facts.status = "done";
561
+ * }
562
+ * ```
563
+ */
564
+ readonly requeue: () => void;
494
565
  }
495
566
  /** Single resolver definition (untyped - use TypedResolversDef for type safety) */
496
567
  interface ResolverDef<S extends Schema, R extends Requirement = Requirement> {
@@ -1222,11 +1293,35 @@ declare function isNamespacedSystem(system: AnySystem): boolean;
1222
1293
  */
1223
1294
 
1224
1295
  /** Lifecycle hooks for modules */
1225
- interface ModuleHooks<_M extends ModuleSchema> {
1296
+ interface ModuleHooks<M extends ModuleSchema> {
1226
1297
  onInit?: (system: System<any>) => void;
1227
1298
  onStart?: (system: System<any>) => void;
1228
1299
  onStop?: (system: System<any>) => void;
1229
1300
  onError?: (error: DirectiveError, context: unknown) => void;
1301
+ /**
1302
+ * Called when a resolver owned by this module throws after all retries
1303
+ * have been exhausted. The hook fires *after* the engine's internal error
1304
+ * handling (error boundary, plugin notification, retry decision) so it is
1305
+ * a side-channel observer — not a recovery mechanism.
1306
+ *
1307
+ * Use it to forward resolver failures into module-local error sinks
1308
+ * (logging, telemetry, user-facing toast machines) without coupling those
1309
+ * sinks to the engine's plugin system.
1310
+ *
1311
+ * **Failure isolation:** Errors thrown from inside `onResolverError` are
1312
+ * caught by the engine and logged via `console.error`; they do not abort
1313
+ * the engine or other modules' hooks.
1314
+ *
1315
+ * @param error - The error the resolver threw (already normalized to `Error`).
1316
+ * @param requirement - The requirement object that the failing resolver was handling.
1317
+ * @param ctx - Hook context, including a typed snapshot of this module's facts.
1318
+ */
1319
+ onResolverError?: (error: Error, requirement: {
1320
+ type: string;
1321
+ [key: string]: unknown;
1322
+ }, ctx: {
1323
+ facts: Facts<M["facts"]>;
1324
+ }) => void;
1230
1325
  }
1231
1326
  /** Helper to get derivations schema, defaulting to empty */
1232
1327
  type GetDerivationsSchema<M extends ModuleSchema> = M["derivations"] extends DerivationsSchema ? M["derivations"] : Record<string, never>;
@@ -1390,6 +1485,32 @@ interface TypedResolverContext<M extends ModuleSchema> {
1390
1485
  readonly signal: AbortSignal;
1391
1486
  /** Returns a read-only snapshot of the current facts state, useful for before/after comparisons inside resolvers. */
1392
1487
  readonly snapshot: () => FactsSnapshot<M["facts"]>;
1488
+ /**
1489
+ * Mark this resolver's owning requirement(s) as eligible for re-evaluation
1490
+ * in the next reconciliation pass — even if the constraint that produced
1491
+ * them re-emits the same requirement ID.
1492
+ *
1493
+ * See {@link ResolverContext.requeue} for full semantics and guidance on
1494
+ * when (and when not) to use this. The default behavior — silently
1495
+ * suppressing same-constraint re-fires — is intentional and prevents
1496
+ * accidental loops; `requeue()` is the explicit opt-in for chained
1497
+ * pipelines.
1498
+ *
1499
+ * @example
1500
+ * ```typescript
1501
+ * resolve: async (req, ctx) => {
1502
+ * if (ctx.facts.pendingAction?.kind === "first") {
1503
+ * await doFirst();
1504
+ * ctx.facts.pendingAction = { kind: "second" };
1505
+ * ctx.requeue();
1506
+ * return;
1507
+ * }
1508
+ * await doSecond();
1509
+ * ctx.facts.status = "done";
1510
+ * }
1511
+ * ```
1512
+ */
1513
+ readonly requeue: () => void;
1393
1514
  }
1394
1515
  /**
1395
1516
  * Helper to extract a specific requirement type from the schema.
@@ -2049,8 +2170,8 @@ type ObservationEvent = {
2049
2170
  type: "reconcile.start";
2050
2171
  } | {
2051
2172
  type: "reconcile.end";
2052
- added: number;
2053
- removed: number;
2173
+ resolversCompleted: number;
2174
+ resolversCanceled: number;
2054
2175
  } | {
2055
2176
  type: "system.init";
2056
2177
  } | {
@@ -0,0 +1,2 @@
1
+ export{a as createSystem}from'./chunk-JYGG4RIL.js';import'./chunk-GVVNFVEX.js';import'./chunk-FK7BD7XT.js';import'./chunk-4CMO5OVZ.js';//# sourceMappingURL=system-F2QGHEG7.js.map
2
+ //# sourceMappingURL=system-F2QGHEG7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"system-5OAYXJIG.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"system-F2QGHEG7.js"}
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkU3DN2WML_cjs=require('./chunk-U3DN2WML.cjs');require('./chunk-RCCTZCZZ.cjs'),require('./chunk-DDUARSUH.cjs'),require('./chunk-BEJ6ICA7.cjs');Object.defineProperty(exports,"createSystem",{enumerable:true,get:function(){return chunkU3DN2WML_cjs.a}});//# sourceMappingURL=system-LZMEZBOA.cjs.map
2
+ //# sourceMappingURL=system-LZMEZBOA.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"system-4J3B25OD.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"system-LZMEZBOA.cjs"}
package/dist/testing.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkL76IJROE_cjs=require('./chunk-L76IJROE.cjs');require('./chunk-4KFEHIIX.cjs'),require('./chunk-KKHSUZA5.cjs'),require('./chunk-BEJ6ICA7.cjs');async function R(){for(let t=0;t<10;t++)await Promise.resolve();}async function T(t,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,u=0;for(;m<o&&u<l;){if(await R(),t.inspect().inflight.length===0){await R();return}s(c),m+=c,u++;}let v=t.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function D(){let t=0,s=[];return {async advance(r){let o=t+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();t=c.time,c.callback(),await Promise.resolve();}t=o;},async next(){if(s.length===0)return;let r=s.shift();t=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return t},reset(){t=0,s.length=0;}}}function b(t){let s=typeof t=="string"?{requirement:(o=>o.type===t)}:t,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function C(t){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((u,v)=>{r.push({requirement:l,resolve:f=>u(f),reject:v});}))}}function E(t){return "module"in t?x(t):M(t)}function x(t){let s=[],r=new Map,o=[],c=[],l={};if(t.mocks?.resolvers)for(let[i,e]of Object.entries(t.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...e,calls:n});}let m={...t.module,resolvers:{...t.module.resolvers,...l}},v=chunkL76IJROE_cjs.a({...t,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,e,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:e,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...t.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let e=Date.now(),n=async()=>{await new Promise(d=>setTimeout(d,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-e>i){let d=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${d}`)}return await new Promise(d=>setTimeout(d,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,e){let n=r.get(i)??[];if(e!==void 0){if(n.length!==e)throw new Error(`[Directive] Expected resolver "${i}" to be called ${e} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,e){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(e!==void 0&&!n.some(d=>d.newValue===e)){let d=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(e)} but got: ${d}`)}},assertFactChanges(i,e){let n=c.filter(a=>a.key===i);if(n.length!==e)throw new Error(`[Directive] Expected fact "${i}" to change ${e} times but it changed ${n.length} times`)}}}function M(t){let s=[],r=new Map,o=[],c=[],l={};if(t.mocks?.resolvers)for(let[e,n]of Object.entries(t.mocks.resolvers)){let a=[];r.set(e,a),l[e]=b({...n,calls:a});}let m={};for(let[e,n]of Object.entries(t.modules))m[e]={...n,resolvers:{...n.resolvers,...l}};let u=new Set(Object.keys(t.modules)),f=chunkL76IJROE_cjs.a({...t,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(e,n,a)=>{let g=e.indexOf("::"),y,h;if(g>0){let w=e.substring(0,g);u.has(w)?(y=w,h=e.substring(g+2)):h=e;}else h=e;c.push({key:h,fullKey:e,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:e=>{o.push(e);}},...t.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=e=>{s.push(e),p(e);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(e=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let d=f.inspect();if(d.inflight.length>0){if(Date.now()-n>e){let g=d.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${e}ms. ${d.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(e){if(!o.some(a=>a.requirement.type===e))throw new Error(`[Directive] Expected requirement of type "${e}" but none found`)},assertResolverCalled(e,n){let a=r.get(e)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${e}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${e}" to be called but it was not`)},assertFactSet(e,n){let a=c.filter(d=>d.key===e);if(a.length===0)throw new Error(`[Directive] Expected fact "${e}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${e}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(e,n){let a=c.filter(d=>d.key===e);if(a.length!==n)throw new Error(`[Directive] Expected fact "${e}" to change ${n} times but it changed ${a.length} times`)}}}function O(t,s,r){if(!k(t,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(t,s,r){if(k(t,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(t,s,r){switch(s){case "constraint":return t.constraints.isDynamic(r);case "resolver":return t.resolvers.isDynamic(r);case "derivation":return t.derive.isDynamic(r);case "effect":return t.effects.isDynamic(r)}}function P(t){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=t.observe(u=>{switch(u.type){case "constraint.evaluate":u.active&&s.add(u.id);break;case "resolver.start":r.add(u.resolver);break;case "effect.run":o.add(u.id);break;case "derivation.compute":c.add(u.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=t.inspect(),u=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of u)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:u.size===0?1:s.size/u.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function F(t){let s=[],r=t.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}exports.assertDynamic=O;exports.assertNotDynamic=$;exports.createCoverageTracker=P;exports.createFakeTimers=D;exports.createMockResolver=b;exports.createTestObserver=F;exports.createTestSystem=E;exports.flushMicrotasks=R;exports.mockResolver=C;exports.settleWithFakeTimers=T;//# sourceMappingURL=testing.cjs.map
1
+ 'use strict';var chunkU3DN2WML_cjs=require('./chunk-U3DN2WML.cjs');require('./chunk-RCCTZCZZ.cjs'),require('./chunk-DDUARSUH.cjs'),require('./chunk-BEJ6ICA7.cjs');async function R(){for(let e=0;e<10;e++)await Promise.resolve();}async function T(){for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();await new Promise(e=>setTimeout(e,0));for(let e=0;e<10;e++)await Promise.resolve();}async function D(e,s,r={}){let{totalTime:o=5e3,stepSize:c=10,maxIterations:l=1e3}=r,m=0,d=0;for(;m<o&&d<l;){if(await R(),e.inspect().inflight.length===0){await R();return}s(c),m+=c,d++;}let v=e.inspect();if(v.inflight.length>0){let f=v.inflight.map(p=>p.resolverId).join(", ");throw new Error(`[Directive] settleWithFakeTimers did not settle after ${o}ms. ${v.inflight.length} resolvers still inflight: ${f}`)}}function C(){let e=0,s=[];return {async advance(r){let o=e+r;for(;s.length>0&&s[0].time<=o;){let c=s.shift();e=c.time,c.callback(),await Promise.resolve();}e=o;},async next(){if(s.length===0)return;let r=s.shift();e=r.time,r.callback(),await Promise.resolve();},async runAll(){for(;s.length>0;)await this.next();},now(){return e},reset(){e=0,s.length=0;}}}function b(e){let s=typeof e=="string"?{requirement:(o=>o.type===e)}:e,r=s.calls??[];return {requirement:s.requirement??(o=>true),async resolve(o,c){if(r.push(o),s.delay&&await new Promise(l=>setTimeout(l,s.delay)),s.error)throw typeof s.error=="string"?new Error(s.error):s.error;s.resolve&&await s.resolve(o,c);}}}function E(e){let s=[],r=[];return {...{get calls(){return s},get pending(){return r},resolve(l){let m=r.shift();m&&m.resolve(l);},reject(l){let m=r.shift();m&&m.reject(l);},resolveAll(l){for(;r.length>0;)this.resolve(l);},rejectAll(l){for(;r.length>0;)this.reject(l);},reset(){s.length=0,r.length=0;}},handler:(l,m)=>(s.push(l),new Promise((d,v)=>{r.push({requirement:l,resolve:f=>d(f),reject:v});}))}}function P(e){return "module"in e?x(e):M(e)}function x(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[i,t]of Object.entries(e.mocks.resolvers)){let n=[];r.set(i,n),l[i]=b({...t,calls:n});}let m={...e.module,resolvers:{...e.module.resolvers,...l}},v=chunkU3DN2WML_cjs.a({...e,module:m,plugins:[{name:"__test-tracking__",onFactSet:(i,t,n)=>{c.push({key:i,fullKey:i,namespace:void 0,previousValue:n,newValue:t,timestamp:Date.now()});},onRequirementCreated:i=>{o.push(i);}},...e.plugins??[]]}),f=v.dispatch.bind(v);return v.dispatch=i=>{s.push(i),f(i);},{...v,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(i=5e3){let t=Date.now(),n=async()=>{await new Promise(u=>setTimeout(u,0));let a=v.inspect();if(a.inflight.length>0){if(Date.now()-t>i){let u=a.inflight.map(g=>g.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${i}ms. ${a.inflight.length} resolvers still inflight: ${u}`)}return await new Promise(u=>setTimeout(u,10)),n()}};return n()},assertRequirement(i){if(!o.some(n=>n.requirement.type===i))throw new Error(`[Directive] Expected requirement of type "${i}" but none found`)},assertResolverCalled(i,t){let n=r.get(i)??[];if(t!==void 0){if(n.length!==t)throw new Error(`[Directive] Expected resolver "${i}" to be called ${t} times but was called ${n.length} times`)}else if(n.length===0)throw new Error(`[Directive] Expected resolver "${i}" to be called but it was not`)},assertFactSet(i,t){let n=c.filter(a=>a.key===i);if(n.length===0)throw new Error(`[Directive] Expected fact "${i}" to be set but it was not`);if(t!==void 0&&!n.some(u=>u.newValue===t)){let u=n.map(g=>JSON.stringify(g.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${i}" to be set to ${JSON.stringify(t)} but got: ${u}`)}},assertFactChanges(i,t){let n=c.filter(a=>a.key===i);if(n.length!==t)throw new Error(`[Directive] Expected fact "${i}" to change ${t} times but it changed ${n.length} times`)}}}function M(e){let s=[],r=new Map,o=[],c=[],l={};if(e.mocks?.resolvers)for(let[t,n]of Object.entries(e.mocks.resolvers)){let a=[];r.set(t,a),l[t]=b({...n,calls:a});}let m={};for(let[t,n]of Object.entries(e.modules))m[t]={...n,resolvers:{...n.resolvers,...l}};let d=new Set(Object.keys(e.modules)),f=chunkU3DN2WML_cjs.a({...e,modules:m,plugins:[{name:"__test-tracking__",onFactSet:(t,n,a)=>{let g=t.indexOf("::"),y,h;if(g>0){let S=t.substring(0,g);d.has(S)?(y=S,h=t.substring(g+2)):h=t;}else h=t;c.push({key:h,fullKey:t,namespace:y,previousValue:a,newValue:n,timestamp:Date.now()});},onRequirementCreated:t=>{o.push(t);}},...e.plugins??[]]}),p=f.dispatch.bind(f);return f.dispatch=t=>{s.push(t),p(t);},{...f,eventHistory:s,resolverCalls:r,get allRequirements(){return o},getFactsHistory(){return [...c]},resetFactsHistory(){c.length=0;},async waitForIdle(t=5e3){let n=Date.now(),a=async()=>{await new Promise(g=>setTimeout(g,0));let u=f.inspect();if(u.inflight.length>0){if(Date.now()-n>t){let g=u.inflight.map(y=>y.id).join(", ");throw new Error(`[Directive] waitForIdle timed out after ${t}ms. ${u.inflight.length} resolvers still inflight: ${g}`)}return await new Promise(g=>setTimeout(g,10)),a()}};return a()},assertRequirement(t){if(!o.some(a=>a.requirement.type===t))throw new Error(`[Directive] Expected requirement of type "${t}" but none found`)},assertResolverCalled(t,n){let a=r.get(t)??[];if(n!==void 0){if(a.length!==n)throw new Error(`[Directive] Expected resolver "${t}" to be called ${n} times but was called ${a.length} times`)}else if(a.length===0)throw new Error(`[Directive] Expected resolver "${t}" to be called but it was not`)},assertFactSet(t,n){let a=c.filter(u=>u.key===t);if(a.length===0)throw new Error(`[Directive] Expected fact "${t}" to be set but it was not`);if(n!==void 0&&!a.some(g=>g.newValue===n)){let g=a.map(y=>JSON.stringify(y.newValue)).join(", ");throw new Error(`[Directive] Expected fact "${t}" to be set to ${JSON.stringify(n)} but got: ${g}`)}},assertFactChanges(t,n){let a=c.filter(u=>u.key===t);if(a.length!==n)throw new Error(`[Directive] Expected fact "${t}" to change ${n} times but it changed ${a.length} times`)}}}function O(e,s,r){if(!k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to be dynamic, but it is not.`)}function $(e,s,r){if(k(e,s,r))throw new Error(`[Directive] Expected ${s} "${r}" to NOT be dynamic, but it is.`)}function k(e,s,r){switch(s){case "constraint":return e.constraints.isDynamic(r);case "resolver":return e.resolvers.isDynamic(r);case "derivation":return e.derive.isDynamic(r);case "effect":return e.effects.isDynamic(r)}}function F(e){let s=new Set,r=new Set,o=new Set,c=new Set,l=null;return {async run(m){l=e.observe(d=>{switch(d.type){case "constraint.evaluate":d.active&&s.add(d.id);break;case "resolver.start":r.add(d.resolver);break;case "effect.run":o.add(d.id);break;case "derivation.compute":c.add(d.id);break}});try{await m();}finally{l?.(),l=null;}},report(){let m=e.inspect(),d=new Set(m.constraints.map(i=>i.id)),v=new Set(m.resolverDefs.map(i=>i.id)),f=new Set;for(let i of d)s.has(i)||f.add(i);let p=new Set;for(let i of v)r.has(i)||p.add(i);return {constraintsHit:s,constraintsMissed:f,resolversRun:r,resolversMissed:p,effectsRun:o,derivationsComputed:c,constraintCoverage:d.size===0?1:s.size/d.size,resolverCoverage:v.size===0?1:r.size/v.size,effectCoverage:m.effects.length===0?1:o.size/m.effects.length,derivationCoverage:m.derivations.length===0?1:c.size/m.derivations.length}}}}function I(e){let s=[],r=e.observe(o=>s.push(o));return {events:s,ofType(o){return s.filter(c=>c.type===o)},clear(){s.length=0;},dispose(){r();}}}exports.assertDynamic=O;exports.assertNotDynamic=$;exports.createCoverageTracker=F;exports.createFakeTimers=C;exports.createMockResolver=b;exports.createTestObserver=I;exports.createTestSystem=P;exports.flushAsync=T;exports.flushMicrotasks=R;exports.mockResolver=E;exports.settleWithFakeTimers=D;//# sourceMappingURL=testing.cjs.map
2
2
  //# sourceMappingURL=testing.cjs.map