@voltro/workflow 0.1.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/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { C as e, E as t, T as n, _ as r, a as i, b as a, c as o, d as s, f as c, g as l, h as u, i as d, l as f, m as p, n as m, o as h, p as g, r as _, s as v, t as y, u as b, v as x, w as S, x as C, y as w } from "./primitives-CWy1iu5w.js";
2
+ import { _ as T, a as E, b as D, c as O, d as k, f as A, g as j, h as M, i as N, l as P, m as F, n as I, o as L, p as R, r as z, s as B, t as V, u as H, v as U, x as W, y as G } from "./src-CNeLb-4L.js";
3
+ export { a as CurrentWorkflowExecutionId, C as CurrentWorkflowRunId, y as WorkflowMessagesProperty, e as WorkflowRunRecorder, S as WorkflowStepInterceptorTag, m as WorkflowVersionTypeId, _ as WorkflowWorkerLayerTypeId, U as _voltroWorkflowRunEventsTable, G as _voltroWorkflowRunStepsTable, D as _voltroWorkflowRunsTable, T as _voltroWorkflowStartContextsTable, j as awaitSignal, P as awaitSignalSuspending, O as awaitUpdate, z as closeWorkflowChildrenForParent, H as completeSuspendingSignal, d as durableClock, i as durableQueue, h as durableQueueModule, v as durableRateLimiterModule, n as getCurrentWorkflowExecutionId, t as getCurrentWorkflowRunId, o as getWorkflowVersionMetadata, W as inMemoryWorkflowEngineLayer, I as inspectWorkflow, f as isWorkflowWorkerLayer, V as makeInMemoryRecorder, N as makeWorkflowRunRecorder, A as makeWorkflowUpdateId, b as processQueue, s as queueWorker, c as rateLimit, R as resolveWorkflowMessageRun, F as sendWorkflowSignal, M as sendWorkflowUpdate, E as serialiseWorkflowRowForWire, g as sleep, p as step, u as stepIdempotencyKey, l as stepModule, k as suspendingSignalDeferredName, L as truncateWorkflowValue, r as withCompensation, x as workflow, w as workflowModule, B as wrapWorkflowExecuteWithRunRecording };
@@ -0,0 +1,111 @@
1
+ import { Activity as e, Activity as t, DurableClock as n, DurableClock as r, DurableQueue as i, DurableQueue as a, DurableRateLimiter as o, DurableRateLimiter as s, Workflow as c, Workflow as l } from "@effect/workflow";
2
+ import { Cause as u, Context as d, Duration as f, Effect as p, FiberRef as m } from "effect";
3
+ //#region src/recorder.ts
4
+ var h = class extends d.Tag("@voltro/WorkflowRunRecorder")() {}, g = m.unsafeMake(void 0), _ = m.unsafeMake(void 0), v = m.unsafeMake(void 0), y = () => m.get(g), b = () => m.get(_), x = class extends d.Tag("@voltro/WorkflowStepInterceptor")() {}, S = Symbol.for("voltro.workflow.workerLayer"), C = Symbol.for("voltro.workflow.version"), w = "__voltroWorkflowMessages", T = (e) => typeof e == "object" && !!e && e[S] === !0, E = (e) => typeof e == "object" && e && e[C] !== void 0 ? e[C] : {
5
+ version: "1",
6
+ compatibleWith: ["1"],
7
+ patches: []
8
+ }, D = ((e) => {
9
+ let t = c.make(e), n = String(e.version ?? "1"), r = {
10
+ version: n,
11
+ compatibleWith: (e.compatibleWith ?? [n]).map(String),
12
+ patches: [...e.patches ?? []]
13
+ }, i = {
14
+ signals: { ...e.messages?.signals ?? {} },
15
+ updates: { ...e.messages?.updates ?? {} },
16
+ queries: { ...e.messages?.queries ?? {} }
17
+ };
18
+ return Object.defineProperty(t, C, {
19
+ value: r,
20
+ enumerable: !1
21
+ }), Object.defineProperty(t, w, {
22
+ value: i,
23
+ enumerable: !1
24
+ }), t;
25
+ }), O = i.make, k = i.process, A = ((...e) => {
26
+ let t = i.worker(...e);
27
+ return Object.defineProperty(t, S, {
28
+ value: !0,
29
+ enumerable: !1
30
+ }), t;
31
+ }), j = o.rateLimit, M = (e) => p.gen(function* () {
32
+ let t = yield* g, r = yield* p.serviceOption(h), i = f.toMillis(f.decode(e.duration));
33
+ if (t !== void 0 && r._tag === "Some") {
34
+ let a = r.value, o = new Date(Date.now() + i).toISOString(), s = yield* v;
35
+ yield* p.promise(() => a.recordEvent({
36
+ runId: t,
37
+ eventType: "timer-set",
38
+ payload: {
39
+ name: e.name,
40
+ durationMs: i,
41
+ scheduledWakeAt: o,
42
+ ...s === void 0 ? {} : { tenantId: s }
43
+ }
44
+ }).catch(() => {}));
45
+ let c = Date.now();
46
+ yield* n.sleep(e), yield* p.promise(() => a.recordEvent({
47
+ runId: t,
48
+ eventType: "timer-fired",
49
+ payload: {
50
+ name: e.name,
51
+ actualDurationMs: Date.now() - c,
52
+ ...s === void 0 ? {} : { tenantId: s }
53
+ }
54
+ }).catch(() => {}));
55
+ return;
56
+ }
57
+ yield* n.sleep(e);
58
+ }), N = (t, n, r, i) => p.gen(function* () {
59
+ let a = yield* g, o = yield* e.CurrentAttempt, s = yield* p.serviceOption(h), c = yield* p.serviceOption(x), l = c._tag === "Some" ? c.value.interceptor(n, {
60
+ runId: a ?? "unrecorded",
61
+ stepName: t,
62
+ attempt: o
63
+ }) : n, d, f;
64
+ if (a !== void 0 && s._tag === "Some") {
65
+ f = s.value;
66
+ try {
67
+ d = yield* p.promise(() => f.startStep({
68
+ runId: a,
69
+ stepName: t,
70
+ attempt: o,
71
+ stepInput: r,
72
+ ...i === void 0 ? {} : { retryPolicy: i }
73
+ }));
74
+ } catch {
75
+ d = void 0;
76
+ }
77
+ }
78
+ let m = Date.now();
79
+ return yield* l.pipe(p.tap((e) => d && f ? p.promise(async () => {
80
+ try {
81
+ await f.endStepSuccess({
82
+ stepRecordId: d,
83
+ output: e,
84
+ durationMs: Date.now() - m
85
+ });
86
+ } catch {}
87
+ }) : p.void), p.tapErrorCause((e) => d && f && !u.isInterruptedOnly(e) ? p.promise(async () => {
88
+ try {
89
+ let t = u.failureOption(e), n = Array.from(u.failures(e)), r = Array.from(u.defects(e)), i = t._tag === "Some" ? t.value : r[0] ?? u.squash(e), a = i?.message ?? String(i), o = i && typeof i == "object" && "_tag" in i ? String(i._tag) : null;
90
+ await f.endStepFailure({
91
+ stepRecordId: d,
92
+ errorTag: o,
93
+ errorMessage: a,
94
+ errorCause: {
95
+ pretty: u.pretty(e),
96
+ failures: n,
97
+ defects: r
98
+ },
99
+ durationMs: Date.now() - m
100
+ });
101
+ } catch {}
102
+ }) : p.void));
103
+ }), P = (t) => {
104
+ let { input: n, retry: r, ...i } = t;
105
+ return e.make({
106
+ ...i,
107
+ execute: N(i.name, i.execute, n, r)
108
+ });
109
+ }, F = c.withCompensation, I = e.idempotencyKey;
110
+ //#endregion
111
+ export { h as C, y as E, v as S, b as T, F as _, O as a, _ as b, E as c, A as d, j as f, t as g, I as h, r as i, T as l, P as m, C as n, a as o, M as p, S as r, s, w as t, k as u, D as v, x as w, g as x, l as y };
@@ -0,0 +1,229 @@
1
+ import { DurableClock as durableClock } from '@effect/workflow';
2
+ import { DurableQueue as durableQueueModule } from '@effect/workflow';
3
+ import { DurableRateLimiter as durableRateLimiterModule } from '@effect/workflow';
4
+ import { Effect } from 'effect';
5
+ import { Schema } from 'effect';
6
+ import { Activity as stepModule } from '@effect/workflow';
7
+ import { Workflow as workflowModule } from '@effect/workflow';
8
+
9
+ export { durableClock }
10
+
11
+ /** Define a durable queue for concurrency-controlled side work. */
12
+ export declare const durableQueue: typeof durableQueueModule.make;
13
+
14
+ export { durableQueueModule }
15
+
16
+ export { durableRateLimiterModule }
17
+
18
+ export declare const getWorkflowVersionMetadata: (value: unknown) => WorkflowVersionMetadata;
19
+
20
+ export declare const isWorkflowWorkerLayer: (value: unknown) => value is WorkflowWorkerLayerBrand;
21
+
22
+ declare type NormaliseWorkflowMessages<M extends WorkflowMessageSchemas | undefined> = {
23
+ readonly signals: M extends {
24
+ readonly signals: infer Signals;
25
+ } ? NonNullable<Signals> & Readonly<Record<string, Schema.Schema.Any>> : {};
26
+ readonly updates: M extends {
27
+ readonly updates: infer Updates;
28
+ } ? NonNullable<Updates> & Readonly<Record<string, WorkflowMessagePairSchemas>> : {};
29
+ readonly queries: M extends {
30
+ readonly queries: infer Queries;
31
+ } ? NonNullable<Queries> & Readonly<Record<string, WorkflowMessagePairSchemas>> : {};
32
+ };
33
+
34
+ /** Enqueue work and await the durable queue worker's result. */
35
+ export declare const processQueue: typeof durableQueueModule.process;
36
+
37
+ /** Start a durable queue worker layer with bounded concurrency.
38
+ *
39
+ * `DurableQueue.worker` is itself generic (`<Payload, Success, Error, R>`), so
40
+ * a hand-written wrapper can't re-state that generic signature — the body runs
41
+ * against erased args and the const's explicit `: typeof DurableQueue.worker`
42
+ * annotation restores the full generic public type. That annotation (not an
43
+ * inferred type) is what emits in the `.d.ts`, so it stays portable. */
44
+ export declare const queueWorker: typeof durableQueueModule.worker;
45
+
46
+ /** Durable rate limiter activity. Delays through the workflow clock. */
47
+ export declare const rateLimit: typeof durableRateLimiterModule.rateLimit;
48
+
49
+ /**
50
+ * Durable sleep — wake time journaled in the cluster. Wrapper around
51
+ * `DurableClock.sleep` that emits `timer-set` / `timer-fired` events
52
+ * to the recorder so the dashboard's Gantt timeline renders the wait
53
+ * as a visible bar — a workflow waiting on a cron-style delay should
54
+ * not look like a black hole.
55
+ *
56
+ * The wrap is transparent: signature matches `DurableClock.sleep`,
57
+ * no observable behavior change beyond the event emissions. When no
58
+ * recorder is in scope (unit tests, no `voltro dev`/`voltro start`
59
+ * wrapper around the workflow) it's a zero-overhead passthrough.
60
+ */
61
+ export declare const sleep: typeof durableClock.sleep;
62
+
63
+ export declare const step: <R, Success extends Schema.Schema.Any = typeof Schema.Void, Error extends Schema.Schema.All = typeof Schema.Never>(options: StepOptions<R, Success, Error>) => ReturnType<typeof stepModule.make<R, Success, Error>>;
64
+
65
+ /**
66
+ * Derive a deterministic idempotency key for the current workflow run,
67
+ * scoped to `name`. Call it inside a `step()` so a retried external
68
+ * side-effect converges on a single key instead of double-creating —
69
+ * pair it with a read-before-write provider-operations ledger. Pass
70
+ * `{ includeAttempt: true }` to vary the key per attempt.
71
+ *
72
+ * Named for the framework's `step` vocabulary (it is upstream's
73
+ * `Activity.idempotencyKey`).
74
+ */
75
+ export declare const stepIdempotencyKey: typeof stepModule.idempotencyKey;
76
+
77
+ export { stepModule }
78
+
79
+ /**
80
+ * Define a checkpointed step (activity) inside a workflow body.
81
+ *
82
+ * Wraps `@effect/workflow`'s `Activity.make` to record every
83
+ * invocation in `_voltro_workflow_run_steps`. The wrapping is
84
+ * transparent — accepts everything `Activity.make` accepts, plus an
85
+ * optional `input` field whose value is persisted to the step row
86
+ * (truncated to 8 KB by the recorder). The dashboard surfaces it as
87
+ * "Input" alongside Output, so operators can answer "what arguments
88
+ * did this step receive?" without grep-ing logs.
89
+ *
90
+ * ```ts
91
+ * step({
92
+ * name: 'fetch-todos',
93
+ * input: { tenantId, since: lastFetch }, // ← optional, recorded
94
+ * execute: Effect.tryPromise({ try: () => ctx.store.query(...) }),
95
+ * })
96
+ * ```
97
+ *
98
+ * Without the recorder service in scope (unit tests, etc.) the input
99
+ * is dropped and the wrap is a no-op.
100
+ */
101
+ declare type StepOptions<R, Success extends Schema.Schema.Any, Error extends Schema.Schema.All> = {
102
+ readonly name: string;
103
+ readonly success?: Success | undefined;
104
+ readonly error?: Error | undefined;
105
+ readonly execute: Effect.Effect<Success['Type'], Error['Type'], R>;
106
+ readonly interruptRetryPolicy?: Parameters<typeof stepModule.make<R, Success, Error>>[0]['interruptRetryPolicy'];
107
+ /** Structured value recorded into `_voltro_workflow_run_steps.input`.
108
+ * Pass whatever makes the step debuggable in isolation. */
109
+ readonly input?: unknown;
110
+ /** Declarative retry-policy summary recorded into
111
+ * `_voltro_workflow_run_steps.retryPolicy`. Pure metadata — does
112
+ * NOT change retry behavior on its own. Wire actual retries via
113
+ * `Effect.retry` inside `execute:` or via `interruptRetryPolicy`
114
+ * above; this field tells the dashboard what the intended policy
115
+ * looks like so the per-attempt panel can show "attempt 2 of 5,
116
+ * exponential 1s base" instead of just "attempt 2". */
117
+ readonly retry?: StepRetryPolicy;
118
+ };
119
+
120
+ /**
121
+ * Declarative retry-policy summary. Pure metadata for the dashboard;
122
+ * the framework does NOT apply this. Users wire actual retry behavior
123
+ * via `Effect.retry(Schedule.*)` inside `execute:` or
124
+ * `Activity.make`'s `interruptRetryPolicy`.
125
+ *
126
+ * Shape is intentionally close to Effect's Schedule combinators so a
127
+ * future framework version can auto-translate declarative policies
128
+ * into a Schedule + apply it. For now: record + display.
129
+ *
130
+ * { strategy: 'exponential', maxAttempts: 5, baseDelay: '1 second', maxDelay: '30 seconds' }
131
+ * { strategy: 'fixed', maxAttempts: 3, baseDelay: '500 millis' }
132
+ * { strategy: 'linear', maxAttempts: 4, baseDelay: '1 second', step: '2 seconds' }
133
+ */
134
+ declare interface StepRetryPolicy {
135
+ readonly strategy: 'exponential' | 'fixed' | 'linear';
136
+ readonly maxAttempts: number;
137
+ /** Effect Duration string, e.g. `'1 second'`, `'500 millis'`. */
138
+ readonly baseDelay?: string;
139
+ /** Cap on exponential / linear growth, e.g. `'30 seconds'`. */
140
+ readonly maxDelay?: string;
141
+ /** Increment for `linear` strategy. */
142
+ readonly step?: string;
143
+ /** Free-form note rendered as a chip in the dashboard. Useful when
144
+ * the retry behavior is partially implemented in the user's
145
+ * Effect chain and the summary is just documentation. */
146
+ readonly note?: string;
147
+ }
148
+
149
+ /**
150
+ * Add compensating (rollback) logic to a top-level effect in a workflow
151
+ * body. The finalizer runs if the WHOLE workflow later fails — use it for
152
+ * saga-style undo: release a half-acquired resource, revert a partial
153
+ * promotion. Upstream constraint: compensation is registered only for
154
+ * top-level effects in the workflow, NOT for nested steps/activities.
155
+ *
156
+ * Pinned with `typeof` to keep the emitted .d.ts portable (see the TS2742
157
+ * note above the type-explicit re-exports).
158
+ *
159
+ * ```ts
160
+ * yield* withCompensation(
161
+ * step({ name: 'provision-db', execute: ... }),
162
+ * (resource) => releaseResource(resource), // runs only if the workflow fails
163
+ * )
164
+ * ```
165
+ */
166
+ export declare const withCompensation: typeof workflowModule.withCompensation;
167
+
168
+ /** Define a durable workflow. Adds Voltro version metadata on top of `Workflow.make`. */
169
+ export declare const workflow: WorkflowFn;
170
+
171
+ /** Callable shape of `workflow`: the raw `Workflow.make` surface PLUS the
172
+ * Voltro-typed overload that threads the message-schema metadata onto the
173
+ * returned definition. Explicit alias so the `.d.ts` names this type by its
174
+ * own alias — the inferred `Workflow.make` type references internal `@effect`
175
+ * modules via `.pnpm` paths and is not portable (TS2742) when re-emitted. */
176
+ declare type WorkflowFn = WorkflowMake & (<const Options extends WorkflowOptions>(options: Options) => ReturnType<WorkflowMake> & WorkflowMessagesCarrier<NormaliseWorkflowMessages<Options['messages']>>);
177
+
178
+ declare type WorkflowMake = typeof workflowModule.make;
179
+
180
+ export declare interface WorkflowMessagePairSchemas {
181
+ readonly payload: Schema.Schema.Any;
182
+ readonly success: Schema.Schema.Any;
183
+ }
184
+
185
+ export declare interface WorkflowMessagesCarrier<M extends WorkflowMessagesMetadata = WorkflowMessagesMetadata> {
186
+ readonly [WorkflowMessagesProperty]: M;
187
+ }
188
+
189
+ export declare interface WorkflowMessageSchemas {
190
+ readonly signals?: Readonly<Record<string, Schema.Schema.Any>>;
191
+ readonly updates?: Readonly<Record<string, WorkflowMessagePairSchemas>>;
192
+ readonly queries?: Readonly<Record<string, WorkflowMessagePairSchemas>>;
193
+ }
194
+
195
+ export declare interface WorkflowMessagesMetadata {
196
+ readonly signals: Readonly<Record<string, Schema.Schema.Any>>;
197
+ readonly updates: Readonly<Record<string, WorkflowMessagePairSchemas>>;
198
+ readonly queries: Readonly<Record<string, WorkflowMessagePairSchemas>>;
199
+ }
200
+
201
+ export declare const WorkflowMessagesProperty = "__voltroWorkflowMessages";
202
+
203
+ export { workflowModule }
204
+
205
+ declare type WorkflowOptions = Parameters<WorkflowMake>[0] & WorkflowVersionOptions & {
206
+ readonly messages?: WorkflowMessageSchemas;
207
+ };
208
+
209
+ export declare interface WorkflowVersionMetadata {
210
+ readonly version: string;
211
+ readonly compatibleWith: ReadonlyArray<string>;
212
+ readonly patches: ReadonlyArray<string>;
213
+ }
214
+
215
+ export declare interface WorkflowVersionOptions {
216
+ readonly version?: string | number;
217
+ readonly compatibleWith?: ReadonlyArray<string | number>;
218
+ readonly patches?: ReadonlyArray<string>;
219
+ }
220
+
221
+ export declare const WorkflowVersionTypeId: unique symbol;
222
+
223
+ export declare interface WorkflowWorkerLayerBrand {
224
+ readonly [WorkflowWorkerLayerTypeId]: true;
225
+ }
226
+
227
+ export declare const WorkflowWorkerLayerTypeId: unique symbol;
228
+
229
+ export { }
@@ -0,0 +1,2 @@
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _, y as v } from "./primitives-CWy1iu5w.js";
2
+ export { h as WorkflowMessagesProperty, u as WorkflowVersionTypeId, p as WorkflowWorkerLayerTypeId, s as durableClock, t as durableQueue, d as durableQueueModule, m as durableRateLimiterModule, n as getWorkflowVersionMetadata, c as isWorkflowWorkerLayer, g as processQueue, r as queueWorker, i as rateLimit, f as sleep, l as step, o as stepIdempotencyKey, a as stepModule, e as withCompensation, _ as workflow, v as workflowModule };