@orkestrel/workflow 0.0.17 → 0.0.18

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.
@@ -2,11 +2,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let _src_core = require("../core/index.cjs");
3
3
  //#region src/server/NodeScheduler.ts
4
4
  /**
5
- * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.
5
+ * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend
6
+ * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.
7
+ * A `priority` hint is accepted and does nothing, because Node has no priority primitive.
6
8
  *
7
9
  * @remarks
8
10
  * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the
9
- * canonical Node "give the host a turn" — it runs AFTER the current operation and
11
+ * canonical Node "give the host a turn" — it runs after the current operation and
10
12
  * any pending I/O callbacks, so the event loop genuinely regains control before
11
13
  * resuming (unlike a microtask, which drains within the current task). `delay(ms)`
12
14
  * waits on a real `setTimeout`.
@@ -14,7 +16,7 @@ let _src_core = require("../core/index.cjs");
14
16
  * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite
15
17
  * before arming either Node handle, so caller signal method mutation is harmless and the
16
18
  * first completion, abort, or setup failure owns settlement and cleanup. It deliberately
17
- * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
19
+ * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
18
20
  * with a Node `AbortError` (`code: 'ABORT_ERR'`).
19
21
  * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent
20
22
  * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/server/NodeScheduler.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\n\n/**\n * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.\n *\n * @remarks\n * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the\n * canonical Node \"give the host a turn\" — it runs AFTER the current operation and\n * any pending I/O callbacks, so the event loop genuinely regains control before\n * resuming (unlike a microtask, which drains within the current task). `delay(ms)`\n * waits on a real `setTimeout`.\n * - **Abort fidelity is verbatim.** A pending `yield` / `delay` rejects with\n * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite\n * before arming either Node handle, so caller signal method mutation is harmless and the\n * first completion, abort, or setup failure owns settlement and cleanup. It deliberately\n * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason\n * with a Node `AbortError` (`code: 'ABORT_ERR'`).\n * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent\n * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted\n * for contract compliance and ignored — every yield/delay is uniform.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { NodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = new NodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // a setImmediate host-turn\n * }\n * ```\n */\nexport class NodeScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control back to the event loop through `setImmediate` so pending I/O and timers\n\t * can run, then resumes; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#immediate(options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The Node-native immediate boundary; `scheduleHost` owns cancellation lifecycle.\n\t#immediate(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setImmediate(complete)\n\t\t\treturn () => clearImmediate(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { NodeScheduler } from './NodeScheduler.js'\n\n/**\n * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a\n * `setImmediate` host-turn (the canonical Node \"give the event loop a turn\"), `delay(ms)`\n * a real `setTimeout`.\n *\n * @remarks\n * Use it on a server instead of the cross-environment `createScheduler` when a yield must\n * hand the event loop a full turn (after pending I/O) through `setImmediate` rather than a\n * zero-delay timer. Both methods are abort-aware: pass `options.signal` and a\n * pending yield/delay rejects with the signal's exact `reason`; the shared owned-signal\n * lifecycle clears the native handle without invoking caller listener methods.\n * `options.priority` is accepted for contract compliance but a\n * no-op — Node has no priority primitive.\n *\n * @returns A {@link SchedulerInterface} backed by Node's `setImmediate` / `setTimeout`\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { createNodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = createNodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal })\n * }\n * ```\n */\nexport function createNodeScheduler(): SchedulerInterface {\n\treturn new NodeScheduler()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAa,gBAAb,MAAyD;;;;;CAKxD,MAAM,SAA2C;EAChD,OAAO,KAAK,WAAW,SAAS,MAAM;CACvC;;;;;;;;;;CAWA,MAAM,IAAY,SAA2C;EAC5D,QAAA,GAAO,UAAA,UAAA,CAAU,IAAI,SAAS,MAAM;CACrC;CAKA,WAAW,QAAqC;EAC/C,QAAA,GAAO,UAAA,aAAA,EAAc,aAAa;GACjC,MAAM,SAAS,aAAa,QAAQ;GACpC,aAAa,eAAe,MAAM;EACnC,GAAG,MAAM;CACV;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnCA,SAAgB,sBAA0C;CACzD,OAAO,IAAI,cAAc;AAC1B"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/server/NodeScheduler.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\n\n/**\n * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend\n * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.\n * A `priority` hint is accepted and does nothing, because Node has no priority primitive.\n *\n * @remarks\n * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the\n * canonical Node \"give the host a turn\" — it runs after the current operation and\n * any pending I/O callbacks, so the event loop genuinely regains control before\n * resuming (unlike a microtask, which drains within the current task). `delay(ms)`\n * waits on a real `setTimeout`.\n * - **Abort fidelity is verbatim.** A pending `yield` / `delay` rejects with\n * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite\n * before arming either Node handle, so caller signal method mutation is harmless and the\n * first completion, abort, or setup failure owns settlement and cleanup. It deliberately\n * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason\n * with a Node `AbortError` (`code: 'ABORT_ERR'`).\n * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent\n * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted\n * for contract compliance and ignored — every yield/delay is uniform.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { NodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = new NodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // a setImmediate host-turn\n * }\n * ```\n */\nexport class NodeScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control back to the event loop through `setImmediate` so pending I/O and timers\n\t * can run, then resumes; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#immediate(options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The Node-native immediate boundary; `scheduleHost` owns cancellation lifecycle.\n\t#immediate(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setImmediate(complete)\n\t\t\treturn () => clearImmediate(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { NodeScheduler } from './NodeScheduler.js'\n\n/**\n * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a\n * `setImmediate` host-turn (the canonical Node \"give the event loop a turn\"), `delay(ms)`\n * a real `setTimeout`.\n *\n * @remarks\n * Use it on a server instead of the cross-environment `createScheduler` when a yield must\n * hand the event loop a full turn (after pending I/O) through `setImmediate` rather than a\n * zero-delay timer. Both methods are abort-aware: pass `options.signal` and a\n * pending yield/delay rejects with the signal's exact `reason`; the shared owned-signal\n * lifecycle clears the native handle without invoking caller listener methods.\n * `options.priority` is accepted for contract compliance but a\n * no-op — Node has no priority primitive.\n *\n * @returns A {@link SchedulerInterface} backed by Node's `setImmediate` / `setTimeout`\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { createNodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = createNodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal })\n * }\n * ```\n */\nexport function createNodeScheduler(): SchedulerInterface {\n\treturn new NodeScheduler()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,IAAa,gBAAb,MAAyD;;;;;CAKxD,MAAM,SAA2C;EAChD,OAAO,KAAK,WAAW,SAAS,MAAM;CACvC;;;;;;;;;;CAWA,MAAM,IAAY,SAA2C;EAC5D,QAAA,GAAO,UAAA,UAAA,CAAU,IAAI,SAAS,MAAM;CACrC;CAKA,WAAW,QAAqC;EAC/C,QAAA,GAAO,UAAA,aAAA,EAAc,aAAa;GACjC,MAAM,SAAS,aAAa,QAAQ;GACpC,aAAa,eAAe,MAAM;EACnC,GAAG,MAAM;CACV;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrCA,SAAgB,sBAA0C;CACzD,OAAO,IAAI,cAAc;AAC1B"}
@@ -1,5 +1,5 @@
1
- import { SchedulerInterface } from '@orkestrel/workflow';
2
- import { SchedulerOptions } from '@orkestrel/workflow';
1
+ import type { SchedulerInterface } from '@orkestrel/workflow';
2
+ import type { SchedulerOptions } from '@orkestrel/workflow';
3
3
 
4
4
  /**
5
5
  * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a
@@ -33,11 +33,13 @@ import { SchedulerOptions } from '@orkestrel/workflow';
33
33
  export declare function createNodeScheduler(): SchedulerInterface;
34
34
 
35
35
  /**
36
- * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.
36
+ * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend
37
+ * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.
38
+ * A `priority` hint is accepted and does nothing, because Node has no priority primitive.
37
39
  *
38
40
  * @remarks
39
41
  * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the
40
- * canonical Node "give the host a turn" — it runs AFTER the current operation and
42
+ * canonical Node "give the host a turn" — it runs after the current operation and
41
43
  * any pending I/O callbacks, so the event loop genuinely regains control before
42
44
  * resuming (unlike a microtask, which drains within the current task). `delay(ms)`
43
45
  * waits on a real `setTimeout`.
@@ -45,7 +47,7 @@ export declare function createNodeScheduler(): SchedulerInterface;
45
47
  * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite
46
48
  * before arming either Node handle, so caller signal method mutation is harmless and the
47
49
  * first completion, abort, or setup failure owns settlement and cleanup. It deliberately
48
- * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
50
+ * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
49
51
  * with a Node `AbortError` (`code: 'ABORT_ERR'`).
50
52
  * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent
51
53
  * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted
@@ -1,5 +1,5 @@
1
- import { SchedulerInterface } from '@orkestrel/workflow';
2
- import { SchedulerOptions } from '@orkestrel/workflow';
1
+ import type { SchedulerInterface } from '@orkestrel/workflow';
2
+ import type { SchedulerOptions } from '@orkestrel/workflow';
3
3
 
4
4
  /**
5
5
  * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a
@@ -33,11 +33,13 @@ import { SchedulerOptions } from '@orkestrel/workflow';
33
33
  export declare function createNodeScheduler(): SchedulerInterface;
34
34
 
35
35
  /**
36
- * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.
36
+ * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend
37
+ * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.
38
+ * A `priority` hint is accepted and does nothing, because Node has no priority primitive.
37
39
  *
38
40
  * @remarks
39
41
  * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the
40
- * canonical Node "give the host a turn" — it runs AFTER the current operation and
42
+ * canonical Node "give the host a turn" — it runs after the current operation and
41
43
  * any pending I/O callbacks, so the event loop genuinely regains control before
42
44
  * resuming (unlike a microtask, which drains within the current task). `delay(ms)`
43
45
  * waits on a real `setTimeout`.
@@ -45,7 +47,7 @@ export declare function createNodeScheduler(): SchedulerInterface;
45
47
  * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite
46
48
  * before arming either Node handle, so caller signal method mutation is harmless and the
47
49
  * first completion, abort, or setup failure owns settlement and cleanup. It deliberately
48
- * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
50
+ * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
49
51
  * with a Node `AbortError` (`code: 'ABORT_ERR'`).
50
52
  * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent
51
53
  * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted
@@ -1,11 +1,13 @@
1
1
  import { delayHost, scheduleHost } from "../core/index.js";
2
2
  //#region src/server/NodeScheduler.ts
3
3
  /**
4
- * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.
4
+ * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend
5
+ * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.
6
+ * A `priority` hint is accepted and does nothing, because Node has no priority primitive.
5
7
  *
6
8
  * @remarks
7
9
  * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the
8
- * canonical Node "give the host a turn" — it runs AFTER the current operation and
10
+ * canonical Node "give the host a turn" — it runs after the current operation and
9
11
  * any pending I/O callbacks, so the event loop genuinely regains control before
10
12
  * resuming (unlike a microtask, which drains within the current task). `delay(ms)`
11
13
  * waits on a real `setTimeout`.
@@ -13,7 +15,7 @@ import { delayHost, scheduleHost } from "../core/index.js";
13
15
  * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite
14
16
  * before arming either Node handle, so caller signal method mutation is harmless and the
15
17
  * first completion, abort, or setup failure owns settlement and cleanup. It deliberately
16
- * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
18
+ * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason
17
19
  * with a Node `AbortError` (`code: 'ABORT_ERR'`).
18
20
  * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent
19
21
  * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/NodeScheduler.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\n\n/**\n * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend.\n *\n * @remarks\n * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the\n * canonical Node \"give the host a turn\" — it runs AFTER the current operation and\n * any pending I/O callbacks, so the event loop genuinely regains control before\n * resuming (unlike a microtask, which drains within the current task). `delay(ms)`\n * waits on a real `setTimeout`.\n * - **Abort fidelity is verbatim.** A pending `yield` / `delay` rejects with\n * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite\n * before arming either Node handle, so caller signal method mutation is harmless and the\n * first completion, abort, or setup failure owns settlement and cleanup. It deliberately\n * does NOT use `node:timers/promises`, whose `{ signal }` option replaces the caller reason\n * with a Node `AbortError` (`code: 'ABORT_ERR'`).\n * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent\n * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted\n * for contract compliance and ignored — every yield/delay is uniform.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { NodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = new NodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // a setImmediate host-turn\n * }\n * ```\n */\nexport class NodeScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control back to the event loop through `setImmediate` so pending I/O and timers\n\t * can run, then resumes; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#immediate(options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The Node-native immediate boundary; `scheduleHost` owns cancellation lifecycle.\n\t#immediate(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setImmediate(complete)\n\t\t\treturn () => clearImmediate(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { NodeScheduler } from './NodeScheduler.js'\n\n/**\n * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a\n * `setImmediate` host-turn (the canonical Node \"give the event loop a turn\"), `delay(ms)`\n * a real `setTimeout`.\n *\n * @remarks\n * Use it on a server instead of the cross-environment `createScheduler` when a yield must\n * hand the event loop a full turn (after pending I/O) through `setImmediate` rather than a\n * zero-delay timer. Both methods are abort-aware: pass `options.signal` and a\n * pending yield/delay rejects with the signal's exact `reason`; the shared owned-signal\n * lifecycle clears the native handle without invoking caller listener methods.\n * `options.priority` is accepted for contract compliance but a\n * no-op — Node has no priority primitive.\n *\n * @returns A {@link SchedulerInterface} backed by Node's `setImmediate` / `setTimeout`\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { createNodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = createNodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal })\n * }\n * ```\n */\nexport function createNodeScheduler(): SchedulerInterface {\n\treturn new NodeScheduler()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAa,gBAAb,MAAyD;;;;;CAKxD,MAAM,SAA2C;EAChD,OAAO,KAAK,WAAW,SAAS,MAAM;CACvC;;;;;;;;;;CAWA,MAAM,IAAY,SAA2C;EAC5D,OAAO,UAAU,IAAI,SAAS,MAAM;CACrC;CAKA,WAAW,QAAqC;EAC/C,OAAO,cAAc,aAAa;GACjC,MAAM,SAAS,aAAa,QAAQ;GACpC,aAAa,eAAe,MAAM;EACnC,GAAG,MAAM;CACV;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnCA,SAAgB,sBAA0C;CACzD,OAAO,IAAI,cAAc;AAC1B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/NodeScheduler.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\n\n/**\n * Implements the Node {@link SchedulerInterface} — the server-native cooperative-yield backend\n * whose `yield` waits on `setImmediate` and whose abort rejects with the caller's own reason.\n * A `priority` hint is accepted and does nothing, because Node has no priority primitive.\n *\n * @remarks\n * - **`yield` is a `setImmediate` host-turn.** `yield()` waits on `setImmediate`, the\n * canonical Node \"give the host a turn\" — it runs after the current operation and\n * any pending I/O callbacks, so the event loop genuinely regains control before\n * resuming (unlike a microtask, which drains within the current task). `delay(ms)`\n * waits on a real `setTimeout`.\n * - **Abort fidelity is verbatim.** A pending `yield` / `delay` rejects with\n * `signal.reason` exactly. The shared `scheduleHost` lifecycle links an owned composite\n * before arming either Node handle, so caller signal method mutation is harmless and the\n * first completion, abort, or setup failure owns settlement and cleanup. It deliberately\n * does not use `node:timers/promises`, whose `{ signal }` option replaces the caller reason\n * with a Node `AbortError` (`code: 'ABORT_ERR'`).\n * - **Priority is accepted but a no-op.** Node has no priority primitive (no equivalent\n * of the browser's `scheduler.postTask` priorities), so `options.priority` is accepted\n * for contract compliance and ignored — every yield/delay is uniform.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { NodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = new NodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // a setImmediate host-turn\n * }\n * ```\n */\nexport class NodeScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control back to the event loop through `setImmediate` so pending I/O and timers\n\t * can run, then resumes; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#immediate(options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The Node-native immediate boundary; `scheduleHost` owns cancellation lifecycle.\n\t#immediate(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setImmediate(complete)\n\t\t\treturn () => clearImmediate(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { NodeScheduler } from './NodeScheduler.js'\n\n/**\n * Creates the Node-native cooperative-yield {@link SchedulerInterface} — `yield()` is a\n * `setImmediate` host-turn (the canonical Node \"give the event loop a turn\"), `delay(ms)`\n * a real `setTimeout`.\n *\n * @remarks\n * Use it on a server instead of the cross-environment `createScheduler` when a yield must\n * hand the event loop a full turn (after pending I/O) through `setImmediate` rather than a\n * zero-delay timer. Both methods are abort-aware: pass `options.signal` and a\n * pending yield/delay rejects with the signal's exact `reason`; the shared owned-signal\n * lifecycle clears the native handle without invoking caller listener methods.\n * `options.priority` is accepted for contract compliance but a\n * no-op — Node has no priority primitive.\n *\n * @returns A {@link SchedulerInterface} backed by Node's `setImmediate` / `setTimeout`\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { createNodeScheduler } from '@orkestrel/workflow/server'\n *\n * const abort = createAbort()\n * const scheduler = createNodeScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ signal: abort.signal })\n * }\n * ```\n */\nexport function createNodeScheduler(): SchedulerInterface {\n\treturn new NodeScheduler()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,IAAa,gBAAb,MAAyD;;;;;CAKxD,MAAM,SAA2C;EAChD,OAAO,KAAK,WAAW,SAAS,MAAM;CACvC;;;;;;;;;;CAWA,MAAM,IAAY,SAA2C;EAC5D,OAAO,UAAU,IAAI,SAAS,MAAM;CACrC;CAKA,WAAW,QAAqC;EAC/C,OAAO,cAAc,aAAa;GACjC,MAAM,SAAS,aAAa,QAAQ;GACpC,aAAa,eAAe,MAAM;EACnC,GAAG,MAAM;CACV;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrCA,SAAgB,sBAA0C;CACzD,OAAO,IAAI,cAAc;AAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orkestrel/workflow",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "A typed workflow engine for the @orkestrel line — a serializable Workflow → Phase → Task tree run by a composed runner on a cooperative scheduler. Part of the @orkestrel line.",
5
5
  "keywords": [
6
6
  "orchestration",
@@ -61,7 +61,7 @@
61
61
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
62
62
  "copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
63
63
  "scaffold": "scaffold",
64
- "lint": "oxlint --config .oxlintrc.json --fix --deny-warnings .",
64
+ "lint": "oxlint --config .oxlintrc.json --fix .",
65
65
  "check": "tsc --noEmit --project tsconfig.json && npm run check:src",
66
66
  "check:src": "npm run check:src:core && npm run check:src:browser && npm run check:src:server",
67
67
  "check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
@@ -77,7 +77,7 @@
77
77
  "test:src:server": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server",
78
78
  "test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
79
79
  "test:config": "vitest run --config vite.config.ts --no-cache --reporter=dot --project config",
80
- "test:guides": "vitest run --config vite.config.ts --no-cache --reporter=dot --project guides",
80
+ "test:guides": "node --experimental-strip-types tests/guides.test.ts",
81
81
  "build": "npm run clean && npm run build:src",
82
82
  "build:src": "npm run build:src:core && npm run build:src:browser && npm run build:src:server",
83
83
  "build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
@@ -91,28 +91,27 @@
91
91
  "test:setup": "vitest run --config vite.config.ts --no-cache --reporter=dot --project setup"
92
92
  },
93
93
  "dependencies": {
94
- "@orkestrel/abort": "^0.0.9",
95
- "@orkestrel/budget": "^0.0.9",
96
- "@orkestrel/contract": "^0.0.16",
97
- "@orkestrel/database": "^0.0.13",
98
- "@orkestrel/emitter": "^0.0.9",
99
- "@orkestrel/queue": "^0.0.12",
100
- "@orkestrel/timeout": "^0.0.9"
94
+ "@orkestrel/abort": "^0.0.10",
95
+ "@orkestrel/budget": "^0.0.10",
96
+ "@orkestrel/contract": "^0.0.17",
97
+ "@orkestrel/database": "^0.0.14",
98
+ "@orkestrel/emitter": "^0.0.10",
99
+ "@orkestrel/queue": "^0.0.13",
100
+ "@orkestrel/timeout": "^0.0.10"
101
101
  },
102
102
  "devDependencies": {
103
- "@microsoft/api-extractor": "^7.59.0",
104
- "@orkestrel/guide": "^0.0.17",
105
- "@orkestrel/probe": "^0.0.11",
106
- "@orkestrel/scaffold": "^0.0.62",
107
- "@orkestrel/test": "^0.0.13",
108
- "@types/node": "^26.4.1",
103
+ "@microsoft/api-extractor": "^7.59.1",
104
+ "@orkestrel/guide": "^0.0.18",
105
+ "@orkestrel/probe": "^0.0.12",
106
+ "@orkestrel/scaffold": "^0.0.64",
107
+ "@orkestrel/test": "^0.0.14",
108
+ "@types/node": "^26.5.1",
109
109
  "@vitest/browser-playwright": "^4.1.11",
110
- "oxfmt": "^0.66.0",
111
- "oxlint": "^1.81.0",
112
- "playwright": "^1.62.1",
110
+ "oxfmt": "^0.67.0",
111
+ "oxlint": "^1.82.0",
112
+ "playwright": "^1.63.0",
113
113
  "typescript": "^6.0.3",
114
- "vite": "^8.2.2",
115
- "vite-plugin-dts": "^5.1.0",
114
+ "vite": "^8.3.0",
116
115
  "vitest": "^4.1.11"
117
116
  },
118
117
  "engines": {