@vielzeug/familiar 2.0.0 → 2.0.2

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.
@@ -15,6 +15,6 @@ export type TestWorkerHandle<TInput, TOutput> = WorkerPool<TInput, TOutput> & {
15
15
  readonly calls: ReadonlyArray<TestWorkerCall<TInput, TOutput>>;
16
16
  };
17
17
  export declare function createTestWorker<TInput, TOutput>(handler: (input: TInput) => TOutput | Promise<TOutput>, options?: TestWorkerOptions): TestWorkerHandle<TInput, TOutput>;
18
- export type { WorkerPool } from '../types';
19
18
  export { FamiliarError, FamiliarInvalidOptionsError, FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTaskError, FamiliarTerminatedError, FamiliarTimeoutError, } from '../errors';
19
+ export type { WorkerPool } from '../types';
20
20
  //# sourceMappingURL=testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing/testing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUxE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,aAAa,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9G,MAAM,MAAM,cAAc,CAAC,MAAM,EAAE,OAAO,IACxC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAElH,MAAM,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,IAAI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC5E,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChE,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACtD,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAmHnC;AAED,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing/testing.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAgB,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,GAAG,aAAa,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9G,MAAM,MAAM,cAAc,CAAC,MAAM,EAAE,OAAO,IACtC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,gBAAgB,CAAC,MAAM,EAAE,OAAO,IAAI,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC5E,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAChE,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACtD,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAmHnC;AAED,OAAO,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../../src/testing/testing.ts"],"sourcesContent":["import type { SlotStrategy, WorkerOptions, WorkerPool } from '../types';\n\nimport { createPool } from '../_pool';\nimport {\n FamiliarInvalidOptionsError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors';\n\nexport type TestWorkerOptions = Omit<WorkerOptions, 'concurrency' | 'onSlotError'> & { concurrency?: number };\n\nexport type TestWorkerCall<TInput, TOutput> =\n { input: TInput; status: 'fulfilled'; value: TOutput } | { 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 type { WorkerPool } from '../types';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from '../errors';\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';\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"}
package/dist/types.d.ts CHANGED
@@ -33,28 +33,28 @@ export type DrainOptions = {
33
33
  timeout?: number;
34
34
  };
35
35
  export interface WorkerPool<TInput, TOutput> {
36
- [Symbol.asyncDispose](): Promise<void>;
37
- [Symbol.dispose](): void;
38
- readonly disposed: boolean;
39
36
  readonly disposalSignal: AbortSignal;
40
37
  dispose(): void;
38
+ readonly disposed: boolean;
41
39
  drain(options?: DrainOptions): Promise<void>;
42
40
  prime(): Promise<void>;
43
41
  run(input: TInput, options?: RunOptions): Promise<TOutput>;
44
42
  readonly stats: WorkerStats;
45
43
  readonly status: WorkerStatus;
46
- }
47
- export interface StreamWorkerPool<TInput, TChunk> {
48
44
  [Symbol.asyncDispose](): Promise<void>;
49
45
  [Symbol.dispose](): void;
50
- readonly disposed: boolean;
46
+ }
47
+ export interface StreamWorkerPool<TInput, TChunk> {
51
48
  readonly disposalSignal: AbortSignal;
52
49
  dispose(): void;
50
+ readonly disposed: boolean;
53
51
  drain(options?: DrainOptions): Promise<void>;
54
52
  prime(): Promise<void>;
55
53
  runStream(input: TInput, options?: RunOptions): AsyncIterable<TChunk>;
56
54
  readonly stats: WorkerStats;
57
55
  readonly status: WorkerStatus;
56
+ [Symbol.asyncDispose](): Promise<void>;
57
+ [Symbol.dispose](): void;
58
58
  }
59
59
  export type BatchOptions = RunOptions;
60
60
  export type TaskGroup<TInput, TOutput> = {
@@ -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":"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"}
package/dist/worker.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./_timers.cjs"),n=require("./_pool.cjs"),r=require("./_stream-pool.cjs");require("./protocol.cjs");var i=512;function a(t={}){let{concurrency:n=1,maxQueue:r,onFull:a=`reject`,onSlotError:o,timeout:s}=t,c=n===`auto`?Math.max(1,globalThis.navigator?.hardwareConcurrency??1):n;if(!Number.isInteger(c)||c<1||c>i)throw new e.FamiliarInvalidOptionsError(`\`concurrency\` must be a positive integer ≤ ${i} or "auto"`);if(r!==void 0&&(!Number.isInteger(r)||r<1))throw new e.FamiliarInvalidOptionsError("`maxQueue` must be a positive integer");if(s!==void 0&&(!Number.isFinite(s)||s<=0))throw new e.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(t){let n=Error(t.message);return n.name=t.name,n.stack=t.stack,new e.FamiliarTaskError(t.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(t,n){let r=()=>this.cancel(new e.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(t,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 e.FamiliarTerminatedError)}#o(n,r,i,a,o){if(this.#n)return Promise.reject(new e.FamiliarTerminatedError);if(this.#r)return Promise.reject(new e.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 e.FamiliarTimeoutError(i)),i),t.unrefTimer(d.timer));try{s.postMessage({id:c,input:n,kind:a,version:1},r)}catch(t){this.cancel(new e.FamiliarRuntimeError(`Failed to post message to worker`,{cause:t}))}})}catch(e){return Promise.reject(e)}}#s(){if(this.#a)return this.#a;if(typeof Worker>`u`)throw new e.FamiliarRuntimeError(`Worker API is unavailable in this runtime`);try{let t=new Worker(this.#t,{type:`module`});return t.onmessage=e=>this.#c(e.data),t.onerror=t=>{let n=new e.FamiliarRuntimeError(t.message||`Worker failed`);this.#a=void 0,this.#e?.(n),this.#l(`reject`,n)},this.#a=t,t}catch(t){throw new e.FamiliarRuntimeError(`Failed to create Worker`,{cause:t})}}#c(t){if(this.#r){if(!o(t)||t.id!==this.#r.id){this.cancel(new e.FamiliarRuntimeError(`Worker returned an incompatible protocol response`));return}if(t.kind===`chunk`){this.#r.emit?.(t.value);return}if(t.kind===`error`){this.#l(`reject`,s(t.error));return}this.#l(`resolve`,t.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=e.FamiliarError,exports.FamiliarInvalidOptionsError=e.FamiliarInvalidOptionsError,exports.FamiliarQueueFullError=e.FamiliarQueueFullError,exports.FamiliarRuntimeError=e.FamiliarRuntimeError,exports.FamiliarTaskError=e.FamiliarTaskError,exports.FamiliarTerminatedError=e.FamiliarTerminatedError,exports.FamiliarTimeoutError=e.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.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;
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 type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport { batch, createTaskGroup } from './_pool';\n\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } 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 { PROTOCOL_VERSION } from './protocol';\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":["#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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"}
package/dist/worker.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export type { BatchOptions, DrainOptions, RunOptions, StreamWorkerPool, TaskGroup, TaskGroupOptions, WorkerOptions, WorkerPool, WorkerStats, WorkerStatus, } from './types';
2
- export { FamiliarError, FamiliarInvalidOptionsError, FamiliarQueueFullError, FamiliarRuntimeError, FamiliarTaskError, FamiliarTerminatedError, FamiliarTimeoutError, } from './errors';
3
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
4
  import type { StreamWorkerPool, WorkerOptions, WorkerPool } from './types';
5
5
  export type RunningStream<TChunk> = {
6
6
  done: Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,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,EACL,aAAa,EACb,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGjD,OAAO,KAAK,EAA4B,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAgCrG,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,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"}
package/dist/worker.js CHANGED
@@ -1,15 +1,15 @@
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 { unrefTimer as s } from "./_timers.js";
1
+ import { unrefTimer as e } from "./_timers.js";
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
3
  import { batch as c, createPool as l, createTaskGroup as u } from "./_pool.js";
4
4
  import { createStreamPool as d } from "./_stream-pool.js";
5
5
  import "./protocol.js";
6
6
  //#region src/worker.ts
7
7
  var f = 512;
8
8
  function p(e = {}) {
9
- let { concurrency: n = 1, maxQueue: r, onFull: i = "reject", onSlotError: a, timeout: o } = e, s = n === "auto" ? Math.max(1, globalThis.navigator?.hardwareConcurrency ?? 1) : n;
10
- if (!Number.isInteger(s) || s < 1 || s > f) throw new t(`\`concurrency\` must be a positive integer ≤ ${f} or "auto"`);
11
- if (r !== void 0 && (!Number.isInteger(r) || r < 1)) throw new t("`maxQueue` must be a positive integer");
12
- if (o !== void 0 && (!Number.isFinite(o) || o <= 0)) throw new t("`timeout` must be a finite number greater than 0");
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"`);
11
+ 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
13
  return {
14
14
  concurrency: s,
15
15
  maxQueue: r,
@@ -25,7 +25,7 @@ function m(e) {
25
25
  }
26
26
  function h(e) {
27
27
  let t = Error(e.message);
28
- return t.name = e.name, t.stack = e.stack, new i(e.message, { cause: t });
28
+ return t.name = e.name, t.stack = e.stack, new a(e.message, { cause: t });
29
29
  }
30
30
  var g = class {
31
31
  #e;
@@ -47,14 +47,14 @@ var g = class {
47
47
  return this.#o(e, t, n, "run");
48
48
  }
49
49
  stream(e, t) {
50
- let n = () => this.cancel(new a("Stream consumer stopped")), r = [], i = [], o = !1, s, c = (e) => {
50
+ let n = () => this.cancel(new o("Stream consumer stopped")), r = [], i = [], a = !1, s, c = (e) => {
51
51
  let t = i.shift();
52
52
  t ? t({
53
53
  done: !1,
54
54
  value: e
55
55
  }) : r.push(e);
56
56
  }, l = (e) => {
57
- for (o = !0, s = e; i.length > 0;) i.shift()(e === void 0 ? {
57
+ for (a = !0, s = e; i.length > 0;) i.shift()(e === void 0 ? {
58
58
  done: !0,
59
59
  value: void 0
60
60
  } : Promise.reject(e));
@@ -68,7 +68,7 @@ var g = class {
68
68
  value: r.shift()
69
69
  };
70
70
  if (s !== void 0) throw s;
71
- return o ? {
71
+ return a ? {
72
72
  done: !0,
73
73
  value: void 0
74
74
  } : new Promise((e, t) => {
@@ -87,13 +87,13 @@ var g = class {
87
87
  };
88
88
  }
89
89
  terminate() {
90
- this.#n = !0, this.cancel(new a());
90
+ this.#n = !0, this.cancel(new o());
91
91
  }
92
- #o(e, t, n, i, c) {
93
- if (this.#n) return Promise.reject(new a());
94
- if (this.#r) return Promise.reject(new r("Worker slot is already busy"));
92
+ #o(t, n, r, a, c) {
93
+ if (this.#n) return Promise.reject(new o());
94
+ if (this.#r) return Promise.reject(new i("Worker slot is already busy"));
95
95
  try {
96
- let a = this.#s(), l = this.#i++;
96
+ let o = this.#s(), l = this.#i++;
97
97
  return new Promise((u, d) => {
98
98
  let f = {
99
99
  emit: c,
@@ -101,16 +101,16 @@ var g = class {
101
101
  reject: d,
102
102
  resolve: u
103
103
  };
104
- this.#r = f, n !== void 0 && (f.timer = setTimeout(() => this.cancel(new o(n)), n), s(f.timer));
104
+ this.#r = f, r !== void 0 && (f.timer = setTimeout(() => this.cancel(new s(r)), r), e(f.timer));
105
105
  try {
106
- a.postMessage({
106
+ o.postMessage({
107
107
  id: l,
108
- input: e,
109
- kind: i,
108
+ input: t,
109
+ kind: a,
110
110
  version: 1
111
- }, t);
111
+ }, n);
112
112
  } catch (e) {
113
- this.cancel(new r("Failed to post message to worker", { cause: e }));
113
+ this.cancel(new i("Failed to post message to worker", { cause: e }));
114
114
  }
115
115
  });
116
116
  } catch (e) {
@@ -119,21 +119,21 @@ var g = class {
119
119
  }
120
120
  #s() {
121
121
  if (this.#a) return this.#a;
122
- if (typeof Worker > "u") throw new r("Worker API is unavailable in this runtime");
122
+ if (typeof Worker > "u") throw new i("Worker API is unavailable in this runtime");
123
123
  try {
124
124
  let e = new Worker(this.#t, { type: "module" });
125
125
  return e.onmessage = (e) => this.#c(e.data), e.onerror = (e) => {
126
- let t = new r(e.message || "Worker failed");
126
+ let t = new i(e.message || "Worker failed");
127
127
  this.#a = void 0, this.#e?.(t), this.#l("reject", t);
128
128
  }, this.#a = e, e;
129
129
  } catch (e) {
130
- throw new r("Failed to create Worker", { cause: e });
130
+ throw new i("Failed to create Worker", { cause: e });
131
131
  }
132
132
  }
133
133
  #c(e) {
134
134
  if (this.#r) {
135
135
  if (!m(e) || e.id !== this.#r.id) {
136
- this.cancel(new r("Worker returned an incompatible protocol response"));
136
+ this.cancel(new i("Worker returned an incompatible protocol response"));
137
137
  return;
138
138
  }
139
139
  if (e.kind === "chunk") {
@@ -174,6 +174,6 @@ function y(e, t = {}) {
174
174
  });
175
175
  }
176
176
  //#endregion
177
- export { e as FamiliarError, t as FamiliarInvalidOptionsError, n as FamiliarQueueFullError, r as FamiliarRuntimeError, i as FamiliarTaskError, a as FamiliarTerminatedError, o as FamiliarTimeoutError, c as batch, y as createStreamWorker, u as createTaskGroup, v as createWorker };
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 };
178
178
 
179
179
  //# 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 type {\n BatchOptions,\n DrainOptions,\n RunOptions,\n StreamWorkerPool,\n TaskGroup,\n TaskGroupOptions,\n WorkerOptions,\n WorkerPool,\n WorkerStats,\n WorkerStatus,\n} from './types';\nexport {\n FamiliarError,\n FamiliarInvalidOptionsError,\n FamiliarQueueFullError,\n FamiliarRuntimeError,\n FamiliarTaskError,\n FamiliarTerminatedError,\n FamiliarTimeoutError,\n} from './errors';\nexport { batch, createTaskGroup } from './_pool';\n\nimport type { SerializedError, WorkerResponse } from './protocol';\nimport type { RunOptions, SlotStrategy, StreamWorkerPool, WorkerOptions, WorkerPool } 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 { PROTOCOL_VERSION } from './protocol';\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":["#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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"}
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "@vielzeug/familiar",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Typed ES module Worker pools with queueing, streaming, and AbortSignal cancellation",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/helmuthdu/vielzeug",
8
+ "directory": "packages/familiar"
9
+ },
5
10
  "type": "module",
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
6
14
  "files": [
7
15
  "dist"
8
16
  ],
@@ -11,55 +19,52 @@
11
19
  "types": "dist/index.d.ts",
12
20
  "exports": {
13
21
  ".": {
14
- "types": "./dist/index.d.ts",
15
22
  "import": "./dist/index.js",
16
- "require": "./dist/index.cjs"
23
+ "require": "./dist/index.cjs",
24
+ "types": "./dist/index.d.ts"
17
25
  },
18
26
  "./protocol": {
19
- "types": "./dist/protocol.d.ts",
20
27
  "import": "./dist/protocol.js",
21
- "require": "./dist/protocol.cjs"
28
+ "require": "./dist/protocol.cjs",
29
+ "types": "./dist/protocol.d.ts"
22
30
  },
23
31
  "./testing": {
24
- "types": "./dist/testing/index.d.ts",
25
32
  "import": "./dist/testing.js",
26
- "require": "./dist/testing.cjs"
33
+ "require": "./dist/testing.cjs",
34
+ "types": "./dist/testing/index.d.ts"
27
35
  }
28
36
  },
29
- "scripts": {
30
- "build": "vite build && pnpm run build:bundle && pnpm run build:types",
31
- "build:types": "tsc -p tsconfig.declarations.json",
32
- "fix": "eslint --fix src",
33
- "lint": "eslint src",
34
- "prepublishOnly": "pnpm run build",
35
- "preview": "vite preview",
36
- "test": "vitest",
37
- "build:bundle": "vite build --config vite.bundle.config.ts"
37
+ "typesVersions": {
38
+ "*": {
39
+ "protocol": [
40
+ "dist/protocol.d.ts"
41
+ ],
42
+ "testing": [
43
+ "dist/testing/index.d.ts"
44
+ ]
45
+ }
38
46
  },
39
47
  "publishConfig": {
40
48
  "access": "public",
41
49
  "registry": "https://registry.npmjs.org/"
42
50
  },
43
- "engines": {
44
- "node": ">=22"
51
+ "scripts": {
52
+ "build": "vite build && pnpm run build:bundle && pnpm run build:types",
53
+ "build:bundle": "vite build --config vite.bundle.config.ts",
54
+ "build:types": "tsc -p tsconfig.declarations.json",
55
+ "fix": "biome check --write src",
56
+ "lint": "biome ci src",
57
+ "prepublishOnly": "pnpm run build",
58
+ "preview": "vite preview",
59
+ "test": "vitest"
45
60
  },
46
61
  "dependencies": {
47
- "@vielzeug/arsenal": "2.0.1"
62
+ "@vielzeug/arsenal": "2.1.0"
48
63
  },
49
64
  "devDependencies": {
50
- "@types/node": "^26.1.2",
65
+ "@types/node": "^26.2.0",
51
66
  "typescript": "^6.0.3",
52
- "vite": "^8.2.0",
67
+ "vite": "^8.2.1",
53
68
  "vitest": "^4.1.10"
54
- },
55
- "typesVersions": {
56
- "*": {
57
- "protocol": [
58
- "dist/protocol.d.ts"
59
- ],
60
- "testing": [
61
- "dist/testing/index.d.ts"
62
- ]
63
- }
64
69
  }
65
70
  }