@temporal-contract/worker 0.0.4 → 0.0.5

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.
@@ -1,4 +1,5 @@
1
- import { defineQuery, defineSignal, defineUpdate, proxyActivities, setHandler, workflowInfo } from "@temporalio/workflow";
1
+ import { Future, Result } from "@temporal-contract/boxed";
2
+ import { defineQuery, defineSignal, defineUpdate, executeChild, proxyActivities, setHandler, startChild, workflowInfo } from "@temporalio/workflow";
2
3
 
3
4
  //#region src/errors.ts
4
5
  /**
@@ -146,6 +147,27 @@ var UpdateOutputValidationError = class extends WorkerError {
146
147
  this.name = "UpdateOutputValidationError";
147
148
  }
148
149
  };
150
+ /**
151
+ * Error thrown when a child workflow is not found in the contract
152
+ */
153
+ var ChildWorkflowNotFoundError = class extends WorkerError {
154
+ constructor(workflowName, availableWorkflows = []) {
155
+ const available = availableWorkflows.length > 0 ? availableWorkflows.join(", ") : "none";
156
+ super(`Child workflow not found: "${workflowName}". Available workflows: ${available}`);
157
+ this.workflowName = workflowName;
158
+ this.availableWorkflows = availableWorkflows;
159
+ this.name = "ChildWorkflowNotFoundError";
160
+ }
161
+ };
162
+ /**
163
+ * Generic error for child workflow operations
164
+ */
165
+ var ChildWorkflowError = class extends WorkerError {
166
+ constructor(message, cause) {
167
+ super(message, cause);
168
+ this.name = "ChildWorkflowError";
169
+ }
170
+ };
149
171
 
150
172
  //#endregion
151
173
  //#region src/handler.ts
@@ -191,7 +213,7 @@ function createValidatedActivities(rawActivities, workflowActivitiesDefinition,
191
213
  * @example
192
214
  * ```ts
193
215
  * import { declareActivitiesHandler, ActivityError } from '@temporal-contract/worker/activity';
194
- * import { Result, Future } from '@swan-io/boxed';
216
+ * import { Result, Future } from '@temporal-contract/boxed';
195
217
  * import myContract from './contract';
196
218
  *
197
219
  * export const activitiesHandler = declareActivitiesHandler({
@@ -247,7 +269,7 @@ function declareActivitiesHandler(options) {
247
269
  const input = args.length === 1 ? args[0] : args;
248
270
  const inputResult = await activityDef.input["~standard"].validate(input);
249
271
  if (inputResult.issues) throw new ActivityInputValidationError(activityName, inputResult.issues);
250
- const result = await activityImpl(inputResult.value).toPromise();
272
+ const result = await activityImpl(inputResult.value);
251
273
  if (result.isOk()) {
252
274
  const outputResult = await activityDef.output["~standard"].validate(result.value);
253
275
  if (outputResult.issues) throw new ActivityOutputValidationError(activityName, outputResult.issues);
@@ -325,68 +347,150 @@ function declareActivitiesHandler(options) {
325
347
  * ```
326
348
  */
327
349
  function declareWorkflow(options) {
328
- const { workflowName, contract, implementation, activityOptions, signals, queries, updates } = options;
350
+ const { workflowName, contract, implementation, activityOptions } = options;
329
351
  const definition = contract.workflows[workflowName];
330
352
  return async (args) => {
331
353
  const singleArg = Array.isArray(args) ? args[0] : args;
332
354
  const inputResult = await definition.input["~standard"].validate(singleArg);
333
355
  if (inputResult.issues) throw new WorkflowInputValidationError(String(workflowName), inputResult.issues);
334
356
  const validatedInput = inputResult.value;
335
- if (definition.signals && signals) {
336
- const signalDefs = definition.signals;
337
- const signalHandlers = signals;
338
- for (const [signalName, signalDef] of Object.entries(signalDefs)) {
339
- const handler = signalHandlers[signalName];
340
- if (handler) setHandler(defineSignal(signalName), async (...args$1) => {
341
- const input = args$1.length === 1 ? args$1[0] : args$1;
342
- const inputResult$1 = await signalDef.input["~standard"].validate(input);
343
- if (inputResult$1.issues) throw new SignalInputValidationError(signalName, inputResult$1.issues);
344
- await handler(inputResult$1.value);
345
- });
346
- }
347
- }
348
- if (definition.queries && queries) {
349
- const queryDefs = definition.queries;
350
- const queryHandlers = queries;
351
- for (const [queryName, queryDef] of Object.entries(queryDefs)) {
352
- const handler = queryHandlers[queryName];
353
- if (handler) setHandler(defineQuery(queryName), (...args$1) => {
354
- const input = args$1.length === 1 ? args$1[0] : args$1;
355
- const inputResult$1 = queryDef.input["~standard"].validate(input);
356
- if (inputResult$1 instanceof Promise) throw new Error(`Query "${queryName}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
357
- if (inputResult$1.issues) throw new QueryInputValidationError(queryName, inputResult$1.issues);
358
- const result$1 = handler(inputResult$1.value);
359
- const outputResult$1 = queryDef.output["~standard"].validate(result$1);
360
- if (outputResult$1 instanceof Promise) throw new Error(`Query "${queryName}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
361
- if (outputResult$1.issues) throw new QueryOutputValidationError(queryName, outputResult$1.issues);
362
- return outputResult$1.value;
363
- });
364
- }
365
- }
366
- if (definition.updates && updates) {
367
- const updateDefs = definition.updates;
368
- const updateHandlers = updates;
369
- for (const [updateName, updateDef] of Object.entries(updateDefs)) {
370
- const handler = updateHandlers[updateName];
371
- if (handler) setHandler(defineUpdate(updateName), async (...args$1) => {
372
- const input = args$1.length === 1 ? args$1[0] : args$1;
373
- const inputResult$1 = await updateDef.input["~standard"].validate(input);
374
- if (inputResult$1.issues) throw new UpdateInputValidationError(updateName, inputResult$1.issues);
375
- const result$1 = await handler(inputResult$1.value);
376
- const outputResult$1 = await updateDef.output["~standard"].validate(result$1);
377
- if (outputResult$1.issues) throw new UpdateOutputValidationError(updateName, outputResult$1.issues);
378
- return outputResult$1.value;
379
- });
380
- }
381
- }
382
357
  let contextActivities = {};
383
358
  if (definition.activities || contract.activities) contextActivities = createValidatedActivities(proxyActivities({
384
359
  startToCloseTimeout: activityOptions?.startToCloseTimeout ?? 6e4,
385
360
  ...activityOptions
386
361
  }), definition.activities, contract.activities);
362
+ async function validateChildWorkflowOutput(childDefinition, result$1, childWorkflowName) {
363
+ const outputResult$1 = await childDefinition.output["~standard"].validate(result$1);
364
+ if (outputResult$1.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${childWorkflowName}" output validation failed: ${outputResult$1.issues.map((i) => i.message).join("; ")}`));
365
+ return Result.Ok(outputResult$1.value);
366
+ }
367
+ async function getAndValidateChildWorkflow(childContract, childWorkflowName, args$1) {
368
+ const childDefinition = childContract.workflows[childWorkflowName];
369
+ if (!childDefinition) return Result.Error(new ChildWorkflowNotFoundError(String(childWorkflowName), Object.keys(childContract.workflows)));
370
+ const inputResult$1 = await childDefinition.input["~standard"].validate(args$1);
371
+ if (inputResult$1.issues) return Result.Error(new ChildWorkflowError(`Child workflow "${String(childWorkflowName)}" input validation failed: ${inputResult$1.issues.map((i) => i.message).join("; ")}`));
372
+ const validatedInput$1 = inputResult$1.value;
373
+ return Result.Ok({
374
+ definition: childDefinition,
375
+ validatedInput: validatedInput$1,
376
+ taskQueue: childContract.taskQueue
377
+ });
378
+ }
379
+ function createTypedChildHandle(handle, childDefinition, childWorkflowName) {
380
+ return {
381
+ workflowId: handle.workflowId,
382
+ result: () => {
383
+ return Future.make((resolve) => {
384
+ (async () => {
385
+ try {
386
+ resolve(await validateChildWorkflowOutput(childDefinition, await handle.result(), childWorkflowName));
387
+ } catch (error) {
388
+ resolve(Result.Error(new ChildWorkflowError(`Child workflow execution failed: ${error instanceof Error ? error.message : String(error)}`, error)));
389
+ }
390
+ })();
391
+ });
392
+ }
393
+ };
394
+ }
395
+ function createStartChildWorkflow(childContract, childWorkflowName, options$1) {
396
+ return Future.make((resolve) => {
397
+ (async () => {
398
+ const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options$1.args);
399
+ if (validationResult.isError()) {
400
+ resolve(Result.Error(validationResult.error));
401
+ return;
402
+ }
403
+ const { definition: childDefinition, validatedInput: validatedInput$1, taskQueue } = validationResult.value;
404
+ try {
405
+ const { args: _args, ...temporalOptions } = options$1;
406
+ const typedHandle = createTypedChildHandle(await startChild(childWorkflowName, {
407
+ ...temporalOptions,
408
+ taskQueue,
409
+ args: [validatedInput$1]
410
+ }), childDefinition, String(childWorkflowName));
411
+ resolve(Result.Ok(typedHandle));
412
+ } catch (error) {
413
+ resolve(Result.Error(new ChildWorkflowError(`Failed to start child workflow: ${error instanceof Error ? error.message : String(error)}`, error)));
414
+ }
415
+ })();
416
+ });
417
+ }
418
+ function createExecuteChildWorkflow(childContract, childWorkflowName, options$1) {
419
+ return Future.make((resolve) => {
420
+ (async () => {
421
+ const validationResult = await getAndValidateChildWorkflow(childContract, childWorkflowName, options$1.args);
422
+ if (validationResult.isError()) {
423
+ resolve(Result.Error(validationResult.error));
424
+ return;
425
+ }
426
+ const { definition: childDefinition, validatedInput: validatedInput$1, taskQueue } = validationResult.value;
427
+ try {
428
+ const { args: _args, ...temporalOptions } = options$1;
429
+ const outputValidationResult = await validateChildWorkflowOutput(childDefinition, await executeChild(childWorkflowName, {
430
+ ...temporalOptions,
431
+ taskQueue,
432
+ args: [validatedInput$1]
433
+ }), String(childWorkflowName));
434
+ if (outputValidationResult.isError()) {
435
+ resolve(Result.Error(outputValidationResult.error));
436
+ return;
437
+ }
438
+ resolve(Result.Ok(outputValidationResult.value));
439
+ } catch (error) {
440
+ resolve(Result.Error(new ChildWorkflowError(`Failed to execute child workflow: ${error instanceof Error ? error.message : String(error)}`, error)));
441
+ }
442
+ })();
443
+ });
444
+ }
445
+ function createDefineSignal(signalName, handler) {
446
+ if (!definition.signals) throw new Error(`Signal "${String(signalName)}" cannot be defined: workflow "${String(workflowName)}" has no signals in its contract`);
447
+ const signalDef = definition.signals[signalName];
448
+ if (!signalDef) throw new Error(`Signal "${String(signalName)}" not found in workflow "${String(workflowName)}" contract`);
449
+ setHandler(defineSignal(signalName), async (...args$1) => {
450
+ const input = args$1.length === 1 ? args$1[0] : args$1;
451
+ const inputResult$1 = await signalDef.input["~standard"].validate(input);
452
+ if (inputResult$1.issues) throw new SignalInputValidationError(signalName, inputResult$1.issues);
453
+ await handler(inputResult$1.value);
454
+ });
455
+ }
456
+ function createDefineQuery(queryName, handler) {
457
+ if (!definition.queries) throw new Error(`Query "${String(queryName)}" cannot be defined: workflow "${String(workflowName)}" has no queries in its contract`);
458
+ const queryDef = definition.queries[queryName];
459
+ if (!queryDef) throw new Error(`Query "${String(queryName)}" not found in workflow "${String(workflowName)}" contract`);
460
+ setHandler(defineQuery(queryName), (...args$1) => {
461
+ const input = args$1.length === 1 ? args$1[0] : args$1;
462
+ const inputResult$1 = queryDef.input["~standard"].validate(input);
463
+ if (inputResult$1 instanceof Promise) throw new Error(`Query "${String(queryName)}" validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
464
+ if (inputResult$1.issues) throw new QueryInputValidationError(queryName, inputResult$1.issues);
465
+ const result$1 = handler(inputResult$1.value);
466
+ const outputResult$1 = queryDef.output["~standard"].validate(result$1);
467
+ if (outputResult$1 instanceof Promise) throw new Error(`Query "${String(queryName)}" output validation must be synchronous. Use a schema library that supports synchronous validation for queries.`);
468
+ if (outputResult$1.issues) throw new QueryOutputValidationError(queryName, outputResult$1.issues);
469
+ return outputResult$1.value;
470
+ });
471
+ }
472
+ function createDefineUpdate(updateName, handler) {
473
+ if (!definition.updates) throw new Error(`Update "${String(updateName)}" cannot be defined: workflow "${String(workflowName)}" has no updates in its contract`);
474
+ const updateDef = definition.updates[updateName];
475
+ if (!updateDef) throw new Error(`Update "${String(updateName)}" not found in workflow "${String(workflowName)}" contract`);
476
+ setHandler(defineUpdate(updateName), async (...args$1) => {
477
+ const input = args$1.length === 1 ? args$1[0] : args$1;
478
+ const inputResult$1 = await updateDef.input["~standard"].validate(input);
479
+ if (inputResult$1.issues) throw new UpdateInputValidationError(updateName, inputResult$1.issues);
480
+ const result$1 = await handler(inputResult$1.value);
481
+ const outputResult$1 = await updateDef.output["~standard"].validate(result$1);
482
+ if (outputResult$1.issues) throw new UpdateOutputValidationError(updateName, outputResult$1.issues);
483
+ return outputResult$1.value;
484
+ });
485
+ }
387
486
  const result = await implementation({
388
487
  activities: contextActivities,
389
- info: workflowInfo()
488
+ info: workflowInfo(),
489
+ startChildWorkflow: createStartChildWorkflow,
490
+ executeChildWorkflow: createExecuteChildWorkflow,
491
+ defineSignal: createDefineSignal,
492
+ defineQuery: createDefineQuery,
493
+ defineUpdate: createDefineUpdate
390
494
  }, validatedInput);
391
495
  const outputResult = await definition.output["~standard"].validate(result);
392
496
  if (outputResult.issues) throw new WorkflowOutputValidationError(String(workflowName), outputResult.issues);
@@ -395,4 +499,4 @@ function declareWorkflow(options) {
395
499
  }
396
500
 
397
501
  //#endregion
398
- export { ActivityInputValidationError as a, QueryOutputValidationError as c, UpdateOutputValidationError as d, WorkerError as f, ActivityError as i, SignalInputValidationError as l, WorkflowOutputValidationError as m, declareWorkflow as n, ActivityOutputValidationError as o, WorkflowInputValidationError as p, ActivityDefinitionNotFoundError as r, QueryInputValidationError as s, declareActivitiesHandler as t, UpdateInputValidationError as u };
502
+ export { ActivityInputValidationError as a, ChildWorkflowNotFoundError as c, SignalInputValidationError as d, UpdateInputValidationError as f, WorkflowOutputValidationError as g, WorkflowInputValidationError as h, ActivityError as i, QueryInputValidationError as l, WorkerError as m, declareWorkflow as n, ActivityOutputValidationError as o, UpdateOutputValidationError as p, ActivityDefinitionNotFoundError as r, ChildWorkflowError as s, declareActivitiesHandler as t, QueryOutputValidationError as u };