@temporal-contract/worker 0.0.4 → 0.0.6

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
@@ -34,6 +34,78 @@ export const processOrder = declareWorkflow({
34
34
  return { success: true };
35
35
  }
36
36
  });
37
+
38
+ // worker.ts
39
+ import { NativeConnection } from '@temporalio/worker';
40
+ import { createWorker } from '@temporal-contract/worker/worker';
41
+ import { activities } from './activities';
42
+ import myContract from './contract';
43
+
44
+ async function run() {
45
+ const connection = await NativeConnection.connect({
46
+ address: 'localhost:7233',
47
+ });
48
+
49
+ const worker = await createWorker({
50
+ contract: myContract,
51
+ connection,
52
+ workflowsPath: require.resolve('./workflows'),
53
+ activities,
54
+ });
55
+
56
+ await worker.run();
57
+ }
58
+
59
+ run().catch(console.error);
60
+ ```
61
+
62
+ ### Child Workflows
63
+
64
+ Execute child workflows with type-safe Future/Result pattern. Supports both same-contract and cross-contract child workflows:
65
+
66
+ ```typescript
67
+ // workflows.ts
68
+ import { declareWorkflow } from '@temporal-contract/worker/workflow';
69
+
70
+ export const parentWorkflow = declareWorkflow({
71
+ workflowName: 'parentWorkflow',
72
+ contract: myContract,
73
+ implementation: async (context, input) => {
74
+ // Execute child workflow from same contract and wait for result
75
+ const childResult = await context.executeChildWorkflow(myContract, 'processPayment', {
76
+ workflowId: `payment-${input.orderId}`,
77
+ args: { amount: input.totalAmount }
78
+ });
79
+
80
+ childResult.match({
81
+ Ok: (output) => console.log('Payment processed:', output),
82
+ Error: (error) => console.error('Payment failed:', error),
83
+ });
84
+
85
+ // Execute child workflow from another contract (another worker)
86
+ const notificationResult = await context.executeChildWorkflow(notificationContract, 'sendNotification', {
87
+ workflowId: `notification-${input.orderId}`,
88
+ args: { message: 'Order received' }
89
+ });
90
+
91
+ // Or start child workflow without waiting
92
+ const handleResult = await context.startChildWorkflow(myContract, 'sendEmail', {
93
+ workflowId: `email-${input.orderId}`,
94
+ args: { to: 'user@example.com', body: 'Order received' }
95
+ });
96
+
97
+ handleResult.match({
98
+ Ok: async (handle) => {
99
+ // Can wait for result later
100
+ const result = await handle.result();
101
+ // ...
102
+ },
103
+ Error: (error) => console.error('Failed to start:', error),
104
+ });
105
+
106
+ return { success: true };
107
+ }
108
+ });
37
109
  ```
38
110
 
39
111
  ## Documentation
package/dist/activity.cjs CHANGED
@@ -1,33 +1,109 @@
1
- const require_handler = require('./handler-D9BllGor.cjs');
2
- let __swan_io_boxed = require("@swan-io/boxed");
1
+ const require_errors = require('./errors-DjSZg-93.cjs');
3
2
 
4
- exports.ActivityDefinitionNotFoundError = require_handler.ActivityDefinitionNotFoundError;
5
- exports.ActivityError = require_handler.ActivityError;
6
- exports.ActivityInputValidationError = require_handler.ActivityInputValidationError;
7
- exports.ActivityOutputValidationError = require_handler.ActivityOutputValidationError;
8
- Object.defineProperty(exports, 'AsyncData', {
9
- enumerable: true,
10
- get: function () {
11
- return __swan_io_boxed.AsyncData;
12
- }
13
- });
14
- Object.defineProperty(exports, 'Future', {
15
- enumerable: true,
16
- get: function () {
17
- return __swan_io_boxed.Future;
18
- }
19
- });
20
- Object.defineProperty(exports, 'Option', {
21
- enumerable: true,
22
- get: function () {
23
- return __swan_io_boxed.Option;
24
- }
25
- });
26
- Object.defineProperty(exports, 'Result', {
27
- enumerable: true,
28
- get: function () {
29
- return __swan_io_boxed.Result;
30
- }
31
- });
32
- exports.WorkerError = require_handler.WorkerError;
33
- exports.declareActivitiesHandler = require_handler.declareActivitiesHandler;
3
+ //#region src/activity.ts
4
+ /**
5
+ * Activity error class that should be used to wrap all technical exceptions
6
+ * Forces proper error handling and enables retry policies
7
+ */
8
+ var ActivityError = class ActivityError extends Error {
9
+ constructor(code, message, cause) {
10
+ super(message, { cause });
11
+ this.code = code;
12
+ this.name = "ActivityError";
13
+ if (Error.captureStackTrace) Error.captureStackTrace(this, ActivityError);
14
+ }
15
+ };
16
+ /**
17
+ * Create a typed activities handler with automatic validation and Result pattern
18
+ *
19
+ * This wraps all activity implementations with:
20
+ * - Validation at network boundaries
21
+ * - Result<T, ActivityError> pattern for explicit error handling
22
+ * - Automatic conversion from Result to Promise (throwing on Error)
23
+ *
24
+ * TypeScript ensures ALL activities (global + workflow-specific) are implemented.
25
+ *
26
+ * Use this to create the activities object for the Temporal Worker.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { declareActivitiesHandler, ActivityError } from '@temporal-contract/worker/activity';
31
+ * import { Result, Future } from '@temporal-contract/boxed';
32
+ * import myContract from './contract';
33
+ *
34
+ * export const activities = declareActivitiesHandler({
35
+ * contract: myContract,
36
+ * activities: {
37
+ * // Activity returns Result instead of throwing
38
+ * // All technical exceptions must be wrapped in ActivityError for retry policies
39
+ * sendEmail: (args) => {
40
+ * return Future.make(async resolve => {
41
+ * try {
42
+ * await emailService.send(args);
43
+ * resolve(Result.Ok({ sent: true }));
44
+ * } catch (error) {
45
+ * // Wrap technical errors in ActivityError to enable retries
46
+ * resolve(Result.Error(
47
+ * new ActivityError(
48
+ * 'EMAIL_SEND_FAILED',
49
+ * 'Failed to send email',
50
+ * error // Original error as cause for debugging
51
+ * )
52
+ * ));
53
+ * }
54
+ * });
55
+ * },
56
+ * },
57
+ * });
58
+ *
59
+ * // Use with Temporal Worker
60
+ * import { Worker } from '@temporalio/worker';
61
+ *
62
+ * const worker = await Worker.create({
63
+ * workflowsPath: require.resolve('./workflows'),
64
+ * activities: activities,
65
+ * taskQueue: contract.taskQueue,
66
+ * });
67
+ * ```
68
+ */
69
+ function declareActivitiesHandler(options) {
70
+ const { contract, activities } = options;
71
+ const wrappedActivities = {};
72
+ function makeWrapped(activityName, activityDef, activityImpl) {
73
+ return async (...args) => {
74
+ const input = args.length === 1 ? args[0] : args;
75
+ const inputResult = await activityDef.input["~standard"].validate(input);
76
+ if (inputResult.issues) throw new require_errors.ActivityInputValidationError(activityName, inputResult.issues);
77
+ const result = await activityImpl(inputResult.value);
78
+ if (result.isOk()) {
79
+ const outputResult = await activityDef.output["~standard"].validate(result.value);
80
+ if (outputResult.issues) throw new require_errors.ActivityOutputValidationError(activityName, outputResult.issues);
81
+ return outputResult.value;
82
+ } else throw result.error;
83
+ };
84
+ }
85
+ if (contract.activities) for (const [activityName, impl] of Object.entries(activities)) {
86
+ if (contract.workflows && activityName in contract.workflows) continue;
87
+ const activityDef = contract.activities[activityName];
88
+ if (!activityDef) throw new require_errors.ActivityDefinitionNotFoundError(activityName, Object.keys(contract.activities));
89
+ wrappedActivities[activityName] = makeWrapped(activityName, activityDef, impl);
90
+ }
91
+ if (contract.workflows) for (const [workflowName, workflowDef] of Object.entries(contract.workflows)) {
92
+ const wfActivitiesImpl = activities[workflowName];
93
+ if (!wfActivitiesImpl) continue;
94
+ const wfDefs = workflowDef.activities ?? {};
95
+ for (const [activityName, impl] of Object.entries(wfActivitiesImpl)) {
96
+ const activityDef = wfDefs[activityName];
97
+ if (!activityDef) throw new require_errors.ActivityDefinitionNotFoundError(`${workflowName}.${activityName}`, Object.keys(wfDefs));
98
+ wrappedActivities[activityName] = makeWrapped(`${workflowName}.${activityName}`, activityDef, impl);
99
+ }
100
+ }
101
+ return wrappedActivities;
102
+ }
103
+
104
+ //#endregion
105
+ exports.ActivityDefinitionNotFoundError = require_errors.ActivityDefinitionNotFoundError;
106
+ exports.ActivityError = ActivityError;
107
+ exports.ActivityInputValidationError = require_errors.ActivityInputValidationError;
108
+ exports.ActivityOutputValidationError = require_errors.ActivityOutputValidationError;
109
+ exports.declareActivitiesHandler = declareActivitiesHandler;
@@ -1,3 +1,98 @@
1
- import { S as WorkerError, d as declareActivitiesHandler, g as ActivityOutputValidationError, h as ActivityInputValidationError, i as DeclareActivitiesHandlerOptions, m as ActivityError, n as ActivityImplementations, p as ActivityDefinitionNotFoundError, r as BoxedActivityImplementation, t as ActivitiesHandler } from "./handler-Czi-kgwZ.cjs";
2
- import { AsyncData, Future, Option, Result } from "@swan-io/boxed";
3
- export { type ActivitiesHandler, ActivityDefinitionNotFoundError, ActivityError, type ActivityImplementations, ActivityInputValidationError, ActivityOutputValidationError, AsyncData, type BoxedActivityImplementation, type DeclareActivitiesHandlerOptions, Future, Option, Result, WorkerError, declareActivitiesHandler };
1
+ import { g as WorkerInferOutput, h as WorkerInferInput, n as ActivityInputValidationError, r as ActivityOutputValidationError, t as ActivityDefinitionNotFoundError } from "./errors-BqYWpdvd.cjs";
2
+ import { ActivityDefinition, ContractDefinition } from "@temporal-contract/contract";
3
+ import { Future, Result } from "@temporal-contract/boxed";
4
+
5
+ //#region src/activity.d.ts
6
+
7
+ /**
8
+ * Activity error class that should be used to wrap all technical exceptions
9
+ * Forces proper error handling and enables retry policies
10
+ */
11
+ declare class ActivityError extends Error {
12
+ readonly code: string;
13
+ constructor(code: string, message: string, cause?: unknown);
14
+ }
15
+ /**
16
+ * Activity implementation using Future/Result pattern
17
+ *
18
+ * Returns Future<Result<Output, ActivityError>> for explicit error handling instead of throwing exceptions.
19
+ * All errors must be wrapped in ActivityError to enable proper retry policies.
20
+ */
21
+ type BoxedActivityImplementation<TActivity extends ActivityDefinition> = (args: WorkerInferInput<TActivity>) => Future<Result<WorkerInferOutput<TActivity>, ActivityError>>;
22
+ /**
23
+ * Map of all activity implementations for a contract (global + all workflow-specific)
24
+ */
25
+ type ContractBoxedActivitiesImplementations<TContract extends ContractDefinition> = (TContract["activities"] extends Record<string, ActivityDefinition> ? BoxedActivitiesImplementations<TContract["activities"]> : {}) & { [TWorkflow in keyof TContract["workflows"]]: TContract["workflows"][TWorkflow]["activities"] extends Record<string, ActivityDefinition> ? BoxedActivitiesImplementations<TContract["workflows"][TWorkflow]["activities"]> : {} };
26
+ type BoxedActivitiesImplementations<TActivities extends Record<string, ActivityDefinition>> = { [K in keyof TActivities]: BoxedActivityImplementation<TActivities[K]> };
27
+ /**
28
+ * Options for creating activities handler
29
+ */
30
+ interface DeclareActivitiesHandlerOptions<TContract extends ContractDefinition> {
31
+ contract: TContract;
32
+ activities: ContractBoxedActivitiesImplementations<TContract>;
33
+ }
34
+ type ActivityImplementation<TActivity extends ActivityDefinition> = (args: WorkerInferInput<TActivity>) => Promise<WorkerInferOutput<TActivity>>;
35
+ type ActivitiesImplementations<TActivities extends Record<string, ActivityDefinition>> = { [K in keyof TActivities]: ActivityImplementation<TActivities[K]> };
36
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
37
+ /**
38
+ * Activities handler ready for Temporal Worker
39
+ *
40
+ * Flat structure: all activities (global + all workflow-specific) are at the root level
41
+ */
42
+ type ActivitiesHandler<TContract extends ContractDefinition> = (TContract["activities"] extends Record<string, ActivityDefinition> ? ActivitiesImplementations<TContract["activities"]> : {}) & UnionToIntersection<{ [TWorkflow in keyof TContract["workflows"]]: TContract["workflows"][TWorkflow]["activities"] extends Record<string, ActivityDefinition> ? ActivitiesImplementations<TContract["workflows"][TWorkflow]["activities"]> : {} }[keyof TContract["workflows"]]>;
43
+ /**
44
+ * Create a typed activities handler with automatic validation and Result pattern
45
+ *
46
+ * This wraps all activity implementations with:
47
+ * - Validation at network boundaries
48
+ * - Result<T, ActivityError> pattern for explicit error handling
49
+ * - Automatic conversion from Result to Promise (throwing on Error)
50
+ *
51
+ * TypeScript ensures ALL activities (global + workflow-specific) are implemented.
52
+ *
53
+ * Use this to create the activities object for the Temporal Worker.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { declareActivitiesHandler, ActivityError } from '@temporal-contract/worker/activity';
58
+ * import { Result, Future } from '@temporal-contract/boxed';
59
+ * import myContract from './contract';
60
+ *
61
+ * export const activities = declareActivitiesHandler({
62
+ * contract: myContract,
63
+ * activities: {
64
+ * // Activity returns Result instead of throwing
65
+ * // All technical exceptions must be wrapped in ActivityError for retry policies
66
+ * sendEmail: (args) => {
67
+ * return Future.make(async resolve => {
68
+ * try {
69
+ * await emailService.send(args);
70
+ * resolve(Result.Ok({ sent: true }));
71
+ * } catch (error) {
72
+ * // Wrap technical errors in ActivityError to enable retries
73
+ * resolve(Result.Error(
74
+ * new ActivityError(
75
+ * 'EMAIL_SEND_FAILED',
76
+ * 'Failed to send email',
77
+ * error // Original error as cause for debugging
78
+ * )
79
+ * ));
80
+ * }
81
+ * });
82
+ * },
83
+ * },
84
+ * });
85
+ *
86
+ * // Use with Temporal Worker
87
+ * import { Worker } from '@temporalio/worker';
88
+ *
89
+ * const worker = await Worker.create({
90
+ * workflowsPath: require.resolve('./workflows'),
91
+ * activities: activities,
92
+ * taskQueue: contract.taskQueue,
93
+ * });
94
+ * ```
95
+ */
96
+ declare function declareActivitiesHandler<TContract extends ContractDefinition>(options: DeclareActivitiesHandlerOptions<TContract>): ActivitiesHandler<TContract>;
97
+ //#endregion
98
+ export { ActivitiesHandler, ActivityDefinitionNotFoundError, ActivityError, ActivityInputValidationError, ActivityOutputValidationError, declareActivitiesHandler };
@@ -1,3 +1,98 @@
1
- import { S as WorkerError, d as declareActivitiesHandler, g as ActivityOutputValidationError, h as ActivityInputValidationError, i as DeclareActivitiesHandlerOptions, m as ActivityError, n as ActivityImplementations, p as ActivityDefinitionNotFoundError, r as BoxedActivityImplementation, t as ActivitiesHandler } from "./handler-DThqdaaS.mjs";
2
- import { AsyncData, Future, Option, Result } from "@swan-io/boxed";
3
- export { type ActivitiesHandler, ActivityDefinitionNotFoundError, ActivityError, type ActivityImplementations, ActivityInputValidationError, ActivityOutputValidationError, AsyncData, type BoxedActivityImplementation, type DeclareActivitiesHandlerOptions, Future, Option, Result, WorkerError, declareActivitiesHandler };
1
+ import { g as WorkerInferOutput, h as WorkerInferInput, n as ActivityInputValidationError, r as ActivityOutputValidationError, t as ActivityDefinitionNotFoundError } from "./errors-C1RFkCuD.mjs";
2
+ import { Future, Result } from "@temporal-contract/boxed";
3
+ import { ActivityDefinition, ContractDefinition } from "@temporal-contract/contract";
4
+
5
+ //#region src/activity.d.ts
6
+
7
+ /**
8
+ * Activity error class that should be used to wrap all technical exceptions
9
+ * Forces proper error handling and enables retry policies
10
+ */
11
+ declare class ActivityError extends Error {
12
+ readonly code: string;
13
+ constructor(code: string, message: string, cause?: unknown);
14
+ }
15
+ /**
16
+ * Activity implementation using Future/Result pattern
17
+ *
18
+ * Returns Future<Result<Output, ActivityError>> for explicit error handling instead of throwing exceptions.
19
+ * All errors must be wrapped in ActivityError to enable proper retry policies.
20
+ */
21
+ type BoxedActivityImplementation<TActivity extends ActivityDefinition> = (args: WorkerInferInput<TActivity>) => Future<Result<WorkerInferOutput<TActivity>, ActivityError>>;
22
+ /**
23
+ * Map of all activity implementations for a contract (global + all workflow-specific)
24
+ */
25
+ type ContractBoxedActivitiesImplementations<TContract extends ContractDefinition> = (TContract["activities"] extends Record<string, ActivityDefinition> ? BoxedActivitiesImplementations<TContract["activities"]> : {}) & { [TWorkflow in keyof TContract["workflows"]]: TContract["workflows"][TWorkflow]["activities"] extends Record<string, ActivityDefinition> ? BoxedActivitiesImplementations<TContract["workflows"][TWorkflow]["activities"]> : {} };
26
+ type BoxedActivitiesImplementations<TActivities extends Record<string, ActivityDefinition>> = { [K in keyof TActivities]: BoxedActivityImplementation<TActivities[K]> };
27
+ /**
28
+ * Options for creating activities handler
29
+ */
30
+ interface DeclareActivitiesHandlerOptions<TContract extends ContractDefinition> {
31
+ contract: TContract;
32
+ activities: ContractBoxedActivitiesImplementations<TContract>;
33
+ }
34
+ type ActivityImplementation<TActivity extends ActivityDefinition> = (args: WorkerInferInput<TActivity>) => Promise<WorkerInferOutput<TActivity>>;
35
+ type ActivitiesImplementations<TActivities extends Record<string, ActivityDefinition>> = { [K in keyof TActivities]: ActivityImplementation<TActivities[K]> };
36
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
37
+ /**
38
+ * Activities handler ready for Temporal Worker
39
+ *
40
+ * Flat structure: all activities (global + all workflow-specific) are at the root level
41
+ */
42
+ type ActivitiesHandler<TContract extends ContractDefinition> = (TContract["activities"] extends Record<string, ActivityDefinition> ? ActivitiesImplementations<TContract["activities"]> : {}) & UnionToIntersection<{ [TWorkflow in keyof TContract["workflows"]]: TContract["workflows"][TWorkflow]["activities"] extends Record<string, ActivityDefinition> ? ActivitiesImplementations<TContract["workflows"][TWorkflow]["activities"]> : {} }[keyof TContract["workflows"]]>;
43
+ /**
44
+ * Create a typed activities handler with automatic validation and Result pattern
45
+ *
46
+ * This wraps all activity implementations with:
47
+ * - Validation at network boundaries
48
+ * - Result<T, ActivityError> pattern for explicit error handling
49
+ * - Automatic conversion from Result to Promise (throwing on Error)
50
+ *
51
+ * TypeScript ensures ALL activities (global + workflow-specific) are implemented.
52
+ *
53
+ * Use this to create the activities object for the Temporal Worker.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { declareActivitiesHandler, ActivityError } from '@temporal-contract/worker/activity';
58
+ * import { Result, Future } from '@temporal-contract/boxed';
59
+ * import myContract from './contract';
60
+ *
61
+ * export const activities = declareActivitiesHandler({
62
+ * contract: myContract,
63
+ * activities: {
64
+ * // Activity returns Result instead of throwing
65
+ * // All technical exceptions must be wrapped in ActivityError for retry policies
66
+ * sendEmail: (args) => {
67
+ * return Future.make(async resolve => {
68
+ * try {
69
+ * await emailService.send(args);
70
+ * resolve(Result.Ok({ sent: true }));
71
+ * } catch (error) {
72
+ * // Wrap technical errors in ActivityError to enable retries
73
+ * resolve(Result.Error(
74
+ * new ActivityError(
75
+ * 'EMAIL_SEND_FAILED',
76
+ * 'Failed to send email',
77
+ * error // Original error as cause for debugging
78
+ * )
79
+ * ));
80
+ * }
81
+ * });
82
+ * },
83
+ * },
84
+ * });
85
+ *
86
+ * // Use with Temporal Worker
87
+ * import { Worker } from '@temporalio/worker';
88
+ *
89
+ * const worker = await Worker.create({
90
+ * workflowsPath: require.resolve('./workflows'),
91
+ * activities: activities,
92
+ * taskQueue: contract.taskQueue,
93
+ * });
94
+ * ```
95
+ */
96
+ declare function declareActivitiesHandler<TContract extends ContractDefinition>(options: DeclareActivitiesHandlerOptions<TContract>): ActivitiesHandler<TContract>;
97
+ //#endregion
98
+ export { ActivitiesHandler, ActivityDefinitionNotFoundError, ActivityError, ActivityInputValidationError, ActivityOutputValidationError, declareActivitiesHandler };
package/dist/activity.mjs CHANGED
@@ -1,4 +1,105 @@
1
- import { a as ActivityInputValidationError, f as WorkerError, i as ActivityError, o as ActivityOutputValidationError, r as ActivityDefinitionNotFoundError, t as declareActivitiesHandler } from "./handler-B7B5QHez.mjs";
2
- import { AsyncData, Future, Option, Result } from "@swan-io/boxed";
1
+ import { n as ActivityInputValidationError, r as ActivityOutputValidationError, t as ActivityDefinitionNotFoundError } from "./errors-BqVTpfcf.mjs";
3
2
 
4
- export { ActivityDefinitionNotFoundError, ActivityError, ActivityInputValidationError, ActivityOutputValidationError, AsyncData, Future, Option, Result, WorkerError, declareActivitiesHandler };
3
+ //#region src/activity.ts
4
+ /**
5
+ * Activity error class that should be used to wrap all technical exceptions
6
+ * Forces proper error handling and enables retry policies
7
+ */
8
+ var ActivityError = class ActivityError extends Error {
9
+ constructor(code, message, cause) {
10
+ super(message, { cause });
11
+ this.code = code;
12
+ this.name = "ActivityError";
13
+ if (Error.captureStackTrace) Error.captureStackTrace(this, ActivityError);
14
+ }
15
+ };
16
+ /**
17
+ * Create a typed activities handler with automatic validation and Result pattern
18
+ *
19
+ * This wraps all activity implementations with:
20
+ * - Validation at network boundaries
21
+ * - Result<T, ActivityError> pattern for explicit error handling
22
+ * - Automatic conversion from Result to Promise (throwing on Error)
23
+ *
24
+ * TypeScript ensures ALL activities (global + workflow-specific) are implemented.
25
+ *
26
+ * Use this to create the activities object for the Temporal Worker.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { declareActivitiesHandler, ActivityError } from '@temporal-contract/worker/activity';
31
+ * import { Result, Future } from '@temporal-contract/boxed';
32
+ * import myContract from './contract';
33
+ *
34
+ * export const activities = declareActivitiesHandler({
35
+ * contract: myContract,
36
+ * activities: {
37
+ * // Activity returns Result instead of throwing
38
+ * // All technical exceptions must be wrapped in ActivityError for retry policies
39
+ * sendEmail: (args) => {
40
+ * return Future.make(async resolve => {
41
+ * try {
42
+ * await emailService.send(args);
43
+ * resolve(Result.Ok({ sent: true }));
44
+ * } catch (error) {
45
+ * // Wrap technical errors in ActivityError to enable retries
46
+ * resolve(Result.Error(
47
+ * new ActivityError(
48
+ * 'EMAIL_SEND_FAILED',
49
+ * 'Failed to send email',
50
+ * error // Original error as cause for debugging
51
+ * )
52
+ * ));
53
+ * }
54
+ * });
55
+ * },
56
+ * },
57
+ * });
58
+ *
59
+ * // Use with Temporal Worker
60
+ * import { Worker } from '@temporalio/worker';
61
+ *
62
+ * const worker = await Worker.create({
63
+ * workflowsPath: require.resolve('./workflows'),
64
+ * activities: activities,
65
+ * taskQueue: contract.taskQueue,
66
+ * });
67
+ * ```
68
+ */
69
+ function declareActivitiesHandler(options) {
70
+ const { contract, activities } = options;
71
+ const wrappedActivities = {};
72
+ function makeWrapped(activityName, activityDef, activityImpl) {
73
+ return async (...args) => {
74
+ const input = args.length === 1 ? args[0] : args;
75
+ const inputResult = await activityDef.input["~standard"].validate(input);
76
+ if (inputResult.issues) throw new ActivityInputValidationError(activityName, inputResult.issues);
77
+ const result = await activityImpl(inputResult.value);
78
+ if (result.isOk()) {
79
+ const outputResult = await activityDef.output["~standard"].validate(result.value);
80
+ if (outputResult.issues) throw new ActivityOutputValidationError(activityName, outputResult.issues);
81
+ return outputResult.value;
82
+ } else throw result.error;
83
+ };
84
+ }
85
+ if (contract.activities) for (const [activityName, impl] of Object.entries(activities)) {
86
+ if (contract.workflows && activityName in contract.workflows) continue;
87
+ const activityDef = contract.activities[activityName];
88
+ if (!activityDef) throw new ActivityDefinitionNotFoundError(activityName, Object.keys(contract.activities));
89
+ wrappedActivities[activityName] = makeWrapped(activityName, activityDef, impl);
90
+ }
91
+ if (contract.workflows) for (const [workflowName, workflowDef] of Object.entries(contract.workflows)) {
92
+ const wfActivitiesImpl = activities[workflowName];
93
+ if (!wfActivitiesImpl) continue;
94
+ const wfDefs = workflowDef.activities ?? {};
95
+ for (const [activityName, impl] of Object.entries(wfActivitiesImpl)) {
96
+ const activityDef = wfDefs[activityName];
97
+ if (!activityDef) throw new ActivityDefinitionNotFoundError(`${workflowName}.${activityName}`, Object.keys(wfDefs));
98
+ wrappedActivities[activityName] = makeWrapped(`${workflowName}.${activityName}`, activityDef, impl);
99
+ }
100
+ }
101
+ return wrappedActivities;
102
+ }
103
+
104
+ //#endregion
105
+ export { ActivityDefinitionNotFoundError, ActivityError, ActivityInputValidationError, ActivityOutputValidationError, declareActivitiesHandler };