effect-temporal is pre-1.0: minor bumps may break APIs; patch bumps are fixes only.
The effect peer dependency is pinned exactly on purpose — the engine implements
interfaces from effect/unstable/*, whose API can move between releases. Each release
of this package states the one effect version it is built and tested against, and
tracking a new effect release is a new release of this package.
The deletion release: everything deprecated in 0.4.0 is gone, and the API
converges on definition + bundle + activities + client /
engine-client + testing (+ wire and the engine-level corners of
engine-sandbox). No wire change — see the replay drill below.
- BREAKING: REMOVED the
typed-activitymodule and its package export.TypedActivity.make→defineActivity; the type helpers →definition;codecsFor/ACTIVITY_EXIT_TYPE/TypedActivityCodecs→wire. - BREAKING: REMOVED the
versioningmodule and its package export.match→versioned,version→version(bothdefinition). The Temporal-only retirement step moved tobundle:deprecateVersion,deprecatePatch,patched. - BREAKING: REMOVED from
engine-sandbox:callActivity,takeMailbox,pollMailbox,takeUpdate,setStateCell,sleepUntil,continueAsNew, and theUpdateRequest<S, E, P>alias. Their bodies are now module-private machinery behind the TemporalWorkflowOpsruntime.workflowBundle(import it frombundle),callRawActivity,offerMailbox(workflow → workflow),callNexusWorkflowOperation, andSandboxRunremain. - BREAKING: REMOVED the
mailbox,update, andstate-cellpackage exports and theirmakeconstructors (→defineMailbox,defineUpdate,defineState). The modules stay in the source tree as internal wire homes (MAILBOX_SIGNAL,WORKFLOW_UPDATE,STATE_CELL_QUERY, codecs) for the engine halves andtesting. prefer-definitionkeeps its tables (message now "was removed in 0.5.0 — use …"), so a stale import gets a pointer instead of a bare module-not-found; it also reportsworkflowBundleimported fromengine-sandbox(→bundle). The 0.4.0 plan said to empty the tables; keeping them is strictly more useful.- Replay drill:
replay-compat.test.tsnow also replays two histories recorded on 0.4.0 —defDispatch(versionedmarker + awaitedexecuteChild) anddefGrace(durable timer racing a mailbox take) — alongside the 0.3.0defOrderhistory. The version-chain fixtures (generations 2 and 3) author withversioned; generation 1 stays pre-versioning code, so the drill still proves adoption is replay-safe. - The repository has no remaining import of a removed symbol; the examples and every fixture author against the current surface.
Built and tested against effect@4.0.0-rc.112 and @temporalio/*@1.19.0.
Closes the gaps between the definition module and the legacy authoring
surface: after this release a consumer imports definition, bundle,
activities, client/engine-client, testing, and (engine-level) wire
— never engine-sandbox except for the engine-level escape hatches,
never typed-activity, versioning, or mailbox.
- NEW: timers on the
WorkflowOpsseam —sleep({ name, duration })andsleepUntil({ name, timestamp })fromdefinition, requiring onlyWorkflowOps. On Temporal they dispatch toDurableClock.sleep/ the existingsleepUntil(same timestamp rule, now the sharedsleepUntilTarget: zone-less and unparseable timestamps die). InmakeTestWorkflowOpsthey follow Effect'sClock, so aTestClockcanadjustpast them — deliberately not instant, so a mailbox take racing a grace-period timer is testable in both orders (pinned on both engines). - NEW:
continueAsNew(workflow, payload, options?)on the seam and indefinition. In memory it interrupts the handler fiber and records the continuation (world.continuedAsNew,world.continuedAsNewOf(W)), payload round-tripped through the workflow's payload schema (a schema-invalid payload dies, as on the wire). - NEW: child workflows on the seam —
executeChild(workflow, payload, { discard? })fromdefinition. On Temporal it is upstreamexecuteunder the sandbox engine (identical commands:startChildwith the digest id,REQUEST_CANCEL/ABANDON, attach-on-taken).makeTestWorkflowOpsacceptsworkflows: [handleWorkflow(Child, handler)]and runs children in-process with schema round-tripping, discard-forks, and attach on a taken id. - NEW:
versioned(site, { v1: run1, v2: run2 })— the run-table form ofversion(key order is the chain order, oldest first), built on the sameWorkflowOps.version; theversioning-on-main-fiberlint rule recognises it (alias-aware) alongsideversion. - NEW: the activity type helpers live on
definition—PayloadOf,SuccessOf,ErrorOf,AnyTypedActivity,TypedActivity,TypedActivityOptions,DEFAULT_ACTIVITY_OPTIONS.codecsFor,TypedActivityCodecs, andACTIVITY_EXIT_TYPEmoved towire(thetyped-activitymodule re-exports everything, deprecated). - NEW: every client-side operation takes the declaration directly —
offerMailbox(Priority, …),executeUpdate(SetAmount, …),readStateCell(Status, …),deferredState(Approval, …)inengine-clientand onWorkflowClient; the underlying primitive (Priority.mailbox, …) is still accepted (MailboxLike/UpdateLike/StateCellLike/DeferredLike). NEWcompleteDeferred(Approval, { client, workflowId, exit })/wf.completeDeferred(Approval, workflowId, exit): the client half ofApproval.await— same done-signal asDurableDeferred.done, no token, noWorkflowEngine. The workflow → workflowofferMailbox(engine-sandbox) accepts the declaration too. - NEW:
makeFakeTemporalClientgainsoffer(Priority, workflowId, payload)andoffersTo(Priority)(decoded through the declaration) — noMAILBOX_SIGNALimport in consumer tests. The live harness client gainsoffer/request/stateOf/resolve, mirroring the in-memory world. - NEW: the
bundlemodule —workflowBundle's home, "the one file the Temporal worker points at".engine-sandboxstill exports it; its other exports are documented as engine-level (callRawActivity, workflow → workflowofferMailbox,callNexusWorkflowOperation,SandboxRun) or deprecated (below). - NEW:
prefer-definitionlint rule, on in therecommendedpreset as an error: reports any import of a deprecated symbol from this package's modules (published specifier or relative path) with the replacement in the message, sooxlintfails on regressions. - NEW:
replay-compat.test.ts— a history recorded on 0.3.0 (fixtures/histories/definition-order-0.3.0) replays through the current bundle. Wire identity is unchanged: activity types, signal/query/update names, and patch-marker ids are byte-identical. - DEPRECATED (removed in 0.5.0; replacement in each JSDoc):
engine-sandbox'scallActivity,takeMailbox,pollMailbox,takeUpdate,setStateCell,sleepUntil,continueAsNew, and theUpdateRequest<S, E, P>alias (usedefinition'sUpdateRequest<P, S, E>— one parameter order);TypedActivity.make;DurableMailbox.make,DurableUpdate.make,StateCell.make;Versioning.match/Versioning.version; the wholetyped-activityandversioningmodules. defineDeferred/defineMailbox/defineUpdate/defineStatereturn named interfaces (DefinedDeferred,DefinedMailbox,DefinedUpdate,DefinedState) — structurally what they returned before.- The repository authors with the new surface throughout: fixtures and
examples import
workflowBundlefrombundle, the examples usesleepandcontinueAsNewfromdefinitionand drive declarations directly; the versioning-chain and loop fixtures deliberately stay on the deprecated calls so the replay drills keep covering them. effectpeer/dev pin:4.0.0-rc.112(was4.0.0-beta.101); full suite and both examples green against it.@temporalio/*stays1.19.0.
Built and tested against effect@4.0.0-rc.112 and @temporalio/*@1.19.0.
- NEW: the
definitionmodule — declare each capability once and use it directly inside handlers:defineActivity(callable:yield* Charge({ orderId })),defineDeferred(.await),defineMailbox(.take/.poll),defineUpdate(.take),defineState(.set), plusversion(patch-marker logic branches) andevolved(newest-first schema evolution with pure migrations). Every primitive requires only theWorkflowOpsservice — the one seam an engine implements — so handlers import nothing fromengine-sandboxand are engine-agnostic. Client-side driving uses the declaration's underlying primitive (U.update,M.mailbox,C.cell,D.deferred) with the existingengine-clientops. - NEW:
makeTestWorkflowOpsintesting— an in-memoryWorkflowOpsruntime (activities run theirhandlebindings with schema-validated payloads; deferreds/mailboxes/updates/state driven viaresolve/offer/request/stateOf), so the same handler that runs on Temporal runs in a plain unit test with no engine and no test server. workflowBundleprovides the TemporalWorkflowOpsruntime to hosted layers automatically; bundle authoring is otherwise unchanged.- The repository's fixtures, examples, and docs author with the
definitionmodule throughout. The low-level per-primitive calls (callActivity,takeMailbox,pollMailbox,takeUpdate,setStateCell) remain exported fromengine-sandboxas the machinery underneath.
- BREAKING: workflow bundles are authored with
Workflow.toLayer, hosted behindworkflowBundle(layer)— one dynamic default export per bundle, the same registration-driven authoring the cluster and in-memory engines use. Handlers can require services provided by ordinary Layers in the registration environment.makeTemporalWorkflowis REMOVED: one way to author. (If per-typeworkflowDefinitionOptions— e.g. Worker Versioning behavior — becomes a need, the worker-leveldefaultVersioningBehaviorcovers the dynamic workflow, and a per-type escape hatch can return later.)
Initial public release. (0.1.0 was published without provenance during release setup and unpublished; npm version numbers are never reusable.)
Initial standalone release, extracted from the Springbird monorepo.
- Temporal engine for
effect/unstable/workflow(Workflow,Activity,DurableClock,DurableDeferred): sandbox half (engine-sandbox) and client half (engine-client), plus theWorkflowClientservice. - Durable extension primitives:
DurableMailbox,DurableUpdate,StateCell,continueAsNew, patch-marker versioning (Versioning.match), schedules, and workflow-backed Nexus operations. - Typed activities (
TypedActivity.make,callActivity,implementActivities). - Testing:
makeFakeTemporalClient(typed, loud fake) andstartWorkflowTestHarness(real test server). - Lint plugin + oxlint presets for the authoring footguns.
- Fiber-level interruption (
Effect.timeout, lost races) now cancels the in-flight server-side activity/Nexus call instead of abandoning it. - Hardening from the pre-release audit: guarded workflow→workflow
DurableDeferred.doneagainst the closed-receiver race; Nexus operations decode their input before deriving the idempotent execution id (transforming schemas now digest correctly); the attach-poll loop stops on interruption instead of accruing history; malformed mailbox/update payloads are dropped or answered with a defect instead of poisoning the run;sleepUntilrejects zone-less date-time strings and unparseable timestamps; in-sandbox UTF-8 digests matchTextEncoderon lone surrogates.
Built and tested against effect@4.0.0-beta.101 and @temporalio/*@1.19.0.