@aikirun/workflow 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,7 +52,6 @@ Run workflows on a schedule using cron expressions or intervals:
52
52
  import { schedule } from "@aikirun/workflow";
53
53
 
54
54
  const dailyReport = schedule({
55
- name: "daily-report",
56
55
  type: "cron",
57
56
  expression: "0 9 * * *", // Every day at 9 AM
58
57
  });
package/dist/index.d.ts CHANGED
@@ -5,12 +5,12 @@ import { WorkflowRun, TerminalWorkflowRunStatus, WorkflowRunState, WorkflowRunId
5
5
  import { StandardSchemaV1 } from '@standard-schema/spec';
6
6
  import { DurationObject, Duration } from '@aikirun/types/duration';
7
7
  import { SleepResult } from '@aikirun/types/sleep';
8
- import { EventSendOptions, EventWaitOptions, EventWaitState } from '@aikirun/types/event';
8
+ import { EventSendOptions, EventWaitOptions, EventWaitResult } from '@aikirun/types/event';
9
9
  import { Serializable } from '@aikirun/types/serializable';
10
10
  import { DistributiveOmit, RequireAtLeastOneProp } from '@aikirun/types/utils';
11
11
  import { TaskId } from '@aikirun/types/task';
12
12
  import { WorkflowRunStateRequest, WorkflowRunTransitionTaskStateRequestV1 } from '@aikirun/types/workflow-run-api';
13
- import { OverlapPolicy, ScheduleName, ScheduleId } from '@aikirun/types/schedule';
13
+ import { ScheduleOverlapPolicy, ScheduleActivateOptions, ScheduleId } from '@aikirun/types/schedule';
14
14
 
15
15
  type NonEmptyArray<T> = [T, ...T[]];
16
16
 
@@ -151,8 +151,8 @@ type EventWaiters<TEvents extends EventsDefinition> = {
151
151
  [K in keyof TEvents]: EventWaiter<EventData<TEvents[K]>>;
152
152
  };
153
153
  interface EventWaiter<Data> {
154
- wait(options?: EventWaitOptions<false>): Promise<EventWaitState<Data, false>>;
155
- wait(options: EventWaitOptions<true>): Promise<EventWaitState<Data, true>>;
154
+ wait(options?: EventWaitOptions<false>): Promise<EventWaitResult<Data, false>>;
155
+ wait(options: EventWaitOptions<true>): Promise<EventWaitResult<Data, true>>;
156
156
  }
157
157
  type EventSenders<TEvents extends EventsDefinition> = {
158
158
  [K in keyof TEvents]: EventSender<EventData<TEvents[K]>>;
@@ -309,28 +309,29 @@ interface CronScheduleParams {
309
309
  type: "cron";
310
310
  expression: string;
311
311
  timezone?: string;
312
- overlapPolicy?: OverlapPolicy;
312
+ overlapPolicy?: ScheduleOverlapPolicy;
313
313
  }
314
314
  interface IntervalScheduleParams {
315
315
  type: "interval";
316
316
  every: DurationObject;
317
- overlapPolicy?: OverlapPolicy;
317
+ overlapPolicy?: ScheduleOverlapPolicy;
318
318
  }
319
319
  type ScheduleParams = CronScheduleParams | IntervalScheduleParams;
320
320
  interface ScheduleHandle {
321
321
  id: ScheduleId;
322
- name: ScheduleName;
323
322
  pause(): Promise<void>;
324
323
  resume(): Promise<void>;
325
324
  delete(): Promise<void>;
326
325
  }
326
+ interface ScheduleBuilder {
327
+ opt<Path extends PathFromObject<ScheduleActivateOptions>>(path: Path, value: TypeOfValueAtPath<ScheduleActivateOptions, Path>): ScheduleBuilder;
328
+ activate<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, workflow: WorkflowVersion<Input, Output, AppContext, TEvents>, ...args: Input extends void ? [] : [Input]): Promise<ScheduleHandle>;
329
+ }
327
330
  type ScheduleDefinition = ScheduleParams & {
328
- name: ScheduleName;
331
+ with(): ScheduleBuilder;
329
332
  activate<Input, Output, AppContext, TEvents extends EventsDefinition>(client: Client<AppContext>, workflow: WorkflowVersion<Input, Output, AppContext, TEvents>, ...args: Input extends void ? [] : [Input]): Promise<ScheduleHandle>;
330
333
  };
331
- declare function schedule(params: {
332
- name: string;
333
- } & ScheduleParams): ScheduleDefinition;
334
+ declare function schedule(params: ScheduleParams): ScheduleDefinition;
334
335
 
335
336
  /**
336
337
  * Defines a durable workflow with versioning and multiple task execution.
package/dist/index.js CHANGED
@@ -77,6 +77,9 @@ function delay(ms, options) {
77
77
  });
78
78
  }
79
79
 
80
+ // ../../lib/crypto/hash.ts
81
+ import { createHash } from "crypto";
82
+
80
83
  // ../../lib/json/stable-stringify.ts
81
84
  function stableStringify(value) {
82
85
  return stringifyValue(value);
@@ -292,8 +295,8 @@ function getRetryParams(attempts, strategy) {
292
295
  import { INTERNAL } from "@aikirun/types/symbols";
293
296
  import { SchemaValidationError } from "@aikirun/types/validator";
294
297
  import {
295
- WorkflowRunConflictError,
296
298
  WorkflowRunFailedError,
299
+ WorkflowRunRevisionConflictError,
297
300
  WorkflowRunSuspendedError
298
301
  } from "@aikirun/types/workflow-run";
299
302
  function event(params) {
@@ -320,17 +323,17 @@ function createEventWaiter(handle, eventName, schema, logger) {
320
323
  let nextEventIndex = 0;
321
324
  async function wait(options) {
322
325
  await handle.refresh();
323
- const events = handle.run.eventsQueue[eventName]?.events ?? [];
324
- const event2 = events[nextEventIndex];
325
- if (event2) {
326
+ const eventWaits = handle.run.eventWaitQueues[eventName]?.eventWaits ?? [];
327
+ const eventWait = eventWaits[nextEventIndex];
328
+ if (eventWait) {
326
329
  nextEventIndex++;
327
- if (event2.status === "timeout") {
330
+ if (eventWait.status === "timeout") {
328
331
  logger.debug("Timed out waiting for event");
329
332
  return { timeout: true };
330
333
  }
331
- let data = event2.data;
334
+ let data = eventWait.data;
332
335
  if (schema) {
333
- const schemaValidation = schema["~standard"].validate(event2.data);
336
+ const schemaValidation = schema["~standard"].validate(eventWait.data);
334
337
  const schemaValidationResult = schemaValidation instanceof Promise ? await schemaValidation : schemaValidation;
335
338
  if (!schemaValidationResult.issues) {
336
339
  data = schemaValidationResult.value;
@@ -361,7 +364,7 @@ function createEventWaiter(handle, eventName, schema, logger) {
361
364
  ...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
362
365
  });
363
366
  } catch (error) {
364
- if (error instanceof WorkflowRunConflictError) {
367
+ if (error instanceof WorkflowRunRevisionConflictError) {
365
368
  throw new WorkflowRunSuspendedError(handle.run.id);
366
369
  }
367
370
  throw error;
@@ -485,8 +488,8 @@ function createEventMulticaster(workflowName, workflowVersionId, eventName, sche
485
488
  import { INTERNAL as INTERNAL2 } from "@aikirun/types/symbols";
486
489
  import {
487
490
  isTerminalWorkflowRunStatus,
488
- WorkflowRunConflictError as WorkflowRunConflictError2,
489
- WorkflowRunNotExecutableError
491
+ WorkflowRunNotExecutableError,
492
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError2
490
493
  } from "@aikirun/types/workflow-run";
491
494
  async function workflowRunHandle(client, runOrId, eventsDefinition, logger) {
492
495
  const run = typeof runOrId !== "string" ? runOrId : (await client.api.workflowRun.getByIdV1({ id: runOrId })).run;
@@ -622,7 +625,7 @@ var WorkflowRunHandleImpl = class {
622
625
  this._run = run;
623
626
  } catch (error) {
624
627
  if (isConflictError(error)) {
625
- throw new WorkflowRunConflictError2(this.run.id);
628
+ throw new WorkflowRunRevisionConflictError2(this.run.id);
626
629
  }
627
630
  throw error;
628
631
  }
@@ -638,7 +641,7 @@ var WorkflowRunHandleImpl = class {
638
641
  return { taskId };
639
642
  } catch (error) {
640
643
  if (isConflictError(error)) {
641
- throw new WorkflowRunConflictError2(this.run.id);
644
+ throw new WorkflowRunRevisionConflictError2(this.run.id);
642
645
  }
643
646
  throw error;
644
647
  }
@@ -656,7 +659,10 @@ function isConflictError(error) {
656
659
 
657
660
  // run/sleeper.ts
658
661
  import { INTERNAL as INTERNAL3 } from "@aikirun/types/symbols";
659
- import { WorkflowRunConflictError as WorkflowRunConflictError3, WorkflowRunSuspendedError as WorkflowRunSuspendedError2 } from "@aikirun/types/workflow-run";
662
+ import {
663
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError3,
664
+ WorkflowRunSuspendedError as WorkflowRunSuspendedError2
665
+ } from "@aikirun/types/workflow-run";
660
666
  var MAX_SLEEP_YEARS = 10;
661
667
  var MAX_SLEEP_MS = MAX_SLEEP_YEARS * 365 * 24 * 60 * 60 * 1e3;
662
668
  function createSleeper(handle, logger) {
@@ -678,7 +684,7 @@ function createSleeper(handle, logger) {
678
684
  "aiki.durationMs": durationMs
679
685
  });
680
686
  } catch (error) {
681
- if (error instanceof WorkflowRunConflictError3) {
687
+ if (error instanceof WorkflowRunRevisionConflictError3) {
682
688
  throw new WorkflowRunSuspendedError2(handle.run.id);
683
689
  }
684
690
  throw error;
@@ -726,7 +732,7 @@ function createSleeper(handle, logger) {
726
732
  "aiki.durationMs": durationMs
727
733
  });
728
734
  } catch (error) {
729
- if (error instanceof WorkflowRunConflictError3) {
735
+ if (error instanceof WorkflowRunRevisionConflictError3) {
730
736
  throw new WorkflowRunSuspendedError2(handle.run.id);
731
737
  }
732
738
  throw error;
@@ -737,48 +743,61 @@ function createSleeper(handle, logger) {
737
743
 
738
744
  // schedule.ts
739
745
  function schedule(params) {
740
- const { name, ...scheduleParams } = params;
746
+ async function activateWithOpts(client, workflow2, options, ...args) {
747
+ const input = args[0];
748
+ let scheduleSpec;
749
+ if (params.type === "interval") {
750
+ const { every, ...rest } = params;
751
+ scheduleSpec = {
752
+ ...rest,
753
+ everyMs: toMilliseconds(every)
754
+ };
755
+ } else {
756
+ scheduleSpec = params;
757
+ }
758
+ const { schedule: schedule2 } = await client.api.schedule.activateV1({
759
+ workflowName: workflow2.name,
760
+ workflowVersionId: workflow2.versionId,
761
+ spec: scheduleSpec,
762
+ input,
763
+ options
764
+ });
765
+ client.logger.info("Schedule activated", {
766
+ scheduleSpec,
767
+ workflowName: workflow2.name,
768
+ workflowVersionId: workflow2.versionId,
769
+ referenceId: options?.reference?.id
770
+ });
771
+ const scheduleId = schedule2.id;
772
+ return {
773
+ id: scheduleId,
774
+ pause: async () => {
775
+ await client.api.schedule.pauseV1({ id: scheduleId });
776
+ },
777
+ resume: async () => {
778
+ await client.api.schedule.resumeV1({ id: scheduleId });
779
+ },
780
+ delete: async () => {
781
+ await client.api.schedule.deleteV1({ id: scheduleId });
782
+ }
783
+ };
784
+ }
785
+ function createBuilder(optsBuilder) {
786
+ return {
787
+ opt: (path, value) => createBuilder(optsBuilder.with(path, value)),
788
+ async activate(client, workflow2, ...args) {
789
+ return activateWithOpts(client, workflow2, optsBuilder.build(), ...args);
790
+ }
791
+ };
792
+ }
741
793
  return {
742
- name,
743
- ...scheduleParams,
794
+ ...params,
795
+ with() {
796
+ const optsOverrider = objectOverrider({});
797
+ return createBuilder(optsOverrider());
798
+ },
744
799
  async activate(client, workflow2, ...args) {
745
- const input = args[0];
746
- let scheduleSpec;
747
- if (scheduleParams.type === "interval") {
748
- const { every, ...rest } = scheduleParams;
749
- scheduleSpec = {
750
- ...rest,
751
- everyMs: toMilliseconds(every)
752
- };
753
- } else {
754
- scheduleSpec = scheduleParams;
755
- }
756
- const { schedule: schedule2 } = await client.api.schedule.activateV1({
757
- name,
758
- workflowName: workflow2.name,
759
- workflowVersionId: workflow2.versionId,
760
- spec: scheduleSpec,
761
- input
762
- });
763
- client.logger.info("Schedule activated", {
764
- scheduleSpec,
765
- workflowName: workflow2.name,
766
- workflowVersionId: workflow2.versionId
767
- });
768
- const scheduleId = schedule2.id;
769
- return {
770
- id: scheduleId,
771
- name,
772
- pause: async () => {
773
- await client.api.schedule.pauseV1({ id: scheduleId });
774
- },
775
- resume: async () => {
776
- await client.api.schedule.resumeV1({ id: scheduleId });
777
- },
778
- delete: async () => {
779
- await client.api.schedule.deleteV1({ id: scheduleId });
780
- }
781
- };
800
+ return activateWithOpts(client, workflow2, {}, ...args);
782
801
  }
783
802
  };
784
803
  }
@@ -788,7 +807,7 @@ import { INTERNAL as INTERNAL6 } from "@aikirun/types/symbols";
788
807
 
789
808
  // ../../lib/address/index.ts
790
809
  function getWorkflowRunAddress(name, versionId, referenceId) {
791
- return `${name}/${versionId}/${referenceId}`;
810
+ return `${name}:${versionId}:${referenceId}`;
792
811
  }
793
812
 
794
813
  // workflow-version.ts
@@ -796,8 +815,8 @@ import { INTERNAL as INTERNAL5 } from "@aikirun/types/symbols";
796
815
  import { TaskFailedError } from "@aikirun/types/task";
797
816
  import { SchemaValidationError as SchemaValidationError2 } from "@aikirun/types/validator";
798
817
  import {
799
- WorkflowRunConflictError as WorkflowRunConflictError5,
800
818
  WorkflowRunFailedError as WorkflowRunFailedError2,
819
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError5,
801
820
  WorkflowRunSuspendedError as WorkflowRunSuspendedError4
802
821
  } from "@aikirun/types/workflow-run";
803
822
 
@@ -805,7 +824,7 @@ import {
805
824
  import { INTERNAL as INTERNAL4 } from "@aikirun/types/symbols";
806
825
  import {
807
826
  isTerminalWorkflowRunStatus as isTerminalWorkflowRunStatus2,
808
- WorkflowRunConflictError as WorkflowRunConflictError4,
827
+ WorkflowRunRevisionConflictError as WorkflowRunRevisionConflictError4,
809
828
  WorkflowRunSuspendedError as WorkflowRunSuspendedError3
810
829
  } from "@aikirun/types/workflow-run";
811
830
  async function childWorkflowRunHandle(client, run, parentRun, logger, eventsDefinition) {
@@ -884,7 +903,7 @@ function createStatusWaiter(handle, parentRun, logger) {
884
903
  ...timeoutInMs !== void 0 ? { "aiki.timeoutInMs": timeoutInMs } : {}
885
904
  });
886
905
  } catch (error) {
887
- if (error instanceof WorkflowRunConflictError4) {
906
+ if (error instanceof WorkflowRunRevisionConflictError4) {
888
907
  throw new WorkflowRunSuspendedError3(parentRun.id);
889
908
  }
890
909
  throw error;
@@ -1065,7 +1084,7 @@ var WorkflowVersionImpl = class {
1065
1084
  const output = await this.parse(handle, this.params.schema?.output, outputRaw, run.logger);
1066
1085
  return output;
1067
1086
  } catch (error) {
1068
- if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunConflictError5) {
1087
+ if (error instanceof WorkflowRunSuspendedError4 || error instanceof WorkflowRunFailedError2 || error instanceof WorkflowRunRevisionConflictError5) {
1069
1088
  throw error;
1070
1089
  }
1071
1090
  const attempts = handle.run.attempts;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikirun/workflow",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Workflow SDK for Aiki - define durable workflows with tasks, sleeps, waits, and event handling",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "build": "tsup"
19
19
  },
20
20
  "dependencies": {
21
- "@aikirun/types": "0.15.0",
21
+ "@aikirun/types": "0.17.0",
22
22
  "@standard-schema/spec": "^1.1.0"
23
23
  },
24
24
  "publishConfig": {