@btravstack/temporal-worker 0.10.0 → 0.11.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 CHANGED
@@ -23,14 +23,32 @@ All nine are peer dependencies — install them. Node `>=22`.
23
23
  <!-- doctest: prelude
24
24
  import { defineActivity, defineContract, defineWorkflow } from "@temporal-contract/contract";
25
25
  import { workflowsPathFromURL } from "@temporal-contract/worker/worker";
26
- import { Module } from "@btravstack/di";
27
- import { PlaceOrder, OrderRepository, Outbox, OrderApplicationModule } from "@btravstack/example-order-application";
28
- import { OrderPersistenceModule } from "@btravstack/example-order-infrastructure";
29
- import { TenantId } from "@btravstack/example-order-domain";
26
+ import { Module, Port, type AnyModule } from "@btravstack/di";
27
+ import { TaggedError, type AsyncResult } from "unthrown";
30
28
  import { observability } from "@btravstack/observability";
31
29
  import { otel } from "@btravstack/observability/otel";
32
30
  import { z } from "zod";
33
31
 
32
+ // The application's own layers, declared here so this sample stands on the
33
+ // published packages alone: the use case, its errors and its tenant id are
34
+ // yours, not this package's.
35
+ class DuplicateOrder extends TaggedError("DuplicateOrder")<{ readonly id: string }> {}
36
+ class InvalidOrderId extends TaggedError("InvalidOrderId")<{ readonly id: string }> {}
37
+ class InvalidQuantity extends TaggedError("InvalidQuantity")<{ readonly id: string }> {}
38
+ declare const TenantId: (value: string) => string;
39
+ class PlaceOrder extends Port("PlaceOrder")<{
40
+ readonly execute: (
41
+ tenantId: string,
42
+ id: string,
43
+ quantity: number,
44
+ ) => AsyncResult<
45
+ { readonly id: string },
46
+ DuplicateOrder | InvalidOrderId | InvalidQuantity
47
+ >;
48
+ }> {}
49
+ declare const OrderApplicationModule: Module<PlaceOrder, never, never>;
50
+ declare const OrderPersistenceModule: AnyModule;
51
+
34
52
  // The contract this README's worker serves — one workflow, one activity, one
35
53
  // modeled contract error.
36
54
  const contract = defineContract({
@@ -58,7 +76,7 @@ const contract = defineContract({
58
76
 
59
77
  const AppModule = Module("App")({
60
78
  imports: [OrderApplicationModule, OrderPersistenceModule, observability(), otel()],
61
- exports: [PlaceOrder, OrderRepository, Outbox, Logger],
79
+ exports: [PlaceOrder, Logger],
62
80
  });
63
81
  -->
64
82
 
@@ -128,9 +146,12 @@ typed by the key alone, and `TemporalActivities(contract)([...])` composes an
128
146
  array of them into the same activities provider `TemporalModule` takes — the
129
147
  array must cover every key the contract declares, and each piece's own port
130
148
  must still be discharged (`provides`), since the composed provider's deps are
131
- the pieces' ports, not what they close over. Two slices claiming one key are
132
- di's duplicate-provider defect at build, which is the point: a workflow's
133
- activities belong to exactly one slice.
149
+ the pieces' ports, not what they close over. A workflow's activities belong to exactly
150
+ one slice, and the compiler holds only half of that: coverage is checked,
151
+ injectivity is not, so two slices claiming one key type-check together. It is
152
+ di's duplicate-provider defect at build once **both** pieces are discharged as
153
+ providers in one graph — wire in only one and the other's implementation is
154
+ silently never registered.
134
155
 
135
156
  Its own test suite needs a **Docker daemon**: the specs run against the shared
136
157
  `temporalio/auto-setup` container `internal/test-infra` starts once per machine and every
package/dist/index.d.cts CHANGED
@@ -200,6 +200,19 @@ type KeyOfPiece<P> = P extends {
200
200
  } ? K : never;
201
201
  /** The record's top-level keys no piece in `T` covers. */
202
202
  type Uncovered<C extends ContractDefinition, T extends readonly PieceOf<C>[]> = Exclude<ActivitiesKeyOf<C>, KeyOfPiece<T[number]>>;
203
+ /**
204
+ * A refused array: as long as the array the caller wrote, its head the caller's
205
+ * own elements — which match — and its LAST element the marker paired with what
206
+ * is wrong.
207
+ *
208
+ * TypeScript compares two equal-length tuples element by element, so the extra
209
+ * diagnostic it reports lands on the trailing element and carries both the
210
+ * sentence and the missing key. A fixed two-element tuple named the key only
211
+ * when the array happened to be two elements long; every other arity was a
212
+ * length mismatch, and the developer diffed the contract against the array by
213
+ * hand.
214
+ */
215
+ type Refuse<T extends readonly unknown[], Marker extends string, Detail> = T extends readonly [...infer Head, unknown] ? readonly [...Head, readonly [Marker, Detail]] : readonly [readonly [Marker, Detail]];
203
216
  /**
204
217
  * The composing arm. Declared LAST in the intersection below on purpose:
205
218
  * TypeScript reports the last overload's failure, so a non-covering array is
@@ -209,7 +222,7 @@ type Uncovered<C extends ContractDefinition, T extends readonly PieceOf<C>[]> =
209
222
  * The marker is a sentence rather than a bare label because it prints last,
210
223
  * after the caller's own several-hundred-character piece type.
211
224
  */
212
- type Compose<C extends ContractDefinition> = <const T extends readonly PieceOf<C>[]>(pieces: [Uncovered<C, T>] extends [never] ? T : readonly ["UNCOVERED ACTIVITIES — the contract declares a workflow this array does not cover", Uncovered<C, T>]) => Provider<ActivitiesInstanceOf<C>, never, InstanceType<T[number]["port"]>> & {
225
+ type Compose<C extends ContractDefinition> = <const T extends readonly PieceOf<C>[]>(pieces: [Uncovered<C, T>] extends [never] ? T : Refuse<T, "UNCOVERED ACTIVITIES — the contract declares a workflow this array does not cover", Uncovered<C, T>>) => Provider<ActivitiesInstanceOf<C>, never, InstanceType<T[number]["port"]>> & {
213
226
  readonly port: ActivitiesPortOf<C>;
214
227
  };
215
228
  /**
package/dist/index.d.mts CHANGED
@@ -200,6 +200,19 @@ type KeyOfPiece<P> = P extends {
200
200
  } ? K : never;
201
201
  /** The record's top-level keys no piece in `T` covers. */
202
202
  type Uncovered<C extends ContractDefinition, T extends readonly PieceOf<C>[]> = Exclude<ActivitiesKeyOf<C>, KeyOfPiece<T[number]>>;
203
+ /**
204
+ * A refused array: as long as the array the caller wrote, its head the caller's
205
+ * own elements — which match — and its LAST element the marker paired with what
206
+ * is wrong.
207
+ *
208
+ * TypeScript compares two equal-length tuples element by element, so the extra
209
+ * diagnostic it reports lands on the trailing element and carries both the
210
+ * sentence and the missing key. A fixed two-element tuple named the key only
211
+ * when the array happened to be two elements long; every other arity was a
212
+ * length mismatch, and the developer diffed the contract against the array by
213
+ * hand.
214
+ */
215
+ type Refuse<T extends readonly unknown[], Marker extends string, Detail> = T extends readonly [...infer Head, unknown] ? readonly [...Head, readonly [Marker, Detail]] : readonly [readonly [Marker, Detail]];
203
216
  /**
204
217
  * The composing arm. Declared LAST in the intersection below on purpose:
205
218
  * TypeScript reports the last overload's failure, so a non-covering array is
@@ -209,7 +222,7 @@ type Uncovered<C extends ContractDefinition, T extends readonly PieceOf<C>[]> =
209
222
  * The marker is a sentence rather than a bare label because it prints last,
210
223
  * after the caller's own several-hundred-character piece type.
211
224
  */
212
- type Compose<C extends ContractDefinition> = <const T extends readonly PieceOf<C>[]>(pieces: [Uncovered<C, T>] extends [never] ? T : readonly ["UNCOVERED ACTIVITIES — the contract declares a workflow this array does not cover", Uncovered<C, T>]) => Provider<ActivitiesInstanceOf<C>, never, InstanceType<T[number]["port"]>> & {
225
+ type Compose<C extends ContractDefinition> = <const T extends readonly PieceOf<C>[]>(pieces: [Uncovered<C, T>] extends [never] ? T : Refuse<T, "UNCOVERED ACTIVITIES — the contract declares a workflow this array does not cover", Uncovered<C, T>>) => Provider<ActivitiesInstanceOf<C>, never, InstanceType<T[number]["port"]>> & {
213
226
  readonly port: ActivitiesPortOf<C>;
214
227
  };
215
228
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/temporal-worker",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "The Temporal worker runtime for @btravstack/core: one unit per activity attempt, and a drain that honours the kernel's deadline",
5
5
  "keywords": [
6
6
  "graceful-shutdown",
@@ -71,11 +71,11 @@
71
71
  "unthrown": "5.7.0",
72
72
  "vitest": "4.1.11",
73
73
  "zod": "4.5.3",
74
- "@btravstack/config": "0.10.0",
75
- "@btravstack/core": "0.10.0",
76
- "@btravstack/di": "0.10.0",
74
+ "@btravstack/config": "0.11.0",
75
+ "@btravstack/core": "0.11.0",
76
+ "@btravstack/di": "0.11.0",
77
77
  "@btravstack/internal-test-infra": "0.0.0",
78
- "@btravstack/testing": "0.10.0"
78
+ "@btravstack/testing": "0.11.0"
79
79
  },
80
80
  "peerDependencies": {
81
81
  "@temporal-contract/client": "^8.0.0-beta.7",
@@ -85,9 +85,9 @@
85
85
  "@temporalio/common": "^1.22.0",
86
86
  "@temporalio/worker": "^1.22.0",
87
87
  "unthrown": "^5.0.0",
88
- "@btravstack/config": "^0.10.0",
89
- "@btravstack/core": "^0.10.0",
90
- "@btravstack/di": "^0.10.0"
88
+ "@btravstack/config": "^0.11.0",
89
+ "@btravstack/core": "^0.11.0",
90
+ "@btravstack/di": "^0.11.0"
91
91
  },
92
92
  "peerDependenciesMeta": {
93
93
  "@temporal-contract/client": {