@zwave-js/waddle 1.2.0 → 1.2.1
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 +5 -0
- package/build/cjs/Task.d.ts +1 -1
- package/build/cjs/Task.js.map +1 -1
- package/build/cjs/index.d.ts +1 -1
- package/build/cjs/index.js.map +2 -2
- package/build/cjs/utils.d.ts +3 -1
- package/build/cjs/utils.js +2 -2
- package/build/cjs/utils.js.map +2 -2
- package/build/esm/Task.d.ts +1 -1
- package/build/esm/Task.d.ts.map +1 -1
- package/build/esm/index.d.ts +1 -1
- package/build/esm/index.d.ts.map +1 -1
- package/build/esm/index.js.map +1 -1
- package/build/esm/utils.d.ts +3 -1
- package/build/esm/utils.d.ts.map +1 -1
- package/build/esm/utils.js +2 -2
- package/build/esm/utils.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -481,6 +481,11 @@ const scheduler = new TaskScheduler(() => new Error("We are all doomed!"));
|
|
|
481
481
|
```
|
|
482
482
|
|
|
483
483
|
## Changelog
|
|
484
|
+
### 1.2.1 (2025-06-24)
|
|
485
|
+
|
|
486
|
+
- Fixed some type issues for composite task definitions
|
|
487
|
+
- The `waitFor` utility function is now compatible with TaskBuilder objects too
|
|
488
|
+
|
|
484
489
|
### 1.2.0 (2025-06-24)
|
|
485
490
|
|
|
486
491
|
- Add utility method `waitFor` for type-safe yielding of Promises
|
package/build/cjs/Task.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface TaskBuilder<TReturn, TaskTag extends {
|
|
|
58
58
|
*
|
|
59
59
|
* Yielded Promises should not spawn new tasks. If they do, the spawned tasks MUST have a higher priority than the parent task.
|
|
60
60
|
*/
|
|
61
|
-
task: () => AsyncGenerator<(() => Promise<
|
|
61
|
+
task: () => AsyncGenerator<(() => Promise<unknown> | TaskBuilder<unknown, TaskTag, unknown>) | (() => TaskBuilder<unknown, TaskTag, unknown>) | TaskBuilder<unknown, TaskTag, unknown> | undefined, TReturn, TInner>;
|
|
62
62
|
/** A cleanup function that gets called when the task is dropped */
|
|
63
63
|
cleanup?: () => Promise<void>;
|
|
64
64
|
}
|
package/build/cjs/Task.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Task.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CompareResult } from \"alcalzone-shared/comparable\";\nimport {\n\ttype DeferredPromise,\n\tcreateDeferredPromise,\n} from \"alcalzone-shared/deferred-promise\";\nimport { SortedList } from \"alcalzone-shared/sorted-list\";\nimport { createWrappingCounter } from \"./wrappingCounter.js\";\nimport { evalOrStatic, highResTimestamp, noop } from \"./utils.js\";\n\n/** A high-level task that can be started and stepped through */\nexport interface Task<\n\tTReturn,\n\tTaskTag extends { id: string } = { id: string },\n\tTError extends Error = Error,\n> {\n\treadonly id: number;\n\treadonly timestamp: number;\n\treadonly builder: TaskBuilder<TReturn, TaskTag>;\n\n\t/** The parent task spawning this subtask, if any */\n\treadonly parent?: Task<unknown, TaskTag, TError>;\n\n\t/** A name to identify the task */\n\treadonly name?: string;\n\t/** A tag to identify the task programmatically */\n\treadonly tag?: TaskTag;\n\t/** The task's priority */\n\treadonly priority: TaskPriority;\n\t/** The concurrency group this task belongs to */\n\treadonly group?: TaskConcurrencyGroup;\n\t/** How the task should behave when interrupted */\n\treadonly interrupt: TaskInterruptBehavior;\n\t/** Starts the task it if hasn't been started yet, and executes the next step of the task */\n\tstep(): Promise<TaskStepResult<TReturn, TaskTag>>;\n\t/** Stops the task without further executing it, cleans up, and prepares it for starting again */\n\treset(): Promise<void>;\n\t/** Resolves the task's promise to notify the caller */\n\tresolve(result: TReturn): void;\n\t/** Rejects the task's promise to notify the caller */\n\treject(error: TError): void;\n\t/** The current state of the task */\n\tget state(): TaskState;\n\n\treadonly generator: ReturnType<TaskBuilder<TReturn>[\"task\"]> | undefined;\n\treadonly promise: Promise<TReturn>;\n}\n\nfunction getTaskName(task: Task<unknown>): string {\n\treturn `${\n\t\ttask.name ?? (task.tag && JSON.stringify(task.tag)) ?? \"unnamed\"\n\t} (ID ${task.id})`;\n}\n\n/** Defines the necessary information for creating a task */\nexport interface TaskBuilder<\n\tTReturn,\n\tTaskTag extends { id: string } = { id: string },\n\tTInner = unknown,\n> {\n\t/** A name to identify the task */\n\tname?: string;\n\t/** A tag to identify the task programmatically */\n\ttag?: TaskTag;\n\t/** The task's priority */\n\tpriority: TaskPriority;\n\t/** How the task should behave when interrupted */\n\tinterrupt?: TaskInterruptBehavior;\n\t/** The concurrency group this task belongs to */\n\tgroup?: TaskConcurrencyGroup;\n\t/**\n\t * The task's main generator function. This is called repeatedly until it's done.\n\t * The function must yield at points where it may be interrupted.\n\t *\n\t * At those points, the task can also wait for something to happen:\n\t * - Either a Promise, in which case it must yield a function that returns that Promise\n\t * - Or another task, in which case it must yield a TaskBuilder object or a function that returns one\n\t *\n\t * Yielded Promises should not spawn new tasks. If they do, the spawned tasks MUST have a higher priority than the parent task.\n\t */\n\ttask: () => AsyncGenerator<\n\t\t| (() => Promise<TInner> | TaskBuilder<TReturn, TaskTag, TInner>)\n\t\t| (() => TaskBuilder<TReturn, TaskTag, TInner>)\n\t\t| TaskBuilder<TReturn, TaskTag, TInner>\n\t\t| undefined,\n\t\tTReturn,\n\t\tTInner\n\t>;\n\t/** A cleanup function that gets called when the task is dropped */\n\tcleanup?: () => Promise<void>;\n}\n\nexport type TaskReturnType<T extends TaskBuilder<unknown>> =\n\tT extends TaskBuilder<infer R> ? R : never;\n\nfunction isTaskBuilder<T>(obj: any): obj is TaskBuilder<T> {\n\treturn (\n\t\ttypeof obj === \"object\" &&\n\t\ttypeof obj.task === \"function\" &&\n\t\ttypeof obj.priority === \"number\"\n\t);\n}\n\n/**\n * The priority of a task.\n *\n * Higher priority tasks are executed first and interrupt lower priority tasks.\n * The recommended priority for application-initiated communication is `Normal`.\n * `Low` and `Lower` are recommended for internal long-running tasks that should not interfere with user-initiated tasks.\n * `Idle` is recommended for tasks that should only run when no other tasks are pending.\n */\nexport enum TaskPriority {\n\tHighest,\n\tHigh = 1,\n\tNormal = 2,\n\tLow = 3,\n\tLower = 4,\n\tIdle = 5,\n}\n\nexport enum TaskState {\n\t/** The task has not been created yet */\n\tNone,\n\t/** The task is being executed */\n\tActive,\n\t/** The task is waiting for a Promise to resolve */\n\tAwaitingPromise,\n\t/** The task is waiting for another task to finish */\n\tAwaitingTask,\n\t/** The task is finished */\n\tDone,\n}\n\nexport enum TaskInterruptBehavior {\n\t/** The task may not be interrupted */\n\tForbidden,\n\t/** The task will be resumed after being interrupted (default) */\n\tResume,\n\t/** The task needs to be restarted after being interrupted */\n\tRestart,\n}\n\nexport type TaskStepResult<\n\tT,\n\tTaskTag extends { id: string } = { id: string },\n> =\n\t| {\n\t\t\tnewState: TaskState.Done;\n\t\t\tresult: T;\n\t }\n\t| {\n\t\t\tnewState: TaskState.Active;\n\t }\n\t| {\n\t\t\tnewState: TaskState.AwaitingPromise;\n\t\t\tpromise: Promise<unknown>;\n\t }\n\t| {\n\t\t\tnewState: TaskState.AwaitingTask;\n\t\t\ttask: Task<unknown, TaskTag>;\n\t };\n\n/** Identifies a concurrency group. Tasks within the same group cannot run concurrently. */\nexport interface TaskConcurrencyGroup {\n\tid: string;\n}\n\nfunction compareTasks<T1, T2>(a: Task<T1>, b: Task<T2>): CompareResult {\n\t// In the same concurrency group, only one task may be active at a time.\n\tconst aConcurrencyGroup = a.group?.id;\n\tconst bConcurrencyGroup = b.group?.id;\n\tif (\n\t\taConcurrencyGroup &&\n\t\tbConcurrencyGroup &&\n\t\taConcurrencyGroup === bConcurrencyGroup\n\t) {\n\t\tconst aActiveOrWaiting =\n\t\t\ta.state === TaskState.Active ||\n\t\t\ta.state === TaskState.AwaitingPromise ||\n\t\t\ta.state === TaskState.AwaitingTask;\n\t\tconst bActiveOrWaiting =\n\t\t\tb.state === TaskState.Active ||\n\t\t\tb.state === TaskState.AwaitingPromise ||\n\t\t\tb.state === TaskState.AwaitingTask;\n\n\t\tif (aActiveOrWaiting && !bActiveOrWaiting) return 1; // A is already active\n\t\tif (!aActiveOrWaiting && bActiveOrWaiting) return -1; // B is already active\n\n\t\t// None of the tasks is active, fall back to default sorting\n\t}\n\n\t// Sort by priority for tasks not in the same concurrency group\n\tif (a.priority < b.priority) return 1;\n\tif (a.priority > b.priority) return -1;\n\n\t// Deprioritize waiting tasks\n\tconst aWaiting =\n\t\ta.state === TaskState.AwaitingPromise ||\n\t\ta.state === TaskState.AwaitingTask;\n\tconst bWaiting =\n\t\tb.state === TaskState.AwaitingPromise ||\n\t\tb.state === TaskState.AwaitingTask;\n\tif (!aWaiting && bWaiting) return 1;\n\tif (aWaiting && !bWaiting) return -1;\n\n\t// Sort equal priority by timestamp. Newer tasks go to the end of the list\n\tif (a.timestamp < b.timestamp) return 1;\n\tif (a.timestamp > b.timestamp) return -1;\n\n\t// If all else fails, sort by ID\n\treturn Math.sign(b.id - a.id) as CompareResult;\n}\n\nexport class TaskScheduler<\n\tTaskTag extends { id: string } = { id: string },\n\tTError extends Error = Error,\n> {\n\tpublic constructor(\n\t\tprivate defaultErrorFactory: () => TError = () =>\n\t\t\tnew Error(\"Task was removed\") as any,\n\t\tprivate verbose: boolean = false,\n\t) {}\n\n\tprivate _tasks = new SortedList<Task<unknown, TaskTag>>(\n\t\tundefined,\n\t\tcompareTasks,\n\t);\n\tprivate _currentTask: Task<unknown, TaskTag> | undefined;\n\n\tprivate _idGenerator = createWrappingCounter(0xff_ff_ff);\n\tprivate _continueSignal: DeferredPromise<void> | undefined;\n\tprivate _stopSignal: DeferredPromise<void> | undefined;\n\tprivate _stopPromise: DeferredPromise<void> | undefined;\n\n\tpublic queueTask<T>(builder: TaskBuilder<T, TaskTag>): Promise<T> {\n\t\tconst task = this.createTask(builder);\n\t\tthis._tasks.add(task);\n\t\tif (this.verbose) {\n\t\t\tconsole.log(`Task queued: ${getTaskName(task)}`);\n\t\t}\n\n\t\tif (this._continueSignal) this._continueSignal.resolve();\n\t\treturn task.promise;\n\t}\n\n\t/** Removes/stops tasks matching the given predicate. Returns `true` when a task was removed, `false` otherwise. */\n\tpublic async removeTasks(\n\t\tpredicate: (task: Task<unknown, TaskTag>) => boolean,\n\t\treason?: TError,\n\t): Promise<boolean> {\n\t\t// Collect tasks that should be removed, but in reverse order,\n\t\t// so that we handle the current task last.\n\t\tconst tasksToRemove: Task<unknown, TaskTag>[] = [];\n\t\tlet removeCurrentTask = false;\n\t\tfor (const task of this._tasks) {\n\t\t\tif (predicate(task)) {\n\t\t\t\tif (task === this._currentTask) {\n\t\t\t\t\tremoveCurrentTask = true;\n\t\t\t\t} else {\n\t\t\t\t\ttasksToRemove.push(task);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treason ??= this.defaultErrorFactory();\n\n\t\tfor (const task of tasksToRemove) {\n\t\t\tif (this.verbose) {\n\t\t\t\tconsole.log(`Removing task: ${getTaskName(task)}`);\n\t\t\t}\n\t\t\tthis._tasks.remove(task);\n\t\t\tif (\n\t\t\t\ttask.state === TaskState.Active ||\n\t\t\t\ttask.state === TaskState.AwaitingPromise ||\n\t\t\t\ttask.state === TaskState.AwaitingTask\n\t\t\t) {\n\t\t\t\t// The task is running, clean it up\n\t\t\t\tawait task.reset().catch(noop);\n\t\t\t}\n\t\t\ttask.reject(reason);\n\t\t\t// Re-add the parent task to the list if there is one\n\t\t\tif (task.parent) {\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Restoring parent task: ${getTaskName(task.parent)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis._tasks.add(task.parent);\n\t\t\t}\n\t\t}\n\n\t\tif (removeCurrentTask && this._currentTask) {\n\t\t\tif (this.verbose) {\n\t\t\t\tconsole.log(`Removing task: ${getTaskName(this._currentTask)}`);\n\t\t\t}\n\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\tawait this._currentTask.reset().catch(noop);\n\t\t\tthis._currentTask.reject(reason);\n\t\t\t// Re-add the parent task to the list if there is one\n\t\t\tif (this._currentTask.parent) {\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Restoring parent task: ${getTaskName(\n\t\t\t\t\t\t\tthis._currentTask.parent,\n\t\t\t\t\t\t)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis._tasks.add(this._currentTask.parent);\n\t\t\t}\n\t\t\tthis._currentTask = undefined;\n\t\t}\n\n\t\tif (this._continueSignal) this._continueSignal.resolve();\n\n\t\treturn tasksToRemove.length > 0 || removeCurrentTask;\n\t}\n\n\tpublic findTask<T = unknown>(\n\t\tpredicate: (task: Task<T, TaskTag>) => boolean,\n\t): Promise<T> | undefined {\n\t\treturn this._tasks.find((t: any) => predicate(t))?.promise as\n\t\t\t| Promise<T>\n\t\t\t| undefined;\n\t}\n\n\t/** Creates a task that can be executed */\n\tprivate createTask<T>(\n\t\tbuilder: TaskBuilder<T, TaskTag>,\n\t\tparent?: Task<unknown, TaskTag>,\n\t): Task<T, TaskTag, TError> {\n\t\tlet state = TaskState.None;\n\t\tlet generator: ReturnType<TaskBuilder<T, TaskTag>[\"task\"]> | undefined;\n\t\tlet waitForPromise: Promise<unknown> | undefined;\n\t\tconst promise = createDeferredPromise<T>();\n\n\t\tlet prevResult: unknown;\n\t\tlet waitError: unknown;\n\n\t\tconst self = this;\n\n\t\treturn {\n\t\t\tid: this._idGenerator(),\n\t\t\ttimestamp: highResTimestamp(),\n\t\t\tbuilder,\n\t\t\tparent,\n\t\t\tname: builder.name,\n\t\t\ttag: builder.tag,\n\t\t\tpriority: builder.priority,\n\t\t\tgroup: builder.group,\n\t\t\tinterrupt: builder.interrupt ?? TaskInterruptBehavior.Resume,\n\t\t\tpromise,\n\t\t\tasync step() {\n\t\t\t\t// Do not proceed while still waiting for a Promise to resolve\n\t\t\t\tif (state === TaskState.AwaitingPromise && waitForPromise) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\tpromise: waitForPromise,\n\t\t\t\t\t};\n\t\t\t\t} else if (state === TaskState.AwaitingTask) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Cannot step through a task that is waiting for another task\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tgenerator ??= builder.task();\n\t\t\t\tstate = TaskState.Active;\n\n\t\t\t\tconst { value, done } = waitError\n\t\t\t\t\t? await generator.throw(waitError)\n\t\t\t\t\t: await generator.next(prevResult);\n\t\t\t\tprevResult = undefined;\n\t\t\t\twaitError = undefined;\n\t\t\t\tif (done) {\n\t\t\t\t\tstate = TaskState.Done;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\tresult: value,\n\t\t\t\t\t};\n\t\t\t\t} else if (value != undefined) {\n\t\t\t\t\tconst waitFor = evalOrStatic(value);\n\t\t\t\t\tif (waitFor instanceof Promise) {\n\t\t\t\t\t\tstate = TaskState.AwaitingPromise;\n\t\t\t\t\t\twaitForPromise = waitFor\n\t\t\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\t\t\tprevResult = result;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\t\twaitError = e;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\t\twaitForPromise = undefined;\n\t\t\t\t\t\t\t\tif (state === TaskState.AwaitingPromise) {\n\t\t\t\t\t\t\t\t\tstate = TaskState.Active;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\t\tpromise: waitForPromise,\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (isTaskBuilder(waitFor)) {\n\t\t\t\t\t\tif (waitFor.priority > builder.priority) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"Tasks cannot yield to tasks with lower priority than their own\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Create a sub-task with a reference to this task\n\t\t\t\t\t\tstate = TaskState.AwaitingTask;\n\t\t\t\t\t\tconst subTask = self.createTask(waitFor, this);\n\n\t\t\t\t\t\tsubTask.promise\n\t\t\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\t\t\tprevResult = result;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\t\twaitError = e;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\t\tif (state === TaskState.AwaitingTask) {\n\t\t\t\t\t\t\t\t\tstate = TaskState.Active;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\t\ttask: subTask,\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error(\"Invalid value yielded by task\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn { newState: state };\n\t\t\t\t}\n\t\t\t},\n\t\t\tasync reset() {\n\t\t\t\tif (state === TaskState.None) return;\n\t\t\t\tstate = TaskState.None;\n\t\t\t\twaitForPromise = undefined;\n\t\t\t\tgenerator = undefined;\n\n\t\t\t\tawait builder.cleanup?.();\n\t\t\t},\n\t\t\tresolve(result) {\n\t\t\t\tpromise.resolve(result);\n\t\t\t},\n\t\t\treject(error) {\n\t\t\t\tpromise.reject(error);\n\t\t\t},\n\t\t\tget state() {\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tget generator() {\n\t\t\t\treturn generator;\n\t\t\t},\n\t\t};\n\t}\n\n\tpublic start(): void {\n\t\tthis._stopSignal = createDeferredPromise();\n\t\tsetImmediate(async () => {\n\t\t\ttry {\n\t\t\t\tawait this.run();\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\"Task runner crashed\", e);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async run(): Promise<void> {\n\t\twhile (true) {\n\t\t\tlet waitFor: Promise<unknown> | undefined;\n\t\t\tif (this._tasks.length > 0) {\n\t\t\t\tconst firstTask = this._tasks.peekStart()!;\n\t\t\t\tif (!this._currentTask) {\n\t\t\t\t\t// We're not currently executing a task, start executing the first one\n\t\t\t\t\tthis._currentTask = firstTask;\n\t\t\t\t} else if (\n\t\t\t\t\tthis._currentTask !== firstTask &&\n\t\t\t\t\tthis._currentTask.interrupt !==\n\t\t\t\t\t\tTaskInterruptBehavior.Forbidden\n\t\t\t\t) {\n\t\t\t\t\t// We are executing an interruptible task, and a new task with a higher priority was added\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis._currentTask.interrupt ===\n\t\t\t\t\t\tTaskInterruptBehavior.Restart\n\t\t\t\t\t) {\n\t\t\t\t\t\t// The current task needs to be restarted after being interrupted, so reset it\n\t\t\t\t\t\tawait this._currentTask.reset();\n\t\t\t\t\t}\n\t\t\t\t\t// switch to the new task\n\t\t\t\t\tthis._currentTask = firstTask;\n\t\t\t\t}\n\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Stepping through task: ${getTaskName(\n\t\t\t\t\t\t\tthis._currentTask,\n\t\t\t\t\t\t)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst cleanupCurrentTask = async () => {\n\t\t\t\t\tif (this._currentTask) {\n\t\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t\tawait this._currentTask.reset();\n\t\t\t\t\t\t// Re-add the parent task to the list if there is one\n\t\t\t\t\t\tif (this._currentTask.parent) {\n\t\t\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\t`Restoring parent task: ${getTaskName(\n\t\t\t\t\t\t\t\t\t\tthis._currentTask.parent,\n\t\t\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._tasks.add(this._currentTask.parent);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._currentTask = undefined;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Execute the current task one step further\n\t\t\t\twaitFor = undefined;\n\t\t\t\tlet stepResult: TaskStepResult<unknown, TaskTag>;\n\t\t\t\ttry {\n\t\t\t\t\tstepResult = await this._currentTask.step();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.error(`- Task threw an error:`, e);\n\t\t\t\t\t}\n\t\t\t\t\t// The task threw an error, expose the result and clean up.\n\t\t\t\t\tthis._currentTask.reject(e as Error);\n\t\t\t\t\tawait cleanupCurrentTask();\n\t\t\t\t\t// Then continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (stepResult.newState === TaskState.Done) {\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task finished`);\n\t\t\t\t\t}\n\t\t\t\t\t// The task is done, clean up\n\t\t\t\t\tthis._currentTask.resolve(stepResult.result);\n\t\t\t\t\tawait cleanupCurrentTask();\n\t\t\t\t\t// Then continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (stepResult.newState === TaskState.AwaitingPromise) {\n\t\t\t\t\t// The task is waiting for something\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task waiting`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the task may be interrupted, check if there are other same-priority tasks that should be executed instead\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis._currentTask.interrupt !==\n\t\t\t\t\t\tTaskInterruptBehavior.Forbidden\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Re-queue the task, so the queue gets reordered\n\t\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t\tthis._tasks.add(this._currentTask);\n\n\t\t\t\t\t\tif (this._tasks.peekStart() !== this._currentTask) {\n\t\t\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\t\t\tconsole.log(`-- Continuing with another task`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// The task is no longer the first in the queue. Switch to the other one\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Otherwise, we got nothing to do right now than to wait\n\t\t\t\t\twaitFor = stepResult.promise;\n\t\t\t\t} else if (stepResult.newState === TaskState.AwaitingTask) {\n\t\t\t\t\t// The task spawned a sub-task. Replace it with the sub-task and continue executing\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task spawned a sub-task`);\n\t\t\t\t\t}\n\t\t\t\t\tthis._tasks.add(stepResult.task);\n\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t// Continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\t// The current task is not done, continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Task queue empty. Wait for either a new task or the stop signal,\n\t\t\t// or the current task to finish waiting\n\t\t\tthis._continueSignal = createDeferredPromise();\n\t\t\tconst nextAction = await Promise.race(\n\t\t\t\t[\n\t\t\t\t\tthis._continueSignal.then(() => \"continue\" as const),\n\t\t\t\t\tthis._stopSignal!.then(() => \"stop\" as const),\n\t\t\t\t\twaitFor?.then(() => \"continue\" as const),\n\t\t\t\t].filter((p) => p !== undefined),\n\t\t\t);\n\t\t\tthis._continueSignal = undefined;\n\t\t\tif (nextAction === \"stop\") break;\n\t\t}\n\t\tthis._stopPromise!.resolve();\n\t}\n\n\tpublic async stop(): Promise<void> {\n\t\tif (!this._stopSignal) return;\n\t\t// Signal to the task runner that it should stop\n\t\tthis._stopPromise = createDeferredPromise();\n\t\tthis._stopSignal.resolve();\n\t\tawait this._stopPromise;\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { CompareResult } from \"alcalzone-shared/comparable\";\nimport {\n\ttype DeferredPromise,\n\tcreateDeferredPromise,\n} from \"alcalzone-shared/deferred-promise\";\nimport { SortedList } from \"alcalzone-shared/sorted-list\";\nimport { createWrappingCounter } from \"./wrappingCounter.js\";\nimport { evalOrStatic, highResTimestamp, noop } from \"./utils.js\";\n\n/** A high-level task that can be started and stepped through */\nexport interface Task<\n\tTReturn,\n\tTaskTag extends { id: string } = { id: string },\n\tTError extends Error = Error,\n> {\n\treadonly id: number;\n\treadonly timestamp: number;\n\treadonly builder: TaskBuilder<TReturn, TaskTag>;\n\n\t/** The parent task spawning this subtask, if any */\n\treadonly parent?: Task<unknown, TaskTag, TError>;\n\n\t/** A name to identify the task */\n\treadonly name?: string;\n\t/** A tag to identify the task programmatically */\n\treadonly tag?: TaskTag;\n\t/** The task's priority */\n\treadonly priority: TaskPriority;\n\t/** The concurrency group this task belongs to */\n\treadonly group?: TaskConcurrencyGroup;\n\t/** How the task should behave when interrupted */\n\treadonly interrupt: TaskInterruptBehavior;\n\t/** Starts the task it if hasn't been started yet, and executes the next step of the task */\n\tstep(): Promise<TaskStepResult<TReturn, TaskTag>>;\n\t/** Stops the task without further executing it, cleans up, and prepares it for starting again */\n\treset(): Promise<void>;\n\t/** Resolves the task's promise to notify the caller */\n\tresolve(result: TReturn): void;\n\t/** Rejects the task's promise to notify the caller */\n\treject(error: TError): void;\n\t/** The current state of the task */\n\tget state(): TaskState;\n\n\treadonly generator: ReturnType<TaskBuilder<TReturn>[\"task\"]> | undefined;\n\treadonly promise: Promise<TReturn>;\n}\n\nfunction getTaskName(task: Task<unknown>): string {\n\treturn `${\n\t\ttask.name ?? (task.tag && JSON.stringify(task.tag)) ?? \"unnamed\"\n\t} (ID ${task.id})`;\n}\n\n/** Defines the necessary information for creating a task */\nexport interface TaskBuilder<\n\tTReturn,\n\tTaskTag extends { id: string } = { id: string },\n\tTInner = unknown,\n> {\n\t/** A name to identify the task */\n\tname?: string;\n\t/** A tag to identify the task programmatically */\n\ttag?: TaskTag;\n\t/** The task's priority */\n\tpriority: TaskPriority;\n\t/** How the task should behave when interrupted */\n\tinterrupt?: TaskInterruptBehavior;\n\t/** The concurrency group this task belongs to */\n\tgroup?: TaskConcurrencyGroup;\n\t/**\n\t * The task's main generator function. This is called repeatedly until it's done.\n\t * The function must yield at points where it may be interrupted.\n\t *\n\t * At those points, the task can also wait for something to happen:\n\t * - Either a Promise, in which case it must yield a function that returns that Promise\n\t * - Or another task, in which case it must yield a TaskBuilder object or a function that returns one\n\t *\n\t * Yielded Promises should not spawn new tasks. If they do, the spawned tasks MUST have a higher priority than the parent task.\n\t */\n\ttask: () => AsyncGenerator<\n\t\t| (() => Promise<unknown> | TaskBuilder<unknown, TaskTag, unknown>)\n\t\t| (() => TaskBuilder<unknown, TaskTag, unknown>)\n\t\t| TaskBuilder<unknown, TaskTag, unknown>\n\t\t| undefined,\n\t\tTReturn,\n\t\tTInner\n\t>;\n\t/** A cleanup function that gets called when the task is dropped */\n\tcleanup?: () => Promise<void>;\n}\n\nexport type TaskReturnType<T extends TaskBuilder<unknown>> =\n\tT extends TaskBuilder<infer R> ? R : never;\n\nfunction isTaskBuilder<T>(obj: any): obj is TaskBuilder<T> {\n\treturn (\n\t\ttypeof obj === \"object\" &&\n\t\ttypeof obj.task === \"function\" &&\n\t\ttypeof obj.priority === \"number\"\n\t);\n}\n\n/**\n * The priority of a task.\n *\n * Higher priority tasks are executed first and interrupt lower priority tasks.\n * The recommended priority for application-initiated communication is `Normal`.\n * `Low` and `Lower` are recommended for internal long-running tasks that should not interfere with user-initiated tasks.\n * `Idle` is recommended for tasks that should only run when no other tasks are pending.\n */\nexport enum TaskPriority {\n\tHighest,\n\tHigh = 1,\n\tNormal = 2,\n\tLow = 3,\n\tLower = 4,\n\tIdle = 5,\n}\n\nexport enum TaskState {\n\t/** The task has not been created yet */\n\tNone,\n\t/** The task is being executed */\n\tActive,\n\t/** The task is waiting for a Promise to resolve */\n\tAwaitingPromise,\n\t/** The task is waiting for another task to finish */\n\tAwaitingTask,\n\t/** The task is finished */\n\tDone,\n}\n\nexport enum TaskInterruptBehavior {\n\t/** The task may not be interrupted */\n\tForbidden,\n\t/** The task will be resumed after being interrupted (default) */\n\tResume,\n\t/** The task needs to be restarted after being interrupted */\n\tRestart,\n}\n\nexport type TaskStepResult<\n\tT,\n\tTaskTag extends { id: string } = { id: string },\n> =\n\t| {\n\t\t\tnewState: TaskState.Done;\n\t\t\tresult: T;\n\t }\n\t| {\n\t\t\tnewState: TaskState.Active;\n\t }\n\t| {\n\t\t\tnewState: TaskState.AwaitingPromise;\n\t\t\tpromise: Promise<unknown>;\n\t }\n\t| {\n\t\t\tnewState: TaskState.AwaitingTask;\n\t\t\ttask: Task<unknown, TaskTag>;\n\t };\n\n/** Identifies a concurrency group. Tasks within the same group cannot run concurrently. */\nexport interface TaskConcurrencyGroup {\n\tid: string;\n}\n\nfunction compareTasks<T1, T2>(a: Task<T1>, b: Task<T2>): CompareResult {\n\t// In the same concurrency group, only one task may be active at a time.\n\tconst aConcurrencyGroup = a.group?.id;\n\tconst bConcurrencyGroup = b.group?.id;\n\tif (\n\t\taConcurrencyGroup &&\n\t\tbConcurrencyGroup &&\n\t\taConcurrencyGroup === bConcurrencyGroup\n\t) {\n\t\tconst aActiveOrWaiting =\n\t\t\ta.state === TaskState.Active ||\n\t\t\ta.state === TaskState.AwaitingPromise ||\n\t\t\ta.state === TaskState.AwaitingTask;\n\t\tconst bActiveOrWaiting =\n\t\t\tb.state === TaskState.Active ||\n\t\t\tb.state === TaskState.AwaitingPromise ||\n\t\t\tb.state === TaskState.AwaitingTask;\n\n\t\tif (aActiveOrWaiting && !bActiveOrWaiting) return 1; // A is already active\n\t\tif (!aActiveOrWaiting && bActiveOrWaiting) return -1; // B is already active\n\n\t\t// None of the tasks is active, fall back to default sorting\n\t}\n\n\t// Sort by priority for tasks not in the same concurrency group\n\tif (a.priority < b.priority) return 1;\n\tif (a.priority > b.priority) return -1;\n\n\t// Deprioritize waiting tasks\n\tconst aWaiting =\n\t\ta.state === TaskState.AwaitingPromise ||\n\t\ta.state === TaskState.AwaitingTask;\n\tconst bWaiting =\n\t\tb.state === TaskState.AwaitingPromise ||\n\t\tb.state === TaskState.AwaitingTask;\n\tif (!aWaiting && bWaiting) return 1;\n\tif (aWaiting && !bWaiting) return -1;\n\n\t// Sort equal priority by timestamp. Newer tasks go to the end of the list\n\tif (a.timestamp < b.timestamp) return 1;\n\tif (a.timestamp > b.timestamp) return -1;\n\n\t// If all else fails, sort by ID\n\treturn Math.sign(b.id - a.id) as CompareResult;\n}\n\nexport class TaskScheduler<\n\tTaskTag extends { id: string } = { id: string },\n\tTError extends Error = Error,\n> {\n\tpublic constructor(\n\t\tprivate defaultErrorFactory: () => TError = () =>\n\t\t\tnew Error(\"Task was removed\") as any,\n\t\tprivate verbose: boolean = false,\n\t) {}\n\n\tprivate _tasks = new SortedList<Task<unknown, TaskTag>>(\n\t\tundefined,\n\t\tcompareTasks,\n\t);\n\tprivate _currentTask: Task<unknown, TaskTag> | undefined;\n\n\tprivate _idGenerator = createWrappingCounter(0xff_ff_ff);\n\tprivate _continueSignal: DeferredPromise<void> | undefined;\n\tprivate _stopSignal: DeferredPromise<void> | undefined;\n\tprivate _stopPromise: DeferredPromise<void> | undefined;\n\n\tpublic queueTask<T>(builder: TaskBuilder<T, TaskTag>): Promise<T> {\n\t\tconst task = this.createTask(builder);\n\t\tthis._tasks.add(task);\n\t\tif (this.verbose) {\n\t\t\tconsole.log(`Task queued: ${getTaskName(task)}`);\n\t\t}\n\n\t\tif (this._continueSignal) this._continueSignal.resolve();\n\t\treturn task.promise;\n\t}\n\n\t/** Removes/stops tasks matching the given predicate. Returns `true` when a task was removed, `false` otherwise. */\n\tpublic async removeTasks(\n\t\tpredicate: (task: Task<unknown, TaskTag>) => boolean,\n\t\treason?: TError,\n\t): Promise<boolean> {\n\t\t// Collect tasks that should be removed, but in reverse order,\n\t\t// so that we handle the current task last.\n\t\tconst tasksToRemove: Task<unknown, TaskTag>[] = [];\n\t\tlet removeCurrentTask = false;\n\t\tfor (const task of this._tasks) {\n\t\t\tif (predicate(task)) {\n\t\t\t\tif (task === this._currentTask) {\n\t\t\t\t\tremoveCurrentTask = true;\n\t\t\t\t} else {\n\t\t\t\t\ttasksToRemove.push(task);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treason ??= this.defaultErrorFactory();\n\n\t\tfor (const task of tasksToRemove) {\n\t\t\tif (this.verbose) {\n\t\t\t\tconsole.log(`Removing task: ${getTaskName(task)}`);\n\t\t\t}\n\t\t\tthis._tasks.remove(task);\n\t\t\tif (\n\t\t\t\ttask.state === TaskState.Active ||\n\t\t\t\ttask.state === TaskState.AwaitingPromise ||\n\t\t\t\ttask.state === TaskState.AwaitingTask\n\t\t\t) {\n\t\t\t\t// The task is running, clean it up\n\t\t\t\tawait task.reset().catch(noop);\n\t\t\t}\n\t\t\ttask.reject(reason);\n\t\t\t// Re-add the parent task to the list if there is one\n\t\t\tif (task.parent) {\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Restoring parent task: ${getTaskName(task.parent)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis._tasks.add(task.parent);\n\t\t\t}\n\t\t}\n\n\t\tif (removeCurrentTask && this._currentTask) {\n\t\t\tif (this.verbose) {\n\t\t\t\tconsole.log(`Removing task: ${getTaskName(this._currentTask)}`);\n\t\t\t}\n\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\tawait this._currentTask.reset().catch(noop);\n\t\t\tthis._currentTask.reject(reason);\n\t\t\t// Re-add the parent task to the list if there is one\n\t\t\tif (this._currentTask.parent) {\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Restoring parent task: ${getTaskName(\n\t\t\t\t\t\t\tthis._currentTask.parent,\n\t\t\t\t\t\t)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis._tasks.add(this._currentTask.parent);\n\t\t\t}\n\t\t\tthis._currentTask = undefined;\n\t\t}\n\n\t\tif (this._continueSignal) this._continueSignal.resolve();\n\n\t\treturn tasksToRemove.length > 0 || removeCurrentTask;\n\t}\n\n\tpublic findTask<T = unknown>(\n\t\tpredicate: (task: Task<T, TaskTag>) => boolean,\n\t): Promise<T> | undefined {\n\t\treturn this._tasks.find((t: any) => predicate(t))?.promise as\n\t\t\t| Promise<T>\n\t\t\t| undefined;\n\t}\n\n\t/** Creates a task that can be executed */\n\tprivate createTask<T>(\n\t\tbuilder: TaskBuilder<T, TaskTag>,\n\t\tparent?: Task<unknown, TaskTag>,\n\t): Task<T, TaskTag, TError> {\n\t\tlet state = TaskState.None;\n\t\tlet generator: ReturnType<TaskBuilder<T, TaskTag>[\"task\"]> | undefined;\n\t\tlet waitForPromise: Promise<unknown> | undefined;\n\t\tconst promise = createDeferredPromise<T>();\n\n\t\tlet prevResult: unknown;\n\t\tlet waitError: unknown;\n\n\t\tconst self = this;\n\n\t\treturn {\n\t\t\tid: this._idGenerator(),\n\t\t\ttimestamp: highResTimestamp(),\n\t\t\tbuilder,\n\t\t\tparent,\n\t\t\tname: builder.name,\n\t\t\ttag: builder.tag,\n\t\t\tpriority: builder.priority,\n\t\t\tgroup: builder.group,\n\t\t\tinterrupt: builder.interrupt ?? TaskInterruptBehavior.Resume,\n\t\t\tpromise,\n\t\t\tasync step() {\n\t\t\t\t// Do not proceed while still waiting for a Promise to resolve\n\t\t\t\tif (state === TaskState.AwaitingPromise && waitForPromise) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\tpromise: waitForPromise,\n\t\t\t\t\t};\n\t\t\t\t} else if (state === TaskState.AwaitingTask) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Cannot step through a task that is waiting for another task\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tgenerator ??= builder.task();\n\t\t\t\tstate = TaskState.Active;\n\n\t\t\t\tconst { value, done } = waitError\n\t\t\t\t\t? await generator.throw(waitError)\n\t\t\t\t\t: await generator.next(prevResult);\n\t\t\t\tprevResult = undefined;\n\t\t\t\twaitError = undefined;\n\t\t\t\tif (done) {\n\t\t\t\t\tstate = TaskState.Done;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\tresult: value,\n\t\t\t\t\t};\n\t\t\t\t} else if (value != undefined) {\n\t\t\t\t\tconst waitFor = evalOrStatic(value);\n\t\t\t\t\tif (waitFor instanceof Promise) {\n\t\t\t\t\t\tstate = TaskState.AwaitingPromise;\n\t\t\t\t\t\twaitForPromise = waitFor\n\t\t\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\t\t\tprevResult = result;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\t\twaitError = e;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\t\twaitForPromise = undefined;\n\t\t\t\t\t\t\t\tif (state === TaskState.AwaitingPromise) {\n\t\t\t\t\t\t\t\t\tstate = TaskState.Active;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\t\tpromise: waitForPromise,\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (isTaskBuilder(waitFor)) {\n\t\t\t\t\t\tif (waitFor.priority > builder.priority) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"Tasks cannot yield to tasks with lower priority than their own\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Create a sub-task with a reference to this task\n\t\t\t\t\t\tstate = TaskState.AwaitingTask;\n\t\t\t\t\t\tconst subTask = self.createTask(waitFor, this);\n\n\t\t\t\t\t\tsubTask.promise\n\t\t\t\t\t\t\t.then((result) => {\n\t\t\t\t\t\t\t\tprevResult = result;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch((e) => {\n\t\t\t\t\t\t\t\twaitError = e;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\t\t\tif (state === TaskState.AwaitingTask) {\n\t\t\t\t\t\t\t\t\tstate = TaskState.Active;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tnewState: state,\n\t\t\t\t\t\t\ttask: subTask,\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error(\"Invalid value yielded by task\");\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn { newState: state };\n\t\t\t\t}\n\t\t\t},\n\t\t\tasync reset() {\n\t\t\t\tif (state === TaskState.None) return;\n\t\t\t\tstate = TaskState.None;\n\t\t\t\twaitForPromise = undefined;\n\t\t\t\tgenerator = undefined;\n\n\t\t\t\tawait builder.cleanup?.();\n\t\t\t},\n\t\t\tresolve(result) {\n\t\t\t\tpromise.resolve(result);\n\t\t\t},\n\t\t\treject(error) {\n\t\t\t\tpromise.reject(error);\n\t\t\t},\n\t\t\tget state() {\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tget generator() {\n\t\t\t\treturn generator;\n\t\t\t},\n\t\t};\n\t}\n\n\tpublic start(): void {\n\t\tthis._stopSignal = createDeferredPromise();\n\t\tsetImmediate(async () => {\n\t\t\ttry {\n\t\t\t\tawait this.run();\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\"Task runner crashed\", e);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async run(): Promise<void> {\n\t\twhile (true) {\n\t\t\tlet waitFor: Promise<unknown> | undefined;\n\t\t\tif (this._tasks.length > 0) {\n\t\t\t\tconst firstTask = this._tasks.peekStart()!;\n\t\t\t\tif (!this._currentTask) {\n\t\t\t\t\t// We're not currently executing a task, start executing the first one\n\t\t\t\t\tthis._currentTask = firstTask;\n\t\t\t\t} else if (\n\t\t\t\t\tthis._currentTask !== firstTask &&\n\t\t\t\t\tthis._currentTask.interrupt !==\n\t\t\t\t\t\tTaskInterruptBehavior.Forbidden\n\t\t\t\t) {\n\t\t\t\t\t// We are executing an interruptible task, and a new task with a higher priority was added\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis._currentTask.interrupt ===\n\t\t\t\t\t\tTaskInterruptBehavior.Restart\n\t\t\t\t\t) {\n\t\t\t\t\t\t// The current task needs to be restarted after being interrupted, so reset it\n\t\t\t\t\t\tawait this._currentTask.reset();\n\t\t\t\t\t}\n\t\t\t\t\t// switch to the new task\n\t\t\t\t\tthis._currentTask = firstTask;\n\t\t\t\t}\n\n\t\t\t\tif (this.verbose) {\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t`Stepping through task: ${getTaskName(\n\t\t\t\t\t\t\tthis._currentTask,\n\t\t\t\t\t\t)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst cleanupCurrentTask = async () => {\n\t\t\t\t\tif (this._currentTask) {\n\t\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t\tawait this._currentTask.reset();\n\t\t\t\t\t\t// Re-add the parent task to the list if there is one\n\t\t\t\t\t\tif (this._currentTask.parent) {\n\t\t\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t\t\t\t`Restoring parent task: ${getTaskName(\n\t\t\t\t\t\t\t\t\t\tthis._currentTask.parent,\n\t\t\t\t\t\t\t\t\t)}`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._tasks.add(this._currentTask.parent);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._currentTask = undefined;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Execute the current task one step further\n\t\t\t\twaitFor = undefined;\n\t\t\t\tlet stepResult: TaskStepResult<unknown, TaskTag>;\n\t\t\t\ttry {\n\t\t\t\t\tstepResult = await this._currentTask.step();\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.error(`- Task threw an error:`, e);\n\t\t\t\t\t}\n\t\t\t\t\t// The task threw an error, expose the result and clean up.\n\t\t\t\t\tthis._currentTask.reject(e as Error);\n\t\t\t\t\tawait cleanupCurrentTask();\n\t\t\t\t\t// Then continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (stepResult.newState === TaskState.Done) {\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task finished`);\n\t\t\t\t\t}\n\t\t\t\t\t// The task is done, clean up\n\t\t\t\t\tthis._currentTask.resolve(stepResult.result);\n\t\t\t\t\tawait cleanupCurrentTask();\n\t\t\t\t\t// Then continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (stepResult.newState === TaskState.AwaitingPromise) {\n\t\t\t\t\t// The task is waiting for something\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task waiting`);\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the task may be interrupted, check if there are other same-priority tasks that should be executed instead\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis._currentTask.interrupt !==\n\t\t\t\t\t\tTaskInterruptBehavior.Forbidden\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Re-queue the task, so the queue gets reordered\n\t\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t\tthis._tasks.add(this._currentTask);\n\n\t\t\t\t\t\tif (this._tasks.peekStart() !== this._currentTask) {\n\t\t\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\t\t\tconsole.log(`-- Continuing with another task`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// The task is no longer the first in the queue. Switch to the other one\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Otherwise, we got nothing to do right now than to wait\n\t\t\t\t\twaitFor = stepResult.promise;\n\t\t\t\t} else if (stepResult.newState === TaskState.AwaitingTask) {\n\t\t\t\t\t// The task spawned a sub-task. Replace it with the sub-task and continue executing\n\t\t\t\t\tif (this.verbose) {\n\t\t\t\t\t\tconsole.log(`- Task spawned a sub-task`);\n\t\t\t\t\t}\n\t\t\t\t\tthis._tasks.add(stepResult.task);\n\t\t\t\t\tthis._tasks.remove(this._currentTask);\n\t\t\t\t\t// Continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\t// The current task is not done, continue with the next iteration\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Task queue empty. Wait for either a new task or the stop signal,\n\t\t\t// or the current task to finish waiting\n\t\t\tthis._continueSignal = createDeferredPromise();\n\t\t\tconst nextAction = await Promise.race(\n\t\t\t\t[\n\t\t\t\t\tthis._continueSignal.then(() => \"continue\" as const),\n\t\t\t\t\tthis._stopSignal!.then(() => \"stop\" as const),\n\t\t\t\t\twaitFor?.then(() => \"continue\" as const),\n\t\t\t\t].filter((p) => p !== undefined),\n\t\t\t);\n\t\t\tthis._continueSignal = undefined;\n\t\t\tif (nextAction === \"stop\") break;\n\t\t}\n\t\tthis._stopPromise!.resolve();\n\t}\n\n\tpublic async stop(): Promise<void> {\n\t\tif (!this._stopSignal) return;\n\t\t// Signal to the task runner that it should stop\n\t\tthis._stopPromise = createDeferredPromise();\n\t\tthis._stopSignal.resolve();\n\t\tawait this._stopPromise;\n\t}\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["TaskPriority", "TaskState", "TaskInterruptBehavior"]
|
|
7
7
|
}
|
package/build/cjs/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { type Task, type TaskBuilder, TaskInterruptBehavior, TaskPriority, type TaskReturnType, TaskScheduler, TaskState, type TaskStepResult, type TaskConcurrencyGroup, } from "./Task.js";
|
|
2
|
-
export { waitFor } from "./utils.js";
|
|
2
|
+
export { waitFor, type WaitForReturnType } from "./utils.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export {\n\ttype Task,\n\ttype TaskBuilder,\n\tTaskInterruptBehavior,\n\tTaskPriority,\n\ttype TaskReturnType,\n\tTaskScheduler,\n\tTaskState,\n\ttype TaskStepResult,\n\ttype TaskConcurrencyGroup,\n} from \"./Task.js\";\nexport { waitFor } from \"./utils.js\";\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;AAAA,kBAUO;AACP,
|
|
4
|
+
"sourcesContent": ["export {\n\ttype Task,\n\ttype TaskBuilder,\n\tTaskInterruptBehavior,\n\tTaskPriority,\n\ttype TaskReturnType,\n\tTaskScheduler,\n\tTaskState,\n\ttype TaskStepResult,\n\ttype TaskConcurrencyGroup,\n} from \"./Task.js\";\nexport { waitFor, type WaitForReturnType } from \"./utils.js\";\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;AAAA,kBAUO;AACP,mBAAgD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/cjs/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TaskBuilder } from "./Task.js";
|
|
1
2
|
/** Returns a timestamp with nano-second precision */
|
|
2
3
|
export declare function highResTimestamp(): number;
|
|
3
4
|
/** Does nothing. Can be used for empty `.catch(...)` calls. */
|
|
@@ -5,5 +6,6 @@ export declare function noop(): void;
|
|
|
5
6
|
export type FnOrStatic<TArgs extends any[], TReturn> = ((...args: TArgs) => TReturn) | TReturn;
|
|
6
7
|
export type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
7
8
|
export declare function evalOrStatic<T>(fnOrConst: T, ...args: any[]): ReturnTypeOrStatic<T>;
|
|
8
|
-
export
|
|
9
|
+
export type WaitForReturnType<T> = T extends Promise<infer U> ? U : T extends TaskBuilder<infer U> ? U : never;
|
|
10
|
+
export declare function waitFor<T extends Promise<unknown> | TaskBuilder<unknown>>(thing: T): AsyncGenerator<() => T, WaitForReturnType<T>>;
|
|
9
11
|
//# sourceMappingURL=utils.d.ts.map
|
package/build/cjs/utils.js
CHANGED
|
@@ -43,8 +43,8 @@ function evalOrStatic(fnOrConst, ...args) {
|
|
|
43
43
|
return typeof fnOrConst === "function" ? fnOrConst(...args) : fnOrConst;
|
|
44
44
|
}
|
|
45
45
|
__name(evalOrStatic, "evalOrStatic");
|
|
46
|
-
async function* waitFor(
|
|
47
|
-
const result = yield () =>
|
|
46
|
+
async function* waitFor(thing) {
|
|
47
|
+
const result = yield () => thing;
|
|
48
48
|
return result;
|
|
49
49
|
}
|
|
50
50
|
__name(waitFor, "waitFor");
|
package/build/cjs/utils.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils.ts"],
|
|
4
|
-
"sourcesContent": ["/** Returns a timestamp with nano-second precision */\nexport function highResTimestamp(): number {\n\tif (typeof process !== \"undefined\") {\n\t\tconst [s, ns] = process.hrtime();\n\t\treturn s * 1e9 + ns;\n\t} else if (performance != undefined) {\n\t\treturn performance.now() * 1e6;\n\t} else {\n\t\tthrow new Error(\"No high-resolution timer available\");\n\t}\n}\n\n/** Does nothing. Can be used for empty `.catch(...)` calls. */\nexport function noop(): void {\n\t// intentionally empty\n}\n\nexport type FnOrStatic<TArgs extends any[], TReturn> =\n\t| ((...args: TArgs) => TReturn)\n\t| TReturn;\n\nexport type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R\n\t? R\n\t: T;\n\nexport function evalOrStatic<T>(\n\tfnOrConst: T,\n\t...args: any[]\n): ReturnTypeOrStatic<T> {\n\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337\n\treturn typeof fnOrConst === \"function\" ? fnOrConst(...args) : fnOrConst;\n}\n\nexport async function* waitFor
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;
|
|
4
|
+
"sourcesContent": ["import { type TaskBuilder } from \"./Task.js\";\n\n/** Returns a timestamp with nano-second precision */\nexport function highResTimestamp(): number {\n\tif (typeof process !== \"undefined\") {\n\t\tconst [s, ns] = process.hrtime();\n\t\treturn s * 1e9 + ns;\n\t} else if (performance != undefined) {\n\t\treturn performance.now() * 1e6;\n\t} else {\n\t\tthrow new Error(\"No high-resolution timer available\");\n\t}\n}\n\n/** Does nothing. Can be used for empty `.catch(...)` calls. */\nexport function noop(): void {\n\t// intentionally empty\n}\n\nexport type FnOrStatic<TArgs extends any[], TReturn> =\n\t| ((...args: TArgs) => TReturn)\n\t| TReturn;\n\nexport type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R\n\t? R\n\t: T;\n\nexport function evalOrStatic<T>(\n\tfnOrConst: T,\n\t...args: any[]\n): ReturnTypeOrStatic<T> {\n\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337\n\treturn typeof fnOrConst === \"function\" ? fnOrConst(...args) : fnOrConst;\n}\n\nexport type WaitForReturnType<T> =\n\tT extends Promise<infer U> ? U : T extends TaskBuilder<infer U> ? U : never;\n\nexport async function* waitFor<\n\tT extends Promise<unknown> | TaskBuilder<unknown>,\n>(thing: T): AsyncGenerator<() => T, WaitForReturnType<T>> {\n\tconst result = yield () => thing;\n\treturn result;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAEA;;;;;;;;AACM,SAAU,mBAAgB;AAC/B,MAAI,OAAO,YAAY,aAAa;AACnC,UAAM,CAAC,GAAG,EAAE,IAAI,QAAQ,OAAM;AAC9B,WAAO,IAAI,MAAM;EAClB,WAAW,eAAe,QAAW;AACpC,WAAO,YAAY,IAAG,IAAK;EAC5B,OAAO;AACN,UAAM,IAAI,MAAM,oCAAoC;EACrD;AACD;AATgB;AAYV,SAAU,OAAI;AAEpB;AAFgB;AAYV,SAAU,aACf,cACG,MAAW;AAGd,SAAO,OAAO,cAAc,aAAa,UAAU,GAAG,IAAI,IAAI;AAC/D;AANgB;AAWhB,gBAAuB,QAErB,OAAQ;AACT,QAAM,SAAS,MAAM,MAAM;AAC3B,SAAO;AACR;AALuB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/esm/Task.d.ts
CHANGED
|
@@ -58,7 +58,7 @@ export interface TaskBuilder<TReturn, TaskTag extends {
|
|
|
58
58
|
*
|
|
59
59
|
* Yielded Promises should not spawn new tasks. If they do, the spawned tasks MUST have a higher priority than the parent task.
|
|
60
60
|
*/
|
|
61
|
-
task: () => AsyncGenerator<(() => Promise<
|
|
61
|
+
task: () => AsyncGenerator<(() => Promise<unknown> | TaskBuilder<unknown, TaskTag, unknown>) | (() => TaskBuilder<unknown, TaskTag, unknown>) | TaskBuilder<unknown, TaskTag, unknown> | undefined, TReturn, TInner>;
|
|
62
62
|
/** A cleanup function that gets called when the task is dropped */
|
|
63
63
|
cleanup?: () => Promise<void>;
|
|
64
64
|
}
|
package/build/esm/Task.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"AASA,gEAAgE;AAChE,MAAM,WAAW,IAAI,CACpB,OAAO,EACP,OAAO,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAC/C,MAAM,SAAS,KAAK,GAAG,KAAK;IAE5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEhD,oDAAoD;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEjD,kCAAkC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IACtC,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,qBAAqB,CAAC;IAC1C,4FAA4F;IAC5F,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,iGAAiG;IACjG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,uDAAuD;IACvD,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,sDAAsD;IACtD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oCAAoC;IACpC,IAAI,KAAK,IAAI,SAAS,CAAC;IAEvB,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC;AAQD,4DAA4D;AAC5D,MAAM,WAAW,WAAW,CAC3B,OAAO,EACP,OAAO,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAC/C,MAAM,GAAG,OAAO;IAEhB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,0BAA0B;IAC1B,QAAQ,EAAE,YAAY,CAAC;IACvB,kDAAkD;IAClD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,iDAAiD;IACjD,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,cAAc,CACvB,CAAC,MAAM,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../src/Task.ts"],"names":[],"mappings":"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"}
|
package/build/esm/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { type Task, type TaskBuilder, TaskInterruptBehavior, TaskPriority, type TaskReturnType, TaskScheduler, TaskState, type TaskStepResult, type TaskConcurrencyGroup, } from "./Task.js";
|
|
2
|
-
export { waitFor } from "./utils.js";
|
|
2
|
+
export { waitFor, type WaitForReturnType } from "./utils.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/build/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,qBAAqB,EACrB,YAAY,EACZ,KAAK,cAAc,EACnB,aAAa,EACb,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,oBAAoB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,qBAAqB,EACrB,YAAY,EACZ,KAAK,cAAc,EACnB,aAAa,EACb,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,oBAAoB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,qBAAqB,EACrB,YAAY,EAEZ,aAAa,EACb,SAAS,GAGT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,qBAAqB,EACrB,YAAY,EAEZ,aAAa,EACb,SAAS,GAGT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAA0B,MAAM,YAAY,CAAC"}
|
package/build/esm/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TaskBuilder } from "./Task.js";
|
|
1
2
|
/** Returns a timestamp with nano-second precision */
|
|
2
3
|
export declare function highResTimestamp(): number;
|
|
3
4
|
/** Does nothing. Can be used for empty `.catch(...)` calls. */
|
|
@@ -5,5 +6,6 @@ export declare function noop(): void;
|
|
|
5
6
|
export type FnOrStatic<TArgs extends any[], TReturn> = ((...args: TArgs) => TReturn) | TReturn;
|
|
6
7
|
export type ReturnTypeOrStatic<T> = T extends (...args: any[]) => infer R ? R : T;
|
|
7
8
|
export declare function evalOrStatic<T>(fnOrConst: T, ...args: any[]): ReturnTypeOrStatic<T>;
|
|
8
|
-
export
|
|
9
|
+
export type WaitForReturnType<T> = T extends Promise<infer U> ? U : T extends TaskBuilder<infer U> ? U : never;
|
|
10
|
+
export declare function waitFor<T extends Promise<unknown> | TaskBuilder<unknown>>(thing: T): AsyncGenerator<() => T, WaitForReturnType<T>>;
|
|
9
11
|
//# sourceMappingURL=utils.d.ts.map
|
package/build/esm/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,wBAAgB,gBAAgB,IAAI,MAAM,CASzC;AAED,+DAA+D;AAC/D,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,IAChD,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,GAC7B,OAAO,CAAC;AAEX,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GACtE,CAAC,GACD,CAAC,CAAC;AAEL,wBAAgB,YAAY,CAAC,CAAC,EAC7B,SAAS,EAAE,CAAC,EACZ,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,kBAAkB,CAAC,CAAC,CAAC,CAGvB;AAED,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,qDAAqD;AACrD,wBAAgB,gBAAgB,IAAI,MAAM,CASzC;AAED,+DAA+D;AAC/D,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAED,MAAM,MAAM,UAAU,CAAC,KAAK,SAAS,GAAG,EAAE,EAAE,OAAO,IAChD,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,GAC7B,OAAO,CAAC;AAEX,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GACtE,CAAC,GACD,CAAC,CAAC;AAEL,wBAAgB,YAAY,CAAC,CAAC,EAC7B,SAAS,EAAE,CAAC,EACZ,GAAG,IAAI,EAAE,GAAG,EAAE,GACZ,kBAAkB,CAAC,CAAC,CAAC,CAGvB;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAC9B,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE7E,wBAAuB,OAAO,CAC7B,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,EAChD,KAAK,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAGzD"}
|
package/build/esm/utils.js
CHANGED
|
@@ -19,8 +19,8 @@ export function evalOrStatic(fnOrConst, ...args) {
|
|
|
19
19
|
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/61337
|
|
20
20
|
return typeof fnOrConst === "function" ? fnOrConst(...args) : fnOrConst;
|
|
21
21
|
}
|
|
22
|
-
export async function* waitFor(
|
|
23
|
-
const result = yield () =>
|
|
22
|
+
export async function* waitFor(thing) {
|
|
23
|
+
const result = yield () => thing;
|
|
24
24
|
return result;
|
|
25
25
|
}
|
|
26
26
|
//# sourceMappingURL=utils.js.map
|
package/build/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,qDAAqD;AACrD,MAAM,UAAU,gBAAgB;IAC/B,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;IACrB,CAAC;SAAM,IAAI,WAAW,IAAI,SAAS,EAAE,CAAC;QACrC,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC;IAChC,CAAC;SAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACvD,CAAC;AACF,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,IAAI;IACnB,sBAAsB;AACvB,CAAC;AAUD,MAAM,UAAU,YAAY,CAC3B,SAAY,EACZ,GAAG,IAAW;IAEd,wEAAwE;IACxE,OAAO,OAAO,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC;AAKD,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,CAE5B,KAAQ;IACT,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC;IACjC,OAAO,MAAM,CAAC;AACf,CAAC"}
|