@vielzeug/familiar 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -11
- package/dist/_dev.cjs +2 -0
- package/dist/_dev.cjs.map +1 -0
- package/dist/_dev.js +6 -0
- package/dist/_dev.js.map +1 -0
- package/dist/_pool-core.cjs +1 -1
- package/dist/_pool-core.cjs.map +1 -1
- package/dist/_pool-core.d.ts +7 -6
- package/dist/_pool-core.d.ts.map +1 -1
- package/dist/_pool-core.js +80 -67
- package/dist/_pool-core.js.map +1 -1
- package/dist/_pool.cjs +1 -1
- package/dist/_pool.cjs.map +1 -1
- package/dist/_pool.d.ts +8 -5
- package/dist/_pool.d.ts.map +1 -1
- package/dist/_pool.js +116 -109
- package/dist/_pool.js.map +1 -1
- package/dist/_queue.cjs +1 -1
- package/dist/_queue.cjs.map +1 -1
- package/dist/_queue.d.ts +1 -1
- package/dist/_queue.d.ts.map +1 -1
- package/dist/_queue.js +10 -7
- package/dist/_queue.js.map +1 -1
- package/dist/_stream-pool.cjs +1 -1
- package/dist/_stream-pool.cjs.map +1 -1
- package/dist/_stream-pool.d.ts +3 -4
- package/dist/_stream-pool.d.ts.map +1 -1
- package/dist/_stream-pool.js +81 -61
- package/dist/_stream-pool.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +8 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +16 -6
- package/dist/errors.js.map +1 -1
- package/dist/familiar.cjs +1 -1
- package/dist/familiar.cjs.map +1 -1
- package/dist/familiar.iife.js +1 -1
- package/dist/familiar.iife.js.map +1 -1
- package/dist/familiar.js +1 -1
- package/dist/familiar.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/protocol.cjs +1 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +16 -5
- package/dist/protocol.js.map +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/testing.cjs +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.d.ts +3 -3
- package/dist/testing/testing.d.ts.map +1 -1
- package/dist/testing/testing.js +25 -24
- package/dist/testing/testing.js.map +1 -1
- package/dist/types.d.ts +2 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.ts +5 -4
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +49 -38
- package/dist/worker.js.map +1 -1
- package/package.json +10 -8
package/dist/_stream-pool.js
CHANGED
|
@@ -1,98 +1,118 @@
|
|
|
1
|
-
import { FamiliarQueueFullError as e,
|
|
2
|
-
import { createPoolCore as
|
|
3
|
-
import { abortError as
|
|
1
|
+
import { FamiliarQueueFullError as e, FamiliarRuntimeError as t, FamiliarTerminatedError as n } from "./errors.js";
|
|
2
|
+
import { createPoolCore as r, validatePriority as i, validateTimeout as a } from "./_pool-core.js";
|
|
3
|
+
import { abortError as o } from "@vielzeug/arsenal";
|
|
4
4
|
//#region src/_stream-pool.ts
|
|
5
|
-
function
|
|
6
|
-
let
|
|
7
|
-
isIdle: () =>
|
|
5
|
+
function s(s, c) {
|
|
6
|
+
let l = [...s], u = [], d = 0, f = r({
|
|
7
|
+
isIdle: () => l.length === s.length && u.length === 0,
|
|
8
8
|
onDispose() {
|
|
9
|
-
for (let e of
|
|
10
|
-
for (let e of
|
|
9
|
+
for (let e of s) e.terminate();
|
|
10
|
+
for (let e of u.splice(0)) e.reject(new n());
|
|
11
11
|
},
|
|
12
12
|
onDrainStart() {
|
|
13
|
-
for (let e of
|
|
13
|
+
for (let e of u.splice(0)) e.reject(new n("Worker is draining"));
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
-
function
|
|
17
|
-
let t =
|
|
18
|
-
t ? (t.resolve(e),
|
|
16
|
+
function p(e) {
|
|
17
|
+
let t = u.shift();
|
|
18
|
+
t ? (t.resolve(e), f.releaseCapacity()) : l.push(e);
|
|
19
19
|
}
|
|
20
|
-
async function
|
|
21
|
-
if (
|
|
22
|
-
if (
|
|
23
|
-
if (
|
|
24
|
-
for (;
|
|
25
|
-
if (
|
|
26
|
-
if (await
|
|
27
|
-
if (
|
|
28
|
-
if (
|
|
20
|
+
async function m(t) {
|
|
21
|
+
if (f.disposed) throw new n();
|
|
22
|
+
if (f.drainPromise) throw new n("Worker is draining");
|
|
23
|
+
if (t.signal?.aborted) throw o(t.signal);
|
|
24
|
+
for (; c.maxQueue !== void 0 && u.length >= c.maxQueue;) {
|
|
25
|
+
if (c.onFull === "reject") throw new e(c.maxQueue);
|
|
26
|
+
if (await f.waitForCapacity(t.signal, t.priority ?? 0), f.disposed) throw new n();
|
|
27
|
+
if (f.drainPromise) throw new n("Worker is draining");
|
|
28
|
+
if (t.signal?.aborted) throw f.releaseCapacity(), o(t.signal);
|
|
29
29
|
}
|
|
30
|
-
return
|
|
31
|
-
let
|
|
30
|
+
return l.pop() || new Promise((e, n) => {
|
|
31
|
+
let r = {
|
|
32
32
|
cleanup() {
|
|
33
|
-
|
|
33
|
+
r.signal?.removeEventListener("abort", i);
|
|
34
34
|
},
|
|
35
|
-
priority:
|
|
35
|
+
priority: t.priority ?? 0,
|
|
36
36
|
reject(e) {
|
|
37
|
-
|
|
38
|
-
let
|
|
39
|
-
|
|
37
|
+
r.cleanup();
|
|
38
|
+
let t = u.indexOf(r);
|
|
39
|
+
t !== -1 && (u.splice(t, 1), f.releaseCapacity()), n(e), f.settleIdle();
|
|
40
40
|
},
|
|
41
41
|
resolve(t) {
|
|
42
|
-
|
|
42
|
+
r.cleanup(), e(t);
|
|
43
43
|
},
|
|
44
|
-
sequence:
|
|
45
|
-
signal:
|
|
46
|
-
},
|
|
47
|
-
|
|
44
|
+
sequence: d++,
|
|
45
|
+
signal: t.signal
|
|
46
|
+
}, i = () => r.reject(o(r.signal));
|
|
47
|
+
r.signal?.addEventListener("abort", i, { once: !0 }), u.push(r), u.sort((e, t) => t.priority - e.priority || e.sequence - t.sequence);
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
return {
|
|
51
51
|
get disposalSignal() {
|
|
52
|
-
return
|
|
52
|
+
return f.disposalSignal;
|
|
53
53
|
},
|
|
54
|
-
dispose:
|
|
54
|
+
dispose: f.dispose,
|
|
55
55
|
get disposed() {
|
|
56
|
-
return
|
|
56
|
+
return f.disposed;
|
|
57
57
|
},
|
|
58
|
-
drain:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let i = new AbortController(), o = () => i.abort(n.signal?.reason);
|
|
64
|
-
return n.signal?.addEventListener("abort", o, { once: !0 }), { [Symbol.asyncIterator]: async function* () {
|
|
65
|
-
let s, c;
|
|
58
|
+
drain: f.drain,
|
|
59
|
+
runStream(e, r = {}) {
|
|
60
|
+
let s = i(r.priority ?? 0), l = a(r.timeout) ?? c.defaultTimeout, u = [...r.transferables ?? []], d, h = async function* (t) {
|
|
61
|
+
let i = () => t.abort(r.signal?.reason), a, c;
|
|
62
|
+
r.signal?.aborted ? t.abort(r.signal.reason) : r.signal?.addEventListener("abort", i, { once: !0 });
|
|
66
63
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
signal:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
a = await m({
|
|
65
|
+
priority: s,
|
|
66
|
+
signal: t.signal,
|
|
67
|
+
timeout: l,
|
|
68
|
+
transferables: u
|
|
69
|
+
}), f.trackActive(1), c = () => a?.cancel(o(t.signal)), t.signal.addEventListener("abort", c, { once: !0 });
|
|
70
|
+
let n = a.stream(e, {
|
|
71
|
+
priority: s,
|
|
72
|
+
signal: t.signal,
|
|
73
|
+
timeout: l,
|
|
74
|
+
transferables: u
|
|
75
75
|
});
|
|
76
|
-
for await (let e of
|
|
77
|
-
await
|
|
76
|
+
for await (let e of n.iterable) yield e;
|
|
77
|
+
await n.done, f.trackCompleted();
|
|
78
78
|
} catch (e) {
|
|
79
|
-
throw
|
|
79
|
+
throw a && !t.signal.aborted && !(e instanceof n) && f.trackFailed(), e;
|
|
80
80
|
} finally {
|
|
81
|
-
|
|
81
|
+
r.signal?.removeEventListener("abort", i), a && (c && t.signal.removeEventListener("abort", c), f.trackActive(-1), p(a), f.settleIdle());
|
|
82
82
|
}
|
|
83
|
+
};
|
|
84
|
+
return { [Symbol.asyncIterator]() {
|
|
85
|
+
let e = {}, r = new AbortController(), i, a = () => {
|
|
86
|
+
if (d ??= e, d === e) return i ??= h(r), i;
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
next: () => a()?.next() ?? Promise.reject(new t("Worker streams can only be consumed once")),
|
|
90
|
+
return: async (t) => !d || d !== e ? {
|
|
91
|
+
done: !0,
|
|
92
|
+
value: t
|
|
93
|
+
} : (r.abort(new n("Stream consumer stopped")), i?.return(t) ?? {
|
|
94
|
+
done: !0,
|
|
95
|
+
value: t
|
|
96
|
+
}),
|
|
97
|
+
throw: async (e) => {
|
|
98
|
+
let n = a();
|
|
99
|
+
if (!n) throw new t("Worker streams can only be consumed once");
|
|
100
|
+
return r.abort(e), n.throw(e);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
83
103
|
} };
|
|
84
104
|
},
|
|
85
105
|
get stats() {
|
|
86
|
-
return
|
|
106
|
+
return f.stats(u.length);
|
|
87
107
|
},
|
|
88
108
|
get status() {
|
|
89
|
-
return
|
|
109
|
+
return f.status();
|
|
90
110
|
},
|
|
91
|
-
[Symbol.asyncDispose]: () =>
|
|
92
|
-
[Symbol.dispose]:
|
|
111
|
+
[Symbol.asyncDispose]: () => f.drain({}),
|
|
112
|
+
[Symbol.dispose]: f.dispose
|
|
93
113
|
};
|
|
94
114
|
}
|
|
95
115
|
//#endregion
|
|
96
|
-
export {
|
|
116
|
+
export { s as createStreamPool };
|
|
97
117
|
|
|
98
118
|
//# sourceMappingURL=_stream-pool.js.map
|
package/dist/_stream-pool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_stream-pool.js","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal/async';\n\nimport { createPoolCore, type PoolCore, type PoolOptions } from './_pool-core';\nimport { FamiliarQueueFullError, FamiliarTerminatedError } from './errors';\nimport type { RunOptions, StreamWorkerPool } from './types';\nimport type { RunningStream } from './worker';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n prime(): Promise<void>;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n let sequence = 0;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && waiters.length === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n },\n onDrainStart() {\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n },\n });\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n core.releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await core.waitForCapacity(runOptions.signal);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n core.releaseCapacity();\n }\n\n reject(reason);\n core.settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n async prime(): Promise<void> {\n await core.prime(slots);\n },\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const controller = new AbortController();\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n\n runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n return {\n [Symbol.asyncIterator]: async function* () {\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n try {\n slot = await acquire({ ...runOptions, signal: controller.signal });\n core.trackActive(1);\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, {\n ...runOptions,\n signal: controller.signal,\n timeout: runOptions.timeout ?? options.defaultTimeout,\n });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n core.trackCompleted();\n } catch (error) {\n if (error instanceof Error && error.name !== 'AbortError' && !(error instanceof FamiliarTerminatedError))\n core.trackFailed();\n\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n core.trackActive(-1);\n release(slot);\n core.settleIdle();\n }\n }\n },\n };\n },\n get stats() {\n return core.stats(waiters.length);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"_stream-pool.js","names":[],"sources":["../src/_stream-pool.ts"],"sourcesContent":["import { abortError } from '@vielzeug/arsenal';\nimport { createPoolCore, type PoolCore, type PoolOptions, validatePriority, validateTimeout } from './_pool-core.js';\nimport { FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTerminatedError } from './errors.js';\nimport type { RunOptions, StreamWorkerPool } from './types.js';\nimport type { RunningStream } from './worker.js';\n\nexport type StreamSlot<TInput, TChunk> = {\n cancel(reason: unknown): void;\n stream(input: TInput, options: RunOptions): RunningStream<TChunk>;\n terminate(): void;\n};\n\ntype Waiter<TSlot> = {\n cleanup(): void;\n priority: number;\n reject(reason: unknown): void;\n resolve(slot: TSlot): void;\n sequence: number;\n signal?: AbortSignal;\n};\n\nexport function createStreamPool<TInput, TChunk>(\n slots: StreamSlot<TInput, TChunk>[],\n options: PoolOptions,\n): StreamWorkerPool<TInput, TChunk> {\n const freeSlots = [...slots];\n const waiters: Waiter<StreamSlot<TInput, TChunk>>[] = [];\n let sequence = 0;\n\n const isIdle = (): boolean => freeSlots.length === slots.length && waiters.length === 0;\n\n const core: PoolCore = createPoolCore({\n isIdle,\n onDispose() {\n for (const slot of slots) slot.terminate();\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError());\n },\n onDrainStart() {\n for (const waiter of waiters.splice(0)) waiter.reject(new FamiliarTerminatedError('Worker is draining'));\n },\n });\n\n function release(slot: StreamSlot<TInput, TChunk>): void {\n const next = waiters.shift();\n\n if (next) {\n next.resolve(slot);\n core.releaseCapacity();\n } else {\n freeSlots.push(slot);\n }\n }\n\n async function acquire(runOptions: RunOptions): Promise<StreamSlot<TInput, TChunk>> {\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) throw abortError(runOptions.signal);\n\n while (options.maxQueue !== undefined && waiters.length >= options.maxQueue) {\n if (options.onFull === 'reject') throw new FamiliarQueueFullError(options.maxQueue);\n\n await core.waitForCapacity(runOptions.signal, runOptions.priority ?? 0);\n\n if (core.disposed) throw new FamiliarTerminatedError();\n\n if (core.drainPromise) throw new FamiliarTerminatedError('Worker is draining');\n\n if (runOptions.signal?.aborted) {\n core.releaseCapacity();\n throw abortError(runOptions.signal);\n }\n }\n\n const free = freeSlots.pop();\n\n if (free) return free;\n\n return new Promise<StreamSlot<TInput, TChunk>>((resolve, reject) => {\n const waiter: Waiter<StreamSlot<TInput, TChunk>> = {\n cleanup() {\n waiter.signal?.removeEventListener('abort', onAbort);\n },\n priority: runOptions.priority ?? 0,\n reject(reason) {\n waiter.cleanup();\n\n const index = waiters.indexOf(waiter);\n\n if (index !== -1) {\n waiters.splice(index, 1);\n core.releaseCapacity();\n }\n\n reject(reason);\n core.settleIdle();\n },\n resolve(slot) {\n waiter.cleanup();\n resolve(slot);\n },\n sequence: sequence++,\n signal: runOptions.signal,\n };\n const onAbort = () => waiter.reject(abortError(waiter.signal!));\n\n waiter.signal?.addEventListener('abort', onAbort, { once: true });\n waiters.push(waiter);\n waiters.sort((a, b) => b.priority - a.priority || a.sequence - b.sequence);\n });\n }\n\n return {\n get disposalSignal() {\n return core.disposalSignal;\n },\n dispose: core.dispose,\n get disposed() {\n return core.disposed;\n },\n drain: core.drain,\n runStream(input, runOptions = {}): AsyncIterable<TChunk> {\n const priority = validatePriority(runOptions.priority ?? 0);\n const timeout = validateTimeout(runOptions.timeout) ?? options.defaultTimeout;\n const transferables = [...(runOptions.transferables ?? [])];\n let owner: object | undefined;\n\n const iterate = async function* (controller: AbortController): AsyncGenerator<TChunk> {\n const onAbort = () => controller.abort(runOptions.signal?.reason);\n let slot: StreamSlot<TInput, TChunk> | undefined;\n let onCancel: (() => void) | undefined;\n\n if (runOptions.signal?.aborted) controller.abort(runOptions.signal.reason);\n else runOptions.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n slot = await acquire({ priority, signal: controller.signal, timeout, transferables });\n core.trackActive(1);\n onCancel = () => slot?.cancel(abortError(controller.signal));\n controller.signal.addEventListener('abort', onCancel, { once: true });\n\n const running = slot.stream(input, { priority, signal: controller.signal, timeout, transferables });\n\n for await (const value of running.iterable) yield value;\n await running.done;\n core.trackCompleted();\n } catch (error) {\n if (slot && !controller.signal.aborted && !(error instanceof FamiliarTerminatedError)) core.trackFailed();\n throw error;\n } finally {\n runOptions.signal?.removeEventListener('abort', onAbort);\n\n if (slot) {\n if (onCancel) controller.signal.removeEventListener('abort', onCancel);\n\n core.trackActive(-1);\n release(slot);\n core.settleIdle();\n }\n }\n };\n\n return {\n [Symbol.asyncIterator]() {\n const token = {};\n const controller = new AbortController();\n let iterator: AsyncGenerator<TChunk> | undefined;\n const start = (): AsyncGenerator<TChunk> | undefined => {\n owner ??= token;\n if (owner !== token) return undefined;\n iterator ??= iterate(controller);\n return iterator;\n };\n\n return {\n next: () =>\n start()?.next() ?? Promise.reject(new FamiliarRuntimeError('Worker streams can only be consumed once')),\n return: async (value?: unknown) => {\n if (!owner) return { done: true, value: value as TChunk };\n if (owner !== token) return { done: true, value: value as TChunk };\n controller.abort(new FamiliarTerminatedError('Stream consumer stopped'));\n return iterator?.return(value as TChunk) ?? { done: true, value: value as TChunk };\n },\n throw: async (error?: unknown) => {\n const active = start();\n if (!active) throw new FamiliarRuntimeError('Worker streams can only be consumed once');\n controller.abort(error);\n return active.throw(error);\n },\n };\n },\n };\n },\n get stats() {\n return core.stats(waiters.length);\n },\n get status() {\n return core.status();\n },\n [Symbol.asyncDispose]: () => core.drain({}),\n [Symbol.dispose]: core.dispose,\n };\n}\n"],"mappings":"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"}
|
package/dist/errors.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.
|
|
1
|
+
var e=class extends Error{static errorName=`FamiliarError`;constructor(e,t){super(e,t),this.name=new.target.errorName,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{static errorName=`FamiliarInvalidOptionsError`},n=class extends e{static errorName=`FamiliarQueueFullError`;maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},r=class extends e{static errorName=`FamiliarTaskError`},i=class extends e{static errorName=`FamiliarTerminatedError`;constructor(e=`Worker was terminated`){super(e)}},a=class extends e{static errorName=`FamiliarTimeoutError`;timeoutMs;constructor(e,t=`Task`){super(`${t} timed out after ${e}ms`),this.timeoutMs=e}},o=class extends e{static errorName=`FamiliarRuntimeError`};exports.FamiliarError=e,exports.FamiliarInvalidOptionsError=t,exports.FamiliarQueueFullError=n,exports.FamiliarRuntimeError=o,exports.FamiliarTaskError=r,exports.FamiliarTerminatedError=i,exports.FamiliarTimeoutError=a;
|
|
2
2
|
//# sourceMappingURL=errors.cjs.map
|
package/dist/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.
|
|
1
|
+
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n protected static readonly errorName: string = 'FamiliarError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof FamiliarError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarInvalidOptionsError';\n}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarQueueFullError';\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTaskError';\n}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTerminatedError';\n\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTimeoutError';\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, operation = 'Task') {\n super(`${operation} timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarRuntimeError';\n}\n"],"mappings":"AACA,IAAa,EAAb,cAAmC,KAAM,CACvC,OAA0B,UAAoB,gBAE9C,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAQ,WAAoC,UACjD,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAiD,CAAc,CAC7D,OAAmC,UAAY,6BACjD,EAGa,EAAb,cAA4C,CAAc,CACxD,OAAmC,UAAY,yBAE/C,SAEA,YAAY,EAAkB,CAC5B,MAAM,2BAA2B,EAAS,EAAE,EAC5C,KAAK,SAAW,CAClB,CACF,EAGa,EAAb,cAAuC,CAAc,CACnD,OAAmC,UAAY,mBACjD,EAGa,EAAb,cAA6C,CAAc,CACzD,OAAmC,UAAY,0BAE/C,YAAY,EAAU,wBAAyB,CAC7C,MAAM,CAAO,CACf,CACF,EAGa,EAAb,cAA0C,CAAc,CACtD,OAAmC,UAAY,uBAE/C,UAEA,YAAY,EAAmB,EAAY,OAAQ,CACjD,MAAM,GAAG,EAAU,mBAAmB,EAAU,GAAG,EACnD,KAAK,UAAY,CACnB,CACF,EAGa,EAAb,cAA0C,CAAc,CACtD,OAAmC,UAAY,sBACjD"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */
|
|
2
2
|
export declare class FamiliarError extends Error {
|
|
3
|
+
protected static readonly errorName: string;
|
|
3
4
|
constructor(message: string, opts?: ErrorOptions);
|
|
4
5
|
}
|
|
5
6
|
/** Thrown when invalid options are passed to a Familiar pool factory. */
|
|
6
7
|
export declare class FamiliarInvalidOptionsError extends FamiliarError {
|
|
8
|
+
protected static readonly errorName = "FamiliarInvalidOptionsError";
|
|
7
9
|
}
|
|
8
10
|
/** Thrown when run() is called and the queue is full (`onFull='reject'`). */
|
|
9
11
|
export declare class FamiliarQueueFullError extends FamiliarError {
|
|
12
|
+
protected static readonly errorName = "FamiliarQueueFullError";
|
|
10
13
|
/** The configured `maxQueue` value. */
|
|
11
14
|
readonly maxQueue: number;
|
|
12
15
|
constructor(maxQueue: number);
|
|
13
16
|
}
|
|
14
17
|
/** Thrown when the task function throws. The original error is available as `.cause`. */
|
|
15
18
|
export declare class FamiliarTaskError extends FamiliarError {
|
|
19
|
+
protected static readonly errorName = "FamiliarTaskError";
|
|
16
20
|
}
|
|
17
21
|
/** Thrown when a task or operation is rejected because the worker was terminated. */
|
|
18
22
|
export declare class FamiliarTerminatedError extends FamiliarError {
|
|
23
|
+
protected static readonly errorName = "FamiliarTerminatedError";
|
|
19
24
|
constructor(message?: string);
|
|
20
25
|
}
|
|
21
26
|
/** Thrown when a task exceeds its timeout or `drain()` times out. */
|
|
22
27
|
export declare class FamiliarTimeoutError extends FamiliarError {
|
|
28
|
+
protected static readonly errorName = "FamiliarTimeoutError";
|
|
23
29
|
/** The configured timeout in milliseconds. */
|
|
24
30
|
readonly timeoutMs: number;
|
|
25
|
-
constructor(timeoutMs: number);
|
|
31
|
+
constructor(timeoutMs: number, operation?: string);
|
|
26
32
|
}
|
|
27
33
|
/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */
|
|
28
34
|
export declare class FamiliarRuntimeError extends FamiliarError {
|
|
35
|
+
protected static readonly errorName = "FamiliarRuntimeError";
|
|
29
36
|
}
|
|
30
37
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,qBAAa,aAAc,SAAQ,KAAK;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAmB;gBAElD,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED,yEAAyE;AACzE,qBAAa,2BAA4B,SAAQ,aAAa;IAC5D,0BAAmC,SAAS,iCAAiC;CAC9E;AAED,6EAA6E;AAC7E,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,0BAAmC,SAAS,4BAA4B;IACxE,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;CAI7B;AAED,yFAAyF;AACzF,qBAAa,iBAAkB,SAAQ,aAAa;IAClD,0BAAmC,SAAS,uBAAuB;CACpE;AAED,qFAAqF;AACrF,qBAAa,uBAAwB,SAAQ,aAAa;IACxD,0BAAmC,SAAS,6BAA6B;gBAE7D,OAAO,SAA0B;CAG9C;AAED,qEAAqE;AACrE,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,0BAAmC,SAAS,0BAA0B;IACtE,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM,EAAE,SAAS,SAAS;CAIlD;AAED,mGAAmG;AACnG,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,0BAAmC,SAAS,0BAA0B;CACvE"}
|
package/dist/errors.js
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
//#region src/errors.ts
|
|
2
2
|
var e = class extends Error {
|
|
3
|
+
static errorName = "FamiliarError";
|
|
3
4
|
constructor(e, t) {
|
|
4
|
-
super(e, t), this.name = new.target.
|
|
5
|
+
super(e, t), this.name = new.target.errorName, Object.setPrototypeOf(this, new.target.prototype);
|
|
5
6
|
}
|
|
6
|
-
}, t = class extends e {
|
|
7
|
+
}, t = class extends e {
|
|
8
|
+
static errorName = "FamiliarInvalidOptionsError";
|
|
9
|
+
}, n = class extends e {
|
|
10
|
+
static errorName = "FamiliarQueueFullError";
|
|
7
11
|
maxQueue;
|
|
8
12
|
constructor(e) {
|
|
9
13
|
super(`Queue is full (maxQueue=${e})`), this.maxQueue = e;
|
|
10
14
|
}
|
|
11
|
-
}, r = class extends e {
|
|
15
|
+
}, r = class extends e {
|
|
16
|
+
static errorName = "FamiliarTaskError";
|
|
17
|
+
}, i = class extends e {
|
|
18
|
+
static errorName = "FamiliarTerminatedError";
|
|
12
19
|
constructor(e = "Worker was terminated") {
|
|
13
20
|
super(e);
|
|
14
21
|
}
|
|
15
22
|
}, a = class extends e {
|
|
23
|
+
static errorName = "FamiliarTimeoutError";
|
|
16
24
|
timeoutMs;
|
|
17
|
-
constructor(e) {
|
|
18
|
-
super(
|
|
25
|
+
constructor(e, t = "Task") {
|
|
26
|
+
super(`${t} timed out after ${e}ms`), this.timeoutMs = e;
|
|
19
27
|
}
|
|
20
|
-
}, o = class extends e {
|
|
28
|
+
}, o = class extends e {
|
|
29
|
+
static errorName = "FamiliarRuntimeError";
|
|
30
|
+
};
|
|
21
31
|
//#endregion
|
|
22
32
|
export { e as FamiliarError, t as FamiliarInvalidOptionsError, n as FamiliarQueueFullError, o as FamiliarRuntimeError, r as FamiliarTaskError, i as FamiliarTerminatedError, a as FamiliarTimeoutError };
|
|
23
33
|
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all familiar errors. Use `instanceof FamiliarError` to catch any familiar-originated error. */\nexport class FamiliarError extends Error {\n protected static readonly errorName: string = 'FamiliarError';\n\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = (new.target as typeof FamiliarError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when invalid options are passed to a Familiar pool factory. */\nexport class FamiliarInvalidOptionsError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarInvalidOptionsError';\n}\n\n/** Thrown when run() is called and the queue is full (`onFull='reject'`). */\nexport class FamiliarQueueFullError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarQueueFullError';\n /** The configured `maxQueue` value. */\n readonly maxQueue: number;\n\n constructor(maxQueue: number) {\n super(`Queue is full (maxQueue=${maxQueue})`);\n this.maxQueue = maxQueue;\n }\n}\n\n/** Thrown when the task function throws. The original error is available as `.cause`. */\nexport class FamiliarTaskError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTaskError';\n}\n\n/** Thrown when a task or operation is rejected because the worker was terminated. */\nexport class FamiliarTerminatedError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTerminatedError';\n\n constructor(message = 'Worker was terminated') {\n super(message);\n }\n}\n\n/** Thrown when a task exceeds its timeout or `drain()` times out. */\nexport class FamiliarTimeoutError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarTimeoutError';\n /** The configured timeout in milliseconds. */\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, operation = 'Task') {\n super(`${operation} timed out after ${timeoutMs}ms`);\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** Thrown when the Worker API is unavailable or an unhandled error occurs in the worker thread. */\nexport class FamiliarRuntimeError extends FamiliarError {\n protected static override readonly errorName = 'FamiliarRuntimeError';\n}\n"],"mappings":";AACA,IAAa,IAAb,cAAmC,MAAM;CACvC,OAA0B,YAAoB;CAE9C,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAQ,WAAoC,WACjD,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAiD,EAAc;CAC7D,OAAmC,YAAY;AACjD,GAGa,IAAb,cAA4C,EAAc;CACxD,OAAmC,YAAY;CAE/C;CAEA,YAAY,GAAkB;EAE5B,AADA,MAAM,2BAA2B,EAAS,EAAE,GAC5C,KAAK,WAAW;CAClB;AACF,GAGa,IAAb,cAAuC,EAAc;CACnD,OAAmC,YAAY;AACjD,GAGa,IAAb,cAA6C,EAAc;CACzD,OAAmC,YAAY;CAE/C,YAAY,IAAU,yBAAyB;EAC7C,MAAM,CAAO;CACf;AACF,GAGa,IAAb,cAA0C,EAAc;CACtD,OAAmC,YAAY;CAE/C;CAEA,YAAY,GAAmB,IAAY,QAAQ;EAEjD,AADA,MAAM,GAAG,EAAU,mBAAmB,EAAU,GAAG,GACnD,KAAK,YAAY;CACnB;AACF,GAGa,IAAb,cAA0C,EAAc;CACtD,OAAmC,YAAY;AACjD"}
|
package/dist/familiar.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e?.reason??new DOMException(`Aborted`,`AbortError`)}function t(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}var n=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{},i=class extends n{maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},a=class extends n{},o=class extends n{constructor(e=`Worker was terminated`){super(e)}},s=class extends n{timeoutMs;constructor(e){super(`Task timed out after ${e}ms`),this.timeoutMs=e}},c=class extends n{};function l(n){let r=new AbortController,i=[],a=[],c=0,l=0,u=0,d,f=!1;function p(){if(n.isIdle())for(let e of i.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function m(e){return n.isIdle()?Promise.resolve():new Promise((n,r)=>{let a={reject:r,resolve:n};e.timeout!==void 0&&(a.timer=setTimeout(()=>{let t=i.indexOf(a);t!==-1&&i.splice(t,1),r(new s(e.timeout))},e.timeout),t(a.timer)),i.push(a)})}function h(){a.shift()?.resolve()}function g(e){for(let t of a.splice(0))t.reject(e)}function _(t){return t?.aborted?Promise.reject(e(t)):new Promise((n,r)=>{let i=!1,o={cleanup(){t?.removeEventListener(`abort`,s)},reject(e){if(i)return;i=!0,o.cleanup();let t=a.indexOf(o);t!==-1&&a.splice(t,1),r(e)},resolve(){i||(i=!0,o.cleanup(),n())}},s=()=>o.reject(e(t));t?.addEventListener(`abort`,s,{once:!0}),a.push(o)})}function v(){f||(f=!0,r.abort(),n.onDispose(),g(new o),p())}function y(e){return f?Promise.resolve():d||(n.onDrainStart(),g(new o(`Worker is draining`)),d=m(e).then(()=>v(),e=>{throw v(),e}),d)}function b(e){return Promise.all(e.map(e=>e.prime())).then(()=>void 0)}function x(e){c+=e}function S(){l+=1}function C(){u+=1}function w(e){return{active:c,completed:l,failed:u,queued:e}}function T(){return f?`terminated`:c===0?`idle`:`running`}return{disposalSignal:r.signal,dispose:v,get disposed(){return f},drain:y,get drainPromise(){return d},isIdle:n.isIdle,prime:b,rejectCapacity:g,releaseCapacity:h,settleIdle:p,stats:w,status:T,trackActive:x,trackCompleted:S,trackFailed:C,waitForCapacity:_,waitForIdle:m}}var u=class{#e=[];#t=0;#n=0;get size(){return this.#t}enqueue(e,t){return t!==void 0&&this.#t>=t?!1:(this.#e.push({item:e,sequence:this.#n++}),this.#a(this.#e.length-1),this.#t+=1,!0)}remove(e){if(e.cancelled)return!1;for(let t of this.#e)if(t.item===e)return e.cancelled=!0,--this.#t,!0;return!1}shift(){for(;this.#e.length>0;){let e=this.#r().item;if(!e.cancelled)return--this.#t,e}}#r(){let e=this.#e[0],t=this.#e.pop();return this.#e.length>0&&(this.#e[0]=t,this.#o(0)),e}#i(e,t){return e.item.priority===t.item.priority?e.sequence<t.sequence:e.item.priority>t.item.priority}#a(e){for(;e>0;){let t=e-1>>1;if(!this.#i(this.#e[e],this.#e[t]))return;[this.#e[e],this.#e[t]]=[this.#e[t],this.#e[e]],e=t}}#o(e){for(;;){let t=e*2+1,n=t+1,r=e;if(t<this.#e.length&&this.#i(this.#e[t],this.#e[r])&&(r=t),n<this.#e.length&&this.#i(this.#e[n],this.#e[r])&&(r=n),r===e)return;[this.#e[e],this.#e[r]]=[this.#e[r],this.#e[e]],e=r}}};function d(t,n){let r=[...t],a=new u,s=!1,c=l({isIdle:()=>r.length===t.length&&a.size===0,onDispose(){for(let e of t)e.terminate();for(;a.size>0;){let e=a.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new o)}},onDrainStart(){}});function d(){for(;a.size>0;){let t=a.shift();if(!t)break;if(t.signal?.aborted){t.cleanupAbort?.(),t.reject(e(t.signal)),c.releaseCapacity();continue}return t}c.settleIdle()}function f(){if(!(s||c.disposed)){for(s=!0;!c.disposed&&r.length>0&&a.size>0;){let a=d();if(!a)break;let s=a,l=r.pop(),u=s.timeout??n.defaultTimeout;c.trackActive(1),c.releaseCapacity();let p=()=>l.cancel(e(s.signal));s.cleanupAbort=()=>{s.signal?.removeEventListener(`abort`,p),s.cleanupAbort=void 0},s.signal?.addEventListener(`abort`,p,{once:!0}),l.run(s.input,s.transferables,u).then(e=>t(e),e=>i(e));function t(e){s.cleanupAbort?.(),r.push(l),c.trackActive(-1),c.trackCompleted(),s.resolve(e),f(),c.settleIdle()}function i(e){s.cleanupAbort?.(),r.push(l),c.trackActive(-1),!(e instanceof o)&&e instanceof Error&&e.name!==`AbortError`&&c.trackFailed(),s.reject(e),f(),c.settleIdle()}}s=!1}}async function p(t,r={}){let{priority:s=0,signal:l,timeout:u,transferables:d=[]}=r;if(c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(l?.aborted)throw e(l);for(;n.onFull===`wait`&&n.maxQueue!==void 0&&a.size>=n.maxQueue;){if(await c.waitForCapacity(l),c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(l?.aborted)throw e(l)}let p,m,h=new Promise((e,t)=>{p=e,m=t}),g={input:t,priority:s,reject:m,resolve:p,signal:l,timeout:u,transferables:d};if(!a.enqueue(g,n.onFull===`wait`?void 0:n.maxQueue))throw new i(n.maxQueue);if(l){let t=()=>{a.remove(g)&&(g.cleanupAbort?.(),m(e(l)),c.releaseCapacity(),c.settleIdle())};g.cleanupAbort=()=>{l.removeEventListener(`abort`,t),g.cleanupAbort=void 0},l.addEventListener(`abort`,t,{once:!0})}return f(),h}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,async prime(){await c.prime(t)},run:p,get stats(){return c.stats(a.size)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}async function*f(e,t,n={}){let r=new AbortController,i=()=>r.abort(n.signal?.reason);n.signal?.addEventListener(`abort`,i,{once:!0});let a=t.map(t=>e.run(t,{...n,signal:r.signal}));try{for(let e of a)yield await e}catch(e){throw r.abort(e),await Promise.allSettled(a),e}finally{n.signal?.removeEventListener(`abort`,i),r.abort(),await Promise.allSettled(a)}}function p(e,t=void 0,n={}){let r=new AbortController,i=new Set,a=0;return n.signal?.addEventListener(`abort`,()=>r.abort(n.signal?.reason),{once:!0}),{abort(e){r.abort(e)},async drain(){return Promise.allSettled([...i])},get name(){return t},get pending(){return i.size},run(t,n={}){let o=e.run(t,{...n,signal:r.signal});return a+=1,i.add(o),o.finally(()=>i.delete(o)),o},get size(){return a}}}function m(t,n){let r=[...t],a=[],s=0,c=l({isIdle:()=>r.length===t.length&&a.length===0,onDispose(){for(let e of t)e.terminate();for(let e of a.splice(0))e.reject(new o)},onDrainStart(){for(let e of a.splice(0))e.reject(new o(`Worker is draining`))}});function u(e){let t=a.shift();t?(t.resolve(e),c.releaseCapacity()):r.push(e)}async function d(t){if(c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw e(t.signal);for(;n.maxQueue!==void 0&&a.length>=n.maxQueue;){if(n.onFull===`reject`)throw new i(n.maxQueue);if(await c.waitForCapacity(t.signal),c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw e(t.signal)}return r.pop()||new Promise((n,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,o)},priority:t.priority??0,reject(e){i.cleanup();let t=a.indexOf(i);t!==-1&&(a.splice(t,1),c.releaseCapacity()),r(e),c.settleIdle()},resolve(e){i.cleanup(),n(e)},sequence:s++,signal:t.signal},o=()=>i.reject(e(i.signal));i.signal?.addEventListener(`abort`,o,{once:!0}),a.push(i),a.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,async prime(){await c.prime(t)},runStream(t,r={}){let i=new AbortController,a=()=>i.abort(r.signal?.reason);return r.signal?.addEventListener(`abort`,a,{once:!0}),{[Symbol.asyncIterator]:async function*(){let s,l;try{s=await d({...r,signal:i.signal}),c.trackActive(1),l=()=>s?.cancel(e(i.signal)),i.signal.addEventListener(`abort`,l,{once:!0});let a=s.stream(t,{...r,signal:i.signal,timeout:r.timeout??n.defaultTimeout});for await(let e of a.iterable)yield e;await a.done,c.trackCompleted()}catch(e){throw e instanceof Error&&e.name!==`AbortError`&&!(e instanceof o)&&c.trackFailed(),e}finally{r.signal?.removeEventListener(`abort`,a),s&&(l&&i.signal.removeEventListener(`abort`,l),c.trackActive(-1),u(s),c.settleIdle())}}}},get stats(){return c.stats(a.length)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}var h=512;function g(e={}){let{concurrency:t=1,maxQueue:n,onFull:i=`reject`,onSlotError:a,timeout:o}=e,s=t===`auto`?Math.max(1,globalThis.navigator?.hardwareConcurrency??1):t;if(!Number.isInteger(s)||s<1||s>h)throw new r(`\`concurrency\` must be a positive integer ≤ ${h} or "auto"`);if(n!==void 0&&(!Number.isInteger(n)||n<1))throw new r("`maxQueue` must be a positive integer");if(o!==void 0&&(!Number.isFinite(o)||o<=0))throw new r("`timeout` must be a finite number greater than 0");return{concurrency:s,maxQueue:n,onFull:i,onSlotError:a,timeout:o}}function _(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.id==`number`&&(t.kind===`chunk`||t.kind===`error`||t.kind===`result`)}function v(e){let t=Error(e.message);return t.name=e.name,t.stack=e.stack,new a(e.message,{cause:t})}var y=class{#e;#t;#n=!1;#r;#i=0;#a;constructor(e,t){this.#t=e,this.#e=t}cancel(e){this.#a?.terminate(),this.#a=void 0,this.#l(`reject`,e)}prime(){return this.#n||this.#s(),Promise.resolve()}run(e,t,n){return this.#o(e,t,n,`run`)}stream(e,t){let n=()=>this.cancel(new o(`Stream consumer stopped`)),r=[],i=[],a=!1,s,c=e=>{let t=i.shift();t?t({done:!1,value:e}):r.push(e)},l=e=>{for(a=!0,s=e;i.length>0;)i.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,t.transferables??[],t.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(r.length>0)return{done:!1,value:r.shift()};if(s!==void 0)throw s;return a?{done:!0,value:void 0}:new Promise((e,t)=>{i.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return n(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.cancel(new o)}#o(e,n,r,i,a){if(this.#n)return Promise.reject(new o);if(this.#r)return Promise.reject(new c(`Worker slot is already busy`));try{let o=this.#s(),l=this.#i++;return new Promise((u,d)=>{let f={emit:a,id:l,reject:d,resolve:u};this.#r=f,r!==void 0&&(f.timer=setTimeout(()=>this.cancel(new s(r)),r),t(f.timer));try{o.postMessage({id:l,input:e,kind:i,version:1},n)}catch(e){this.cancel(new c(`Failed to post message to worker`,{cause:e}))}})}catch(e){return Promise.reject(e)}}#s(){if(this.#a)return this.#a;if(typeof Worker>`u`)throw new c(`Worker API is unavailable in this runtime`);try{let e=new Worker(this.#t,{type:`module`});return e.onmessage=e=>this.#c(e.data),e.onerror=e=>{let t=new c(e.message||`Worker failed`);this.#a=void 0,this.#e?.(t),this.#l(`reject`,t)},this.#a=e,e}catch(e){throw new c(`Failed to create Worker`,{cause:e})}}#c(e){if(this.#r){if(!_(e)||e.id!==this.#r.id){this.cancel(new c(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#l(`reject`,v(e.error));return}this.#l(`resolve`,e.value)}}#l(e,t){let n=this.#r;n&&(this.#r=void 0,n.timer&&clearTimeout(n.timer),e===`resolve`?n.resolve(t):n.reject(t))}};function b(e,t){return Array.from({length:t.concurrency},()=>new y(e,t.onSlotError))}function x(e,t={}){let n=g(t);return d(b(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function S(e,t={}){let n=g(t);return m(b(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}exports.FamiliarError=n,exports.FamiliarInvalidOptionsError=r,exports.FamiliarQueueFullError=i,exports.FamiliarRuntimeError=c,exports.FamiliarTaskError=a,exports.FamiliarTerminatedError=o,exports.FamiliarTimeoutError=s,exports.batch=f,exports.createStreamWorker=S,exports.createTaskGroup=p,exports.createWorker=x;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/arsenal");function t(e){typeof e==`object`&&e&&`unref`in e&&e.unref()}var n=class extends Error{static errorName=`FamiliarError`;constructor(e,t){super(e,t),this.name=new.target.errorName,Object.setPrototypeOf(this,new.target.prototype)}},r=class extends n{static errorName=`FamiliarInvalidOptionsError`},i=class extends n{static errorName=`FamiliarQueueFullError`;maxQueue;constructor(e){super(`Queue is full (maxQueue=${e})`),this.maxQueue=e}},a=class extends n{static errorName=`FamiliarTaskError`},o=class extends n{static errorName=`FamiliarTerminatedError`;constructor(e=`Worker was terminated`){super(e)}},s=class extends n{static errorName=`FamiliarTimeoutError`;timeoutMs;constructor(e,t=`Task`){super(`${t} timed out after ${e}ms`),this.timeoutMs=e}},c=class extends n{static errorName=`FamiliarRuntimeError`},l=2147483647;function u(e){if(!Number.isFinite(e))throw new r("`priority` must be a finite number");return e}function d(e,t=`timeout`){if(e!==void 0&&(!Number.isInteger(e)||e<1||e>2147483647))throw new r(`\`${t}\` must be an integer from 1 through ${l}`);return e}function f(n){let r=new AbortController,i=[],a=[],c=0,l=0,u=0,f=0,p,m=!1;function h(){if(n.isIdle())for(let e of i.splice(0))e.timer&&clearTimeout(e.timer),e.resolve()}function g(e){return n.isIdle()?Promise.resolve():new Promise((n,r)=>{let a={reject:r,resolve:n};e.timeout!==void 0&&(a.timer=setTimeout(()=>{let t=i.indexOf(a);t!==-1&&i.splice(t,1),r(new s(e.timeout,`Drain`))},e.timeout),t(a.timer)),i.push(a)})}function _(){a.shift()?.resolve()}function v(e){for(let t of a.splice(0))t.reject(e)}function y(t,n){return t?.aborted?Promise.reject((0,e.abortError)(t)):new Promise((r,i)=>{let o=!1,s={cleanup(){t?.removeEventListener(`abort`,c)},priority:n,reject(e){if(o)return;o=!0,s.cleanup();let t=a.indexOf(s);t!==-1&&a.splice(t,1),i(e)},resolve(){o||(o=!0,s.cleanup(),r())},sequence:l++},c=()=>s.reject((0,e.abortError)(t));t?.addEventListener(`abort`,c,{once:!0}),a.push(s),a.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}function b(){m||(m=!0,r.abort(),n.onDispose(),v(new o),h())}function x(e={}){if(m)return Promise.resolve();try{d(e.timeout,`drain.timeout`)}catch(e){return Promise.reject(e)}return p||(n.onDrainStart(),v(new o(`Worker is draining`)),p=g(e).then(()=>b(),e=>{throw b(),e}),p)}function S(e){c+=e}function C(){u+=1}function w(){f+=1}function T(e){return{active:c,completed:u,failed:f,queued:e+a.length}}function E(){return m?`terminated`:c===0?`idle`:`running`}return{disposalSignal:r.signal,dispose:b,get disposed(){return m},drain:x,get drainPromise(){return p},isIdle:n.isIdle,rejectCapacity:v,releaseCapacity:_,settleIdle:h,stats:T,status:E,trackActive:S,trackCompleted:C,trackFailed:w,waitForCapacity:y,waitForIdle:g}}var p=class{#e=[];#t=0;#n=0;get size(){return this.#t}enqueue(e,t){return t!==void 0&&this.#t>=t?!1:(this.#e.push({item:e,sequence:this.#n++}),this.#a(this.#e.length-1),this.#t+=1,!0)}remove(e){let t=this.#e.findIndex(t=>t.item===e);if(t===-1)return!1;let n=this.#e.pop();if(--this.#t,t<this.#e.length){this.#e[t]=n;let e=t-1>>1;t>0&&this.#i(this.#e[t],this.#e[e])?this.#a(t):this.#o(t)}return!0}shift(){if(this.#e.length!==0)return--this.#t,this.#r().item}#r(){let e=this.#e[0],t=this.#e.pop();return this.#e.length>0&&(this.#e[0]=t,this.#o(0)),e}#i(e,t){return e.item.priority===t.item.priority?e.sequence<t.sequence:e.item.priority>t.item.priority}#a(e){for(;e>0;){let t=e-1>>1;if(!this.#i(this.#e[e],this.#e[t]))return;[this.#e[e],this.#e[t]]=[this.#e[t],this.#e[e]],e=t}}#o(e){for(;;){let t=e*2+1,n=t+1,r=e;if(t<this.#e.length&&this.#i(this.#e[t],this.#e[r])&&(r=t),n<this.#e.length&&this.#i(this.#e[n],this.#e[r])&&(r=n),r===e)return;[this.#e[e],this.#e[r]]=[this.#e[r],this.#e[e]],e=r}}};function m(t,n){let r=[...t],a=new p,s=!1,c=f({isIdle:()=>r.length===t.length&&a.size===0,onDispose(){for(let e of t)e.terminate();for(;a.size>0;){let e=a.shift();if(!e)break;e.cleanupAbort?.(),e.reject(new o)}},onDrainStart(){}});function l(){for(;a.size>0;){let t=a.shift();if(!t)break;if(t.signal?.aborted){t.cleanupAbort?.(),t.reject((0,e.abortError)(t.signal)),c.releaseCapacity();continue}return t}c.settleIdle()}function m(){if(!(s||c.disposed)){for(s=!0;!c.disposed&&r.length>0&&a.size>0;){let a=l();if(!a)break;let s=a,u=r.pop(),d=s.timeout??n.defaultTimeout;c.trackActive(1),c.releaseCapacity();let f=()=>{s.aborted=!0,u.cancel((0,e.abortError)(s.signal))};s.cleanupAbort=()=>{s.signal?.removeEventListener(`abort`,f),s.cleanupAbort=void 0},s.signal?.addEventListener(`abort`,f,{once:!0}),u.run(s.input,s.transferables,d).then(e=>t(e),e=>i(e));function t(e){s.cleanupAbort?.(),r.push(u),c.trackActive(-1),c.trackCompleted(),s.resolve(e),m(),c.settleIdle()}function i(e){s.cleanupAbort?.(),r.push(u),c.trackActive(-1),!s.aborted&&!(e instanceof o)&&c.trackFailed(),s.reject(e),m(),c.settleIdle()}}s=!1}}async function h(t,r={}){let{signal:s}=r,l=u(r.priority??0),f=d(r.timeout),p=[...r.transferables??[]];if(c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(s?.aborted)throw(0,e.abortError)(s);for(;n.onFull===`wait`&&n.maxQueue!==void 0&&a.size>=n.maxQueue;){if(await c.waitForCapacity(s,l),c.disposed)throw new o;if(c.drainPromise)throw new o(`Worker is draining`);if(s?.aborted)throw c.releaseCapacity(),(0,e.abortError)(s)}let h,g,_=new Promise((e,t)=>{h=e,g=t}),v={input:t,priority:l,reject:g,resolve:h,signal:s,timeout:f,transferables:p};if(!a.enqueue(v,n.onFull===`wait`?void 0:n.maxQueue))throw new i(n.maxQueue);if(s){let t=()=>{a.remove(v)&&(v.cleanupAbort?.(),g((0,e.abortError)(s)),c.releaseCapacity(),c.settleIdle())};v.cleanupAbort=()=>{s.removeEventListener(`abort`,t),v.cleanupAbort=void 0},s.addEventListener(`abort`,t,{once:!0})}return m(),_}return{get disposalSignal(){return c.disposalSignal},dispose:c.dispose,get disposed(){return c.disposed},drain:c.drain,run:h,get stats(){return c.stats(a.size)},get status(){return c.status()},[Symbol.asyncDispose]:()=>c.drain({}),[Symbol.dispose]:c.dispose}}function h(t,n,r={}){let i,a=async function*(i){let a=[],o=()=>i.abort(r.signal?.reason);r.signal?.aborted?i.abort(r.signal.reason):r.signal?.addEventListener(`abort`,o,{once:!0});try{for(let[e,o]of n.entries()){let n=t.run(o,{priority:r.priority,signal:i.signal,timeout:r.timeout,transferables:r.getTransferables?.(o,e)}).catch(e=>{throw i.abort(e),e});n.catch(()=>void 0),a.push(n)}if(a.length===0&&i.signal.aborted)throw(0,e.abortError)(i.signal);for(let t of a){if(i.signal.aborted)throw(0,e.abortError)(i.signal);let n=await t;if(i.signal.aborted)throw(0,e.abortError)(i.signal);yield n}}catch(e){throw i.abort(e),e}finally{r.signal?.removeEventListener(`abort`,o),i.abort(new DOMException(`Batch consumer stopped`,`AbortError`)),await Promise.allSettled(a)}};return{[Symbol.asyncIterator](){let e={},t=new AbortController,n,r=()=>{if(i??=e,i===e)return n??=a(t),n};return{next:()=>r()?.next()??Promise.reject(new c(`Worker batches can only be consumed once`)),return:async r=>!i||i!==e?{done:!0,value:r}:(t.abort(new o(`Batch consumer stopped`)),n?.return(r)??{done:!0,value:r}),throw:async e=>{let n=r();if(!n)throw new c(`Worker batches can only be consumed once`);return t.abort(e),n.throw(e)}}}}}function g(t,n){let r=[...t],a=[],s=0,l=f({isIdle:()=>r.length===t.length&&a.length===0,onDispose(){for(let e of t)e.terminate();for(let e of a.splice(0))e.reject(new o)},onDrainStart(){for(let e of a.splice(0))e.reject(new o(`Worker is draining`))}});function p(e){let t=a.shift();t?(t.resolve(e),l.releaseCapacity()):r.push(e)}async function m(t){if(l.disposed)throw new o;if(l.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw(0,e.abortError)(t.signal);for(;n.maxQueue!==void 0&&a.length>=n.maxQueue;){if(n.onFull===`reject`)throw new i(n.maxQueue);if(await l.waitForCapacity(t.signal,t.priority??0),l.disposed)throw new o;if(l.drainPromise)throw new o(`Worker is draining`);if(t.signal?.aborted)throw l.releaseCapacity(),(0,e.abortError)(t.signal)}return r.pop()||new Promise((n,r)=>{let i={cleanup(){i.signal?.removeEventListener(`abort`,o)},priority:t.priority??0,reject(e){i.cleanup();let t=a.indexOf(i);t!==-1&&(a.splice(t,1),l.releaseCapacity()),r(e),l.settleIdle()},resolve(e){i.cleanup(),n(e)},sequence:s++,signal:t.signal},o=()=>i.reject((0,e.abortError)(i.signal));i.signal?.addEventListener(`abort`,o,{once:!0}),a.push(i),a.sort((e,t)=>t.priority-e.priority||e.sequence-t.sequence)})}return{get disposalSignal(){return l.disposalSignal},dispose:l.dispose,get disposed(){return l.disposed},drain:l.drain,runStream(t,r={}){let i=u(r.priority??0),a=d(r.timeout)??n.defaultTimeout,s=[...r.transferables??[]],f,h=async function*(n){let c=()=>n.abort(r.signal?.reason),u,d;r.signal?.aborted?n.abort(r.signal.reason):r.signal?.addEventListener(`abort`,c,{once:!0});try{u=await m({priority:i,signal:n.signal,timeout:a,transferables:s}),l.trackActive(1),d=()=>u?.cancel((0,e.abortError)(n.signal)),n.signal.addEventListener(`abort`,d,{once:!0});let r=u.stream(t,{priority:i,signal:n.signal,timeout:a,transferables:s});for await(let e of r.iterable)yield e;await r.done,l.trackCompleted()}catch(e){throw u&&!n.signal.aborted&&!(e instanceof o)&&l.trackFailed(),e}finally{r.signal?.removeEventListener(`abort`,c),u&&(d&&n.signal.removeEventListener(`abort`,d),l.trackActive(-1),p(u),l.settleIdle())}};return{[Symbol.asyncIterator](){let e={},t=new AbortController,n,r=()=>{if(f??=e,f===e)return n??=h(t),n};return{next:()=>r()?.next()??Promise.reject(new c(`Worker streams can only be consumed once`)),return:async r=>!f||f!==e?{done:!0,value:r}:(t.abort(new o(`Stream consumer stopped`)),n?.return(r)??{done:!0,value:r}),throw:async e=>{let n=r();if(!n)throw new c(`Worker streams can only be consumed once`);return t.abort(e),n.throw(e)}}}}},get stats(){return l.stats(a.length)},get status(){return l.status()},[Symbol.asyncDispose]:()=>l.drain({}),[Symbol.dispose]:l.dispose}}function _(e={}){let{concurrency:t=1,maxQueue:n,onFull:i=`reject`,onSlotError:a,timeout:o}=e,s=t===`auto`?Math.min(512,Math.max(1,globalThis.navigator?.hardwareConcurrency??1)):t;if(!Number.isInteger(s)||s<1||s>512)throw new r('`concurrency` must be a positive integer ≤ 512 or "auto"');if(n!==void 0&&(!Number.isInteger(n)||n<1))throw new r("`maxQueue` must be a positive integer");if(i!==`reject`&&i!==`wait`)throw new r('`onFull` must be "reject" or "wait"');return d(o),{concurrency:s,maxQueue:n,onFull:i,onSlotError:a,timeout:o}}function v(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version!==1||typeof t.id!=`number`||!Number.isSafeInteger(t.id)||t.id<0?!1:t.kind===`chunk`||t.kind===`result`?`value`in t:t.kind!==`error`||typeof t.error!=`object`||t.error===null?!1:(t.error.category===void 0||t.error.category===`protocol`)&&typeof t.error.message==`string`&&typeof t.error.name==`string`&&(t.error.stack===void 0||typeof t.error.stack==`string`)}function y(e){let t=Error(e.message);return t.name=e.name,t.stack=e.stack,e.category===`protocol`?new c(e.message,{cause:t}):new a(e.message,{cause:t})}var b=class{#e;#t;#n=!1;#r;#i=0;#a;constructor(e,t){this.#t=e,this.#e=t}cancel(e){this.#r&&(this.#c(),this.#d(`reject`,e))}run(e,t,n){return this.#o(e,t,n,`run`)}stream(e,t){let n=()=>this.cancel(new o(`Stream consumer stopped`)),r=[],i=[],a=!1,s,c=e=>{let t=i.shift();t?t({done:!1,value:e}):r.push(e)},l=e=>{for(a=!0,s=e;i.length>0;)i.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,[...t.transferables??[]],t.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(r.length>0)return{done:!1,value:r.shift()};if(s!==void 0)throw s;return a?{done:!0,value:void 0}:new Promise((e,t)=>{i.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return n(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.#c(),this.#d(`reject`,new o)}#o(e,n,r,i,a){if(this.#n)return Promise.reject(new o);if(this.#r)return Promise.reject(new c(`Worker slot is already busy`));try{let o=this.#s(),l=this.#i;return this.#i=l===2**53-1?0:l+1,new Promise((u,d)=>{let f={emit:a,id:l,kind:i,reject:d,resolve:u};this.#r=f,r!==void 0&&(f.timer=setTimeout(()=>this.cancel(new s(r)),r),t(f.timer));try{o.postMessage({id:l,input:e,kind:i,version:1},n)}catch(e){this.cancel(new c(`Failed to post message to worker`,{cause:e}))}})}catch(e){return Promise.reject(e)}}#s(){if(this.#a)return this.#a;if(typeof Worker>`u`)throw new c(`Worker API is unavailable in this runtime`);try{let e=new Worker(this.#t,{type:`module`});return e.onmessage=t=>{this.#a===e&&this.#u(t.data)},e.onerror=t=>this.#l(e,new c(t.message||`Worker failed`)),e.onmessageerror=()=>this.#l(e,new c(`Worker response could not be deserialized`)),this.#a=e,e}catch(e){throw new c(`Failed to create Worker`,{cause:e})}}#c(){let e=this.#a;this.#a=void 0,e&&(e.onmessage=null,e.onerror=null,e.onmessageerror=null,e.terminate())}#l(e,t){if(this.#a===e){this.#c(),this.#d(`reject`,t);try{this.#e?.(t)}catch{}}}#u(e){if(this.#r){if(!v(e)||e.id!==this.#r.id||this.#r.kind===`run`&&e.kind===`chunk`){this.cancel(new c(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#d(`reject`,y(e.error));return}this.#d(`resolve`,e.value)}}#d(e,t){let n=this.#r;n&&(this.#r=void 0,n.timer&&clearTimeout(n.timer),e===`resolve`?n.resolve(t):n.reject(t))}};function x(e,t){let n=typeof e==`string`?e:e.href;return Array.from({length:t.concurrency},()=>new b(n,t.onSlotError))}function S(e,t={}){let n=_(t);return m(x(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function C(e,t={}){let n=_(t);return g(x(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}exports.FamiliarError=n,exports.FamiliarInvalidOptionsError=r,exports.FamiliarQueueFullError=i,exports.FamiliarRuntimeError=c,exports.FamiliarTaskError=a,exports.FamiliarTerminatedError=o,exports.FamiliarTimeoutError=s,exports.createStreamWorker=C,exports.createWorker=S,exports.runBatch=h;
|
|
2
2
|
//# sourceMappingURL=familiar.cjs.map
|