@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.
- package/dist/adapter-utils.cjs +1 -1
- package/dist/adapter-utils.d.cts +1 -1
- package/dist/adapter-utils.d.ts +1 -1
- package/dist/adapter-utils.js +1 -1
- package/dist/chunk-DDUARSUH.cjs +7 -0
- package/dist/chunk-DDUARSUH.cjs.map +1 -0
- package/dist/chunk-FK7BD7XT.js +7 -0
- package/dist/chunk-FK7BD7XT.js.map +1 -0
- package/dist/chunk-GVVNFVEX.js +3 -0
- package/dist/chunk-GVVNFVEX.js.map +1 -0
- package/dist/chunk-JYGG4RIL.js +16 -0
- package/dist/chunk-JYGG4RIL.js.map +1 -0
- package/dist/chunk-RCCTZCZZ.cjs +3 -0
- package/dist/chunk-RCCTZCZZ.cjs.map +1 -0
- package/dist/chunk-U3DN2WML.cjs +16 -0
- package/dist/chunk-U3DN2WML.cjs.map +1 -0
- package/dist/{helpers-CroApnZa.d.cts → helpers-CCljEIsG.d.cts} +1 -1
- package/dist/{helpers-B8RS-sa_.d.ts → helpers-CfZCxxkR.d.ts} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +307 -8
- package/dist/index.d.ts +307 -8
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +1 -1
- package/dist/internals.d.cts +11 -4
- package/dist/internals.d.ts +11 -4
- package/dist/internals.js +1 -1
- package/dist/plugins/index.d.cts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/{plugins-day_qfBB.d.cts → plugins-CLZ3xci0.d.cts} +124 -3
- package/dist/{plugins-day_qfBB.d.ts → plugins-CLZ3xci0.d.ts} +124 -3
- package/dist/system-F2QGHEG7.js +2 -0
- package/dist/{system-5OAYXJIG.js.map → system-F2QGHEG7.js.map} +1 -1
- package/dist/system-LZMEZBOA.cjs +2 -0
- package/dist/{system-4J3B25OD.cjs.map → system-LZMEZBOA.cjs.map} +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +37 -2
- package/dist/testing.d.ts +37 -2
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2HKKISIL.js +0 -3
- package/dist/chunk-2HKKISIL.js.map +0 -1
- package/dist/chunk-4KFEHIIX.cjs +0 -3
- package/dist/chunk-4KFEHIIX.cjs.map +0 -1
- package/dist/chunk-KKHSUZA5.cjs +0 -2
- package/dist/chunk-KKHSUZA5.cjs.map +0 -1
- package/dist/chunk-L76IJROE.cjs +0 -16
- package/dist/chunk-L76IJROE.cjs.map +0 -1
- package/dist/chunk-LN4YQDLL.js +0 -2
- package/dist/chunk-LN4YQDLL.js.map +0 -1
- package/dist/chunk-WIMO6TQ3.js +0 -16
- package/dist/chunk-WIMO6TQ3.js.map +0 -1
- package/dist/system-4J3B25OD.cjs +0 -2
- 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<
|
|
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
|
-
|
|
2053
|
-
|
|
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<
|
|
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
|
-
|
|
2053
|
-
|
|
2173
|
+
resolversCompleted: number;
|
|
2174
|
+
resolversCanceled: number;
|
|
2054
2175
|
} | {
|
|
2055
2176
|
type: "system.init";
|
|
2056
2177
|
} | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"system-
|
|
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-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"system-LZMEZBOA.cjs"}
|
package/dist/testing.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var
|
|
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
|