@btravstack/temporal-worker 0.11.0 → 0.13.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.d.cts CHANGED
@@ -1,10 +1,119 @@
1
1
  import { ConfigInvalid, Env } from "@btravstack/config";
2
- import { AnyModule, AnyPort, AnyProvider, Exportable, Module, NeedsGate, PortClassOf, PortInstance, Provider, Scope } from "@btravstack/di";
2
+ import { AnyModule, AnyPort, AnyProvider, Exportable, Module, NeedsGate, PortClassOf, PortInstance, Provider, Scope, ServiceOf } from "@btravstack/di";
3
3
  import { ContractDefinition } from "@temporal-contract/contract";
4
4
  import { Runtime, RuntimePort } from "@btravstack/core";
5
- import { DeclareActivitiesHandlerOptions } from "@temporal-contract/worker/activity";
5
+ import { DeclareActivitiesHandlerOptions, EmptyContext } from "@temporal-contract/worker/activity";
6
6
  import { Duration } from "@temporalio/common";
7
7
  import { NativeConnection, WorkflowBundleWithSourceMap } from "@temporalio/worker";
8
+ //#region src/unit.d.ts
9
+ /** What a bound unit module exports — the port instances an activity of that kind may read. */
10
+ type UnitExportsOf<M> = M extends Module<infer X, never, unknown> ? X : never;
11
+ /** The declared `unit:` record, as the services an activity reads off `context.unit`. */
12
+ type UnitRecordOf<U extends Readonly<Record<string, AnyPort>>> = { readonly [N in keyof U]: ServiceOf<InstanceType<U[N]>>; };
13
+ /**
14
+ * A piece injecting a port the bound `unit.activity` module does not export.
15
+ * `unknown` when every declared port is covered — including the empty case, so
16
+ * a worker whose pieces declare no `unit:` is gated on nothing.
17
+ */
18
+ type UnitGate<Unit, Declared> = [Exclude<NonNullable<Declared>, UnitExportsOf<Unit>>] extends [never] ? unknown : {
19
+ readonly "UNIT DOES NOT PROVIDE — a piece injects a port the bound unit module does not export": Exclude<NonNullable<Declared>, UnitExportsOf<Unit>>;
20
+ };
21
+ //#endregion
22
+ //#region src/workflow-activities.d.ts
23
+ /**
24
+ * `ActivitiesOf<C, …>` is a `NoInfer`-wrapped conditional TypeScript refuses to
25
+ * index by a generic key. Routing it through `infer` resolves it to a plain
26
+ * object type first, which IS indexable.
27
+ */
28
+ type ActivitiesRecordOf<C extends ContractDefinition, TContext extends Record<string, unknown> | EmptyContext = EmptyContext> = ActivitiesOf<C, TContext> extends (infer Resolved) ? Resolved : never;
29
+ /** The top-level keys of `C`'s activities record: a workflow that declares activities, or a contract-global activity. */
30
+ type ActivitiesKeyOf<C extends ContractDefinition> = keyof ActivitiesRecordOf<C> & string;
31
+ /**
32
+ * One entry's validated input, reached through the implementation's own second
33
+ * parameter — a workflow key carries a record of implementations, a
34
+ * contract-global one carries the implementation itself. `WorkerInferInput` is
35
+ * declared by `@temporal-contract/worker` and exported from none of its
36
+ * subpaths, so the by-index route is the only one open.
37
+ */
38
+ type InputOfEntry<V> = V extends ((helpers: never, input: infer I) => unknown) ? I : V extends Readonly<Record<string, unknown>> ? InputOfEntry<V[keyof V]> : never;
39
+ /** The validated activity input, typed by the contract: the union of every activity's own input. */
40
+ type ActivityInputOf<C extends ContractDefinition> = InputOfEntry<ActivitiesRecordOf<C>[ActivitiesKeyOf<C>]>;
41
+ /** The seeded port's class, typed for `C`: what `ActivityInput(contract)` answers. */
42
+ type ActivityInputPortOf<C extends ContractDefinition> = PortClassOf<"ActivityInput", ActivityInputOf<C>>;
43
+ /**
44
+ * The seed's port instance, as it appears in a needs union — subtracted from
45
+ * what a bound `unit.activity` module still owes, since the fork is what
46
+ * discharges it.
47
+ */
48
+ type ActivityInputInstance = PortInstance<"ActivityInput", unknown>;
49
+ /**
50
+ * The validated activity input as a port: the one thing the worker seeds the
51
+ * fork with, so a `unit.activity` module derives a tenant — or anything else —
52
+ * from the invocation rather than from an ambient record.
53
+ *
54
+ * ```ts
55
+ * const Input = ActivityInput(orderContract);
56
+ * const ActivityUnit = Module("ActivityUnit")({
57
+ * needs: [Input],
58
+ * provides: [Provider(Tenant)({ inject: { input: Input }, sync: ({ input }) => input.tenantId })],
59
+ * exports: [Tenant],
60
+ * });
61
+ * ```
62
+ *
63
+ * `contract` is read for its TYPE only. One `Port(...)` call fixed per contract
64
+ * at the type level, the move `TemporalActivitiesPort` makes, so a module built
65
+ * for one contract cannot read another's input.
66
+ */
67
+ declare const ActivityInput: <C extends ContractDefinition>(contract: C) => ActivityInputPortOf<C>;
68
+ /** The prefix a piece's port id carries; the composing form strips it to recover the key. */
69
+ declare const WORKFLOW_ACTIVITIES_PREFIX = "TemporalWorkflowActivities:";
70
+ /**
71
+ * The port one piece targets. Its id carries the key, which is what makes two
72
+ * slices claiming one workflow di's duplicate-provider defect rather than a
73
+ * silent merge.
74
+ */
75
+ type WorkflowActivitiesPortOf<C extends ContractDefinition, K extends ActivitiesKeyOf<C>> = PortClassOf<`${typeof WORKFLOW_ACTIVITIES_PREFIX}${K}`, ActivitiesRecordOf<C>[K]>;
76
+ /** What a minted piece returns. */
77
+ type MintedActivities<C extends ContractDefinition, K extends ActivitiesKeyOf<C>, N, U extends Readonly<Record<string, AnyPort>>> = Provider<InstanceType<WorkflowActivitiesPortOf<C, K>>, never, N> & {
78
+ readonly port: WorkflowActivitiesPortOf<C, K>;
79
+ /** The declared `unit:` record, which the wrapper resolves against. */
80
+ readonly unit: U;
81
+ /** Phantom: the ports this piece injects, which the root's `unit.activity` must export. */
82
+ readonly _declared?: InstanceType<U[keyof U]>;
83
+ };
84
+ /** The activities `sync` hands back, typed by the record THIS piece declared. */
85
+ type ScopedActivitiesOf<C extends ContractDefinition, K extends ActivitiesKeyOf<C>, U extends Readonly<Record<string, AnyPort>>> = ActivitiesRecordOf<C, {
86
+ readonly unit: UnitRecordOf<U>;
87
+ }>[K & keyof ActivitiesRecordOf<C, {
88
+ readonly unit: UnitRecordOf<U>;
89
+ }>];
90
+ /**
91
+ * One workflow's activities, as a provider on a port of its own.
92
+ *
93
+ * A worker that polls one queue for several workflows is several pieces, each
94
+ * declaring the services its own activities call;
95
+ * `TemporalActivities(contract)([...])` composes them. `contract` is read for
96
+ * its TYPE only, and types both `key` and the record — so an activity the
97
+ * workflow does not declare is a compile error here rather than at startup.
98
+ *
99
+ * `key` is any top-level key of the activities record, which includes a
100
+ * contract-global activity as well as a workflow; the name is imprecise in that
101
+ * one case deliberately, since narrowing it would lock such a contract out of
102
+ * the split.
103
+ *
104
+ * There is no name to give: the key IS the port's name.
105
+ *
106
+ * `unit` declares the ports the activities read off `context.unit`, resolved
107
+ * out of the fork the attempt opened; the root's `unit.activity` module must
108
+ * export every one of them.
109
+ */
110
+ declare const TemporalWorkflowActivities: <C extends ContractDefinition, const K extends ActivitiesKeyOf<C>>(contract: C, key: K) => <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
111
+ readonly inject: D;
112
+ /** The unit-scoped ports these activities read off `context.unit`. */
113
+ readonly unit?: U;
114
+ readonly sync: (services: { readonly [N in keyof D]: ServiceOf<InstanceType<D[N]>>; }) => ScopedActivitiesOf<C, K, U>;
115
+ }) => MintedActivities<C, K, InstanceType<D[keyof D]>, U>;
116
+ //#endregion
8
117
  //#region src/temporal-runtime.d.ts
9
118
  /** What the worker publishes once it is polling, read back through `RunningApp.runtimeInfo()`. */
10
119
  type TemporalInfo = {
@@ -58,8 +167,29 @@ declare class TemporalUnreachable extends TemporalUnreachable_base<{
58
167
  }
59
168
  /** The runtime's port: what `temporal()` provides, and what the module `start` boots must export. */
60
169
  declare class TemporalRuntime extends RuntimePort<Runtime<never, TemporalInfo>> {}
61
- /** The activity implementations `declareActivitiesHandler` takes for `C`, with no injected context. */
62
- type ActivitiesOf<C extends ContractDefinition> = DeclareActivitiesHandlerOptions<C>["activities"];
170
+ /**
171
+ * A module `unit.activity` may bind, as the upper bound `temporal()`
172
+ * constrains its own `Unit` type parameter to. `Module`'s `_exports` channel
173
+ * is contravariant, so `Exports = never` — never `unknown` — is what makes a
174
+ * REAL module's own (necessarily narrower) export type assignable to this
175
+ * bound: `(x: Concrete) => void` is assignable to `(x: never) => void`, not
176
+ * to `(x: unknown) => void`.
177
+ */
178
+ type AnyUnitModule = Module<never, never, unknown>;
179
+ /**
180
+ * The needs a bound `unit.activity` module still owes, or `never` when none is
181
+ * bound. `Scope` is excluded, since nothing can ever provide it — the same
182
+ * exemption `NeedsGate` itself carries — and so is the activity input, which
183
+ * the fork's own seed discharges.
184
+ */
185
+ type UnitNeedsOf<Unit> = Unit extends Module<never, never, infer N> ? Exclude<N, Scope | ActivityInputInstance> : never;
186
+ /**
187
+ * The activity implementations `declareActivitiesHandler` takes for `C`.
188
+ * `TContext` is what an implementation reads off `helpers.context` — left
189
+ * empty for the port the composed record lands on, and the declared
190
+ * `{ unit }` record for the piece that declared it.
191
+ */
192
+ type ActivitiesOf<C extends ContractDefinition, TContext extends Record<string, unknown> | EmptyContext = EmptyContext> = DeclareActivitiesHandlerOptions<C, TContext>["activities"];
63
193
  /** The activities port class, typed for `C`: what `TemporalActivities(contract)(…).port` is. */
64
194
  type ActivitiesPortOf<C extends ContractDefinition> = PortClassOf<"TemporalActivities", ActivitiesOf<C>>;
65
195
  /** The activities port's instance for `C` — the module's one need. */
@@ -69,7 +199,7 @@ type ActivitiesInstanceOf<C extends ContractDefinition> = PortInstance<"Temporal
69
199
  * `TemporalModule` — spelled once so the two cannot drift, which is what a
70
200
  * second copy of an option list always eventually does.
71
201
  */
72
- type TemporalTuning = {
202
+ type TemporalTuning<Unit extends AnyUnitModule | undefined = undefined> = {
73
203
  /** Pins `TemporalConfig.address` instead of reading `TEMPORAL_ADDRESS`. */
74
204
  readonly address?: string;
75
205
  /** Pins `TemporalConfig.namespace` instead of reading `TEMPORAL_NAMESPACE`. */
@@ -88,8 +218,17 @@ type TemporalTuning = {
88
218
  * `shutdownGraceTime`.
89
219
  */
90
220
  readonly gracePeriod?: Duration;
221
+ /**
222
+ * The unit module the worker forks around every activity attempt it
223
+ * dispatches, with no seed. Built after the activity is invoked, torn down
224
+ * when the unit closes — the point where a later phase seeds it with the
225
+ * workflow's tenant.
226
+ */
227
+ readonly unit?: {
228
+ readonly activity?: Unit;
229
+ };
91
230
  };
92
- type TemporalOptions<C extends ContractDefinition> = TemporalTuning & {
231
+ type TemporalOptions<C extends ContractDefinition, Unit extends AnyUnitModule | undefined = undefined> = TemporalTuning<Unit> & {
93
232
  /**
94
233
  * The contract; the task queue this worker polls is read off it, and the
95
234
  * activities port is typed by it. The starter calls
@@ -110,56 +249,28 @@ type Provided = TemporalRuntime | TemporalConfig | TemporalConnection;
110
249
  * With both configuration fields pinned the module reads nothing from the
111
250
  * environment; pin only one and the other still comes from it.
112
251
  */
113
- declare const temporal: <C extends ContractDefinition>(options: TemporalOptions<C>) => Module<Provided, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C>>;
114
- //#endregion
115
- //#region src/workflow-activities.d.ts
116
- /**
117
- * `ActivitiesOf<C>` is a `NoInfer`-wrapped conditional TypeScript refuses to
118
- * index by a generic key. Routing it through `infer` resolves it to a plain
119
- * object type first, which IS indexable.
120
- */
121
- type ActivitiesRecordOf<C extends ContractDefinition> = ActivitiesOf<C> extends (infer Resolved) ? Resolved : never;
122
- /** The top-level keys of `C`'s activities record: a workflow that declares activities, or a contract-global activity. */
123
- type ActivitiesKeyOf<C extends ContractDefinition> = keyof ActivitiesRecordOf<C> & string;
124
- /** The prefix a piece's port id carries; the composing form strips it to recover the key. */
125
- declare const WORKFLOW_ACTIVITIES_PREFIX = "TemporalWorkflowActivities:";
126
- /**
127
- * The port one piece targets. Its id carries the key, which is what makes two
128
- * slices claiming one workflow di's duplicate-provider defect rather than a
129
- * silent merge.
130
- */
131
- type WorkflowActivitiesPortOf<C extends ContractDefinition, K extends ActivitiesKeyOf<C>> = PortClassOf<`${typeof WORKFLOW_ACTIVITIES_PREFIX}${K}`, ActivitiesRecordOf<C>[K]>;
132
- /**
133
- * One workflow's activities, as a provider on a port of its own.
134
- *
135
- * A worker that polls one queue for several workflows is several pieces, each
136
- * declaring the services its own activities call;
137
- * `TemporalActivities(contract)([...])` composes them. `contract` is read for
138
- * its TYPE only, and types both `key` and the record — so an activity the
139
- * workflow does not declare is a compile error here rather than at startup.
140
- *
141
- * `key` is any top-level key of the activities record, which includes a
142
- * contract-global activity as well as a workflow; the name is imprecise in that
143
- * one case deliberately, since narrowing it would lock such a contract out of
144
- * the split.
145
- *
146
- * There is no name to give: the key IS the port's name.
147
- */
148
- declare const TemporalWorkflowActivities: <C extends ContractDefinition, const K extends ActivitiesKeyOf<C>>(contract: C, key: K) => ReturnType<typeof Provider<WorkflowActivitiesPortOf<C, K>>>;
252
+ declare const temporal: <C extends ContractDefinition, Unit extends AnyUnitModule | undefined = undefined>(options: TemporalOptions<C, Unit>) => Module<Provided, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C> | UnitNeedsOf<Unit>>;
149
253
  //#endregion
150
254
  //#region src/temporal-module.d.ts
151
255
  /** The starter's own module, as the sugar adds it to the application's imports. */
152
- type TemporalStarter<C extends ContractDefinition> = Module<TemporalRuntime | TemporalConfig | TemporalConnection, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C>>;
256
+ type TemporalStarter<C extends ContractDefinition, Unit extends AnyUnitModule | undefined> = Module<TemporalRuntime | TemporalConfig | TemporalConnection, ConfigInvalid | TemporalUnreachable, Env | Scope | ActivitiesInstanceOf<C> | UnitNeedsOf<Unit>>;
153
257
  /** The application's imports plus the starter — the tuple `Module(name)` is handed. */
154
- type Imports<I extends readonly AnyModule[], C extends ContractDefinition> = readonly [...I, TemporalStarter<C>];
258
+ type Imports<I extends readonly AnyModule[], C extends ContractDefinition, Unit extends AnyUnitModule | undefined> = readonly [...I, TemporalStarter<C, Unit>];
155
259
  /** The activities provider plus the application's own — the tuple `Module(name)` is handed. */
156
260
  type Provides<P extends readonly AnyProvider[], C extends ContractDefinition, ActivitiesError, ActivitiesNeeds> = readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P];
157
- type TemporalModuleOptions<C extends ContractDefinition, ActivitiesError, ActivitiesNeeds, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, C>, Provides<P, C, ActivitiesError, ActivitiesNeeds>>[], N extends readonly AnyPort[]> = TemporalTuning & {
261
+ type TemporalModuleOptions<C extends ContractDefinition, ActivitiesError, ActivitiesNeeds, Declared, Unit extends AnyUnitModule | undefined, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, C, Unit>, Provides<P, C, ActivitiesError, ActivitiesNeeds>>[], N extends readonly AnyPort[]> = TemporalTuning<Unit> & {
158
262
  /** The `temporal-contract` contract; the task queue this worker polls is read off it. */
159
263
  readonly contract: C;
160
264
  readonly workflows: WorkflowSource;
161
- /** The application's activity implementations — what `TemporalActivities(contract)(…)` returns. */
162
- readonly activities: Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>;
265
+ /**
266
+ * The application's activity implementations — what
267
+ * `TemporalActivities(contract)(…)` returns. Its `_declaredUnit` phantom
268
+ * carries every port its pieces read off `context.unit`, which is what
269
+ * {@link UnitGate} checks `unit.activity` against.
270
+ */
271
+ readonly activities: Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds> & {
272
+ readonly _declaredUnit?: Declared;
273
+ };
163
274
  readonly imports?: I;
164
275
  readonly provides?: P;
165
276
  /** The application's own exports; `TemporalRuntime` is added, since `start` resolves it. */
@@ -169,7 +280,7 @@ type TemporalModuleOptions<C extends ContractDefinition, ActivitiesError, Activi
169
280
  * over the augmented tuples below, so forgetting one is an error at THIS call.
170
281
  */
171
282
  readonly needs?: N;
172
- } & NeedsGate<Imports<I, C>, Provides<P, C, ActivitiesError, ActivitiesNeeds>, N>;
283
+ } & NeedsGate<Imports<I, C, Unit>, Provides<P, C, ActivitiesError, ActivitiesNeeds>, N> & UnitGate<Unit, Declared>;
173
284
  /**
174
285
  * `Module(name)({...})` for a Temporal worker deployment: everything a di module
175
286
  * takes, plus the contract, the activities provider and the workflow source. The
@@ -187,11 +298,17 @@ type TemporalModuleOptions<C extends ContractDefinition, ActivitiesError, Activi
187
298
  * await runMain(OrderTemporalWorker);
188
299
  * ```
189
300
  */
190
- declare const TemporalModule: <const Name extends string>(name: Name) => <C extends ContractDefinition, ActivitiesError, ActivitiesNeeds, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, C>, Provides<P, C, ActivitiesError, ActivitiesNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: TemporalModuleOptions<C, ActivitiesError, ActivitiesNeeds, I, P, X, N>) => Module<(Extract<(readonly [typeof TemporalRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof TemporalRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof TemporalRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, TemporalStarter<C>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, TemporalStarter<C>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, TemporalStarter<C>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, TemporalStarter<C>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, TemporalStarter<C>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
301
+ declare const TemporalModule: <const Name extends string>(name: Name) => <C extends ContractDefinition, ActivitiesError, ActivitiesNeeds, Declared = never, Unit extends AnyUnitModule | undefined = undefined, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, C, Unit>, Provides<P, C, ActivitiesError, ActivitiesNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: TemporalModuleOptions<C, ActivitiesError, ActivitiesNeeds, Declared, Unit, I, P, X, N>) => Module<(Extract<(readonly [typeof TemporalRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof TemporalRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof TemporalRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, TemporalStarter<C, Unit>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, TemporalStarter<C, Unit>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, TemporalStarter<C, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, TemporalStarter<C, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, TemporalStarter<C, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, TemporalStarter<C, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<ActivitiesInstanceOf<C>, ActivitiesError, ActivitiesNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
191
302
  /** One piece of the activities record — what `TemporalWorkflowActivities(contract, key)(…)` returns. */
192
303
  type PieceOf<C extends ContractDefinition> = { readonly [K in ActivitiesKeyOf<C>]: {
193
304
  readonly port: WorkflowActivitiesPortOf<C, K>;
305
+ /** Phantom, carrying the ports the piece injects off `context.unit`. */
306
+ readonly _declared?: unknown;
194
307
  }; }[ActivitiesKeyOf<C>];
308
+ /** Every port the pieces in `T` inject off `context.unit` — what the root's `unit.activity` must export. */
309
+ type DeclaredOf<T extends readonly {
310
+ readonly _declared?: unknown;
311
+ }[]> = NonNullable<T[number]["_declared"]>;
195
312
  /** The key a piece carries, read back off its port id. */
196
313
  type KeyOfPiece<P> = P extends {
197
314
  readonly port: {
@@ -213,6 +330,29 @@ type Uncovered<C extends ContractDefinition, T extends readonly PieceOf<C>[]> =
213
330
  * hand.
214
331
  */
215
332
  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]];
333
+ /**
334
+ * The record arm: the whole activities record from one `sync`, with one `unit:`
335
+ * record shared by every entry in it.
336
+ *
337
+ * It is `{ inject, unit?, sync }` — di's other arms are gone — for PARITY, not
338
+ * for a type-system reason: `value` could have carried the record just as well,
339
+ * since `U` infers from `unit` and never from the arm. `@btravstack/http-server`'s
340
+ * `api.OrpcRouter(contract)` is `{ inject, unit?, sync }` and so are all three
341
+ * packages' piece factories, so one arm across the family is one surface to
342
+ * learn and one to keep.
343
+ */
344
+ type Whole<C extends ContractDefinition> = <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
345
+ readonly inject: D;
346
+ /** The unit-scoped ports every activity in the record reads off `context.unit`. */
347
+ readonly unit?: U;
348
+ readonly sync: (services: { readonly [N in keyof D]: ServiceOf<InstanceType<D[N]>>; }) => ActivitiesOf<C, {
349
+ readonly unit: UnitRecordOf<U>;
350
+ }>;
351
+ }) => Provider<ActivitiesInstanceOf<C>, never, InstanceType<D[keyof D]>> & {
352
+ readonly port: ActivitiesPortOf<C>;
353
+ /** Phantom: the declared ports, which `TemporalModule` gates `unit.activity` against. */
354
+ readonly _declaredUnit?: InstanceType<U[keyof U]>;
355
+ };
216
356
  /**
217
357
  * The composing arm. Declared LAST in the intersection below on purpose:
218
358
  * TypeScript reports the last overload's failure, so a non-covering array is
@@ -224,6 +364,8 @@ type Refuse<T extends readonly unknown[], Marker extends string, Detail> = T ext
224
364
  */
225
365
  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"]>> & {
226
366
  readonly port: ActivitiesPortOf<C>;
367
+ /** Phantom: the union of every piece's declared ports, which `TemporalModule` gates `unit.activity` against. */
368
+ readonly _declaredUnit?: DeclaredOf<T>;
227
369
  };
228
370
  /**
229
371
  * The activities as a provider, from the contract. Two call forms, one port.
@@ -233,13 +375,13 @@ type Compose<C extends ContractDefinition> = <const T extends readonly PieceOf<C
233
375
  * TemporalActivities(orderContract)([fulfillOrder, chargeOrder])
234
376
  * ```
235
377
  *
236
- * The first is di's own `Provider(port)` on the starter's activities port
237
- * typed for the contract. The second takes the pieces
238
- * `TemporalWorkflowActivities(contract, key)` builds: they are the provider's
239
- * deps, keyed by the contract key each piece's port id carries, so the services
240
- * record IS the activities record. Every key must be covered, and two slices
241
- * claiming one key are di's duplicate-provider defect at build.
242
- */
243
- declare const TemporalActivities: <C extends ContractDefinition>(contract: C) => ReturnType<typeof Provider<ActivitiesPortOf<C>>> & Compose<C>;
378
+ * The first is `{ inject, unit?, sync }`, whose `sync` hands back the whole
379
+ * activities record — one `unit:` record for every entry in it. The second
380
+ * takes the pieces `TemporalWorkflowActivities(contract, key)` builds: they are
381
+ * the provider's deps, keyed by the contract key each piece's port id carries,
382
+ * so the services record IS the activities record. Every key must be covered,
383
+ * and two slices claiming one key are di's duplicate-provider defect at build.
384
+ */
385
+ declare const TemporalActivities: <C extends ContractDefinition>(contract: C) => Whole<C> & Compose<C>;
244
386
  //#endregion
245
- export { type ActivitiesInstanceOf, type ActivitiesPortOf, TemporalActivities, TemporalConfig, TemporalConnection, type TemporalInfo, TemporalModule, type TemporalModuleOptions, type TemporalOptions, TemporalRuntime, TemporalUnreachable, TemporalWorkflowActivities, type WorkflowActivitiesPortOf, type WorkflowSource, temporal };
387
+ export { type ActivitiesInstanceOf, type ActivitiesPortOf, ActivityInput, type ActivityInputOf, type ActivityInputPortOf, TemporalActivities, TemporalConfig, TemporalConnection, type TemporalInfo, TemporalModule, type TemporalModuleOptions, type TemporalOptions, TemporalRuntime, TemporalUnreachable, TemporalWorkflowActivities, type WorkflowActivitiesPortOf, type WorkflowSource, temporal };