@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.
- package/dist/src/core/index.cjs +60 -46
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +28 -9
- package/dist/src/core/index.d.ts +28 -9
- package/dist/src/core/index.js +61 -47
- package/dist/src/core/index.js.map +1 -1
- package/package.json +14 -14
package/dist/src/core/index.cjs
CHANGED
|
@@ -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,
|
|
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
|
|
695
|
-
return Promise.reject(
|
|
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) {
|