@orkestrel/workflow 0.0.10 → 0.0.11

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.
@@ -110,6 +110,51 @@ var DEFAULT_PHASE_CONCURRENCY = 1024;
110
110
  */
111
111
  var MAX_TIMER_MS = 2147483647;
112
112
  //#endregion
113
+ //#region src/core/errors.ts
114
+ /**
115
+ * An error raised by the workflow runtime.
116
+ *
117
+ * @remarks
118
+ * Carries a {@link WorkflowErrorCode} and an optional `context` bag naming the
119
+ * offending node id / status / parameter. Raised for an illegal lifecycle transition
120
+ * (`TRANSITION`), a structurally invalid {@link import('./types.js').WorkflowSnapshot}
121
+ * boundary (`RESTORE`), a refused structural/activity edit (`MUTATION`), or a host
122
+ * schedule refused before arming because the caller's `signal` is not a native
123
+ * `AbortSignal` (`SCHEDULE`, delivered as a rejected promise).
124
+ */
125
+ var WorkflowError = class extends Error {
126
+ code;
127
+ context;
128
+ constructor(code, message, context) {
129
+ super(message);
130
+ this.name = "WorkflowError";
131
+ this.code = code;
132
+ if (context !== void 0) this.context = context;
133
+ }
134
+ };
135
+ /**
136
+ * Narrow an unknown caught value to a {@link WorkflowError}.
137
+ *
138
+ * @param value - The value to test (typically a `catch` binding)
139
+ * @returns `true` when `value` is a {@link WorkflowError}
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * try {
144
+ * task.complete('done')
145
+ * } catch (error) {
146
+ * if (isWorkflowError(error) && error.code === 'TRANSITION') retry()
147
+ * }
148
+ * ```
149
+ */
150
+ function isWorkflowError(value) {
151
+ try {
152
+ return value instanceof WorkflowError;
153
+ } catch {
154
+ return false;
155
+ }
156
+ }
157
+ //#endregion
113
158
  //#region src/core/helpers.ts
114
159
  /**
115
160
  * Capture every top-level {@link WorkflowOptions} value exactly once into an owned plain bag.
@@ -672,6 +717,16 @@ function createDeferred() {
672
717
  * Schedule one cancellable host operation behind an owned settlement signal.
673
718
  *
674
719
  * @remarks
720
+ * A defined `signal` that is not a native `AbortSignal` is refused before anything is armed, as a
721
+ * rejected promise carrying a {@link import('./errors.js').WorkflowError} with the `SCHEDULE` code.
722
+ * Rejecting rather than throwing keeps every caller on one settlement path, so a backend never has
723
+ * to guard the call itself.
724
+ *
725
+ * The guard is necessary but not sufficient, so linking stays contained. A `Proxy` over a native
726
+ * signal passes the guard and can still make linking throw from a trap, and that escape would be
727
+ * synchronous — the one shape every caller here is built not to expect. Containment turns it into
728
+ * the same `SCHEDULE` rejection, so setup has exactly one failure shape however hostile the input.
729
+ *
675
730
  * The completion and failure paths each own an {@link AbortController}; their native composite is
676
731
  * linked to the optional caller signal before `start` can arm host work. Scheduler backends attach
677
732
  * only to that safe composite, so caller mutation of `addEventListener` or `removeEventListener`
@@ -683,16 +738,18 @@ function createDeferred() {
683
738
  *
684
739
  * @param start - Arm host work and return its cancellation closure
685
740
  * @param signal - Optional caller cancellation signal
686
- * @returns A promise settled exactly once by completion, host failure, or caller abort
741
+ * @returns A promise settled exactly once by an invalid-signal refusal, completion, host failure,
742
+ * or caller abort
687
743
  */
688
744
  function scheduleHost(start, signal) {
745
+ if (signal !== void 0 && !(0, _orkestrel_abort.isAbortSignal)(signal)) return Promise.reject(new WorkflowError("SCHEDULE", "scheduleHost signal must be an AbortSignal", { signal: typeof signal }));
689
746
  const completion = new AbortController();
690
747
  const failed = new AbortController();
691
748
  let settled;
692
749
  try {
693
750
  settled = (0, _orkestrel_abort.linkSignal)(AbortSignal.any([completion.signal, failed.signal]), signal);
694
- } catch (error) {
695
- return Promise.reject(error);
751
+ } catch {
752
+ return Promise.reject(new WorkflowError("SCHEDULE", "scheduleHost could not link the caller signal", { signal: typeof signal }));
696
753
  }
697
754
  if (settled.aborted) return Promise.reject(settled.reason);
698
755
  return new Promise((resolve, reject) => {
@@ -815,49 +872,6 @@ var Scheduler = class {
815
872
  }
816
873
  };
817
874
  //#endregion
818
- //#region src/core/errors.ts
819
- /**
820
- * An error raised by the workflow runtime.
821
- *
822
- * @remarks
823
- * Carries a {@link WorkflowErrorCode} and an optional `context` bag naming the
824
- * offending node id / status. Raised for an illegal lifecycle transition
825
- * (`TRANSITION`), a structurally invalid {@link import('./types.js').WorkflowSnapshot}
826
- * boundary (`RESTORE`), or a refused structural/activity edit (`MUTATION`).
827
- */
828
- var WorkflowError = class extends Error {
829
- code;
830
- context;
831
- constructor(code, message, context) {
832
- super(message);
833
- this.name = "WorkflowError";
834
- this.code = code;
835
- if (context !== void 0) this.context = context;
836
- }
837
- };
838
- /**
839
- * Narrow an unknown caught value to a {@link WorkflowError}.
840
- *
841
- * @param value - The value to test (typically a `catch` binding)
842
- * @returns `true` when `value` is a {@link WorkflowError}
843
- *
844
- * @example
845
- * ```ts
846
- * try {
847
- * task.complete('done')
848
- * } catch (error) {
849
- * if (isWorkflowError(error) && error.code === 'TRANSITION') retry()
850
- * }
851
- * ```
852
- */
853
- function isWorkflowError(value) {
854
- try {
855
- return value instanceof WorkflowError;
856
- } catch {
857
- return false;
858
- }
859
- }
860
- //#endregion
861
875
  //#region src/core/validators.ts
862
876
  /** Test the workflow lifecycle vocabulary. */
863
877
  function isLifecycleStatus(value) {