@lostgradient/weft 0.6.0 → 0.8.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 +7 -5
- package/dist/cli/generated/operation-client.generated.d.ts +1 -0
- package/dist/cli-main.js +63 -63
- package/dist/client/event-stream-options.d.ts +58 -0
- package/dist/client/event-stream-options.js +0 -0
- package/dist/client/event-stream.d.ts +27 -44
- package/dist/client/event-stream.js +21 -56
- package/dist/client/event-tail-lifecycle.d.ts +21 -0
- package/dist/client/event-tail-lifecycle.js +71 -0
- package/dist/client/event-tail.d.ts +3 -1
- package/dist/client/http-client.d.ts +4 -5
- package/dist/client/http-client.js +4 -1
- package/dist/client/http-handle.d.ts +4 -5
- package/dist/client/http-request.d.ts +7 -0
- package/dist/client/index.d.ts +2 -1
- package/dist/client/interface.d.ts +23 -7
- package/dist/client/local-handles.d.ts +2 -0
- package/dist/client/local-handles.js +10 -1
- package/dist/client/local.d.ts +3 -3
- package/dist/client/open-event-subscription.d.ts +3 -2
- package/dist/client/open-event-subscription.js +28 -1
- package/dist/client/sse-event-stream.d.ts +27 -0
- package/dist/client/sse-event-stream.js +276 -0
- package/dist/client/start-body.d.ts +2 -2
- package/dist/client/start-body.js +1 -0
- package/dist/core/context/activity-retry-state.d.ts +6 -5
- package/dist/core/context/activity-retry-state.js +31 -21
- package/dist/core/context/durable-activity.d.ts +117 -0
- package/dist/core/context/durable-activity.js +79 -0
- package/dist/core/context/operation-request.d.ts +15 -0
- package/dist/core/context/parallel-operations.js +1 -0
- package/dist/core/context/run-operation-cached-request.d.ts +8 -0
- package/dist/core/context/run-operation-cached-request.js +59 -0
- package/dist/core/context/run-operation.d.ts +23 -5
- package/dist/core/context/run-operation.js +62 -47
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +8 -17
- package/dist/core/engine/activity-heartbeat-tracking.js +7 -1
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +7 -2
- package/dist/core/engine/anonymous-signal-sequence.js +6 -4
- package/dist/core/engine/async-activity-completion.d.ts +5 -7
- package/dist/core/engine/async-activity-completion.js +13 -9
- package/dist/core/engine/bulk-operations-purge.js +2 -1
- package/dist/core/engine/bulk-operations.js +8 -7
- package/dist/core/engine/callback-checkpoint-persistence.d.ts +3 -0
- package/dist/core/engine/callback-checkpoint-persistence.js +25 -0
- package/dist/core/engine/callback-creators-bundles.js +4 -1
- package/dist/core/engine/checkpoint-io.d.ts +4 -1
- package/dist/core/engine/checkpoint-io.js +19 -10
- package/dist/core/engine/completed-review-storage.d.ts +2 -1
- package/dist/core/engine/completed-review-storage.js +4 -3
- package/dist/core/engine/construction.js +3 -1
- package/dist/core/engine/engine-internal-types.d.ts +2 -0
- package/dist/core/engine/errors.d.ts +6 -6
- package/dist/core/engine/errors.js +1 -1
- package/dist/core/engine/handles.js +1 -1
- package/dist/core/engine/index.d.ts +37 -5
- package/dist/core/engine/index.js +7 -1
- package/dist/core/engine/internals.d.ts +2 -1
- package/dist/core/engine/lease-manager.js +2 -2
- package/dist/core/engine/lifecycle/recovered-services.js +8 -1
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +2 -2
- package/dist/core/engine/lifecycle/start-or-signal-create.js +17 -15
- package/dist/core/engine/lifecycle/start-or-signal-resolution.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-or-signal-resolution.js +23 -5
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +6 -4
- package/dist/core/engine/lifecycle/start-or-signal.js +21 -4
- package/dist/core/engine/memo-durable-activity.d.ts +11 -0
- package/dist/core/engine/memo-durable-activity.js +282 -0
- package/dist/core/engine/operations-activity.d.ts +5 -1
- package/dist/core/engine/operations-activity.js +19 -7
- package/dist/core/engine/operations-data.d.ts +4 -1
- package/dist/core/engine/operations-data.js +3 -3
- package/dist/core/engine/reviews.js +7 -4
- package/dist/core/engine/schedule-run.js +12 -3
- package/dist/core/engine/schedule-timer.js +2 -0
- package/dist/core/engine/storage-io.js +2 -2
- package/dist/core/engine/termination/complete.js +3 -3
- package/dist/core/json.js +1 -1
- package/dist/core/scheduler/scheduler-class.js +2 -1
- package/dist/core/start-workflow-validation.d.ts +3 -4
- package/dist/core/start-workflow-validation.js +1 -1
- package/dist/core/timeouts.d.ts +13 -1
- package/dist/core/timeouts.js +4 -1
- package/dist/core/types/constants.d.ts +16 -0
- package/dist/core/types/options.d.ts +60 -12
- package/dist/core/types/services-resolution.d.ts +49 -3
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +3 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +7 -0
- package/dist/json-schema.js +1 -1
- package/dist/mcp/cli.js +26 -26
- package/dist/server/asyncapi-channels.js +82 -16
- package/dist/server/handler/auth-context-principal.d.ts +19 -0
- package/dist/server/handler/auth-context-principal.js +25 -0
- package/dist/server/handler/index.d.ts +2 -1
- package/dist/server/handler/index.js +35 -18
- package/dist/server/handler/route-dispatch.d.ts +12 -22
- package/dist/server/handler/route-dispatch.js +30 -36
- package/dist/server/handler/sse-route-dispatch.d.ts +25 -0
- package/dist/server/handler/sse-route-dispatch.js +45 -0
- package/dist/server/handler.js +28 -28
- package/dist/server/index.d.ts +8 -7
- package/dist/server/index.js +17 -17
- package/dist/server/operations/fleet-events-sse.d.ts +11 -0
- package/dist/server/operations/fleet-events-sse.js +164 -0
- package/dist/server/operations/sse-stream.d.ts +43 -0
- package/dist/server/operations/sse-stream.js +152 -7
- package/dist/server/operations/start-or-signal-workflow.d.ts +2 -0
- package/dist/server/operations/start-or-signal-workflow.js +25 -14
- package/dist/server/operations/start-workflow-options.d.ts +9 -6
- package/dist/server/operations/start-workflow-options.js +13 -0
- package/dist/server/operations/workflow-events-sse.d.ts +17 -0
- package/dist/server/operations/workflow-events-sse.js +200 -0
- package/dist/server/rest-bindings.js +12 -0
- package/dist/server/runtime/authentication-bridge.js +4 -0
- package/dist/server/runtime/cors.d.ts +1 -1
- package/dist/server/runtime/cors.js +6 -1
- package/dist/server/runtime/websocket-stream.d.ts +4 -0
- package/dist/server/runtime/websocket-stream.js +20 -3
- package/dist/server/runtime/websocket-worker.js +7 -2
- package/dist/server/serve-internals.d.ts +28 -0
- package/dist/server/serve-internals.js +4 -2
- package/dist/server/workflow-event-feed.d.ts +1 -0
- package/dist/server/workflow-event-feed.js +17 -6
- package/dist/service-worker/index.js +28 -28
- package/dist/service-worker/setup.d.ts +18 -1
- package/dist/service-worker/setup.js +7 -4
- package/dist/storage/typed-storage.d.ts +1 -1
- package/dist/storage/typed-storage.js +1 -1
- package/dist/testing/index.js +27 -27
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Weft
|
|
2
2
|
|
|
3
|
-
A Bun-native durable execution engine. Current release: `0.
|
|
3
|
+
A Bun-native durable execution engine. Current release: `0.8.0`.
|
|
4
4
|
|
|
5
5
|
Install the library from npm as `@lostgradient/weft`:
|
|
6
6
|
|
|
@@ -101,7 +101,7 @@ const result = await handle.result();
|
|
|
101
101
|
|
|
102
102
|
That's the core loop: `workflow({ name })` is a **chained builder** that co-locates the workflow's side-effecting steps inside `.activities({...})`, and `.execute(fn)` seals it all together and returns a `WorkflowDefinition`. Inside the generator, `ctx.run('formatGreeting', input)` autocompletes from the workflow's own activity table, typechecks the input, and infers the output. Every `yield*` is a checkpoint boundary; `handle.result()` waits for the output. Checkpoints are written to `./weft.db`, so running workflows survive process crashes.
|
|
103
103
|
|
|
104
|
-
`Engine.create()` does the registration dance for you: it constructs the engine and registers each workflow in the `workflows` map, pulling in all the activities each workflow declares. It then **recovers by default** — `engine.recoverAll()` runs after registration, so any workflows still running from a previous process pick up where they left off. That's the point of durable storage, so you don't have to ask for it. Pass `recover: false` to opt out (handy for tests, for `ScopedStorage`-isolated engines, or when you want to inspect a store before migrating it). Durability is separate: each step is persisted before it commits no matter what `recover` is set to — `recover` only decides whether _this_ engine resumes that persisted work on boot. Run a single engine per durable store; pointing two at the same store is not yet coordinated and can double-resume a workflow.
|
|
104
|
+
`Engine.create()` does the registration dance for you: it constructs the engine and registers each workflow in the `workflows` map, pulling in all the activities each workflow declares. It then **recovers by default** — `engine.recoverAll()` runs after registration, so any workflows still running from a previous process pick up where they left off. That's the point of durable storage, so you don't have to ask for it. Pass `recover: false` to opt out (handy for tests, for `ScopedStorage`-isolated engines, or when you want to inspect a store before migrating it). Durability is separate: each step is persisted before it commits no matter what `recover` is set to — `recover` only decides whether _this_ engine resumes that persisted work on boot. If a host owns recovery but still needs durable timers, use `startScheduler: true`; otherwise `recover: false` also leaves the real-time scheduler stopped. Run a single engine per durable store; pointing two at the same store is not yet coordinated and can double-resume a workflow.
|
|
105
105
|
|
|
106
106
|
Passing an explicitly empty workflow map is the same default-registry boot shape as omitting `workflows`: `Engine.create({ workflows: {} })` recovers after registration and returns an engine whose TypeScript type is compatible with default-registry consumers such as `serve({ engine })`. Use a non-empty `workflows` map when you want TypeScript to narrow `engine.start(...)` to the registered names.
|
|
107
107
|
|
|
@@ -147,7 +147,7 @@ Because recovery never re-executes the workflow from the beginning, your workflo
|
|
|
147
147
|
|
|
148
148
|
### Durable Workflows
|
|
149
149
|
|
|
150
|
-
Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, condition gates with `ctx.waitUntil()`, queries, updates, structured logs with `ctx.log`, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks. `ctx.all()` and `ctx.race()` can branch over activities, sleeps, and signal waits; use `ctx.race([ctx.waitForSignal(name), ctx.sleep(timeout)])` for signal timeouts instead of placing an unbounded signal wait directly in `ctx.all()`.
|
|
150
|
+
Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, condition gates with `ctx.waitUntil()`, queries, updates, structured logs with `ctx.log`, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks. Plain async helpers called from inline `ctx.memo()` callbacks can use `durableActivity()` for activity-level retry, heartbeat, reconciliation, and observability without converting the helper stack to generators. `ctx.all()` and `ctx.race()` can branch over activities, sleeps, and signal waits; use `ctx.race([ctx.waitForSignal(name), ctx.sleep(timeout)])` for signal timeouts instead of placing an unbounded signal wait directly in `ctx.all()`.
|
|
151
151
|
|
|
152
152
|
Every workflow context exposes `ctx.workflowId` and `ctx.workflowType`. `workflowType` is the registered name from `workflow({ name })`, so shared workflow code can log, tag, or branch on the current workflow type without closing over definition-site state.
|
|
153
153
|
|
|
@@ -216,7 +216,7 @@ const quorum = workflow({ name: 'quorum' })
|
|
|
216
216
|
|
|
217
217
|
### Live Workflow Events
|
|
218
218
|
|
|
219
|
-
Workflow handles expose lifecycle events through `addEventListener`, and client handles can open a live tail for progress UIs or operators. `LocalClient` reads from the in-process engine stream; `HttpClient`
|
|
219
|
+
Workflow handles expose lifecycle events through `addEventListener`, and client handles can open a live tail for progress UIs or operators. `LocalClient` reads from the in-process engine stream; `HttpClient` defaults to the per-workflow `/v1/workflows/:id/watch` WebSocket channel when the runtime can carry authentication headers, and falls back to fetch-based SSE at `/v1/workflows/:id/events/sse` when it cannot. Both transports run history catch-up on connect and reconnect, so `addEventListener`, `client.tail(id)`, and `handle.tail()` are push-based rather than a polling loop. JSON-RPC clients can subscribe over WebSocket with `weft.workflows.subscribe` for one workflow or `weft.events.subscribe` for the fleet-wide event feed. Client code that receives a workflow id from another process can call `client.getHandle(id)` to re-attach a `ClientHandle` or get `null` when the run does not exist.
|
|
220
220
|
|
|
221
221
|
```typescript
|
|
222
222
|
const handle = await client.start('checkout', order);
|
|
@@ -229,7 +229,7 @@ for await (const event of tail) {
|
|
|
229
229
|
}
|
|
230
230
|
```
|
|
231
231
|
|
|
232
|
-
The tail is single-consumer and stops on terminal workflow events or `tail.close()`.
|
|
232
|
+
The tail is single-consumer and stops on terminal workflow events or `tail.close()`. Pass `eventTransport: 'websocket'` to require WebSocket, `eventTransport: 'sse'` to require SSE, or `HttpClientOptions.webSocketFactory` to provide a runtime-specific WebSocket constructor.
|
|
233
233
|
|
|
234
234
|
### Idempotent Starts and Signal-With-Start
|
|
235
235
|
|
|
@@ -248,6 +248,8 @@ console.log(handle.id, outcome); // outcome is 'started' or 'signalled'
|
|
|
248
248
|
|
|
249
249
|
The idempotency mapping intentionally outlives terminal cleanup. If retention removes the workflow record, the key is spent and future calls return a conflict instead of starting a replacement.
|
|
250
250
|
|
|
251
|
+
For stable-id re-sync flows, `engine.startOrSignal()` can replace a terminal prior run with `{ id, onTerminalConflict: 'start-new' }` when the initial signal also carries a deterministic `signalId`. Non-terminal runs are still signalled, not replaced, and restart-capable calls reject `idempotencyKey` because idempotency keys are permanent at-most-once mappings. Signal identifiers are treated as opaque user identifiers before storage-key construction, so caller-provided values that contain separator-looking text such as `anonymous:` stay explicit signal IDs instead of colliding with Weft's generated anonymous-signal sequence.
|
|
252
|
+
|
|
251
253
|
### Search Attributes
|
|
252
254
|
|
|
253
255
|
Attach indexed metadata to a workflow at runtime, then list and filter on it.
|
|
@@ -560,6 +560,7 @@ export type CatalogOperationTypes = {
|
|
|
560
560
|
readonly id?: unknown;
|
|
561
561
|
readonly idempotencyKey?: unknown;
|
|
562
562
|
readonly input?: unknown;
|
|
563
|
+
readonly onTerminalConflict?: unknown;
|
|
563
564
|
readonly searchAttributes?: unknown;
|
|
564
565
|
readonly signalId?: string;
|
|
565
566
|
readonly signalName: string;
|