@vielzeug/familiar 2.1.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.
Files changed (68) hide show
  1. package/README.md +4 -11
  2. package/dist/_dev.cjs +2 -0
  3. package/dist/_dev.cjs.map +1 -0
  4. package/dist/_dev.js +6 -0
  5. package/dist/_dev.js.map +1 -0
  6. package/dist/_pool-core.cjs +2 -0
  7. package/dist/_pool-core.cjs.map +1 -0
  8. package/dist/_pool-core.d.ts +41 -0
  9. package/dist/_pool-core.d.ts.map +1 -0
  10. package/dist/_pool-core.js +118 -0
  11. package/dist/_pool-core.js.map +1 -0
  12. package/dist/_pool.cjs +1 -1
  13. package/dist/_pool.cjs.map +1 -1
  14. package/dist/_pool.d.ts +8 -9
  15. package/dist/_pool.d.ts.map +1 -1
  16. package/dist/_pool.js +117 -164
  17. package/dist/_pool.js.map +1 -1
  18. package/dist/_queue.cjs +1 -1
  19. package/dist/_queue.cjs.map +1 -1
  20. package/dist/_queue.d.ts +1 -1
  21. package/dist/_queue.d.ts.map +1 -1
  22. package/dist/_queue.js +10 -7
  23. package/dist/_queue.js.map +1 -1
  24. package/dist/_stream-pool.cjs +1 -1
  25. package/dist/_stream-pool.cjs.map +1 -1
  26. package/dist/_stream-pool.d.ts +3 -4
  27. package/dist/_stream-pool.d.ts.map +1 -1
  28. package/dist/_stream-pool.js +84 -118
  29. package/dist/_stream-pool.js.map +1 -1
  30. package/dist/errors.cjs +1 -1
  31. package/dist/errors.cjs.map +1 -1
  32. package/dist/errors.d.ts +8 -1
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/errors.js +16 -6
  35. package/dist/errors.js.map +1 -1
  36. package/dist/familiar.cjs +1 -1
  37. package/dist/familiar.cjs.map +1 -1
  38. package/dist/familiar.iife.js +1 -1
  39. package/dist/familiar.iife.js.map +1 -1
  40. package/dist/familiar.js +1 -1
  41. package/dist/familiar.js.map +1 -1
  42. package/dist/index.cjs +1 -1
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -3
  46. package/dist/protocol.cjs +1 -1
  47. package/dist/protocol.cjs.map +1 -1
  48. package/dist/protocol.d.ts +1 -0
  49. package/dist/protocol.d.ts.map +1 -1
  50. package/dist/protocol.js +16 -5
  51. package/dist/protocol.js.map +1 -1
  52. package/dist/testing/index.d.ts +1 -1
  53. package/dist/testing/index.d.ts.map +1 -1
  54. package/dist/testing/testing.cjs +1 -1
  55. package/dist/testing/testing.cjs.map +1 -1
  56. package/dist/testing/testing.d.ts +3 -3
  57. package/dist/testing/testing.d.ts.map +1 -1
  58. package/dist/testing/testing.js +25 -24
  59. package/dist/testing/testing.js.map +1 -1
  60. package/dist/types.d.ts +7 -28
  61. package/dist/types.d.ts.map +1 -1
  62. package/dist/worker.cjs +1 -1
  63. package/dist/worker.cjs.map +1 -1
  64. package/dist/worker.d.ts +5 -4
  65. package/dist/worker.d.ts.map +1 -1
  66. package/dist/worker.js +49 -38
  67. package/dist/worker.js.map +1 -1
  68. package/package.json +10 -8
@@ -1,19 +1,20 @@
1
1
  import { FamiliarError as e, FamiliarInvalidOptionsError as t, FamiliarQueueFullError as n, FamiliarRuntimeError as r, FamiliarTaskError as i, FamiliarTerminatedError as a, FamiliarTimeoutError as o } from "../errors.js";
2
- import { createPool as s } from "../_pool.js";
2
+ import { validateTimeout as s } from "../_pool-core.js";
3
+ import { createPool as c } from "../_pool.js";
3
4
  //#region src/testing/testing.ts
4
- function c(e, n = {}) {
5
- let { concurrency: r = 1, maxQueue: c, onFull: l = "reject", timeout: u } = n;
6
- if (!Number.isInteger(r) || r < 1) throw new t("`concurrency` must be a positive integer");
7
- if (c !== void 0 && (!Number.isInteger(c) || c < 1)) throw new t("`maxQueue` must be a positive integer");
8
- if (u !== void 0 && (!Number.isFinite(u) || u <= 0)) throw new t("`timeout` must be a finite number greater than 0");
9
- let d = [];
10
- function f() {
5
+ function l(e, n = {}) {
6
+ let { concurrency: r = 1, maxQueue: l, onFull: u = "reject", timeout: d } = n;
7
+ if (!Number.isInteger(r) || r < 1 || r > 512) throw new t("`concurrency` must be a positive integer ≤ 512");
8
+ if (l !== void 0 && (!Number.isInteger(l) || l < 1)) throw new t("`maxQueue` must be a positive integer");
9
+ if (u !== "reject" && u !== "wait") throw new t("`onFull` must be \"reject\" or \"wait\"");
10
+ s(d);
11
+ let f = [];
12
+ function p() {
11
13
  let t, n = !1;
12
14
  return {
13
15
  cancel(e) {
14
16
  t?.reject(e), t = void 0;
15
17
  },
16
- prime: () => Promise.resolve(),
17
18
  run(r, s, c) {
18
19
  if (n) return Promise.reject(new a());
19
20
  let l;
@@ -25,32 +26,32 @@ function c(e, n = {}) {
25
26
  return new Promise((n, r) => {
26
27
  let a = Symbol("task"), s, u = (e, n) => {
27
28
  t?.token === a && (t = void 0, s && clearTimeout(s), e(n));
28
- }, f = (e) => {
29
- t?.token === a && (t = void 0, s && clearTimeout(s), d.push({
29
+ }, d = (e) => {
30
+ t?.token === a && (t = void 0, s && clearTimeout(s), f.push({
30
31
  input: l,
31
32
  reason: e,
32
33
  status: "rejected"
33
34
  }), r(e));
34
35
  };
35
36
  t = {
36
- reject: f,
37
+ reject: d,
37
38
  token: a
38
- }, c !== void 0 && (s = setTimeout(() => f(new o(c)), c)), Promise.resolve().then(() => e(l)).then((e) => {
39
+ }, c !== void 0 && (s = setTimeout(() => d(new o(c)), c)), Promise.resolve().then(() => e(l)).then((e) => {
39
40
  let r;
40
41
  try {
41
42
  r = structuredClone(e);
42
43
  } catch (e) {
43
- f(new i("Failed to clone task output", { cause: e }));
44
+ d(new i("Failed to clone task output", { cause: e }));
44
45
  return;
45
46
  }
46
- t?.token === a && (d.push({
47
+ t?.token === a && (f.push({
47
48
  input: l,
48
49
  status: "fulfilled",
49
50
  value: r
50
51
  }), u(n, r));
51
52
  }, (e) => {
52
53
  let t = e instanceof Error ? e : Error(String(e));
53
- f(new i(t.message, { cause: t }));
54
+ d(new i(t.message, { cause: t }));
54
55
  });
55
56
  });
56
57
  },
@@ -59,18 +60,18 @@ function c(e, n = {}) {
59
60
  }
60
61
  };
61
62
  }
62
- let p = s(Array.from({ length: r }, f), {
63
+ let m = c(Array.from({ length: r }, p), {
63
64
  concurrency: r,
64
- defaultTimeout: u,
65
- maxQueue: c,
66
- onFull: l
65
+ defaultTimeout: d,
66
+ maxQueue: l,
67
+ onFull: u
67
68
  });
68
- return Object.defineProperty(p, "calls", {
69
+ return Object.defineProperty(m, "calls", {
69
70
  enumerable: !0,
70
- get: () => d
71
- }), p;
71
+ get: () => f
72
+ }), m;
72
73
  }
73
74
  //#endregion
74
- export { e as FamiliarError, t as FamiliarInvalidOptionsError, n as FamiliarQueueFullError, r as FamiliarRuntimeError, i as FamiliarTaskError, a as FamiliarTerminatedError, o as FamiliarTimeoutError, c as createTestWorker };
75
+ export { e as FamiliarError, t as FamiliarInvalidOptionsError, n as FamiliarQueueFullError, r as FamiliarRuntimeError, i as FamiliarTaskError, a as FamiliarTerminatedError, o as FamiliarTimeoutError, l as createTestWorker };
75
76
 
76
77
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import { createPool } from '../_pool';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors';\nimport type { SlotStrategy, WorkerOptions, WorkerPool } from '../types';\n\nexport type TestWorkerOptions = Omit<WorkerOptions, 'concurrency' | 'onSlotError'> & { concurrency?: number };\n\nexport type TestWorkerCall<TInput, TOutput> =\n | { input: TInput; status: 'fulfilled'; value: TOutput }\n | { input: TInput; reason: unknown; status: 'rejected' };\n\nexport type TestWorkerHandle<TInput, TOutput> = WorkerPool<TInput, TOutput> & {\n readonly calls: ReadonlyArray<TestWorkerCall<TInput, TOutput>>;\n};\n\nexport function createTestWorker<TInput, TOutput>(\n handler: (input: TInput) => TOutput | Promise<TOutput>,\n options: TestWorkerOptions = {},\n): TestWorkerHandle<TInput, TOutput> {\n const { concurrency = 1, maxQueue, onFull = 'reject', timeout } = options;\n\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new FamiliarInvalidOptionsError('`concurrency` must be a positive integer');\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {\n throw new FamiliarInvalidOptionsError('`timeout` must be a finite number greater than 0');\n }\n\n const calls: TestWorkerCall<TInput, TOutput>[] = [];\n\n function makeSlot(): SlotStrategy<TInput, TOutput> {\n let current: { reject(reason: unknown): void; token: symbol } | undefined;\n let terminated = false;\n\n return {\n cancel(reason: unknown): void {\n current?.reject(reason);\n current = undefined;\n },\n prime: () => Promise.resolve(),\n run(input, transferables, timeoutMs): Promise<TOutput> {\n if (terminated) return Promise.reject(new FamiliarTerminatedError());\n\n let clonedInput: TInput;\n\n try {\n clonedInput = structuredClone(input, { transfer: transferables });\n } catch (error) {\n return Promise.reject(new FamiliarTaskError('Failed to clone task input', { cause: error }));\n }\n\n return new Promise<TOutput>((resolve, reject) => {\n const token = Symbol('task');\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: (value: TOutput) => void, value: TOutput): void => {\n if (current?.token !== token) return;\n\n current = undefined;\n\n if (timer) clearTimeout(timer);\n\n fn(value);\n };\n const rejectTask = (reason: unknown): void => {\n if (current?.token !== token) return;\n\n current = undefined;\n\n if (timer) clearTimeout(timer);\n\n calls.push({ input: clonedInput, reason, status: 'rejected' });\n reject(reason);\n };\n\n current = { reject: rejectTask, token };\n\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => rejectTask(new FamiliarTimeoutError(timeoutMs)), timeoutMs);\n }\n\n void Promise.resolve()\n .then(() => handler(clonedInput))\n .then(\n (output) => {\n let clonedOutput: TOutput;\n\n try {\n clonedOutput = structuredClone(output);\n } catch (error) {\n rejectTask(new FamiliarTaskError('Failed to clone task output', { cause: error }));\n\n return;\n }\n\n if (current?.token !== token) return;\n\n calls.push({ input: clonedInput, status: 'fulfilled', value: clonedOutput });\n settle(resolve, clonedOutput);\n },\n (error: unknown) => {\n const cause = error instanceof Error ? error : new Error(String(error));\n\n rejectTask(new FamiliarTaskError(cause.message, { cause }));\n },\n );\n });\n },\n terminate(): void {\n terminated = true;\n current?.reject(new FamiliarTerminatedError());\n current = undefined;\n },\n };\n }\n\n const pool = createPool(Array.from({ length: concurrency }, makeSlot), {\n concurrency,\n defaultTimeout: timeout,\n maxQueue,\n onFull,\n });\n\n Object.defineProperty(pool, 'calls', {\n enumerable: true,\n get: () => calls as ReadonlyArray<TestWorkerCall<TInput, TOutput>>,\n });\n\n return pool as TestWorkerHandle<TInput, TOutput>;\n}\n\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors';\nexport type { WorkerPool } from '../types';\n"],"mappings":";;;AAmBA,SAAgB,EACd,GACA,IAA6B,CAAC,GACK;CACnC,IAAM,EAAE,iBAAc,GAAG,aAAU,YAAS,UAAU,eAAY;CAElE,IAAI,CAAC,OAAO,UAAU,CAAW,KAAK,IAAc,GAClD,MAAM,IAAI,EAA4B,0CAA0C;CAGlF,IAAI,MAAa,KAAA,MAAc,CAAC,OAAO,UAAU,CAAQ,KAAK,IAAW,IACvE,MAAM,IAAI,EAA4B,uCAAuC;CAG/E,IAAI,MAAY,KAAA,MAAc,CAAC,OAAO,SAAS,CAAO,KAAK,KAAW,IACpE,MAAM,IAAI,EAA4B,kDAAkD;CAG1F,IAAM,IAA2C,CAAC;CAElD,SAAS,IAA0C;EACjD,IAAI,GACA,IAAa;EAEjB,OAAO;GACL,OAAO,GAAuB;IAE5B,AADA,GAAS,OAAO,CAAM,GACtB,IAAU,KAAA;GACZ;GACA,aAAa,QAAQ,QAAQ;GAC7B,IAAI,GAAO,GAAe,GAA6B;IACrD,IAAI,GAAY,OAAO,QAAQ,OAAO,IAAI,EAAwB,CAAC;IAEnE,IAAI;IAEJ,IAAI;KACF,IAAc,gBAAgB,GAAO,EAAE,UAAU,EAAc,CAAC;IAClE,SAAS,GAAO;KACd,OAAO,QAAQ,OAAO,IAAI,EAAkB,8BAA8B,EAAE,OAAO,EAAM,CAAC,CAAC;IAC7F;IAEA,OAAO,IAAI,SAAkB,GAAS,MAAW;KAC/C,IAAM,IAAQ,OAAO,MAAM,GACvB,GACE,KAAU,GAA8B,MAAyB;MACjE,GAAS,UAAU,MAEvB,IAAU,KAAA,GAEN,KAAO,aAAa,CAAK,GAE7B,EAAG,CAAK;KACV,GACM,KAAc,MAA0B;MACxC,GAAS,UAAU,MAEvB,IAAU,KAAA,GAEN,KAAO,aAAa,CAAK,GAE7B,EAAM,KAAK;OAAE,OAAO;OAAa;OAAQ,QAAQ;MAAW,CAAC,GAC7D,EAAO,CAAM;KACf;KAQA,AANA,IAAU;MAAE,QAAQ;MAAY;KAAM,GAElC,MAAc,KAAA,MAChB,IAAQ,iBAAiB,EAAW,IAAI,EAAqB,CAAS,CAAC,GAAG,CAAS,IAGrF,QAAa,QAAQ,CAAC,CACnB,WAAW,EAAQ,CAAW,CAAC,CAAC,CAChC,MACE,MAAW;MACV,IAAI;MAEJ,IAAI;OACF,IAAe,gBAAgB,CAAM;MACvC,SAAS,GAAO;OACd,EAAW,IAAI,EAAkB,+BAA+B,EAAE,OAAO,EAAM,CAAC,CAAC;OAEjF;MACF;MAEI,GAAS,UAAU,MAEvB,EAAM,KAAK;OAAE,OAAO;OAAa,QAAQ;OAAa,OAAO;MAAa,CAAC,GAC3E,EAAO,GAAS,CAAY;KAC9B,IACC,MAAmB;MAClB,IAAM,IAAQ,aAAiB,QAAQ,IAAY,MAAM,OAAO,CAAK,CAAC;MAEtE,EAAW,IAAI,EAAkB,EAAM,SAAS,EAAE,SAAM,CAAC,CAAC;KAC5D,CACF;IACJ,CAAC;GACH;GACA,YAAkB;IAGhB,AAFA,IAAa,IACb,GAAS,OAAO,IAAI,EAAwB,CAAC,GAC7C,IAAU,KAAA;GACZ;EACF;CACF;CAEA,IAAM,IAAO,EAAW,MAAM,KAAK,EAAE,QAAQ,EAAY,GAAG,CAAQ,GAAG;EACrE;EACA,gBAAgB;EAChB;EACA;CACF,CAAC;CAOD,OALA,OAAO,eAAe,GAAM,SAAS;EACnC,YAAY;EACZ,WAAW;CACb,CAAC,GAEM;AACT"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import { createPool } from '../_pool.js';\nimport { MAX_CONCURRENCY, validateTimeout } from '../_pool-core.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors.js';\nimport type { SlotStrategy, WorkerOptions, WorkerPool } from '../types.js';\n\nexport type TestWorkerOptions = Omit<WorkerOptions, 'concurrency' | 'onSlotError'> & { concurrency?: number };\n\nexport type TestWorkerCall<TInput, TOutput> =\n | { input: TInput; status: 'fulfilled'; value: TOutput }\n | { input: TInput; reason: unknown; status: 'rejected' };\n\nexport type TestWorkerHandle<TInput, TOutput> = WorkerPool<TInput, TOutput> & {\n readonly calls: ReadonlyArray<TestWorkerCall<TInput, TOutput>>;\n};\n\nexport function createTestWorker<TInput, TOutput>(\n handler: (input: TInput) => TOutput | Promise<TOutput>,\n options: TestWorkerOptions = {},\n): TestWorkerHandle<TInput, TOutput> {\n const { concurrency = 1, maxQueue, onFull = 'reject', timeout } = options;\n\n if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY}`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (onFull !== 'reject' && onFull !== 'wait') {\n throw new FamiliarInvalidOptionsError('`onFull` must be \"reject\" or \"wait\"');\n }\n\n validateTimeout(timeout);\n\n const calls: TestWorkerCall<TInput, TOutput>[] = [];\n\n function makeSlot(): SlotStrategy<TInput, TOutput> {\n let current: { reject(reason: unknown): void; token: symbol } | undefined;\n let terminated = false;\n\n return {\n cancel(reason: unknown): void {\n current?.reject(reason);\n current = undefined;\n },\n run(input, transferables, timeoutMs): Promise<TOutput> {\n if (terminated) return Promise.reject(new FamiliarTerminatedError());\n\n let clonedInput: TInput;\n\n try {\n clonedInput = structuredClone(input, { transfer: transferables });\n } catch (error) {\n return Promise.reject(new FamiliarTaskError('Failed to clone task input', { cause: error }));\n }\n\n return new Promise<TOutput>((resolve, reject) => {\n const token = Symbol('task');\n let timer: ReturnType<typeof setTimeout> | undefined;\n const settle = (fn: (value: TOutput) => void, value: TOutput): void => {\n if (current?.token !== token) return;\n\n current = undefined;\n\n if (timer) clearTimeout(timer);\n\n fn(value);\n };\n const rejectTask = (reason: unknown): void => {\n if (current?.token !== token) return;\n\n current = undefined;\n\n if (timer) clearTimeout(timer);\n\n calls.push({ input: clonedInput, reason, status: 'rejected' });\n reject(reason);\n };\n\n current = { reject: rejectTask, token };\n\n if (timeoutMs !== undefined) {\n timer = setTimeout(() => rejectTask(new FamiliarTimeoutError(timeoutMs)), timeoutMs);\n }\n\n void Promise.resolve()\n .then(() => handler(clonedInput))\n .then(\n (output) => {\n let clonedOutput: TOutput;\n\n try {\n clonedOutput = structuredClone(output);\n } catch (error) {\n rejectTask(new FamiliarTaskError('Failed to clone task output', { cause: error }));\n\n return;\n }\n\n if (current?.token !== token) return;\n\n calls.push({ input: clonedInput, status: 'fulfilled', value: clonedOutput });\n settle(resolve, clonedOutput);\n },\n (error: unknown) => {\n const cause = error instanceof Error ? error : new Error(String(error));\n\n rejectTask(new FamiliarTaskError(cause.message, { cause }));\n },\n );\n });\n },\n terminate(): void {\n terminated = true;\n current?.reject(new FamiliarTerminatedError());\n current = undefined;\n },\n };\n }\n\n const pool = createPool(Array.from({ length: concurrency }, makeSlot), {\n concurrency,\n defaultTimeout: timeout,\n maxQueue,\n onFull,\n });\n\n Object.defineProperty(pool, 'calls', {\n enumerable: true,\n get: () => calls as ReadonlyArray<TestWorkerCall<TInput, TOutput>>,\n });\n\n return pool as TestWorkerHandle<TInput, TOutput>;\n}\n\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors.js';\nexport type { WorkerPool } from '../types.js';\n"],"mappings":";;;;AAoBA,SAAgB,EACd,GACA,IAA6B,CAAC,GACK;CACnC,IAAM,EAAE,iBAAc,GAAG,aAAU,YAAS,UAAU,eAAY;CAElE,IAAI,CAAC,OAAO,UAAU,CAAW,KAAK,IAAc,KAAK,IAAA,KACvD,MAAM,IAAI,EAA4B,gDAAiE;CAGzG,IAAI,MAAa,KAAA,MAAc,CAAC,OAAO,UAAU,CAAQ,KAAK,IAAW,IACvE,MAAM,IAAI,EAA4B,uCAAuC;CAG/E,IAAI,MAAW,YAAY,MAAW,QACpC,MAAM,IAAI,EAA4B,yCAAqC;CAG7E,EAAgB,CAAO;CAEvB,IAAM,IAA2C,CAAC;CAElD,SAAS,IAA0C;EACjD,IAAI,GACA,IAAa;EAEjB,OAAO;GACL,OAAO,GAAuB;IAE5B,AADA,GAAS,OAAO,CAAM,GACtB,IAAU,KAAA;GACZ;GACA,IAAI,GAAO,GAAe,GAA6B;IACrD,IAAI,GAAY,OAAO,QAAQ,OAAO,IAAI,EAAwB,CAAC;IAEnE,IAAI;IAEJ,IAAI;KACF,IAAc,gBAAgB,GAAO,EAAE,UAAU,EAAc,CAAC;IAClE,SAAS,GAAO;KACd,OAAO,QAAQ,OAAO,IAAI,EAAkB,8BAA8B,EAAE,OAAO,EAAM,CAAC,CAAC;IAC7F;IAEA,OAAO,IAAI,SAAkB,GAAS,MAAW;KAC/C,IAAM,IAAQ,OAAO,MAAM,GACvB,GACE,KAAU,GAA8B,MAAyB;MACjE,GAAS,UAAU,MAEvB,IAAU,KAAA,GAEN,KAAO,aAAa,CAAK,GAE7B,EAAG,CAAK;KACV,GACM,KAAc,MAA0B;MACxC,GAAS,UAAU,MAEvB,IAAU,KAAA,GAEN,KAAO,aAAa,CAAK,GAE7B,EAAM,KAAK;OAAE,OAAO;OAAa;OAAQ,QAAQ;MAAW,CAAC,GAC7D,EAAO,CAAM;KACf;KAQA,AANA,IAAU;MAAE,QAAQ;MAAY;KAAM,GAElC,MAAc,KAAA,MAChB,IAAQ,iBAAiB,EAAW,IAAI,EAAqB,CAAS,CAAC,GAAG,CAAS,IAGrF,QAAa,QAAQ,CAAC,CACnB,WAAW,EAAQ,CAAW,CAAC,CAAC,CAChC,MACE,MAAW;MACV,IAAI;MAEJ,IAAI;OACF,IAAe,gBAAgB,CAAM;MACvC,SAAS,GAAO;OACd,EAAW,IAAI,EAAkB,+BAA+B,EAAE,OAAO,EAAM,CAAC,CAAC;OAEjF;MACF;MAEI,GAAS,UAAU,MAEvB,EAAM,KAAK;OAAE,OAAO;OAAa,QAAQ;OAAa,OAAO;MAAa,CAAC,GAC3E,EAAO,GAAS,CAAY;KAC9B,IACC,MAAmB;MAClB,IAAM,IAAQ,aAAiB,QAAQ,IAAY,MAAM,OAAO,CAAK,CAAC;MAEtE,EAAW,IAAI,EAAkB,EAAM,SAAS,EAAE,SAAM,CAAC,CAAC;KAC5D,CACF;IACJ,CAAC;GACH;GACA,YAAkB;IAGhB,AAFA,IAAa,IACb,GAAS,OAAO,IAAI,EAAwB,CAAC,GAC7C,IAAU,KAAA;GACZ;EACF;CACF;CAEA,IAAM,IAAO,EAAW,MAAM,KAAK,EAAE,QAAQ,EAAY,GAAG,CAAQ,GAAG;EACrE;EACA,gBAAgB;EAChB;EACA;CACF,CAAC;CAOD,OALA,OAAO,eAAe,GAAM,SAAS;EACnC,YAAY;EACZ,WAAW;CACb,CAAC,GAEM;AACT"}
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FamiliarRuntimeError } from './errors';
1
+ import type { FamiliarRuntimeError } from './errors.js';
2
2
  export type WorkerStatus = 'idle' | 'running' | 'terminated';
3
3
  export type WorkerStats = {
4
4
  readonly active: number;
@@ -26,51 +26,30 @@ export type RunOptions = {
26
26
  /** Per-operation timeout in milliseconds. Overrides WorkerOptions.timeout. */
27
27
  timeout?: number;
28
28
  /** Values transferred to the worker instead of structured-cloned. */
29
- transferables?: Transferable[];
29
+ transferables?: readonly Transferable[];
30
30
  };
31
31
  export type DrainOptions = {
32
32
  /** Maximum time to wait before terminating remaining work. */
33
33
  timeout?: number;
34
34
  };
35
- export interface WorkerPool<TInput, TOutput> {
35
+ export interface PoolBase {
36
36
  readonly disposalSignal: AbortSignal;
37
37
  dispose(): void;
38
38
  readonly disposed: boolean;
39
39
  drain(options?: DrainOptions): Promise<void>;
40
- prime(): Promise<void>;
41
- run(input: TInput, options?: RunOptions): Promise<TOutput>;
42
40
  readonly stats: WorkerStats;
43
41
  readonly status: WorkerStatus;
44
42
  [Symbol.asyncDispose](): Promise<void>;
45
43
  [Symbol.dispose](): void;
46
44
  }
47
- export interface StreamWorkerPool<TInput, TChunk> {
48
- readonly disposalSignal: AbortSignal;
49
- dispose(): void;
50
- readonly disposed: boolean;
51
- drain(options?: DrainOptions): Promise<void>;
52
- prime(): Promise<void>;
45
+ export interface WorkerPool<TInput, TOutput> extends PoolBase {
46
+ run(input: TInput, options?: RunOptions): Promise<TOutput>;
47
+ }
48
+ export interface StreamWorkerPool<TInput, TChunk> extends PoolBase {
53
49
  runStream(input: TInput, options?: RunOptions): AsyncIterable<TChunk>;
54
- readonly stats: WorkerStats;
55
- readonly status: WorkerStatus;
56
- [Symbol.asyncDispose](): Promise<void>;
57
- [Symbol.dispose](): void;
58
50
  }
59
- export type BatchOptions = RunOptions;
60
- export type TaskGroup<TInput, TOutput> = {
61
- abort(reason?: unknown): void;
62
- drain(): Promise<PromiseSettledResult<TOutput>[]>;
63
- readonly name: string | undefined;
64
- readonly pending: number;
65
- run(input: TInput, options?: Omit<RunOptions, 'signal'>): Promise<TOutput>;
66
- readonly size: number;
67
- };
68
- export type TaskGroupOptions = {
69
- signal?: AbortSignal;
70
- };
71
51
  export type SlotStrategy<TInput, TOutput> = {
72
52
  cancel(reason: unknown): void;
73
- prime(): Promise<void>;
74
53
  run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput>;
75
54
  terminate(): void;
76
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,0FAA0F;IAC1F,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACpD,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU,CAAC,MAAM,EAAE,OAAO,CAAE,SAAQ,QAAQ;IAC3D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAE,SAAQ,QAAQ;IAChE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CACvE;AAED,MAAM,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,IAAI;IAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjG,SAAS,IAAI,IAAI,CAAC;CACnB,CAAC"}
package/dist/worker.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./_timers.cjs"),t=require("./errors.cjs"),n=require("./_pool.cjs"),r=require("./_stream-pool.cjs");require("./protocol.cjs");var i=512;function a(e={}){let{concurrency:n=1,maxQueue:r,onFull:a=`reject`,onSlotError:o,timeout:s}=e,c=n===`auto`?Math.max(1,globalThis.navigator?.hardwareConcurrency??1):n;if(!Number.isInteger(c)||c<1||c>i)throw new t.FamiliarInvalidOptionsError(`\`concurrency\` must be a positive integer ≤ ${i} or "auto"`);if(r!==void 0&&(!Number.isInteger(r)||r<1))throw new t.FamiliarInvalidOptionsError("`maxQueue` must be a positive integer");if(s!==void 0&&(!Number.isFinite(s)||s<=0))throw new t.FamiliarInvalidOptionsError("`timeout` must be a finite number greater than 0");return{concurrency:c,maxQueue:r,onFull:a,onSlotError:o,timeout:s}}function o(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 s(e){let n=Error(e.message);return n.name=e.name,n.stack=e.stack,new t.FamiliarTaskError(e.message,{cause:n})}var c=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,n){let r=()=>this.cancel(new t.FamiliarTerminatedError(`Stream consumer stopped`)),i=[],a=[],o=!1,s,c=e=>{let t=a.shift();t?t({done:!1,value:e}):i.push(e)},l=e=>{for(o=!0,s=e;a.length>0;)a.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,n.transferables??[],n.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(i.length>0)return{done:!1,value:i.shift()};if(s!==void 0)throw s;return o?{done:!0,value:void 0}:new Promise((e,t)=>{a.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return r(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.cancel(new t.FamiliarTerminatedError)}#o(n,r,i,a,o){if(this.#n)return Promise.reject(new t.FamiliarTerminatedError);if(this.#r)return Promise.reject(new t.FamiliarRuntimeError(`Worker slot is already busy`));try{let s=this.#s(),c=this.#i++;return new Promise((l,u)=>{let d={emit:o,id:c,reject:u,resolve:l};this.#r=d,i!==void 0&&(d.timer=setTimeout(()=>this.cancel(new t.FamiliarTimeoutError(i)),i),e.unrefTimer(d.timer));try{s.postMessage({id:c,input:n,kind:a,version:1},r)}catch(e){this.cancel(new t.FamiliarRuntimeError(`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 t.FamiliarRuntimeError(`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 n=new t.FamiliarRuntimeError(e.message||`Worker failed`);this.#a=void 0,this.#e?.(n),this.#l(`reject`,n)},this.#a=e,e}catch(e){throw new t.FamiliarRuntimeError(`Failed to create Worker`,{cause:e})}}#c(e){if(this.#r){if(!o(e)||e.id!==this.#r.id){this.cancel(new t.FamiliarRuntimeError(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#l(`reject`,s(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 l(e,t){return Array.from({length:t.concurrency},()=>new c(e,t.onSlotError))}function u(e,t={}){let r=a(t);return n.createPool(l(e,r),{concurrency:r.concurrency,defaultTimeout:r.timeout,maxQueue:r.maxQueue,onFull:r.onFull})}function d(e,t={}){let n=a(t);return r.createStreamPool(l(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}exports.FamiliarError=t.FamiliarError,exports.FamiliarInvalidOptionsError=t.FamiliarInvalidOptionsError,exports.FamiliarQueueFullError=t.FamiliarQueueFullError,exports.FamiliarRuntimeError=t.FamiliarRuntimeError,exports.FamiliarTaskError=t.FamiliarTaskError,exports.FamiliarTerminatedError=t.FamiliarTerminatedError,exports.FamiliarTimeoutError=t.FamiliarTimeoutError,exports.batch=n.batch,exports.createStreamWorker=d,exports.createTaskGroup=n.createTaskGroup,exports.createWorker=u;
1
+ const e=require("./_timers.cjs"),t=require("./errors.cjs"),n=require("./_pool-core.cjs"),r=require("./_pool.cjs");require("./_dev.cjs");const i=require("./_stream-pool.cjs");require("./protocol.cjs");function a(e={}){let{concurrency:r=1,maxQueue:i,onFull:a=`reject`,onSlotError:o,timeout:s}=e,c=r===`auto`?Math.min(512,Math.max(1,globalThis.navigator?.hardwareConcurrency??1)):r;if(!Number.isInteger(c)||c<1||c>512)throw new t.FamiliarInvalidOptionsError('`concurrency` must be a positive integer ≤ 512 or "auto"');if(i!==void 0&&(!Number.isInteger(i)||i<1))throw new t.FamiliarInvalidOptionsError("`maxQueue` must be a positive integer");if(a!==`reject`&&a!==`wait`)throw new t.FamiliarInvalidOptionsError('`onFull` must be "reject" or "wait"');return n.validateTimeout(s),{concurrency:c,maxQueue:i,onFull:a,onSlotError:o,timeout:s}}function o(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 s(e){let n=Error(e.message);return n.name=e.name,n.stack=e.stack,e.category===`protocol`?new t.FamiliarRuntimeError(e.message,{cause:n}):new t.FamiliarTaskError(e.message,{cause:n})}var c=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,n){let r=()=>this.cancel(new t.FamiliarTerminatedError(`Stream consumer stopped`)),i=[],a=[],o=!1,s,c=e=>{let t=a.shift();t?t({done:!1,value:e}):i.push(e)},l=e=>{for(o=!0,s=e;a.length>0;)a.shift()(e===void 0?{done:!0,value:void 0}:Promise.reject(e))};return{done:this.#o(e,[...n.transferables??[]],n.timeout,`stream`,c).then(()=>l(),e=>l(e)),iterable:{[Symbol.asyncIterator]:()=>({async next(){if(i.length>0)return{done:!1,value:i.shift()};if(s!==void 0)throw s;return o?{done:!0,value:void 0}:new Promise((e,t)=>{a.push(n=>{n instanceof Promise?n.then(e,t):e(n)})})},async return(){return r(),{done:!0,value:void 0}}})}}}terminate(){this.#n=!0,this.#c(),this.#d(`reject`,new t.FamiliarTerminatedError)}#o(n,r,i,a,o){if(this.#n)return Promise.reject(new t.FamiliarTerminatedError);if(this.#r)return Promise.reject(new t.FamiliarRuntimeError(`Worker slot is already busy`));try{let s=this.#s(),c=this.#i;return this.#i=c===2**53-1?0:c+1,new Promise((l,u)=>{let d={emit:o,id:c,kind:a,reject:u,resolve:l};this.#r=d,i!==void 0&&(d.timer=setTimeout(()=>this.cancel(new t.FamiliarTimeoutError(i)),i),e.unrefTimer(d.timer));try{s.postMessage({id:c,input:n,kind:a,version:1},r)}catch(e){this.cancel(new t.FamiliarRuntimeError(`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 t.FamiliarRuntimeError(`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=n=>this.#l(e,new t.FamiliarRuntimeError(n.message||`Worker failed`)),e.onmessageerror=()=>this.#l(e,new t.FamiliarRuntimeError(`Worker response could not be deserialized`)),this.#a=e,e}catch(e){throw new t.FamiliarRuntimeError(`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(!o(e)||e.id!==this.#r.id||this.#r.kind===`run`&&e.kind===`chunk`){this.cancel(new t.FamiliarRuntimeError(`Worker returned an incompatible protocol response`));return}if(e.kind===`chunk`){this.#r.emit?.(e.value);return}if(e.kind===`error`){this.#d(`reject`,s(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 l(e,t){let n=typeof e==`string`?e:e.href;return Array.from({length:t.concurrency},()=>new c(n,t.onSlotError))}function u(e,t={}){let n=a(t);return r.createPool(l(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}function d(e,t={}){let n=a(t);return i.createStreamPool(l(e,n),{concurrency:n.concurrency,defaultTimeout:n.timeout,maxQueue:n.maxQueue,onFull:n.onFull})}exports.FamiliarError=t.FamiliarError,exports.FamiliarInvalidOptionsError=t.FamiliarInvalidOptionsError,exports.FamiliarQueueFullError=t.FamiliarQueueFullError,exports.FamiliarRuntimeError=t.FamiliarRuntimeError,exports.FamiliarTaskError=t.FamiliarTaskError,exports.FamiliarTerminatedError=t.FamiliarTerminatedError,exports.FamiliarTimeoutError=t.FamiliarTimeoutError,exports.createStreamWorker=d,exports.createWorker=u,exports.runBatch=r.runBatch;
2
2
  //# sourceMappingURL=worker.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.cjs","names":["#onSlotError","#url","#worker","#settlePending","#disposed","#ensureWorker","#dispatch","#pending","#taskId","#onMessage"],"sources":["../src/worker.ts"],"sourcesContent":["export { batch, createTaskGroup } from './_pool';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { createPool } from './_pool';\nimport { createStreamPool, type StreamSlot } from './_stream-pool';\nimport { unrefTimer } from './_timers';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport { PROTOCOL_VERSION } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types';\n\nconst MAX_CONCURRENCY = 512;\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto' ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {\n throw new FamiliarInvalidOptionsError('`timeout` must be a finite number greater than 0');\n }\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n\n return (\n response.version === PROTOCOL_VERSION &&\n typeof response.id === 'number' &&\n (response.kind === 'chunk' || response.kind === 'error' || response.kind === 'result')\n );\n}\n\nfunction taskError(error: SerializedError): FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n this.#worker?.terminate();\n this.#worker = undefined;\n this.#settlePending('reject', reason);\n }\n\n prime(): Promise<void> {\n if (!this.#disposed) this.#ensureWorker();\n\n return Promise.resolve();\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, options.transferables ?? [], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.cancel(new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId++;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => this.#onMessage(event.data);\n worker.onerror = (event) => {\n const error = new FamiliarRuntimeError(event.message || 'Worker failed');\n\n this.#worker = undefined;\n this.#onSlotError?.(error);\n this.#settlePending('reject', error);\n };\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (!isWorkerResponse<TOutput>(message) || message.id !== this.#pending.id) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', taskError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(url, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"worker.cjs","names":[],"sources":["../src/worker.ts"],"sourcesContent":["export type { BatchOptions } from './_pool.js';\nexport { runBatch } from './_pool.js';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nexport type {\n DrainOptions,\n PoolBase,\n RunOptions,\n StreamWorkerPool,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types.js';\n\nimport { warn } from './_dev.js';\nimport { createPool } from './_pool.js';\nimport { MAX_CONCURRENCY, validateTimeout } from './_pool-core.js';\nimport { createStreamPool, type StreamSlot } from './_stream-pool.js';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { SerializedError, WorkerResponse } from './protocol.js';\nimport { PROTOCOL_VERSION } from './protocol.js';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types.js';\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n kind: 'run' | 'stream';\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto'\n ? Math.min(MAX_CONCURRENCY, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1))\n : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (onFull !== 'reject' && onFull !== 'wait') {\n throw new FamiliarInvalidOptionsError('`onFull` must be \"reject\" or \"wait\"');\n }\n\n validateTimeout(timeout);\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n if (\n response.version !== PROTOCOL_VERSION ||\n typeof response.id !== 'number' ||\n !Number.isSafeInteger(response.id) ||\n response.id < 0\n )\n return false;\n\n if (response.kind === 'chunk' || response.kind === 'result') return 'value' in response;\n if (response.kind !== 'error' || typeof response.error !== 'object' || response.error === null) return false;\n\n return (\n (response.error.category === undefined || response.error.category === 'protocol') &&\n typeof response.error.message === 'string' &&\n typeof response.error.name === 'string' &&\n (response.error.stack === undefined || typeof response.error.stack === 'string')\n );\n}\n\nfunction responseError(error: SerializedError): FamiliarRuntimeError | FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return error.category === 'protocol'\n ? new FamiliarRuntimeError(error.message, { cause })\n : new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n if (!this.#pending) return;\n this.#stopWorker();\n this.#settlePending('reject', reason);\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, [...(options.transferables ?? [])], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.#stopWorker();\n this.#settlePending('reject', new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId;\n this.#taskId = id === Number.MAX_SAFE_INTEGER ? 0 : id + 1;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, kind, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => {\n if (this.#worker === worker) this.#onMessage(event.data);\n };\n worker.onerror = (event) => this.#failWorker(worker, new FamiliarRuntimeError(event.message || 'Worker failed'));\n worker.onmessageerror = () =>\n this.#failWorker(worker, new FamiliarRuntimeError('Worker response could not be deserialized'));\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #stopWorker(): void {\n const worker = this.#worker;\n this.#worker = undefined;\n if (!worker) return;\n\n worker.onmessage = null;\n worker.onerror = null;\n worker.onmessageerror = null;\n worker.terminate();\n }\n\n #failWorker(worker: Worker, error: FamiliarRuntimeError): void {\n if (this.#worker !== worker) return;\n\n this.#stopWorker();\n this.#settlePending('reject', error);\n\n try {\n this.#onSlotError?.(error);\n } catch {\n warn('onSlotError callback failed; Familiar continued replacing the failed worker slot.');\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (\n !isWorkerResponse<TOutput>(message) ||\n message.id !== this.#pending.id ||\n (this.#pending.kind === 'run' && message.kind === 'chunk')\n ) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', responseError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n const resolvedUrl = typeof url === 'string' ? url : url.href;\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(resolvedUrl, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
package/dist/worker.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export { batch, createTaskGroup } from './_pool';
2
- export { FamiliarError, FamiliarInvalidOptionsError, FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTaskError, FamiliarTerminatedError, FamiliarTimeoutError, } from './errors';
3
- export type { BatchOptions, DrainOptions, RunOptions, StreamWorkerPool, TaskGroup, TaskGroupOptions, WorkerOptions, WorkerPool, WorkerStats, WorkerStatus, } from './types';
4
- import type { StreamWorkerPool, WorkerOptions, WorkerPool } from './types';
1
+ export type { BatchOptions } from './_pool.js';
2
+ export { runBatch } from './_pool.js';
3
+ export { FamiliarError, FamiliarInvalidOptionsError, FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTaskError, FamiliarTerminatedError, FamiliarTimeoutError, } from './errors.js';
4
+ export type { DrainOptions, PoolBase, RunOptions, StreamWorkerPool, WorkerOptions, WorkerPool, WorkerStats, WorkerStatus, } from './types.js';
5
+ import type { StreamWorkerPool, WorkerOptions, WorkerPool } from './types.js';
5
6
  export type RunningStream<TChunk> = {
6
7
  done: Promise<void>;
7
8
  iterable: AsyncIterable<TChunk>;
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,SAAS,CAAC;AAcjB,OAAO,KAAK,EAA4B,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAoBrG,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI;IAClC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjC,CAAC;AA2OF,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAC1C,GAAG,EAAE,GAAG,GAAG,MAAM,EACjB,OAAO,GAAE,aAAkB,GAC1B,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAS7B;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAC/C,GAAG,EAAE,GAAG,GAAG,MAAM,EACjB,OAAO,GAAE,aAAkB,GAC1B,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CASlC"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAgBpB,OAAO,KAAK,EAA4B,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAmBxG,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI;IAClC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjC,CAAC;AAmRF,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAC1C,GAAG,EAAE,GAAG,GAAG,MAAM,EACjB,OAAO,GAAE,aAAkB,GAC1B,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAS7B;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAC/C,GAAG,EAAE,GAAG,GAAG,MAAM,EACjB,OAAO,GAAE,aAAkB,GAC1B,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CASlC"}
package/dist/worker.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import { unrefTimer as e } from "./_timers.js";
2
2
  import { FamiliarError as t, FamiliarInvalidOptionsError as n, FamiliarQueueFullError as r, FamiliarRuntimeError as i, FamiliarTaskError as a, FamiliarTerminatedError as o, FamiliarTimeoutError as s } from "./errors.js";
3
- import { batch as c, createPool as l, createTaskGroup as u } from "./_pool.js";
3
+ import { validateTimeout as c } from "./_pool-core.js";
4
+ import { createPool as l, runBatch as u } from "./_pool.js";
5
+ import "./_dev.js";
4
6
  import { createStreamPool as d } from "./_stream-pool.js";
5
7
  import "./protocol.js";
6
8
  //#region src/worker.ts
7
- var f = 512;
8
- function p(e = {}) {
9
- let { concurrency: t = 1, maxQueue: r, onFull: i = "reject", onSlotError: a, timeout: o } = e, s = t === "auto" ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : t;
10
- if (!Number.isInteger(s) || s < 1 || s > f) throw new n(`\`concurrency\` must be a positive integer ≤ ${f} or "auto"`);
9
+ function f(e = {}) {
10
+ let { concurrency: t = 1, maxQueue: r, onFull: i = "reject", onSlotError: a, timeout: o } = e, s = t === "auto" ? Math.min(512, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1)) : t;
11
+ if (!Number.isInteger(s) || s < 1 || s > 512) throw new n("`concurrency` must be a positive integer ≤ 512 or \"auto\"");
11
12
  if (r !== void 0 && (!Number.isInteger(r) || r < 1)) throw new n("`maxQueue` must be a positive integer");
12
- if (o !== void 0 && (!Number.isFinite(o) || o <= 0)) throw new n("`timeout` must be a finite number greater than 0");
13
- return {
13
+ if (i !== "reject" && i !== "wait") throw new n("`onFull` must be \"reject\" or \"wait\"");
14
+ return c(o), {
14
15
  concurrency: s,
15
16
  maxQueue: r,
16
17
  onFull: i,
@@ -18,16 +19,16 @@ function p(e = {}) {
18
19
  timeout: o
19
20
  };
20
21
  }
21
- function m(e) {
22
+ function p(e) {
22
23
  if (typeof e != "object" || !e) return !1;
23
24
  let t = e;
24
- return t.version === 1 && typeof t.id == "number" && (t.kind === "chunk" || t.kind === "error" || t.kind === "result");
25
+ 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");
25
26
  }
26
- function h(e) {
27
+ function m(e) {
27
28
  let t = Error(e.message);
28
- return t.name = e.name, t.stack = e.stack, new a(e.message, { cause: t });
29
+ return t.name = e.name, t.stack = e.stack, e.category === "protocol" ? new i(e.message, { cause: t }) : new a(e.message, { cause: t });
29
30
  }
30
- var g = class {
31
+ var h = class {
31
32
  #e;
32
33
  #t;
33
34
  #n = !1;
@@ -38,10 +39,7 @@ var g = class {
38
39
  this.#t = e, this.#e = t;
39
40
  }
40
41
  cancel(e) {
41
- this.#a?.terminate(), this.#a = void 0, this.#l("reject", e);
42
- }
43
- prime() {
44
- return this.#n || this.#s(), Promise.resolve();
42
+ this.#r && (this.#c(), this.#d("reject", e));
45
43
  }
46
44
  run(e, t, n) {
47
45
  return this.#o(e, t, n, "run");
@@ -60,7 +58,7 @@ var g = class {
60
58
  } : Promise.reject(e));
61
59
  };
62
60
  return {
63
- done: this.#o(e, t.transferables ?? [], t.timeout, "stream", c).then(() => l(), (e) => l(e)),
61
+ done: this.#o(e, [...t.transferables ?? []], t.timeout, "stream", c).then(() => l(), (e) => l(e)),
64
62
  iterable: { [Symbol.asyncIterator]: () => ({
65
63
  async next() {
66
64
  if (r.length > 0) return {
@@ -87,17 +85,18 @@ var g = class {
87
85
  };
88
86
  }
89
87
  terminate() {
90
- this.#n = !0, this.cancel(new o());
88
+ this.#n = !0, this.#c(), this.#d("reject", new o());
91
89
  }
92
90
  #o(t, n, r, a, c) {
93
91
  if (this.#n) return Promise.reject(new o());
94
92
  if (this.#r) return Promise.reject(new i("Worker slot is already busy"));
95
93
  try {
96
- let o = this.#s(), l = this.#i++;
97
- return new Promise((u, d) => {
94
+ let o = this.#s(), l = this.#i;
95
+ return this.#i = l === 2 ** 53 - 1 ? 0 : l + 1, new Promise((u, d) => {
98
96
  let f = {
99
97
  emit: c,
100
98
  id: l,
99
+ kind: a,
101
100
  reject: d,
102
101
  resolve: u
103
102
  };
@@ -122,17 +121,28 @@ var g = class {
122
121
  if (typeof Worker > "u") throw new i("Worker API is unavailable in this runtime");
123
122
  try {
124
123
  let e = new Worker(this.#t, { type: "module" });
125
- return e.onmessage = (e) => this.#c(e.data), e.onerror = (e) => {
126
- let t = new i(e.message || "Worker failed");
127
- this.#a = void 0, this.#e?.(t), this.#l("reject", t);
128
- }, this.#a = e, e;
124
+ return e.onmessage = (t) => {
125
+ this.#a === e && this.#u(t.data);
126
+ }, e.onerror = (t) => this.#l(e, new i(t.message || "Worker failed")), e.onmessageerror = () => this.#l(e, new i("Worker response could not be deserialized")), this.#a = e, e;
129
127
  } catch (e) {
130
128
  throw new i("Failed to create Worker", { cause: e });
131
129
  }
132
130
  }
133
- #c(e) {
131
+ #c() {
132
+ let e = this.#a;
133
+ this.#a = void 0, e && (e.onmessage = null, e.onerror = null, e.onmessageerror = null, e.terminate());
134
+ }
135
+ #l(e, t) {
136
+ if (this.#a === e) {
137
+ this.#c(), this.#d("reject", t);
138
+ try {
139
+ this.#e?.(t);
140
+ } catch {}
141
+ }
142
+ }
143
+ #u(e) {
134
144
  if (this.#r) {
135
- if (!m(e) || e.id !== this.#r.id) {
145
+ if (!p(e) || e.id !== this.#r.id || this.#r.kind === "run" && e.kind === "chunk") {
136
146
  this.cancel(new i("Worker returned an incompatible protocol response"));
137
147
  return;
138
148
  }
@@ -141,32 +151,33 @@ var g = class {
141
151
  return;
142
152
  }
143
153
  if (e.kind === "error") {
144
- this.#l("reject", h(e.error));
154
+ this.#d("reject", m(e.error));
145
155
  return;
146
156
  }
147
- this.#l("resolve", e.value);
157
+ this.#d("resolve", e.value);
148
158
  }
149
159
  }
150
- #l(e, t) {
160
+ #d(e, t) {
151
161
  let n = this.#r;
152
162
  n && (this.#r = void 0, n.timer && clearTimeout(n.timer), e === "resolve" ? n.resolve(t) : n.reject(t));
153
163
  }
154
164
  };
155
- function _(e, t) {
156
- return Array.from({ length: t.concurrency }, () => new g(e, t.onSlotError));
165
+ function g(e, t) {
166
+ let n = typeof e == "string" ? e : e.href;
167
+ return Array.from({ length: t.concurrency }, () => new h(n, t.onSlotError));
157
168
  }
158
- function v(e, t = {}) {
159
- let n = p(t);
160
- return l(_(e, n), {
169
+ function _(e, t = {}) {
170
+ let n = f(t);
171
+ return l(g(e, n), {
161
172
  concurrency: n.concurrency,
162
173
  defaultTimeout: n.timeout,
163
174
  maxQueue: n.maxQueue,
164
175
  onFull: n.onFull
165
176
  });
166
177
  }
167
- function y(e, t = {}) {
168
- let n = p(t);
169
- return d(_(e, n), {
178
+ function v(e, t = {}) {
179
+ let n = f(t);
180
+ return d(g(e, n), {
170
181
  concurrency: n.concurrency,
171
182
  defaultTimeout: n.timeout,
172
183
  maxQueue: n.maxQueue,
@@ -174,6 +185,6 @@ function y(e, t = {}) {
174
185
  });
175
186
  }
176
187
  //#endregion
177
- export { t as FamiliarError, n as FamiliarInvalidOptionsError, r as FamiliarQueueFullError, i as FamiliarRuntimeError, a as FamiliarTaskError, o as FamiliarTerminatedError, s as FamiliarTimeoutError, c as batch, y as createStreamWorker, u as createTaskGroup, v as createWorker };
188
+ export { t as FamiliarError, n as FamiliarInvalidOptionsError, r as FamiliarQueueFullError, i as FamiliarRuntimeError, a as FamiliarTaskError, o as FamiliarTerminatedError, s as FamiliarTimeoutError, v as createStreamWorker, _ as createWorker, u as runBatch };
178
189
 
179
190
  //# sourceMappingURL=worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","names":["#onSlotError","#url","#worker","#settlePending","#disposed","#ensureWorker","#dispatch","#pending","#taskId","#onMessage"],"sources":["../src/worker.ts"],"sourcesContent":["export { batch, createTaskGroup } from './_pool';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\n\nimport { createPool } from './_pool';\nimport { createStreamPool, type StreamSlot } from './_stream-pool';\nimport { unrefTimer } from './_timers';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport { PROTOCOL_VERSION } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types';\n\nconst MAX_CONCURRENCY = 512;\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto' ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {\n throw new FamiliarInvalidOptionsError('`timeout` must be a finite number greater than 0');\n }\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n\n return (\n response.version === PROTOCOL_VERSION &&\n typeof response.id === 'number' &&\n (response.kind === 'chunk' || response.kind === 'error' || response.kind === 'result')\n );\n}\n\nfunction taskError(error: SerializedError): FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n this.#worker?.terminate();\n this.#worker = undefined;\n this.#settlePending('reject', reason);\n }\n\n prime(): Promise<void> {\n if (!this.#disposed) this.#ensureWorker();\n\n return Promise.resolve();\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, options.transferables ?? [], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.cancel(new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId++;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => this.#onMessage(event.data);\n worker.onerror = (event) => {\n const error = new FamiliarRuntimeError(event.message || 'Worker failed');\n\n this.#worker = undefined;\n this.#onSlotError?.(error);\n this.#settlePending('reject', error);\n };\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (!isWorkerResponse<TOutput>(message) || message.id !== this.#pending.id) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', taskError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(url, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","names":[],"sources":["../src/worker.ts"],"sourcesContent":["export type { BatchOptions } from './_pool.js';\nexport { runBatch } from './_pool.js';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nexport type {\n DrainOptions,\n PoolBase,\n RunOptions,\n StreamWorkerPool,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types.js';\n\nimport { warn } from './_dev.js';\nimport { createPool } from './_pool.js';\nimport { MAX_CONCURRENCY, validateTimeout } from './_pool-core.js';\nimport { createStreamPool, type StreamSlot } from './_stream-pool.js';\nimport { unrefTimer } from './_timers.js';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors.js';\nimport type { SerializedError, WorkerResponse } from './protocol.js';\nimport { PROTOCOL_VERSION } from './protocol.js';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } from './types.js';\n\ntype ResolvedOptions = {\n concurrency: number;\n maxQueue: number | undefined;\n onFull: 'reject' | 'wait';\n onSlotError: WorkerOptions['onSlotError'];\n timeout: number | undefined;\n};\n\ntype Pending<TOutput> = {\n emit?: (value: TOutput) => void;\n id: number;\n kind: 'run' | 'stream';\n reject: (reason: unknown) => void;\n resolve: (value: TOutput) => void;\n timer?: ReturnType<typeof setTimeout>;\n};\n\nexport type RunningStream<TChunk> = {\n done: Promise<void>;\n iterable: AsyncIterable<TChunk>;\n};\n\nfunction resolveOptions(options: WorkerOptions = {}): ResolvedOptions {\n const { concurrency = 1, maxQueue, onFull = 'reject', onSlotError, timeout } = options;\n const resolvedConcurrency =\n concurrency === 'auto'\n ? Math.min(MAX_CONCURRENCY, Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1))\n : concurrency;\n\n if (!Number.isInteger(resolvedConcurrency) || resolvedConcurrency < 1 || resolvedConcurrency > MAX_CONCURRENCY) {\n throw new FamiliarInvalidOptionsError(`\\`concurrency\\` must be a positive integer ≤ ${MAX_CONCURRENCY} or \"auto\"`);\n }\n\n if (maxQueue !== undefined && (!Number.isInteger(maxQueue) || maxQueue < 1)) {\n throw new FamiliarInvalidOptionsError('`maxQueue` must be a positive integer');\n }\n\n if (onFull !== 'reject' && onFull !== 'wait') {\n throw new FamiliarInvalidOptionsError('`onFull` must be \"reject\" or \"wait\"');\n }\n\n validateTimeout(timeout);\n\n return { concurrency: resolvedConcurrency, maxQueue, onFull, onSlotError, timeout };\n}\n\nfunction isWorkerResponse<TOutput>(value: unknown): value is WorkerResponse<TOutput> {\n if (typeof value !== 'object' || value === null) return false;\n\n const response = value as Partial<WorkerResponse<TOutput>>;\n if (\n response.version !== PROTOCOL_VERSION ||\n typeof response.id !== 'number' ||\n !Number.isSafeInteger(response.id) ||\n response.id < 0\n )\n return false;\n\n if (response.kind === 'chunk' || response.kind === 'result') return 'value' in response;\n if (response.kind !== 'error' || typeof response.error !== 'object' || response.error === null) return false;\n\n return (\n (response.error.category === undefined || response.error.category === 'protocol') &&\n typeof response.error.message === 'string' &&\n typeof response.error.name === 'string' &&\n (response.error.stack === undefined || typeof response.error.stack === 'string')\n );\n}\n\nfunction responseError(error: SerializedError): FamiliarRuntimeError | FamiliarTaskError {\n const cause = new Error(error.message);\n\n cause.name = error.name;\n cause.stack = error.stack;\n\n return error.category === 'protocol'\n ? new FamiliarRuntimeError(error.message, { cause })\n : new FamiliarTaskError(error.message, { cause });\n}\n\nclass Slot<TInput, TOutput> implements SlotStrategy<TInput, TOutput>, StreamSlot<TInput, TOutput> {\n readonly #onSlotError: WorkerOptions['onSlotError'];\n readonly #url: URL | string;\n #disposed = false;\n #pending: Pending<TOutput> | undefined;\n #taskId = 0;\n #worker: Worker | undefined;\n\n constructor(url: URL | string, onSlotError: WorkerOptions['onSlotError']) {\n this.#url = url;\n this.#onSlotError = onSlotError;\n }\n\n cancel(reason: unknown): void {\n if (!this.#pending) return;\n this.#stopWorker();\n this.#settlePending('reject', reason);\n }\n\n run(input: TInput, transferables: Transferable[], timeout: number | undefined): Promise<TOutput> {\n return this.#dispatch(input, transferables, timeout, 'run') as Promise<TOutput>;\n }\n\n stream(input: TInput, options: RunOptions): RunningStream<TOutput> {\n const stop = () => this.cancel(new FamiliarTerminatedError('Stream consumer stopped'));\n const chunks: TOutput[] = [];\n const waiters: Array<(result: IteratorResult<TOutput>) => void> = [];\n let done = false;\n let error: unknown;\n const emit = (value: TOutput) => {\n const waiter = waiters.shift();\n\n if (waiter) waiter({ done: false, value });\n else chunks.push(value);\n };\n const finish = (reason?: unknown) => {\n done = true;\n error = reason;\n\n while (waiters.length > 0) {\n const waiter = waiters.shift()!;\n\n if (reason !== undefined) waiter(Promise.reject(reason) as never);\n else waiter({ done: true, value: undefined as never });\n }\n };\n const donePromise = this.#dispatch(input, [...(options.transferables ?? [])], options.timeout, 'stream', emit).then(\n () => finish(),\n (reason: unknown) => finish(reason),\n );\n\n return {\n done: donePromise,\n iterable: {\n [Symbol.asyncIterator]: () => ({\n async next(): Promise<IteratorResult<TOutput>> {\n if (chunks.length > 0) return { done: false, value: chunks.shift()! };\n\n if (error !== undefined) throw error;\n\n if (done) return { done: true, value: undefined as never };\n\n return new Promise<IteratorResult<TOutput>>((resolve, reject) => {\n waiters.push((result) => {\n if (result instanceof Promise) void result.then(resolve, reject);\n else resolve(result);\n });\n });\n },\n async return(): Promise<IteratorResult<TOutput>> {\n stop();\n\n return { done: true, value: undefined as never };\n },\n }),\n },\n };\n }\n\n terminate(): void {\n this.#disposed = true;\n this.#stopWorker();\n this.#settlePending('reject', new FamiliarTerminatedError());\n }\n\n #dispatch(\n input: TInput,\n transferables: Transferable[],\n timeout: number | undefined,\n kind: 'run' | 'stream',\n emit?: (value: TOutput) => void,\n ): Promise<TOutput> {\n if (this.#disposed) return Promise.reject(new FamiliarTerminatedError());\n\n if (this.#pending) return Promise.reject(new FamiliarRuntimeError('Worker slot is already busy'));\n\n try {\n const worker = this.#ensureWorker();\n const id = this.#taskId;\n this.#taskId = id === Number.MAX_SAFE_INTEGER ? 0 : id + 1;\n\n return new Promise<TOutput>((resolve, reject) => {\n const pending: Pending<TOutput> = { emit, id, kind, reject, resolve };\n\n this.#pending = pending;\n\n if (timeout !== undefined) {\n pending.timer = setTimeout(() => this.cancel(new FamiliarTimeoutError(timeout)), timeout);\n unrefTimer(pending.timer);\n }\n\n try {\n worker.postMessage({ id, input, kind, version: PROTOCOL_VERSION }, transferables);\n } catch (error) {\n this.cancel(new FamiliarRuntimeError('Failed to post message to worker', { cause: error }));\n }\n });\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n #ensureWorker(): Worker {\n if (this.#worker) return this.#worker;\n\n if (typeof Worker === 'undefined') throw new FamiliarRuntimeError('Worker API is unavailable in this runtime');\n\n try {\n const worker = new Worker(this.#url, { type: 'module' });\n\n worker.onmessage = (event: MessageEvent<unknown>) => {\n if (this.#worker === worker) this.#onMessage(event.data);\n };\n worker.onerror = (event) => this.#failWorker(worker, new FamiliarRuntimeError(event.message || 'Worker failed'));\n worker.onmessageerror = () =>\n this.#failWorker(worker, new FamiliarRuntimeError('Worker response could not be deserialized'));\n this.#worker = worker;\n\n return worker;\n } catch (error) {\n throw new FamiliarRuntimeError('Failed to create Worker', { cause: error });\n }\n }\n\n #stopWorker(): void {\n const worker = this.#worker;\n this.#worker = undefined;\n if (!worker) return;\n\n worker.onmessage = null;\n worker.onerror = null;\n worker.onmessageerror = null;\n worker.terminate();\n }\n\n #failWorker(worker: Worker, error: FamiliarRuntimeError): void {\n if (this.#worker !== worker) return;\n\n this.#stopWorker();\n this.#settlePending('reject', error);\n\n try {\n this.#onSlotError?.(error);\n } catch {\n warn('onSlotError callback failed; Familiar continued replacing the failed worker slot.');\n }\n }\n\n #onMessage(message: unknown): void {\n if (!this.#pending) return;\n\n if (\n !isWorkerResponse<TOutput>(message) ||\n message.id !== this.#pending.id ||\n (this.#pending.kind === 'run' && message.kind === 'chunk')\n ) {\n this.cancel(new FamiliarRuntimeError('Worker returned an incompatible protocol response'));\n\n return;\n }\n\n if (message.kind === 'chunk') {\n this.#pending.emit?.(message.value);\n\n return;\n }\n\n if (message.kind === 'error') {\n this.#settlePending('reject', responseError(message.error));\n\n return;\n }\n\n this.#settlePending('resolve', message.value);\n }\n\n #settlePending(kind: 'resolve' | 'reject', value: unknown): void {\n const pending = this.#pending;\n\n if (!pending) return;\n\n this.#pending = undefined;\n\n if (pending.timer) clearTimeout(pending.timer);\n\n if (kind === 'resolve') pending.resolve(value as TOutput);\n else pending.reject(value);\n }\n}\n\nfunction slots<TInput, TOutput>(url: URL | string, options: ResolvedOptions): Slot<TInput, TOutput>[] {\n const resolvedUrl = typeof url === 'string' ? url : url.href;\n return Array.from({ length: options.concurrency }, () => new Slot<TInput, TOutput>(resolvedUrl, options.onSlotError));\n}\n\n/** Create a pool backed by an ES module worker registered with exposeTask(). */\nexport function createWorker<TInput, TOutput>(\n url: URL | string,\n options: WorkerOptions = {},\n): WorkerPool<TInput, TOutput> {\n const resolved = resolveOptions(options);\n\n return createPool(slots<TInput, TOutput>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n\n/** Create a stream-only pool backed by an ES module worker registered with exposeStream(). */\nexport function createStreamWorker<TInput, TChunk>(\n url: URL | string,\n options: WorkerOptions = {},\n): StreamWorkerPool<TInput, TChunk> {\n const resolved = resolveOptions(options);\n\n return createStreamPool(slots<TInput, TChunk>(url, resolved), {\n concurrency: resolved.concurrency,\n defaultTimeout: resolved.timeout,\n maxQueue: resolved.maxQueue,\n onFull: resolved.onFull,\n });\n}\n"],"mappings":"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"}