Skip to content

Commit ee189ef

Browse files
btraversclaude
andcommitted
feat(worker)!: remove deprecated createWorkerOrThrow
Completes the no-deprecated-aliases policy applied to the client's createOrThrow: createWorker returns AsyncResult<Worker, never>, so .get() provides the same throw-on-defect behavior with the original cause. Migration guide, checklist, changeset, and handlers.md updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e7a9ef4 commit ee189ef

12 files changed

Lines changed: 35 additions & 87 deletions

File tree

.agents/rules/handlers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ shape on the client: the connection-scoped `TypedClient.create({ client })`
108108
returns `AsyncResult<TypedClient, never>` (a `TechnicalError`-caused defect on
109109
setup failure); bind a contract with the synchronous, infallible
110110
`typedClient.for(contract)`, which returns a `ContractClient<TContract>` (the
111-
type to use in annotations). There is no `TypedClient.createOrThrow`; the
112-
deprecated `createWorkerOrThrow` still exists for migration.
111+
type to use in annotations). There is no `TypedClient.createOrThrow` and no
112+
`createWorkerOrThrow` — use `.get()` on the returned `AsyncResult`.
113113

114114
```typescript
115115
import { createWorker, workflowsPathFromURL } from "@temporal-contract/worker/worker";

.changeset/v8-review-remediation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ v8 review remediation — the full-surface overhaul from the six-track 8.0 revie
2828

2929
- Invalid signal payloads are dropped and logged (`log.warn`), never thrown — `SignalInputValidationError` is deleted; a stale client can no longer terminally kill a workflow execution.
3030
- Contract misuse inside workflow code (unknown signal/query/update or workflow name, async schema, uncovered activity options) now fails fast as a non-retryable `ContractMisuseError` `ApplicationFailure` instead of hanging executions in Workflow Task retries.
31-
- Exported `qualify` is renamed `qualifyFailure` (no alias).
31+
- Exported `qualify` is renamed `qualifyFailure` (no alias), and the deprecated `createWorkerOrThrow` is removed — use `createWorker(...).get()`.
3232
- `activities` is optional on `createWorker`, and activity-less workflows no longer need `{}` entries in the implementations map.
3333
- `TypedChildWorkflowHandle` gains a typed `signals` map and `firstExecutionRunId`.
3434

docs/how-to/add-activity-middleware.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ export const activities = declareActivitiesHandler({
6464
## Inject typed context
6565

6666
The most useful thing middleware does is extend the typed context that flows to
67-
implementations. Use `defineActivityMiddleware` to pin the in and out types:
67+
implementations. Use `declareActivityMiddleware` to pin the in and out types:
6868

6969
```typescript
70-
import { defineActivityMiddleware, type EmptyContext } from "@temporal-contract/worker/activity";
70+
import { declareActivityMiddleware, type EmptyContext } from "@temporal-contract/worker/activity";
7171
import { Err } from "unthrown";
7272

73-
const withTenant = defineActivityMiddleware<EmptyContext, { tenantId: string }>(
73+
const withTenant = declareActivityMiddleware<EmptyContext, { tenantId: string }>(
7474
(invocation, next) => {
7575
const tenantId = (invocation.input as { tenantId?: string }).tenantId;
7676

@@ -160,7 +160,7 @@ export const activities = declareActivitiesHandler({
160160
smuggle unvalidated data past the contract:
161161

162162
```typescript
163-
const normalizeEmail = defineActivityMiddleware((invocation, next) => {
163+
const normalizeEmail = declareActivityMiddleware((invocation, next) => {
164164
const input = invocation.input as { email?: string };
165165
if (typeof input.email !== "string") {
166166
return next();

docs/how-to/configure-a-worker.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ await result.value.run();
5252
`.get()` is the terse form — on a defect it rethrows the original cause with its
5353
stack intact, which is usually what you want at process startup.
5454

55-
::: tip `createWorkerOrThrow` is deprecated
56-
It exists to ease migration from the pre-`AsyncResult` API and will be removed
57-
in a future major. Use `createWorker`.
58-
:::
59-
6055
## Resolve the workflows path
6156

6257
Temporal bundles workflow code into an isolated sandbox, so it needs a _path_,

docs/how-to/upgrade-to-v8.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ Or, more concisely — `.get()` rethrows a defect's original cause:
169169
const typedClient = await TypedClient.create({ client }).get();
170170
```
171171

172-
The same applies to `createWorker`.
172+
The same applies to `createWorker`. The deprecated `createWorkerOrThrow`
173+
migration alias is removed in 8.0 — use `createWorker(...).get()`.
173174

174175
### Every other operation
175176

@@ -412,6 +413,17 @@ A mechanical rename, no alias kept:
412413
+ fromPromise(gateway.charge(customerId, amount), qualifyFailure("CHARGE_FAILED"))
413414
```
414415

416+
### `createWorkerOrThrow` is removed
417+
418+
The deprecated throwing alias goes the same way as the client's
419+
`createOrThrow`: `createWorker` returns `AsyncResult<Worker, never>`, so
420+
`.get()` gives the same throw-on-defect behavior with the original cause.
421+
422+
```diff
423+
- const worker = await createWorkerOrThrow({ contract, connection, workflowsPath, activities });
424+
+ const worker = await createWorker({ contract, connection, workflowsPath, activities }).get();
425+
```
426+
415427
### Contract misuse fails the execution instead of hanging it
416428

417429
Binding a signal/query/update handler for a name the contract does not
@@ -592,6 +604,7 @@ New on the surface:
592604
(imports and `P.tag` arms)
593605
- [ ] `getHandle` calls drop their `await` (it returns a sync `Result`)
594606
- [ ] `qualify``qualifyFailure` in activity implementations
607+
- [ ] `createWorkerOrThrow(...)``createWorker(...).get()`
595608
- [ ] No `SignalInputValidationError` imports remain; alerting expects
596609
invalid signals to be dropped and logged, not to fail executions
597610
- [ ] `schedule.create` matchers handle `ScheduleAlreadyExistsError`;

docs/reference/worker-surface.md

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ Runs **inside** the validation boundary.
305305
Calling `next` more than once re-runs the rest of the chain (retry). Returning
306306
without calling it short-circuits.
307307

308-
#### `defineActivityMiddleware(middleware)`
308+
#### `declareActivityMiddleware(middleware)`
309309

310310
Identity helper that pins the context type parameters without a variable
311311
annotation.
@@ -350,15 +350,6 @@ technical faults on the **defect** channel with a `TechnicalError` cause.
350350
Inspect with `isDefect()` / `match({ defect })` / `recoverDefect`, or use
351351
`.get()` to rethrow the original cause.
352352

353-
### `createWorkerOrThrow(options)`
354-
355-
::: warning Deprecated
356-
Pre-`AsyncResult` behaviour, kept to ease migration. Removed in a future major.
357-
Use `createWorker`.
358-
:::
359-
360-
Rethrows the original cause rather than the `TechnicalError` wrapper.
361-
362353
### `workflowsPathFromURL(baseURL, relativePath)`
363354

364355
```typescript

packages/testing/src/time-skipping.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function createTimeSkippingEnvironment(
7878
*/
7979
export function createTimeSkippingTest(options?: TimeSkippingTestWorkflowEnvironmentOptions) {
8080
return vitestIt.extend<{
81-
$worker: { testEnv: TestWorkflowEnvironment };
81+
testEnv: TestWorkflowEnvironment;
8282
}>({
8383
testEnv: [
8484
// oxlint-disable-next-line no-empty-pattern

packages/worker/src/__tests__/time-skipping.inprocess.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { describe, expect } from "vitest";
2424
import {
2525
composeActivityMiddleware,
2626
declareActivitiesHandler,
27-
defineActivityMiddleware,
27+
declareActivityMiddleware,
2828
} from "../activity.js";
2929
import { createWorker, TechnicalError } from "../worker.js";
3030
import { inprocessContract } from "./inprocess.contract.js";
@@ -35,7 +35,7 @@ const errAsync = <E>(error: E): AsyncResult<never, E> => Err(error).toAsync();
3535
const seenContexts: Record<string, unknown>[] = [];
3636

3737
const tracing = composeActivityMiddleware(
38-
defineActivityMiddleware<{ gateway: string }, { gateway: string; traceId: string }>(
38+
declareActivityMiddleware<{ gateway: string }, { gateway: string; traceId: string }>(
3939
(invocation, next) => next({ context: { ...invocation.context, traceId: "trace-1" } }),
4040
),
4141
);

packages/worker/src/activity-contract-errors.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
ApplicationFailure,
1616
composeActivityMiddleware,
1717
declareActivitiesHandler,
18-
defineActivityMiddleware,
18+
declareActivityMiddleware,
1919
type ActivityMiddleware,
2020
} from "./activity.js";
2121
import { ContractErrorDataValidationError } from "./errors.js";
@@ -379,10 +379,11 @@ describe("declareActivitiesHandler — middleware", () => {
379379
const seenByInner: unknown[] = [];
380380
const seenByImplementation: unknown[] = [];
381381

382-
const outer = defineActivityMiddleware<{ tenant: string }, { tenant: string; traceId: string }>(
383-
(invocation, next) => next({ context: { ...invocation.context, traceId: "t-1" } }),
384-
);
385-
const inner = defineActivityMiddleware<
382+
const outer = declareActivityMiddleware<
383+
{ tenant: string },
384+
{ tenant: string; traceId: string }
385+
>((invocation, next) => next({ context: { ...invocation.context, traceId: "t-1" } }));
386+
const inner = declareActivityMiddleware<
386387
{ tenant: string; traceId: string },
387388
{ tenant: string; traceId: string; attempt: number }
388389
>((invocation, next) => {

packages/worker/src/activity.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ export type ActivityMiddlewareNext<
313313
* `next({ context })`. A middleware that only reads context leaves both
314314
* parameters equal and stays valid unchanged. Compose typed chains with
315315
* {@link composeActivityMiddleware}; pin a middleware's context types
316-
* without a variable annotation via {@link defineActivityMiddleware}.
316+
* without a variable annotation via {@link declareActivityMiddleware}.
317317
*
318318
* @example Log every activity invocation and its outcome (read-only)
319319
* ```ts
@@ -334,7 +334,7 @@ export type ActivityMiddlewareNext<
334334
*
335335
* @example Guard-and-narrow: inject a tenant id for everything downstream
336336
* ```ts
337-
* const auth = defineActivityMiddleware<EmptyContext, { tenantId: string }>(
337+
* const auth = declareActivityMiddleware<EmptyContext, { tenantId: string }>(
338338
* (invocation, next) => {
339339
* const tenantId = readTenant(invocation.input);
340340
* if (!tenantId) {
@@ -370,7 +370,7 @@ export type AnyActivityMiddleware = ActivityMiddleware<
370370
* Identity helper that pins a middleware's context types without a variable
371371
* annotation. (Mirrors amqp-contract's `defineMiddleware`.)
372372
*/
373-
export function defineActivityMiddleware<
373+
export function declareActivityMiddleware<
374374
TContextIn extends Record<string, unknown> | EmptyContext = EmptyContext,
375375
TContextOut extends TContextIn = TContextIn,
376376
>(

0 commit comments

Comments
 (0)