@temporal-contract/client 1.0.0 → 2.0.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { TypedSearchAttributes, WorkflowNotFoundError as WorkflowNotFoundError$1, defineSearchAttributeKey } from "@temporalio/common";
2
- import { Future, Result } from "@swan-io/boxed";
2
+ import { ResultAsync, err, ok } from "neverthrow";
3
3
  import { WorkflowExecutionAlreadyStartedError, WorkflowFailedError as WorkflowFailedError$1 } from "@temporalio/client";
4
4
  //#region src/errors.ts
5
5
  /**
@@ -191,21 +191,19 @@ var UpdateValidationError = class extends TypedClientError {
191
191
  * In-package modules and tests import it directly via relative path.
192
192
  */
193
193
  /**
194
- * Wrap an async result-producing function in a `Future`, catching any
194
+ * Wrap an async result-producing function in a `ResultAsync`, catching any
195
195
  * unhandled rejection as a `RuntimeClientError("unexpected", error)`.
196
196
  *
197
197
  * The work function is expected to handle its own domain errors and return
198
- * a `Result.Error(...)` for them; the catch here is a safety net for
199
- * thrown exceptions the work didn't anticipate.
198
+ * an `err(...)` for them; the catch here is a safety net for thrown
199
+ * exceptions the work didn't anticipate.
200
200
  *
201
201
  * Used by `client.ts` (workflow operations) and `schedule.ts` (schedule
202
202
  * operations) so the unexpected-rejection shape is identical across the
203
203
  * typed client surface.
204
204
  */
205
- function makeFuture(work) {
206
- return Future.make((resolve) => {
207
- work().then(resolve).catch((e) => resolve(Result.Error(new RuntimeClientError("unexpected", e))));
208
- });
205
+ function makeResultAsync(work) {
206
+ return new ResultAsync(work().catch((e) => err(new RuntimeClientError("unexpected", e))));
209
207
  }
210
208
  /**
211
209
  * Map a thrown error from `client.workflow.start` / `signalWithStart` into
@@ -274,9 +272,9 @@ var TypedScheduleClient = class {
274
272
  create(workflowName, options) {
275
273
  const work = async () => {
276
274
  const definition = this.contract.workflows[workflowName];
277
- if (!definition) return Result.Error(new WorkflowNotFoundError(String(workflowName), Object.keys(this.contract.workflows)));
275
+ if (!definition) return err(new WorkflowNotFoundError(String(workflowName), Object.keys(this.contract.workflows)));
278
276
  const inputResult = await definition.input["~standard"].validate(options.args);
279
- if (inputResult.issues) return Result.Error(new WorkflowValidationError(String(workflowName), "input", inputResult.issues));
277
+ if (inputResult.issues) return err(new WorkflowValidationError(String(workflowName), "input", inputResult.issues));
280
278
  try {
281
279
  const overrides = options.action ?? {};
282
280
  const action = {
@@ -293,20 +291,19 @@ var TypedScheduleClient = class {
293
291
  ...overrides.staticDetails !== void 0 ? { staticDetails: overrides.staticDetails } : {},
294
292
  ...overrides.staticSummary !== void 0 ? { staticSummary: overrides.staticSummary } : {}
295
293
  };
296
- const handle = await this.scheduleClient.create({
294
+ return ok(wrapScheduleHandle(await this.scheduleClient.create({
297
295
  scheduleId: options.scheduleId,
298
296
  spec: options.spec,
299
297
  action,
300
298
  ...options.policies !== void 0 ? { policies: options.policies } : {},
301
299
  ...options.state !== void 0 ? { state: options.state } : {},
302
300
  ...options.memo !== void 0 ? { memo: options.memo } : {}
303
- });
304
- return Result.Ok(wrapScheduleHandle(handle));
301
+ })));
305
302
  } catch (error) {
306
- return Result.Error(new RuntimeClientError("schedule.create", error));
303
+ return err(new RuntimeClientError("schedule.create", error));
307
304
  }
308
305
  };
309
- return makeFuture(work);
306
+ return makeResultAsync(work);
310
307
  }
311
308
  /**
312
309
  * Get a typed handle to an existing schedule. Does not validate that the
@@ -320,11 +317,11 @@ var TypedScheduleClient = class {
320
317
  function wrapScheduleHandle(handle) {
321
318
  return {
322
319
  scheduleId: handle.scheduleId,
323
- pause: (note) => Future.fromPromise(handle.pause(note)).mapError((error) => new RuntimeClientError("schedule.pause", error)).mapOk(() => void 0),
324
- unpause: (note) => Future.fromPromise(handle.unpause(note)).mapError((error) => new RuntimeClientError("schedule.unpause", error)).mapOk(() => void 0),
325
- trigger: (overlap) => Future.fromPromise(handle.trigger(overlap)).mapError((error) => new RuntimeClientError("schedule.trigger", error)).mapOk(() => void 0),
326
- delete: () => Future.fromPromise(handle.delete()).mapError((error) => new RuntimeClientError("schedule.delete", error)).mapOk(() => void 0),
327
- describe: () => Future.fromPromise(handle.describe()).mapError((error) => new RuntimeClientError("schedule.describe", error))
320
+ pause: (note) => ResultAsync.fromPromise(handle.pause(note), (error) => new RuntimeClientError("schedule.pause", error)).map(() => void 0),
321
+ unpause: (note) => ResultAsync.fromPromise(handle.unpause(note), (error) => new RuntimeClientError("schedule.unpause", error)).map(() => void 0),
322
+ trigger: (overlap) => ResultAsync.fromPromise(handle.trigger(overlap), (error) => new RuntimeClientError("schedule.trigger", error)).map(() => void 0),
323
+ delete: () => ResultAsync.fromPromise(handle.delete(), (error) => new RuntimeClientError("schedule.delete", error)).map(() => void 0),
324
+ describe: () => ResultAsync.fromPromise(handle.describe(), (error) => new RuntimeClientError("schedule.describe", error))
328
325
  };
329
326
  }
330
327
  //#endregion
@@ -354,7 +351,7 @@ function toTypedSearchAttributes(workflowDef, values) {
354
351
  return pairs.length > 0 ? new TypedSearchAttributes(pairs) : void 0;
355
352
  }
356
353
  /**
357
- * Typed Temporal client with Result/Future pattern based on a contract
354
+ * Typed Temporal client with neverthrow Result/ResultAsync pattern based on a contract
358
355
  *
359
356
  * Provides type-safe methods to start and execute workflows
360
357
  * defined in the contract, with explicit error handling using Result pattern.
@@ -378,10 +375,10 @@ var TypedClient = class TypedClient {
378
375
  * args: { orderId: "sweep" },
379
376
  * });
380
377
  *
381
- * result.match({
382
- * Ok: async (handle) => { await handle.pause("maintenance"); },
383
- * Error: (error) => console.error("schedule create failed", error),
384
- * });
378
+ * result.match(
379
+ * async (handle) => { await handle.pause("maintenance"); },
380
+ * (error) => console.error("schedule create failed", error),
381
+ * );
385
382
  * ```
386
383
  */
387
384
  schedule;
@@ -392,7 +389,7 @@ var TypedClient = class TypedClient {
392
389
  this.schedule = new TypedScheduleClient(contract, client.schedule);
393
390
  }
394
391
  /**
395
- * Create a typed Temporal client with boxed pattern from a contract
392
+ * Create a typed Temporal client with neverthrow pattern from a contract
396
393
  *
397
394
  * @example
398
395
  * ```ts
@@ -405,17 +402,17 @@ var TypedClient = class TypedClient {
405
402
  * args: { ... },
406
403
  * });
407
404
  *
408
- * result.match({
409
- * Ok: (output) => console.log('Success:', output),
410
- * Error: (error) => console.error('Failed:', error),
411
- * });
405
+ * result.match(
406
+ * (output) => console.log('Success:', output),
407
+ * (error) => console.error('Failed:', error),
408
+ * );
412
409
  * ```
413
410
  */
414
411
  static create(contract, client) {
415
412
  return new TypedClient(contract, client);
416
413
  }
417
414
  /**
418
- * Start a workflow and return a typed handle with Future pattern
415
+ * Start a workflow and return a typed handle with ResultAsync pattern
419
416
  *
420
417
  * @example
421
418
  * ```ts
@@ -426,21 +423,21 @@ var TypedClient = class TypedClient {
426
423
  * retry: { maximumAttempts: 3 },
427
424
  * });
428
425
  *
429
- * handleResult.match({
430
- * Ok: async (handle) => {
426
+ * handleResult.match(
427
+ * async (handle) => {
431
428
  * const result = await handle.result();
432
429
  * // ... handle result
433
430
  * },
434
- * Error: (error) => console.error('Failed to start:', error),
435
- * });
431
+ * (error) => console.error('Failed to start:', error),
432
+ * );
436
433
  * ```
437
434
  */
438
435
  startWorkflow(workflowName, { args, searchAttributes, ...temporalOptions }) {
439
436
  const work = async () => {
440
437
  const definition = this.contract.workflows[workflowName];
441
- if (!definition) return Result.Error(createWorkflowNotFoundError(workflowName, this.contract));
438
+ if (!definition) return err(createWorkflowNotFoundError(workflowName, this.contract));
442
439
  const inputResult = await definition.input["~standard"].validate(args);
443
- if (inputResult.issues) return Result.Error(createWorkflowValidationError(workflowName, "input", inputResult.issues));
440
+ if (inputResult.issues) return err(createWorkflowValidationError(workflowName, "input", inputResult.issues));
444
441
  const typedSearchAttributes = toTypedSearchAttributes(definition, searchAttributes);
445
442
  try {
446
443
  const handle = await this.client.workflow.start(workflowName, {
@@ -449,12 +446,12 @@ var TypedClient = class TypedClient {
449
446
  args: [inputResult.value],
450
447
  ...typedSearchAttributes ? { typedSearchAttributes } : {}
451
448
  });
452
- return Result.Ok(this.createTypedHandle(handle, definition));
449
+ return ok(this.createTypedHandle(handle, definition));
453
450
  } catch (error) {
454
- return Result.Error(classifyStartError("startWorkflow", error));
451
+ return err(classifyStartError("startWorkflow", error));
455
452
  }
456
453
  };
457
- return makeFuture(work);
454
+ return makeResultAsync(work);
458
455
  }
459
456
  /**
460
457
  * Send a signal to a workflow, starting it first if it doesn't already exist.
@@ -476,22 +473,22 @@ var TypedClient = class TypedClient {
476
473
  * signalArgs: { reason: 'duplicate' },
477
474
  * });
478
475
  *
479
- * result.match({
480
- * Ok: (handle) => console.log('signaled run', handle.signaledRunId),
481
- * Error: (error) => console.error('signalWithStart failed', error),
482
- * });
476
+ * result.match(
477
+ * (handle) => console.log('signaled run', handle.signaledRunId),
478
+ * (error) => console.error('signalWithStart failed', error),
479
+ * );
483
480
  * ```
484
481
  */
485
482
  signalWithStart(workflowName, { args, signalName, signalArgs, searchAttributes, ...temporalOptions }) {
486
483
  const work = async () => {
487
484
  const definition = this.contract.workflows[workflowName];
488
- if (!definition) return Result.Error(createWorkflowNotFoundError(workflowName, this.contract));
485
+ if (!definition) return err(createWorkflowNotFoundError(workflowName, this.contract));
489
486
  const inputResult = await definition.input["~standard"].validate(args);
490
- if (inputResult.issues) return Result.Error(createWorkflowValidationError(workflowName, "input", inputResult.issues));
487
+ if (inputResult.issues) return err(createWorkflowValidationError(workflowName, "input", inputResult.issues));
491
488
  const signalDef = definition.signals?.[signalName];
492
- if (!signalDef) return Result.Error(new SignalValidationError(signalName, [{ message: `Signal "${signalName}" is not declared on workflow "${String(workflowName)}".` }]));
489
+ if (!signalDef) return err(new SignalValidationError(signalName, [{ message: `Signal "${signalName}" is not declared on workflow "${String(workflowName)}".` }]));
493
490
  const signalInputResult = await signalDef.input["~standard"].validate(signalArgs);
494
- if (signalInputResult.issues) return Result.Error(new SignalValidationError(signalName, signalInputResult.issues));
491
+ if (signalInputResult.issues) return err(new SignalValidationError(signalName, signalInputResult.issues));
495
492
  const typedSearchAttributes = toTypedSearchAttributes(definition, searchAttributes);
496
493
  try {
497
494
  const handle = await this.client.workflow.signalWithStart(workflowName, {
@@ -502,19 +499,18 @@ var TypedClient = class TypedClient {
502
499
  signalArgs: [signalInputResult.value],
503
500
  ...typedSearchAttributes ? { typedSearchAttributes } : {}
504
501
  });
505
- const typed = this.createTypedHandle(handle, definition);
506
- return Result.Ok({
507
- ...typed,
502
+ return ok({
503
+ ...this.createTypedHandle(handle, definition),
508
504
  signaledRunId: handle.signaledRunId
509
505
  });
510
506
  } catch (error) {
511
- return Result.Error(classifyStartError("signalWithStart", error));
507
+ return err(classifyStartError("signalWithStart", error));
512
508
  }
513
509
  };
514
- return makeFuture(work);
510
+ return makeResultAsync(work);
515
511
  }
516
512
  /**
517
- * Execute a workflow (start and wait for result) with Future/Result pattern
513
+ * Execute a workflow (start and wait for result) with ResultAsync pattern
518
514
  *
519
515
  * @example
520
516
  * ```ts
@@ -525,18 +521,18 @@ var TypedClient = class TypedClient {
525
521
  * retry: { maximumAttempts: 3 },
526
522
  * });
527
523
  *
528
- * result.match({
529
- * Ok: (output) => console.log('Order processed:', output.status),
530
- * Error: (error) => console.error('Processing failed:', error),
531
- * });
524
+ * result.match(
525
+ * (output) => console.log('Order processed:', output.status),
526
+ * (error) => console.error('Processing failed:', error),
527
+ * );
532
528
  * ```
533
529
  */
534
530
  executeWorkflow(workflowName, { args, searchAttributes, ...temporalOptions }) {
535
531
  const work = async () => {
536
532
  const definition = this.contract.workflows[workflowName];
537
- if (!definition) return Result.Error(createWorkflowNotFoundError(workflowName, this.contract));
533
+ if (!definition) return err(createWorkflowNotFoundError(workflowName, this.contract));
538
534
  const inputResult = await definition.input["~standard"].validate(args);
539
- if (inputResult.issues) return Result.Error(createWorkflowValidationError(workflowName, "input", inputResult.issues));
535
+ if (inputResult.issues) return err(createWorkflowValidationError(workflowName, "input", inputResult.issues));
540
536
  const typedSearchAttributes = toTypedSearchAttributes(definition, searchAttributes);
541
537
  try {
542
538
  const result = await this.client.workflow.execute(workflowName, {
@@ -546,44 +542,44 @@ var TypedClient = class TypedClient {
546
542
  ...typedSearchAttributes ? { typedSearchAttributes } : {}
547
543
  });
548
544
  const outputResult = await definition.output["~standard"].validate(result);
549
- if (outputResult.issues) return Result.Error(createWorkflowValidationError(workflowName, "output", outputResult.issues));
550
- return Result.Ok(outputResult.value);
545
+ if (outputResult.issues) return err(createWorkflowValidationError(workflowName, "output", outputResult.issues));
546
+ return ok(outputResult.value);
551
547
  } catch (error) {
552
- if (error instanceof WorkflowExecutionAlreadyStartedError) return Result.Error(new WorkflowAlreadyStartedError(error.workflowType, error.workflowId, error));
553
- if (error instanceof WorkflowFailedError$1) return Result.Error(new WorkflowFailedError(temporalOptions.workflowId, error.cause));
554
- if (error instanceof WorkflowNotFoundError$1) return Result.Error(new WorkflowExecutionNotFoundError(error.workflowId || temporalOptions.workflowId, error.runId, error));
555
- return Result.Error(createRuntimeClientError("executeWorkflow", error));
548
+ if (error instanceof WorkflowExecutionAlreadyStartedError) return err(new WorkflowAlreadyStartedError(error.workflowType, error.workflowId, error));
549
+ if (error instanceof WorkflowFailedError$1) return err(new WorkflowFailedError(temporalOptions.workflowId, error.cause));
550
+ if (error instanceof WorkflowNotFoundError$1) return err(new WorkflowExecutionNotFoundError(error.workflowId || temporalOptions.workflowId, error.runId, error));
551
+ return err(createRuntimeClientError("executeWorkflow", error));
556
552
  }
557
553
  };
558
- return makeFuture(work);
554
+ return makeResultAsync(work);
559
555
  }
560
556
  /**
561
- * Get a handle to an existing workflow with Future/Result pattern
557
+ * Get a handle to an existing workflow with ResultAsync pattern
562
558
  *
563
559
  * @example
564
560
  * ```ts
565
561
  * const handleResult = await client.getHandle('processOrder', 'order-123');
566
- * handleResult.match({
567
- * Ok: async (handle) => {
562
+ * handleResult.match(
563
+ * async (handle) => {
568
564
  * const result = await handle.result();
569
565
  * // ... handle result
570
566
  * },
571
- * Error: (error) => console.error('Failed to get handle:', error),
572
- * });
567
+ * (error) => console.error('Failed to get handle:', error),
568
+ * );
573
569
  * ```
574
570
  */
575
571
  getHandle(workflowName, workflowId) {
576
572
  const work = async () => {
577
573
  const definition = this.contract.workflows[workflowName];
578
- if (!definition) return Result.Error(createWorkflowNotFoundError(workflowName, this.contract));
574
+ if (!definition) return err(createWorkflowNotFoundError(workflowName, this.contract));
579
575
  try {
580
576
  const handle = this.client.workflow.getHandle(workflowId);
581
- return Result.Ok(this.createTypedHandle(handle, definition));
577
+ return ok(this.createTypedHandle(handle, definition));
582
578
  } catch (error) {
583
- return Result.Error(createRuntimeClientError("getHandle", error));
579
+ return err(createRuntimeClientError("getHandle", error));
584
580
  }
585
581
  };
586
- return makeFuture(work);
582
+ return makeResultAsync(work);
587
583
  }
588
584
  createTypedHandle(workflowHandle, definition) {
589
585
  const queries = buildValidatedProxy({
@@ -622,18 +618,18 @@ var TypedClient = class TypedClient {
622
618
  try {
623
619
  const result = await workflowHandle.result();
624
620
  const outputResult = await definition.output["~standard"].validate(result);
625
- if (outputResult.issues) return Result.Error(new WorkflowValidationError(workflowHandle.workflowId, "output", outputResult.issues));
626
- return Result.Ok(outputResult.value);
621
+ if (outputResult.issues) return err(new WorkflowValidationError(workflowHandle.workflowId, "output", outputResult.issues));
622
+ return ok(outputResult.value);
627
623
  } catch (error) {
628
- return Result.Error(classifyResultError("result", error, workflowHandle.workflowId));
624
+ return err(classifyResultError("result", error, workflowHandle.workflowId));
629
625
  }
630
626
  };
631
- return makeFuture(work);
627
+ return makeResultAsync(work);
632
628
  },
633
- terminate: (reason) => Future.fromPromise(workflowHandle.terminate(reason)).mapError((error) => classifyHandleError("terminate", error, workflowHandle.workflowId)).mapOk(() => void 0),
634
- cancel: () => Future.fromPromise(workflowHandle.cancel()).mapError((error) => classifyHandleError("cancel", error, workflowHandle.workflowId)).mapOk(() => void 0),
635
- describe: () => Future.fromPromise(workflowHandle.describe()).mapError((error) => classifyHandleError("describe", error, workflowHandle.workflowId)),
636
- fetchHistory: () => Future.fromPromise(workflowHandle.fetchHistory()).mapError((error) => classifyHandleError("fetchHistory", error, workflowHandle.workflowId))
629
+ terminate: (reason) => ResultAsync.fromPromise(workflowHandle.terminate(reason), (error) => classifyHandleError("terminate", error, workflowHandle.workflowId)).map(() => void 0),
630
+ cancel: () => ResultAsync.fromPromise(workflowHandle.cancel(), (error) => classifyHandleError("cancel", error, workflowHandle.workflowId)).map(() => void 0),
631
+ describe: () => ResultAsync.fromPromise(workflowHandle.describe(), (error) => classifyHandleError("describe", error, workflowHandle.workflowId)),
632
+ fetchHistory: () => ResultAsync.fromPromise(workflowHandle.fetchHistory(), (error) => classifyHandleError("fetchHistory", error, workflowHandle.workflowId))
637
633
  };
638
634
  }
639
635
  };
@@ -647,7 +643,7 @@ function createWorkflowValidationError(workflowName, direction, issues) {
647
643
  return new WorkflowValidationError(String(workflowName), direction, issues);
648
644
  }
649
645
  /**
650
- * Build a `{ name: (args) => Future<Result<...>> }` proxy for a contract's
646
+ * Build a `{ name: (args) => ResultAsync<...> }` proxy for a contract's
651
647
  * queries/signals/updates. The three call sites differ only in how they
652
648
  * invoke Temporal and whether they validate output, so the shared
653
649
  * input-validate → invoke → output-validate → wrap-Result pipeline lives
@@ -659,19 +655,19 @@ function buildValidatedProxy({ defs, operation, workflowId, makeValidationError,
659
655
  for (const [name, def] of Object.entries(defs)) proxy[name] = (args) => {
660
656
  const work = async () => {
661
657
  const inputResult = await def.input["~standard"].validate(args);
662
- if (inputResult.issues) return Result.Error(makeValidationError(name, "input", inputResult.issues));
658
+ if (inputResult.issues) return err(makeValidationError(name, "input", inputResult.issues));
663
659
  try {
664
660
  const result = await invoke(name, inputResult.value);
665
661
  const outputSchema = validateOutput(def);
666
- if (!outputSchema) return Result.Ok(result);
662
+ if (!outputSchema) return ok(result);
667
663
  const outputResult = await outputSchema["~standard"].validate(result);
668
- if (outputResult.issues) return Result.Error(makeValidationError(name, "output", outputResult.issues));
669
- return Result.Ok(outputResult.value);
664
+ if (outputResult.issues) return err(makeValidationError(name, "output", outputResult.issues));
665
+ return ok(outputResult.value);
670
666
  } catch (error) {
671
- return Result.Error(classifyHandleError(operation, error, workflowId));
667
+ return err(classifyHandleError(operation, error, workflowId));
672
668
  }
673
669
  };
674
- return makeFuture(work);
670
+ return makeResultAsync(work);
675
671
  };
676
672
  return proxy;
677
673
  }