@shware/workflow 3.3.0 → 4.0.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/README.md +91 -29
- package/dist/apns.cjs +113 -26
- package/dist/apns.cjs.map +1 -1
- package/dist/apns.d.cts +52 -6
- package/dist/apns.d.cts.map +1 -1
- package/dist/apns.d.mts +52 -6
- package/dist/apns.d.mts.map +1 -1
- package/dist/apns.mjs +111 -27
- package/dist/apns.mjs.map +1 -1
- package/dist/aws/engine-step.cjs +5 -5
- package/dist/aws/engine-step.cjs.map +1 -1
- package/dist/aws/engine-step.d.cts +8 -2
- package/dist/aws/engine-step.d.cts.map +1 -1
- package/dist/aws/engine-step.d.mts +8 -2
- package/dist/aws/engine-step.d.mts.map +1 -1
- package/dist/aws/engine-step.mjs +5 -5
- package/dist/aws/engine-step.mjs.map +1 -1
- package/dist/aws/index.cjs +47 -6
- package/dist/aws/index.cjs.map +1 -1
- package/dist/aws/index.d.cts +2 -2
- package/dist/aws/index.d.cts.map +1 -1
- package/dist/aws/index.d.mts +2 -2
- package/dist/aws/index.d.mts.map +1 -1
- package/dist/aws/index.mjs +47 -6
- package/dist/aws/index.mjs.map +1 -1
- package/dist/aws/instances.cjs +29 -6
- package/dist/aws/instances.cjs.map +1 -1
- package/dist/aws/instances.d.cts +11 -1
- package/dist/aws/instances.d.cts.map +1 -1
- package/dist/aws/instances.d.mts +11 -1
- package/dist/aws/instances.d.mts.map +1 -1
- package/dist/aws/instances.mjs +27 -4
- package/dist/aws/instances.mjs.map +1 -1
- package/dist/client.cjs +4 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -2
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.mts +2 -2
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs +4 -1
- package/dist/client.mjs.map +1 -1
- package/dist/cloudflare/bindings.cjs +28 -25
- package/dist/cloudflare/bindings.cjs.map +1 -1
- package/dist/cloudflare/bindings.d.cts +15 -129
- package/dist/cloudflare/bindings.d.cts.map +1 -1
- package/dist/cloudflare/bindings.d.mts +15 -129
- package/dist/cloudflare/bindings.d.mts.map +1 -1
- package/dist/cloudflare/bindings.mjs +28 -23
- package/dist/cloudflare/bindings.mjs.map +1 -1
- package/dist/cloudflare/d1-env.cjs +6 -6
- package/dist/cloudflare/d1-env.cjs.map +1 -1
- package/dist/cloudflare/d1-env.d.cts +5 -5
- package/dist/cloudflare/d1-env.d.mts +5 -5
- package/dist/cloudflare/d1-env.mjs +6 -6
- package/dist/cloudflare/d1-env.mjs.map +1 -1
- package/dist/cloudflare/index.cjs +28 -18
- package/dist/cloudflare/index.d.cts +8 -4
- package/dist/cloudflare/index.d.mts +8 -4
- package/dist/cloudflare/index.mjs +9 -5
- package/dist/cloudflare/runner.cjs +29 -14
- package/dist/cloudflare/runner.cjs.map +1 -1
- package/dist/cloudflare/runner.d.cts +9 -2
- package/dist/cloudflare/runner.d.cts.map +1 -1
- package/dist/cloudflare/runner.d.mts +9 -2
- package/dist/cloudflare/runner.d.mts.map +1 -1
- package/dist/cloudflare/runner.mjs +28 -13
- package/dist/cloudflare/runner.mjs.map +1 -1
- package/dist/cloudflare/schema.sql +27 -6
- package/dist/cloudflare/worker.cjs +19 -9
- package/dist/cloudflare/worker.cjs.map +1 -1
- package/dist/cloudflare/worker.d.cts +2 -2
- package/dist/cloudflare/worker.d.cts.map +1 -1
- package/dist/cloudflare/worker.d.mts +2 -2
- package/dist/cloudflare/worker.d.mts.map +1 -1
- package/dist/cloudflare/worker.mjs +19 -9
- package/dist/cloudflare/worker.mjs.map +1 -1
- package/dist/config.cjs +21 -5
- package/dist/config.cjs.map +1 -1
- package/dist/config.mjs +21 -5
- package/dist/config.mjs.map +1 -1
- package/dist/dsl/action.cjs +3 -6
- package/dist/dsl/action.cjs.map +1 -1
- package/dist/dsl/action.d.cts +12 -11
- package/dist/dsl/action.d.cts.map +1 -1
- package/dist/dsl/action.d.mts +12 -11
- package/dist/dsl/action.d.mts.map +1 -1
- package/dist/dsl/action.mjs +3 -6
- package/dist/dsl/action.mjs.map +1 -1
- package/dist/dsl/bundle.cjs +35 -31
- package/dist/dsl/bundle.cjs.map +1 -1
- package/dist/dsl/bundle.d.cts.map +1 -1
- package/dist/dsl/bundle.d.mts.map +1 -1
- package/dist/dsl/bundle.mjs +35 -31
- package/dist/dsl/bundle.mjs.map +1 -1
- package/dist/dsl/condition.cjs +13 -1
- package/dist/dsl/condition.cjs.map +1 -1
- package/dist/dsl/condition.d.cts +9 -1
- package/dist/dsl/condition.d.cts.map +1 -1
- package/dist/dsl/condition.d.mts +9 -1
- package/dist/dsl/condition.d.mts.map +1 -1
- package/dist/dsl/condition.mjs +13 -2
- package/dist/dsl/condition.mjs.map +1 -1
- package/dist/dsl/flow.cjs +33 -11
- package/dist/dsl/flow.cjs.map +1 -1
- package/dist/dsl/flow.d.cts +9 -1
- package/dist/dsl/flow.d.cts.map +1 -1
- package/dist/dsl/flow.d.mts +9 -1
- package/dist/dsl/flow.d.mts.map +1 -1
- package/dist/dsl/flow.mjs +34 -13
- package/dist/dsl/flow.mjs.map +1 -1
- package/dist/dsl/workflow.cjs +2 -3
- package/dist/dsl/workflow.cjs.map +1 -1
- package/dist/dsl/workflow.d.cts.map +1 -1
- package/dist/dsl/workflow.d.mts.map +1 -1
- package/dist/dsl/workflow.mjs +3 -4
- package/dist/dsl/workflow.mjs.map +1 -1
- package/dist/engine/actions.cjs +1 -8
- package/dist/engine/actions.cjs.map +1 -1
- package/dist/engine/actions.d.cts +1 -12
- package/dist/engine/actions.d.cts.map +1 -1
- package/dist/engine/actions.d.mts +1 -12
- package/dist/engine/actions.d.mts.map +1 -1
- package/dist/engine/actions.mjs +1 -8
- package/dist/engine/actions.mjs.map +1 -1
- package/dist/engine/condition.cjs +25 -5
- package/dist/engine/condition.cjs.map +1 -1
- package/dist/engine/condition.d.cts +12 -3
- package/dist/engine/condition.d.cts.map +1 -1
- package/dist/engine/condition.d.mts +12 -3
- package/dist/engine/condition.d.mts.map +1 -1
- package/dist/engine/condition.mjs +25 -6
- package/dist/engine/condition.mjs.map +1 -1
- package/dist/engine/index.cjs +3 -0
- package/dist/engine/index.d.cts +5 -5
- package/dist/engine/index.d.mts +5 -5
- package/dist/engine/index.mjs +4 -4
- package/dist/engine/interpreter.cjs +27 -20
- package/dist/engine/interpreter.cjs.map +1 -1
- package/dist/engine/interpreter.d.cts.map +1 -1
- package/dist/engine/interpreter.d.mts.map +1 -1
- package/dist/engine/interpreter.mjs +27 -20
- package/dist/engine/interpreter.mjs.map +1 -1
- package/dist/engine/ports.d.cts +15 -6
- package/dist/engine/ports.d.cts.map +1 -1
- package/dist/engine/ports.d.mts +15 -6
- package/dist/engine/ports.d.mts.map +1 -1
- package/dist/engine/retry.cjs +13 -0
- package/dist/engine/retry.cjs.map +1 -1
- package/dist/engine/retry.d.cts +12 -0
- package/dist/engine/retry.d.cts.map +1 -1
- package/dist/engine/retry.d.mts +12 -0
- package/dist/engine/retry.d.mts.map +1 -1
- package/dist/engine/retry.mjs +13 -1
- package/dist/engine/retry.mjs.map +1 -1
- package/dist/engine/time-scale.cjs +90 -15
- package/dist/engine/time-scale.cjs.map +1 -1
- package/dist/engine/time-scale.d.cts +9 -6
- package/dist/engine/time-scale.d.cts.map +1 -1
- package/dist/engine/time-scale.d.mts +9 -6
- package/dist/engine/time-scale.d.mts.map +1 -1
- package/dist/engine/time-scale.mjs +90 -16
- package/dist/engine/time-scale.mjs.map +1 -1
- package/dist/fcm.cjs +111 -38
- package/dist/fcm.cjs.map +1 -1
- package/dist/fcm.d.cts +45 -5
- package/dist/fcm.d.cts.map +1 -1
- package/dist/fcm.d.mts +45 -5
- package/dist/fcm.d.mts.map +1 -1
- package/dist/fcm.mjs +110 -39
- package/dist/fcm.mjs.map +1 -1
- package/dist/hash.cjs +6 -6
- package/dist/hash.cjs.map +1 -1
- package/dist/hash.mjs +6 -6
- package/dist/hash.mjs.map +1 -1
- package/dist/host/auth.cjs +49 -0
- package/dist/host/auth.cjs.map +1 -0
- package/dist/host/auth.d.cts +21 -0
- package/dist/host/auth.d.cts.map +1 -0
- package/dist/host/auth.d.mts +21 -0
- package/dist/host/auth.d.mts.map +1 -0
- package/dist/host/auth.mjs +47 -0
- package/dist/host/auth.mjs.map +1 -0
- package/dist/host/channels.cjs +118 -40
- package/dist/host/channels.cjs.map +1 -1
- package/dist/host/channels.d.cts +27 -1
- package/dist/host/channels.d.cts.map +1 -1
- package/dist/host/channels.d.mts +27 -1
- package/dist/host/channels.d.mts.map +1 -1
- package/dist/host/channels.mjs +121 -44
- package/dist/host/channels.mjs.map +1 -1
- package/dist/host/execute.cjs +14 -2
- package/dist/host/execute.cjs.map +1 -1
- package/dist/host/execute.d.cts +4 -4
- package/dist/host/execute.d.cts.map +1 -1
- package/dist/host/execute.d.mts +4 -4
- package/dist/host/execute.d.mts.map +1 -1
- package/dist/host/execute.mjs +13 -1
- package/dist/host/execute.mjs.map +1 -1
- package/dist/host/fresh-read.cjs +30 -0
- package/dist/host/fresh-read.cjs.map +1 -0
- package/dist/host/fresh-read.d.cts +18 -0
- package/dist/host/fresh-read.d.cts.map +1 -0
- package/dist/host/fresh-read.d.mts +18 -0
- package/dist/host/fresh-read.d.mts.map +1 -0
- package/dist/host/fresh-read.mjs +29 -0
- package/dist/host/fresh-read.mjs.map +1 -0
- package/dist/host/http.cjs +321 -0
- package/dist/host/http.cjs.map +1 -0
- package/dist/host/http.d.cts +54 -0
- package/dist/host/http.d.cts.map +1 -0
- package/dist/host/http.d.mts +54 -0
- package/dist/host/http.d.mts.map +1 -0
- package/dist/host/http.mjs +317 -0
- package/dist/host/http.mjs.map +1 -0
- package/dist/host/{router.cjs → ingest.cjs} +147 -175
- package/dist/host/ingest.cjs.map +1 -0
- package/dist/host/{router.d.cts → ingest.d.cts} +48 -30
- package/dist/host/ingest.d.cts.map +1 -0
- package/dist/host/{router.d.mts → ingest.d.mts} +48 -30
- package/dist/host/ingest.d.mts.map +1 -0
- package/dist/host/{router.mjs → ingest.mjs} +144 -173
- package/dist/host/ingest.mjs.map +1 -0
- package/dist/host/journey-host.cjs +65 -93
- package/dist/host/journey-host.cjs.map +1 -1
- package/dist/host/journey-host.d.cts +19 -26
- package/dist/host/journey-host.d.cts.map +1 -1
- package/dist/host/journey-host.d.mts +19 -26
- package/dist/host/journey-host.d.mts.map +1 -1
- package/dist/host/journey-host.mjs +65 -93
- package/dist/host/journey-host.mjs.map +1 -1
- package/dist/host/platform.cjs +21 -0
- package/dist/host/platform.cjs.map +1 -0
- package/dist/host/platform.d.cts +126 -0
- package/dist/host/platform.d.cts.map +1 -0
- package/dist/host/platform.d.mts +126 -0
- package/dist/host/platform.d.mts.map +1 -0
- package/dist/host/platform.mjs +19 -0
- package/dist/host/platform.mjs.map +1 -0
- package/dist/host/senders.cjs +18 -9
- package/dist/host/senders.cjs.map +1 -1
- package/dist/host/senders.d.cts +9 -4
- package/dist/host/senders.d.cts.map +1 -1
- package/dist/host/senders.d.mts +9 -4
- package/dist/host/senders.d.mts.map +1 -1
- package/dist/host/senders.mjs +18 -9
- package/dist/host/senders.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/ir.cjs +5 -7
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +3 -12
- package/dist/ir.d.cts.map +1 -1
- package/dist/ir.d.mts +3 -12
- package/dist/ir.d.mts.map +1 -1
- package/dist/ir.mjs +5 -7
- package/dist/ir.mjs.map +1 -1
- package/dist/plan.cjs +27 -33
- package/dist/plan.cjs.map +1 -1
- package/dist/plan.d.cts +1 -1
- package/dist/plan.d.cts.map +1 -1
- package/dist/plan.d.mts +1 -1
- package/dist/plan.d.mts.map +1 -1
- package/dist/plan.mjs +27 -33
- package/dist/plan.mjs.map +1 -1
- package/dist/reporting/tracking.cjs +14 -4
- package/dist/reporting/tracking.cjs.map +1 -1
- package/dist/reporting/tracking.d.cts +10 -10
- package/dist/reporting/tracking.d.cts.map +1 -1
- package/dist/reporting/tracking.d.mts +10 -10
- package/dist/reporting/tracking.d.mts.map +1 -1
- package/dist/reporting/tracking.mjs +14 -4
- package/dist/reporting/tracking.mjs.map +1 -1
- package/dist/store/d1.cjs +88 -29
- package/dist/store/d1.cjs.map +1 -1
- package/dist/store/d1.d.cts +29 -11
- package/dist/store/d1.d.cts.map +1 -1
- package/dist/store/d1.d.mts +29 -11
- package/dist/store/d1.d.mts.map +1 -1
- package/dist/store/d1.mjs +88 -29
- package/dist/store/d1.mjs.map +1 -1
- package/dist/store/erasure.cjs +22 -0
- package/dist/store/erasure.cjs.map +1 -0
- package/dist/store/erasure.d.cts +18 -0
- package/dist/store/erasure.d.cts.map +1 -0
- package/dist/store/erasure.d.mts +18 -0
- package/dist/store/erasure.d.mts.map +1 -0
- package/dist/store/erasure.mjs +21 -0
- package/dist/store/erasure.mjs.map +1 -0
- package/dist/store/index.cjs +2 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +67 -13
- package/dist/store/index.d.cts.map +1 -1
- package/dist/store/index.d.mts +67 -13
- package/dist/store/index.d.mts.map +1 -1
- package/dist/store/index.mjs +2 -1
- package/dist/store/index.mjs.map +1 -1
- package/dist/store/postgres-reporting.cjs +125 -62
- package/dist/store/postgres-reporting.cjs.map +1 -1
- package/dist/store/postgres-reporting.d.cts +30 -2
- package/dist/store/postgres-reporting.d.cts.map +1 -1
- package/dist/store/postgres-reporting.d.mts +30 -2
- package/dist/store/postgres-reporting.d.mts.map +1 -1
- package/dist/store/postgres-reporting.mjs +125 -62
- package/dist/store/postgres-reporting.mjs.map +1 -1
- package/dist/store/postgres.cjs +179 -60
- package/dist/store/postgres.cjs.map +1 -1
- package/dist/store/postgres.d.cts +44 -7
- package/dist/store/postgres.d.cts.map +1 -1
- package/dist/store/postgres.d.mts +44 -7
- package/dist/store/postgres.d.mts.map +1 -1
- package/dist/store/postgres.mjs +179 -60
- package/dist/store/postgres.mjs.map +1 -1
- package/dist/store/tables.cjs +7 -5
- package/dist/store/tables.cjs.map +1 -1
- package/dist/store/tables.d.cts.map +1 -1
- package/dist/store/tables.d.mts.map +1 -1
- package/dist/store/tables.mjs +7 -5
- package/dist/store/tables.mjs.map +1 -1
- package/dist/store/user-lock.cjs +43 -0
- package/dist/store/user-lock.cjs.map +1 -0
- package/dist/store/user-lock.d.cts +32 -0
- package/dist/store/user-lock.d.cts.map +1 -0
- package/dist/store/user-lock.d.mts +32 -0
- package/dist/store/user-lock.d.mts.map +1 -0
- package/dist/store/user-lock.mjs +40 -0
- package/dist/store/user-lock.mjs.map +1 -0
- package/dist/transports/cloudflare-email.cjs +1 -1
- package/dist/transports/cloudflare-email.mjs +1 -1
- package/dist/transports/ses.cjs +47 -6
- package/dist/transports/ses.cjs.map +1 -1
- package/dist/transports/ses.d.cts +9 -1
- package/dist/transports/ses.d.cts.map +1 -1
- package/dist/transports/ses.d.mts +9 -1
- package/dist/transports/ses.d.mts.map +1 -1
- package/dist/transports/ses.mjs +47 -7
- package/dist/transports/ses.mjs.map +1 -1
- package/dist/webpush.cjs +133 -47
- package/dist/webpush.cjs.map +1 -1
- package/dist/webpush.d.cts +49 -8
- package/dist/webpush.d.cts.map +1 -1
- package/dist/webpush.d.mts +49 -8
- package/dist/webpush.d.mts.map +1 -1
- package/dist/webpush.mjs +130 -47
- package/dist/webpush.mjs.map +1 -1
- package/package.json +1 -1
- package/src/cloudflare/schema.sql +27 -6
- package/dist/host/router.cjs.map +0 -1
- package/dist/host/router.d.cts.map +0 -1
- package/dist/host/router.d.mts.map +0 -1
- package/dist/host/router.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.cts","names":[],"sources":["../../src/engine/retry.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry.d.cts","names":[],"sources":["../../src/engine/retry.ts"],"mappings":";;;;;;;;;;;;;qBAaa,uBAAuB;WAChB;WACT;EACT,YAAY,iBAAiB;IAAY;;;;;;;wBAY3B,YAAY;;wBAOZ,kBAAkB"}
|
package/dist/engine/retry.d.mts
CHANGED
|
@@ -6,6 +6,18 @@
|
|
|
6
6
|
* instead of burning the retry budget and delaying the journey. Every runtime adapter asks this
|
|
7
7
|
* one rule.
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* A failure a retry would only repeat: a missing or malformed configuration, a provider refusing
|
|
11
|
+
* the request itself, an input the runtime cannot act on. Thrown inside a durable step, it ends
|
|
12
|
+
* the step at once (`isRetryable` is false) instead of burning the retry budget.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PermanentError extends Error {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly retryable = false;
|
|
17
|
+
constructor(message: string, options?: {
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
9
21
|
/**
|
|
10
22
|
* False for an error a retry cannot fix: one of the engine's deterministic refusals, or any
|
|
11
23
|
* error that says so with `retryable: false` (the transports' 4xx answers).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.mts","names":[],"sources":["../../src/engine/retry.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry.d.mts","names":[],"sources":["../../src/engine/retry.ts"],"mappings":";;;;;;;;;;;;;qBAaa,uBAAuB;WAChB;WACT;EACT,YAAY,iBAAiB;IAAY;;;;;;;wBAY3B,YAAY;;wBAOZ,kBAAkB"}
|
package/dist/engine/retry.mjs
CHANGED
|
@@ -6,6 +6,18 @@
|
|
|
6
6
|
* instead of burning the retry budget and delaying the journey. Every runtime adapter asks this
|
|
7
7
|
* one rule.
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* A failure a retry would only repeat: a missing or malformed configuration, a provider refusing
|
|
11
|
+
* the request itself, an input the runtime cannot act on. Thrown inside a durable step, it ends
|
|
12
|
+
* the step at once (`isRetryable` is false) instead of burning the retry budget.
|
|
13
|
+
*/
|
|
14
|
+
var PermanentError = class extends Error {
|
|
15
|
+
name = "PermanentError";
|
|
16
|
+
retryable = false;
|
|
17
|
+
constructor(message, options) {
|
|
18
|
+
super(message, options);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
9
21
|
/** Errors the engine raises that are deterministic by construction. */
|
|
10
22
|
const DETERMINISTIC = /* @__PURE__ */ new Set(["TemplateValidationError", "ContractValidationError"]);
|
|
11
23
|
/**
|
|
@@ -22,6 +34,6 @@ function isRetryableStatus(status) {
|
|
|
22
34
|
return status === 408 || status === 429 || status >= 500;
|
|
23
35
|
}
|
|
24
36
|
//#endregion
|
|
25
|
-
export { isRetryable, isRetryableStatus };
|
|
37
|
+
export { PermanentError, isRetryable, isRetryableStatus };
|
|
26
38
|
|
|
27
39
|
//# sourceMappingURL=retry.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.mjs","names":[],"sources":["../../src/engine/retry.ts"],"sourcesContent":["/**\n * Which step failures a retry would only repeat. A durable step retries what it throws; an\n * error that is the same on every attempt — a template refusing its props, the contract\n * refusing an emitted event, a provider rejecting the request itself — ends the step at once\n * instead of burning the retry budget and delaying the journey. Every runtime adapter asks this\n * one rule.\n */\n\n/** Errors the engine raises that are deterministic by construction. */\nconst DETERMINISTIC = new Set(['TemplateValidationError', 'ContractValidationError']);\n\n/**\n * False for an error a retry cannot fix: one of the engine's deterministic refusals, or any\n * error that says so with `retryable: false` (the transports' 4xx answers).\n */\nexport function isRetryable(error: unknown): boolean {\n if (!(error instanceof Error)) return true;\n if (DETERMINISTIC.has(error.name)) return false;\n return (error as { retryable?: unknown }).retryable !== false;\n}\n\n/** An HTTP answer a retry can change: a timeout, throttling, or the provider's own fault. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || status >= 500;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry.mjs","names":[],"sources":["../../src/engine/retry.ts"],"sourcesContent":["/**\n * Which step failures a retry would only repeat. A durable step retries what it throws; an\n * error that is the same on every attempt — a template refusing its props, the contract\n * refusing an emitted event, a provider rejecting the request itself — ends the step at once\n * instead of burning the retry budget and delaying the journey. Every runtime adapter asks this\n * one rule.\n */\n\n/**\n * A failure a retry would only repeat: a missing or malformed configuration, a provider refusing\n * the request itself, an input the runtime cannot act on. Thrown inside a durable step, it ends\n * the step at once (`isRetryable` is false) instead of burning the retry budget.\n */\nexport class PermanentError extends Error {\n override readonly name: string = 'PermanentError';\n readonly retryable = false;\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n }\n}\n\n/** Errors the engine raises that are deterministic by construction. */\nconst DETERMINISTIC = new Set(['TemplateValidationError', 'ContractValidationError']);\n\n/**\n * False for an error a retry cannot fix: one of the engine's deterministic refusals, or any\n * error that says so with `retryable: false` (the transports' 4xx answers).\n */\nexport function isRetryable(error: unknown): boolean {\n if (!(error instanceof Error)) return true;\n if (DETERMINISTIC.has(error.name)) return false;\n return (error as { retryable?: unknown }).retryable !== false;\n}\n\n/** An HTTP answer a retry can change: a timeout, throttling, or the provider's own fault. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 429 || status >= 500;\n}\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAa,iBAAb,cAAoC,MAAM;CACxC,OAAiC;CACjC,YAAqB;CACrB,YAAY,SAAiB,SAA+B;EAC1D,MAAM,SAAS,OAAO;CACxB;AACF;;AAGA,MAAM,gCAAgB,IAAI,IAAI,CAAC,2BAA2B,yBAAyB,CAAC;;;;;AAMpF,SAAgB,YAAY,OAAyB;CACnD,IAAI,EAAE,iBAAiB,QAAQ,OAAO;CACtC,IAAI,cAAc,IAAI,MAAM,IAAI,GAAG,OAAO;CAC1C,OAAQ,MAAkC,cAAc;AAC1D;;AAGA,SAAgB,kBAAkB,QAAyB;CACzD,OAAO,WAAW,OAAO,WAAW,OAAO,UAAU;AACvD"}
|
|
@@ -13,25 +13,96 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
13
13
|
* live in the store rather than the workflow body; `scaleSegmentWindows`
|
|
14
14
|
* scales them as they are read, so a segment's `within` keeps pace too.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* written.
|
|
16
|
+
* The walk follows the IR's own structure — the fields that hold a Duration
|
|
17
|
+
* are known — so a message prop or an event payload that happens to look like
|
|
18
|
+
* one (`{ value, ms }`) is left alone. The source text is kept so the studio
|
|
19
|
+
* still shows what was written.
|
|
20
20
|
*/
|
|
21
21
|
function scaleDurations(ir, factor) {
|
|
22
22
|
if (!(factor > 0) || factor === 1) return ir;
|
|
23
|
-
return
|
|
23
|
+
return {
|
|
24
|
+
...ir,
|
|
25
|
+
trigger: ir.trigger.type === "event" ? {
|
|
26
|
+
...ir.trigger,
|
|
27
|
+
...ir.trigger.filter === void 0 ? {} : { filter: scaleCondition(ir.trigger.filter, factor) }
|
|
28
|
+
} : ir.trigger,
|
|
29
|
+
...ir.goal === void 0 ? {} : { goal: {
|
|
30
|
+
...ir.goal,
|
|
31
|
+
condition: scaleCondition(ir.goal.condition, factor),
|
|
32
|
+
...ir.goal.within === void 0 ? {} : { within: scale(ir.goal.within, factor) }
|
|
33
|
+
} },
|
|
34
|
+
...ir.exitWhen === void 0 ? {} : { exitWhen: scaleCondition(ir.exitWhen, factor) },
|
|
35
|
+
flow: scaleFlow(ir.flow, factor)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** A condition with its `performed(... within)` windows divided by `factor`. */
|
|
39
|
+
function scaleCondition(condition, factor) {
|
|
40
|
+
if (!(factor > 0) || factor === 1) return condition;
|
|
41
|
+
switch (condition.type) {
|
|
42
|
+
case "and":
|
|
43
|
+
case "or": return {
|
|
44
|
+
...condition,
|
|
45
|
+
conditions: condition.conditions.map((child) => scaleCondition(child, factor))
|
|
46
|
+
};
|
|
47
|
+
case "not": return {
|
|
48
|
+
...condition,
|
|
49
|
+
condition: scaleCondition(condition.condition, factor)
|
|
50
|
+
};
|
|
51
|
+
case "performed": return condition.within === void 0 ? condition : {
|
|
52
|
+
...condition,
|
|
53
|
+
within: scale(condition.within, factor)
|
|
54
|
+
};
|
|
55
|
+
default: return condition;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function scaleFlow(nodes, factor) {
|
|
59
|
+
return nodes.map((node) => scaleNode(node, factor));
|
|
60
|
+
}
|
|
61
|
+
function scaleNode(node, factor) {
|
|
62
|
+
switch (node.type) {
|
|
63
|
+
case "delay": return {
|
|
64
|
+
...node,
|
|
65
|
+
duration: scale(node.duration, factor)
|
|
66
|
+
};
|
|
67
|
+
case "random_delay": return {
|
|
68
|
+
...node,
|
|
69
|
+
min: scale(node.min, factor),
|
|
70
|
+
max: scale(node.max, factor)
|
|
71
|
+
};
|
|
72
|
+
case "wait_until": return {
|
|
73
|
+
...node,
|
|
74
|
+
condition: scaleCondition(node.condition, factor),
|
|
75
|
+
timeout: scale(node.timeout, factor),
|
|
76
|
+
onTimeout: Array.isArray(node.onTimeout) ? scaleFlow(node.onTimeout, factor) : node.onTimeout
|
|
77
|
+
};
|
|
78
|
+
case "branch": return {
|
|
79
|
+
...node,
|
|
80
|
+
cases: node.cases.map((branch) => ({
|
|
81
|
+
...branch,
|
|
82
|
+
condition: scaleCondition(branch.condition, factor),
|
|
83
|
+
flow: scaleFlow(branch.flow, factor)
|
|
84
|
+
})),
|
|
85
|
+
...node.otherwise === void 0 ? {} : { otherwise: scaleFlow(node.otherwise, factor) }
|
|
86
|
+
};
|
|
87
|
+
case "filter": return {
|
|
88
|
+
...node,
|
|
89
|
+
condition: scaleCondition(node.condition, factor)
|
|
90
|
+
};
|
|
91
|
+
case "cohort": return {
|
|
92
|
+
...node,
|
|
93
|
+
arms: node.arms.map((arm) => ({
|
|
94
|
+
...arm,
|
|
95
|
+
flow: scaleFlow(arm.flow, factor)
|
|
96
|
+
}))
|
|
97
|
+
};
|
|
98
|
+
default: return node;
|
|
99
|
+
}
|
|
24
100
|
}
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const keys = Object.keys(record);
|
|
30
|
-
if (keys.length === 2 && typeof record.value === "string" && typeof record.ms === "number") return {
|
|
31
|
-
value: record.value,
|
|
32
|
-
ms: Math.max(0, Math.round(record.ms / factor))
|
|
101
|
+
function scale(duration, factor) {
|
|
102
|
+
return {
|
|
103
|
+
value: duration.value,
|
|
104
|
+
ms: Math.max(0, Math.round(duration.ms / factor))
|
|
33
105
|
};
|
|
34
|
-
return Object.fromEntries(keys.map((key) => [key, walk(record[key], factor)]));
|
|
35
106
|
}
|
|
36
107
|
/**
|
|
37
108
|
* A store whose segment definitions come back scaled by `factor` — what journeyWorker reads
|
|
@@ -42,12 +113,16 @@ function walk(value, factor) {
|
|
|
42
113
|
function scaleSegmentWindows(store, factor) {
|
|
43
114
|
if (!(factor > 0) || factor === 1) return store;
|
|
44
115
|
return new Proxy(store, { get(target, property) {
|
|
45
|
-
if (property === "getSegmentCondition") return async (name) =>
|
|
116
|
+
if (property === "getSegmentCondition") return async (name) => {
|
|
117
|
+
const condition = await target.getSegmentCondition(name);
|
|
118
|
+
return condition === void 0 ? void 0 : scaleCondition(condition, factor);
|
|
119
|
+
};
|
|
46
120
|
const value = Reflect.get(target, property, target);
|
|
47
121
|
return typeof value === "function" ? value.bind(target) : value;
|
|
48
122
|
} });
|
|
49
123
|
}
|
|
50
124
|
//#endregion
|
|
125
|
+
exports.scaleCondition = scaleCondition;
|
|
51
126
|
exports.scaleDurations = scaleDurations;
|
|
52
127
|
exports.scaleSegmentWindows = scaleSegmentWindows;
|
|
53
128
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-scale.cjs","names":[],"sources":["../../src/engine/time-scale.ts"],"sourcesContent":["/**\n * Debug time scale: divide every duration in a workflow's IR by a factor so a\n * journey written in days plays out in seconds — with a factor of 3600, a\n * `delay('2 days')` sleeps 48 s, a `waitUntil(..., { timeout: '3 days' })`\n * gives up after 72 s, and a goal `within: '30 days'` closes after 12 min.\n *\n * Everything that is a Duration scales together (delays, random delays, wait\n * timeouts, goal and `performed(... within)` windows inside the workflow), so\n * the journey keeps its shape, just faster. What does not scale: wall-clock\n * `timeWindow`s (they are times of day, not durations). Segment definitions\n * live in the store rather than the workflow body; `scaleSegmentWindows`\n * scales them as they are read, so a segment's `within` keeps pace too.\n *\n *
|
|
1
|
+
{"version":3,"file":"time-scale.cjs","names":[],"sources":["../../src/engine/time-scale.ts"],"sourcesContent":["import type { ConditionIR, DurationIR, NodeIR, WorkflowIR } from '../ir';\n\n/**\n * Debug time scale: divide every duration in a workflow's IR by a factor so a\n * journey written in days plays out in seconds — with a factor of 3600, a\n * `delay('2 days')` sleeps 48 s, a `waitUntil(..., { timeout: '3 days' })`\n * gives up after 72 s, and a goal `within: '30 days'` closes after 12 min.\n *\n * Everything that is a Duration scales together (delays, random delays, wait\n * timeouts, goal and `performed(... within)` windows inside the workflow), so\n * the journey keeps its shape, just faster. What does not scale: wall-clock\n * `timeWindow`s (they are times of day, not durations). Segment definitions\n * live in the store rather than the workflow body; `scaleSegmentWindows`\n * scales them as they are read, so a segment's `within` keeps pace too.\n *\n * The walk follows the IR's own structure — the fields that hold a Duration\n * are known — so a message prop or an event payload that happens to look like\n * one (`{ value, ms }`) is left alone. The source text is kept so the studio\n * still shows what was written.\n */\nexport function scaleDurations(ir: WorkflowIR, factor: number): WorkflowIR {\n if (!(factor > 0) || factor === 1) return ir;\n return {\n ...ir,\n trigger:\n ir.trigger.type === 'event'\n ? {\n ...ir.trigger,\n ...(ir.trigger.filter === undefined\n ? {}\n : { filter: scaleCondition(ir.trigger.filter, factor) }),\n }\n : ir.trigger,\n ...(ir.goal === undefined\n ? {}\n : {\n goal: {\n ...ir.goal,\n condition: scaleCondition(ir.goal.condition, factor),\n ...(ir.goal.within === undefined ? {} : { within: scale(ir.goal.within, factor) }),\n },\n }),\n ...(ir.exitWhen === undefined ? {} : { exitWhen: scaleCondition(ir.exitWhen, factor) }),\n flow: scaleFlow(ir.flow, factor),\n };\n}\n\n/** A condition with its `performed(... within)` windows divided by `factor`. */\nexport function scaleCondition(condition: ConditionIR, factor: number): ConditionIR {\n if (!(factor > 0) || factor === 1) return condition;\n switch (condition.type) {\n case 'and':\n case 'or':\n return {\n ...condition,\n conditions: condition.conditions.map((child) => scaleCondition(child, factor)),\n };\n case 'not':\n return { ...condition, condition: scaleCondition(condition.condition, factor) };\n case 'performed':\n return condition.within === undefined\n ? condition\n : { ...condition, within: scale(condition.within, factor) };\n default:\n return condition;\n }\n}\n\nfunction scaleFlow(nodes: readonly NodeIR[], factor: number): NodeIR[] {\n return nodes.map((node) => scaleNode(node, factor));\n}\n\nfunction scaleNode(node: NodeIR, factor: number): NodeIR {\n switch (node.type) {\n case 'delay':\n return { ...node, duration: scale(node.duration, factor) };\n case 'random_delay':\n return { ...node, min: scale(node.min, factor), max: scale(node.max, factor) };\n case 'wait_until':\n return {\n ...node,\n condition: scaleCondition(node.condition, factor),\n timeout: scale(node.timeout, factor),\n onTimeout: Array.isArray(node.onTimeout)\n ? scaleFlow(node.onTimeout, factor)\n : node.onTimeout,\n };\n case 'branch':\n return {\n ...node,\n cases: node.cases.map((branch) => ({\n ...branch,\n condition: scaleCondition(branch.condition, factor),\n flow: scaleFlow(branch.flow, factor),\n })),\n ...(node.otherwise === undefined ? {} : { otherwise: scaleFlow(node.otherwise, factor) }),\n };\n case 'filter':\n return { ...node, condition: scaleCondition(node.condition, factor) };\n case 'cohort':\n return {\n ...node,\n arms: node.arms.map((arm) => ({ ...arm, flow: scaleFlow(arm.flow, factor) })),\n };\n default:\n return node;\n }\n}\n\nfunction scale(duration: DurationIR, factor: number): DurationIR {\n return { value: duration.value, ms: Math.max(0, Math.round(duration.ms / factor)) };\n}\n\n/**\n * A store whose segment definitions come back scaled by `factor` — what journeyWorker reads\n * through in fast-forward, so a segment's windows (`performed(e.login, { within: '7 days' })`)\n * shrink with the journeys that reference it, and with the segment triggers it routes. Every\n * other method is the store's own.\n */\nexport function scaleSegmentWindows<\n S extends { getSegmentCondition(name: string): Promise<ConditionIR | undefined> },\n>(store: S, factor: number): S {\n if (!(factor > 0) || factor === 1) return store;\n return new Proxy(store, {\n get(target, property) {\n if (property === 'getSegmentCondition') {\n return async (name: string) => {\n const condition = await target.getSegmentCondition(name);\n return condition === undefined ? undefined : scaleCondition(condition, factor);\n };\n }\n const value: unknown = Reflect.get(target, property, target);\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ConditionIR, WorkflowIR } from "../ir.cjs";
|
|
1
2
|
//#region src/engine/time-scale.d.ts
|
|
2
3
|
/**
|
|
3
4
|
* Debug time scale: divide every duration in a workflow's IR by a factor so a
|
|
@@ -12,12 +13,14 @@
|
|
|
12
13
|
* live in the store rather than the workflow body; `scaleSegmentWindows`
|
|
13
14
|
* scales them as they are read, so a segment's `within` keeps pace too.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* written.
|
|
16
|
+
* The walk follows the IR's own structure — the fields that hold a Duration
|
|
17
|
+
* are known — so a message prop or an event payload that happens to look like
|
|
18
|
+
* one (`{ value, ms }`) is left alone. The source text is kept so the studio
|
|
19
|
+
* still shows what was written.
|
|
19
20
|
*/
|
|
20
|
-
export declare function scaleDurations
|
|
21
|
+
export declare function scaleDurations(ir: WorkflowIR, factor: number): WorkflowIR;
|
|
22
|
+
/** A condition with its `performed(... within)` windows divided by `factor`. */
|
|
23
|
+
export declare function scaleCondition(condition: ConditionIR, factor: number): ConditionIR;
|
|
21
24
|
/**
|
|
22
25
|
* A store whose segment definitions come back scaled by `factor` — what journeyWorker reads
|
|
23
26
|
* through in fast-forward, so a segment's windows (`performed(e.login, { within: '7 days' })`)
|
|
@@ -25,7 +28,7 @@ export declare function scaleDurations<T>(ir: T, factor: number): T;
|
|
|
25
28
|
* other method is the store's own.
|
|
26
29
|
*/
|
|
27
30
|
export declare function scaleSegmentWindows<S extends {
|
|
28
|
-
getSegmentCondition(name: string): Promise<
|
|
31
|
+
getSegmentCondition(name: string): Promise<ConditionIR | undefined>;
|
|
29
32
|
}>(store: S, factor: number): S;
|
|
30
33
|
//#endregion
|
|
31
34
|
//# sourceMappingURL=time-scale.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-scale.d.cts","names":[],"sources":["../../src/engine/time-scale.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-scale.d.cts","names":[],"sources":["../../src/engine/time-scale.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;wBAoBgB,eAAe,IAAI,YAAY,iBAAiB;;wBA4BhD,eAAe,WAAW,aAAa,iBAAiB;;;;;;;wBAuExD,oBACd;EAAY,oBAAoB,eAAe,QAAQ;GACvD,OAAO,GAAG,iBAAiB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ConditionIR, WorkflowIR } from "../ir.mjs";
|
|
1
2
|
//#region src/engine/time-scale.d.ts
|
|
2
3
|
/**
|
|
3
4
|
* Debug time scale: divide every duration in a workflow's IR by a factor so a
|
|
@@ -12,12 +13,14 @@
|
|
|
12
13
|
* live in the store rather than the workflow body; `scaleSegmentWindows`
|
|
13
14
|
* scales them as they are read, so a segment's `within` keeps pace too.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* written.
|
|
16
|
+
* The walk follows the IR's own structure — the fields that hold a Duration
|
|
17
|
+
* are known — so a message prop or an event payload that happens to look like
|
|
18
|
+
* one (`{ value, ms }`) is left alone. The source text is kept so the studio
|
|
19
|
+
* still shows what was written.
|
|
19
20
|
*/
|
|
20
|
-
export declare function scaleDurations
|
|
21
|
+
export declare function scaleDurations(ir: WorkflowIR, factor: number): WorkflowIR;
|
|
22
|
+
/** A condition with its `performed(... within)` windows divided by `factor`. */
|
|
23
|
+
export declare function scaleCondition(condition: ConditionIR, factor: number): ConditionIR;
|
|
21
24
|
/**
|
|
22
25
|
* A store whose segment definitions come back scaled by `factor` — what journeyWorker reads
|
|
23
26
|
* through in fast-forward, so a segment's windows (`performed(e.login, { within: '7 days' })`)
|
|
@@ -25,7 +28,7 @@ export declare function scaleDurations<T>(ir: T, factor: number): T;
|
|
|
25
28
|
* other method is the store's own.
|
|
26
29
|
*/
|
|
27
30
|
export declare function scaleSegmentWindows<S extends {
|
|
28
|
-
getSegmentCondition(name: string): Promise<
|
|
31
|
+
getSegmentCondition(name: string): Promise<ConditionIR | undefined>;
|
|
29
32
|
}>(store: S, factor: number): S;
|
|
30
33
|
//#endregion
|
|
31
34
|
//# sourceMappingURL=time-scale.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-scale.d.mts","names":[],"sources":["../../src/engine/time-scale.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"time-scale.d.mts","names":[],"sources":["../../src/engine/time-scale.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;wBAoBgB,eAAe,IAAI,YAAY,iBAAiB;;wBA4BhD,eAAe,WAAW,aAAa,iBAAiB;;;;;;;wBAuExD,oBACd;EAAY,oBAAoB,eAAe,QAAQ;GACvD,OAAO,GAAG,iBAAiB"}
|
|
@@ -12,25 +12,96 @@
|
|
|
12
12
|
* live in the store rather than the workflow body; `scaleSegmentWindows`
|
|
13
13
|
* scales them as they are read, so a segment's `within` keeps pace too.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* written.
|
|
15
|
+
* The walk follows the IR's own structure — the fields that hold a Duration
|
|
16
|
+
* are known — so a message prop or an event payload that happens to look like
|
|
17
|
+
* one (`{ value, ms }`) is left alone. The source text is kept so the studio
|
|
18
|
+
* still shows what was written.
|
|
19
19
|
*/
|
|
20
20
|
function scaleDurations(ir, factor) {
|
|
21
21
|
if (!(factor > 0) || factor === 1) return ir;
|
|
22
|
-
return
|
|
22
|
+
return {
|
|
23
|
+
...ir,
|
|
24
|
+
trigger: ir.trigger.type === "event" ? {
|
|
25
|
+
...ir.trigger,
|
|
26
|
+
...ir.trigger.filter === void 0 ? {} : { filter: scaleCondition(ir.trigger.filter, factor) }
|
|
27
|
+
} : ir.trigger,
|
|
28
|
+
...ir.goal === void 0 ? {} : { goal: {
|
|
29
|
+
...ir.goal,
|
|
30
|
+
condition: scaleCondition(ir.goal.condition, factor),
|
|
31
|
+
...ir.goal.within === void 0 ? {} : { within: scale(ir.goal.within, factor) }
|
|
32
|
+
} },
|
|
33
|
+
...ir.exitWhen === void 0 ? {} : { exitWhen: scaleCondition(ir.exitWhen, factor) },
|
|
34
|
+
flow: scaleFlow(ir.flow, factor)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** A condition with its `performed(... within)` windows divided by `factor`. */
|
|
38
|
+
function scaleCondition(condition, factor) {
|
|
39
|
+
if (!(factor > 0) || factor === 1) return condition;
|
|
40
|
+
switch (condition.type) {
|
|
41
|
+
case "and":
|
|
42
|
+
case "or": return {
|
|
43
|
+
...condition,
|
|
44
|
+
conditions: condition.conditions.map((child) => scaleCondition(child, factor))
|
|
45
|
+
};
|
|
46
|
+
case "not": return {
|
|
47
|
+
...condition,
|
|
48
|
+
condition: scaleCondition(condition.condition, factor)
|
|
49
|
+
};
|
|
50
|
+
case "performed": return condition.within === void 0 ? condition : {
|
|
51
|
+
...condition,
|
|
52
|
+
within: scale(condition.within, factor)
|
|
53
|
+
};
|
|
54
|
+
default: return condition;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function scaleFlow(nodes, factor) {
|
|
58
|
+
return nodes.map((node) => scaleNode(node, factor));
|
|
59
|
+
}
|
|
60
|
+
function scaleNode(node, factor) {
|
|
61
|
+
switch (node.type) {
|
|
62
|
+
case "delay": return {
|
|
63
|
+
...node,
|
|
64
|
+
duration: scale(node.duration, factor)
|
|
65
|
+
};
|
|
66
|
+
case "random_delay": return {
|
|
67
|
+
...node,
|
|
68
|
+
min: scale(node.min, factor),
|
|
69
|
+
max: scale(node.max, factor)
|
|
70
|
+
};
|
|
71
|
+
case "wait_until": return {
|
|
72
|
+
...node,
|
|
73
|
+
condition: scaleCondition(node.condition, factor),
|
|
74
|
+
timeout: scale(node.timeout, factor),
|
|
75
|
+
onTimeout: Array.isArray(node.onTimeout) ? scaleFlow(node.onTimeout, factor) : node.onTimeout
|
|
76
|
+
};
|
|
77
|
+
case "branch": return {
|
|
78
|
+
...node,
|
|
79
|
+
cases: node.cases.map((branch) => ({
|
|
80
|
+
...branch,
|
|
81
|
+
condition: scaleCondition(branch.condition, factor),
|
|
82
|
+
flow: scaleFlow(branch.flow, factor)
|
|
83
|
+
})),
|
|
84
|
+
...node.otherwise === void 0 ? {} : { otherwise: scaleFlow(node.otherwise, factor) }
|
|
85
|
+
};
|
|
86
|
+
case "filter": return {
|
|
87
|
+
...node,
|
|
88
|
+
condition: scaleCondition(node.condition, factor)
|
|
89
|
+
};
|
|
90
|
+
case "cohort": return {
|
|
91
|
+
...node,
|
|
92
|
+
arms: node.arms.map((arm) => ({
|
|
93
|
+
...arm,
|
|
94
|
+
flow: scaleFlow(arm.flow, factor)
|
|
95
|
+
}))
|
|
96
|
+
};
|
|
97
|
+
default: return node;
|
|
98
|
+
}
|
|
23
99
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const keys = Object.keys(record);
|
|
29
|
-
if (keys.length === 2 && typeof record.value === "string" && typeof record.ms === "number") return {
|
|
30
|
-
value: record.value,
|
|
31
|
-
ms: Math.max(0, Math.round(record.ms / factor))
|
|
100
|
+
function scale(duration, factor) {
|
|
101
|
+
return {
|
|
102
|
+
value: duration.value,
|
|
103
|
+
ms: Math.max(0, Math.round(duration.ms / factor))
|
|
32
104
|
};
|
|
33
|
-
return Object.fromEntries(keys.map((key) => [key, walk(record[key], factor)]));
|
|
34
105
|
}
|
|
35
106
|
/**
|
|
36
107
|
* A store whose segment definitions come back scaled by `factor` — what journeyWorker reads
|
|
@@ -41,12 +112,15 @@ function walk(value, factor) {
|
|
|
41
112
|
function scaleSegmentWindows(store, factor) {
|
|
42
113
|
if (!(factor > 0) || factor === 1) return store;
|
|
43
114
|
return new Proxy(store, { get(target, property) {
|
|
44
|
-
if (property === "getSegmentCondition") return async (name) =>
|
|
115
|
+
if (property === "getSegmentCondition") return async (name) => {
|
|
116
|
+
const condition = await target.getSegmentCondition(name);
|
|
117
|
+
return condition === void 0 ? void 0 : scaleCondition(condition, factor);
|
|
118
|
+
};
|
|
45
119
|
const value = Reflect.get(target, property, target);
|
|
46
120
|
return typeof value === "function" ? value.bind(target) : value;
|
|
47
121
|
} });
|
|
48
122
|
}
|
|
49
123
|
//#endregion
|
|
50
|
-
export { scaleDurations, scaleSegmentWindows };
|
|
124
|
+
export { scaleCondition, scaleDurations, scaleSegmentWindows };
|
|
51
125
|
|
|
52
126
|
//# sourceMappingURL=time-scale.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time-scale.mjs","names":[],"sources":["../../src/engine/time-scale.ts"],"sourcesContent":["/**\n * Debug time scale: divide every duration in a workflow's IR by a factor so a\n * journey written in days plays out in seconds — with a factor of 3600, a\n * `delay('2 days')` sleeps 48 s, a `waitUntil(..., { timeout: '3 days' })`\n * gives up after 72 s, and a goal `within: '30 days'` closes after 12 min.\n *\n * Everything that is a Duration scales together (delays, random delays, wait\n * timeouts, goal and `performed(... within)` windows inside the workflow), so\n * the journey keeps its shape, just faster. What does not scale: wall-clock\n * `timeWindow`s (they are times of day, not durations). Segment definitions\n * live in the store rather than the workflow body; `scaleSegmentWindows`\n * scales them as they are read, so a segment's `within` keeps pace too.\n *\n *
|
|
1
|
+
{"version":3,"file":"time-scale.mjs","names":[],"sources":["../../src/engine/time-scale.ts"],"sourcesContent":["import type { ConditionIR, DurationIR, NodeIR, WorkflowIR } from '../ir';\n\n/**\n * Debug time scale: divide every duration in a workflow's IR by a factor so a\n * journey written in days plays out in seconds — with a factor of 3600, a\n * `delay('2 days')` sleeps 48 s, a `waitUntil(..., { timeout: '3 days' })`\n * gives up after 72 s, and a goal `within: '30 days'` closes after 12 min.\n *\n * Everything that is a Duration scales together (delays, random delays, wait\n * timeouts, goal and `performed(... within)` windows inside the workflow), so\n * the journey keeps its shape, just faster. What does not scale: wall-clock\n * `timeWindow`s (they are times of day, not durations). Segment definitions\n * live in the store rather than the workflow body; `scaleSegmentWindows`\n * scales them as they are read, so a segment's `within` keeps pace too.\n *\n * The walk follows the IR's own structure — the fields that hold a Duration\n * are known — so a message prop or an event payload that happens to look like\n * one (`{ value, ms }`) is left alone. The source text is kept so the studio\n * still shows what was written.\n */\nexport function scaleDurations(ir: WorkflowIR, factor: number): WorkflowIR {\n if (!(factor > 0) || factor === 1) return ir;\n return {\n ...ir,\n trigger:\n ir.trigger.type === 'event'\n ? {\n ...ir.trigger,\n ...(ir.trigger.filter === undefined\n ? {}\n : { filter: scaleCondition(ir.trigger.filter, factor) }),\n }\n : ir.trigger,\n ...(ir.goal === undefined\n ? {}\n : {\n goal: {\n ...ir.goal,\n condition: scaleCondition(ir.goal.condition, factor),\n ...(ir.goal.within === undefined ? {} : { within: scale(ir.goal.within, factor) }),\n },\n }),\n ...(ir.exitWhen === undefined ? {} : { exitWhen: scaleCondition(ir.exitWhen, factor) }),\n flow: scaleFlow(ir.flow, factor),\n };\n}\n\n/** A condition with its `performed(... within)` windows divided by `factor`. */\nexport function scaleCondition(condition: ConditionIR, factor: number): ConditionIR {\n if (!(factor > 0) || factor === 1) return condition;\n switch (condition.type) {\n case 'and':\n case 'or':\n return {\n ...condition,\n conditions: condition.conditions.map((child) => scaleCondition(child, factor)),\n };\n case 'not':\n return { ...condition, condition: scaleCondition(condition.condition, factor) };\n case 'performed':\n return condition.within === undefined\n ? condition\n : { ...condition, within: scale(condition.within, factor) };\n default:\n return condition;\n }\n}\n\nfunction scaleFlow(nodes: readonly NodeIR[], factor: number): NodeIR[] {\n return nodes.map((node) => scaleNode(node, factor));\n}\n\nfunction scaleNode(node: NodeIR, factor: number): NodeIR {\n switch (node.type) {\n case 'delay':\n return { ...node, duration: scale(node.duration, factor) };\n case 'random_delay':\n return { ...node, min: scale(node.min, factor), max: scale(node.max, factor) };\n case 'wait_until':\n return {\n ...node,\n condition: scaleCondition(node.condition, factor),\n timeout: scale(node.timeout, factor),\n onTimeout: Array.isArray(node.onTimeout)\n ? scaleFlow(node.onTimeout, factor)\n : node.onTimeout,\n };\n case 'branch':\n return {\n ...node,\n cases: node.cases.map((branch) => ({\n ...branch,\n condition: scaleCondition(branch.condition, factor),\n flow: scaleFlow(branch.flow, factor),\n })),\n ...(node.otherwise === undefined ? {} : { otherwise: scaleFlow(node.otherwise, factor) }),\n };\n case 'filter':\n return { ...node, condition: scaleCondition(node.condition, factor) };\n case 'cohort':\n return {\n ...node,\n arms: node.arms.map((arm) => ({ ...arm, flow: scaleFlow(arm.flow, factor) })),\n };\n default:\n return node;\n }\n}\n\nfunction scale(duration: DurationIR, factor: number): DurationIR {\n return { value: duration.value, ms: Math.max(0, Math.round(duration.ms / factor)) };\n}\n\n/**\n * A store whose segment definitions come back scaled by `factor` — what journeyWorker reads\n * through in fast-forward, so a segment's windows (`performed(e.login, { within: '7 days' })`)\n * shrink with the journeys that reference it, and with the segment triggers it routes. Every\n * other method is the store's own.\n */\nexport function scaleSegmentWindows<\n S extends { getSegmentCondition(name: string): Promise<ConditionIR | undefined> },\n>(store: S, factor: number): S {\n if (!(factor > 0) || factor === 1) return store;\n return new Proxy(store, {\n get(target, property) {\n if (property === 'getSegmentCondition') {\n return async (name: string) => {\n const condition = await target.getSegmentCondition(name);\n return condition === undefined ? undefined : scaleCondition(condition, factor);\n };\n }\n const value: unknown = Reflect.get(target, property, target);\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n"],"mappings":"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"}
|