@nicolastoulemont/std 0.7.0 → 0.7.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.
Files changed (67) hide show
  1. package/README.md +0 -6
  2. package/dist/context-CCHj1nab.mjs.map +1 -1
  3. package/dist/data/index.d.mts +1 -1
  4. package/dist/data/index.mjs +1 -1
  5. package/dist/{data-CJxw6al9.mjs → data-BLXO4XwS.mjs} +2 -2
  6. package/dist/{data-CJxw6al9.mjs.map → data-BLXO4XwS.mjs.map} +1 -1
  7. package/dist/data.tagged-error.types-CGiKD-ES.d.mts +29 -0
  8. package/dist/data.tagged-error.types-CGiKD-ES.d.mts.map +1 -0
  9. package/dist/either/index.d.mts +1 -1
  10. package/dist/either/index.mjs +1 -1
  11. package/dist/{either-6BwadiFj.mjs → either-BMLPfvMl.mjs} +2 -2
  12. package/dist/either-BMLPfvMl.mjs.map +1 -0
  13. package/dist/fx/index.d.mts +1 -1
  14. package/dist/fx/index.mjs +1 -1
  15. package/dist/{fx-BzxLbf1Q.mjs → fx-K-a9Smhn.mjs} +2 -2
  16. package/dist/fx-K-a9Smhn.mjs.map +1 -0
  17. package/dist/{fx.runtime-BcC6yMSy.mjs → fx.runtime-DclEDyjY.mjs} +2 -2
  18. package/dist/{fx.runtime-BcC6yMSy.mjs.map → fx.runtime-DclEDyjY.mjs.map} +1 -1
  19. package/dist/{index-DSsDFLGw.d.mts → index-B1-tBzc0.d.mts} +2 -2
  20. package/dist/{index-DSsDFLGw.d.mts.map → index-B1-tBzc0.d.mts.map} +1 -1
  21. package/dist/{index-CugDqdx6.d.mts → index-BNQ9xSAz.d.mts} +2 -2
  22. package/dist/{index-CugDqdx6.d.mts.map → index-BNQ9xSAz.d.mts.map} +1 -1
  23. package/dist/index-BiiE8NS7.d.mts.map +1 -1
  24. package/dist/index-By6dNRc4.d.mts.map +1 -1
  25. package/dist/{index-DaTvFhZ8.d.mts → index-CGiLfREk.d.mts} +37 -37
  26. package/dist/{index-DaTvFhZ8.d.mts.map → index-CGiLfREk.d.mts.map} +1 -1
  27. package/dist/{index-CCo85AdC.d.mts → index-Cq2IFito.d.mts} +2 -2
  28. package/dist/{index-CCo85AdC.d.mts.map → index-Cq2IFito.d.mts.map} +1 -1
  29. package/dist/{index-Dm2dFysv.d.mts → index-UzMbg1dh.d.mts} +2 -2
  30. package/dist/{index-Dm2dFysv.d.mts.map → index-UzMbg1dh.d.mts.map} +1 -1
  31. package/dist/index.d.mts +5 -5
  32. package/dist/index.mjs +1 -1
  33. package/dist/layer-BttmtDrs.mjs.map +1 -1
  34. package/dist/multithread-xUUh4eLn.mjs.map +1 -1
  35. package/dist/option/index.d.mts +1 -1
  36. package/dist/option/index.mjs +1 -1
  37. package/dist/{option-Qt1H-u7c.mjs → option-Tfbo4wty.mjs} +2 -2
  38. package/dist/option-Tfbo4wty.mjs.map +1 -0
  39. package/dist/option.types-D1mm0zUb.mjs +2 -0
  40. package/dist/option.types-D1mm0zUb.mjs.map +1 -0
  41. package/dist/{option.types-DlAb6Sr0.d.mts → option.types-qPevEZQd.d.mts} +5 -10
  42. package/dist/option.types-qPevEZQd.d.mts.map +1 -0
  43. package/dist/order-D5c4QChk.mjs.map +1 -1
  44. package/dist/provide/index.mjs +1 -1
  45. package/dist/provide-BmSM3Ruy.mjs +2 -0
  46. package/dist/provide-BmSM3Ruy.mjs.map +1 -0
  47. package/dist/queue/index.d.mts +1 -1
  48. package/dist/queue/index.mjs +1 -1
  49. package/dist/{queue-CG5izEBS.mjs → queue-Sg6KJerl.mjs} +2 -2
  50. package/dist/{queue-CG5izEBS.mjs.map → queue-Sg6KJerl.mjs.map} +1 -1
  51. package/dist/result-BEzV0DYC.mjs.map +1 -1
  52. package/dist/result.types-_xDAei3-.d.mts.map +1 -1
  53. package/dist/scope/index.mjs +1 -1
  54. package/dist/{scope-qwL1VUh2.mjs → scope-D_kzd1nT.mjs} +2 -2
  55. package/dist/scope-D_kzd1nT.mjs.map +1 -0
  56. package/package.json +1 -1
  57. package/dist/data.tagged-error.types-CLlJJ3n5.d.mts +0 -50
  58. package/dist/data.tagged-error.types-CLlJJ3n5.d.mts.map +0 -1
  59. package/dist/either-6BwadiFj.mjs.map +0 -1
  60. package/dist/fx-BzxLbf1Q.mjs.map +0 -1
  61. package/dist/option-Qt1H-u7c.mjs.map +0 -1
  62. package/dist/option.types-DRUm2QiI.mjs +0 -2
  63. package/dist/option.types-DRUm2QiI.mjs.map +0 -1
  64. package/dist/option.types-DlAb6Sr0.d.mts.map +0 -1
  65. package/dist/provide-B_SqJpCd.mjs +0 -2
  66. package/dist/provide-B_SqJpCd.mjs.map +0 -1
  67. package/dist/scope-qwL1VUh2.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"multithread-xUUh4eLn.mjs","names":[],"sources":["../src/multithread/multithread.ts"],"sourcesContent":["/**\n * Parallel worker orchestration helpers built on optional `multithreading` runtime.\n *\n * **Mental model**\n * - `MultithreadOp` represents cancelable worker execution.\n * - Use `run`, `task`, and collection combinators (`map`, `forEach`, `race`).\n *\n * **Common tasks**\n * - Execute one worker with `Multithread.run`.\n * - Create reusable tasks with `Multithread.task`.\n * - Process collections in parallel with `Multithread.map` / `forEach`.\n *\n * **Gotchas**\n * - Requires optional `multithreading` peer dependency.\n * - Runtime should be configured before first operation.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.run((ctx) => (ctx.isCancelled() ? 0 : 42))\n * // => cancelable operation with result() and abort()\n * ```\n *\n * @module\n */\nimport { FxTypeId } from \"../fx/fx.types\"\nimport { err, ok } from \"../result/result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport type {\n MultithreadAllFailedError,\n MultithreadCancelledError,\n MultithreadCtx,\n MultithreadError,\n MultithreadFilter,\n MultithreadFilterWorker,\n MultithreadFirstSuccess,\n MultithreadFlatMap,\n MultithreadFlatMapWorker,\n MultithreadForEach,\n MultithreadMap,\n MultithreadMapWorker,\n MultithreadOp,\n MultithreadParallelOptions,\n MultithreadRace,\n MultithreadRun,\n MultithreadRuntimeAlreadyInitializedError,\n MultithreadRuntimeUnavailableError,\n MultithreadSignal,\n MultithreadTask,\n MultithreadWorkerExecutionError,\n WorkerReturn,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported worker context passed to multithread workers.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadCtx\n * ```\n *\n * @category Re-exports\n */\n type MultithreadCtx,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported union of multithread runtime and worker errors.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadError\n * ```\n *\n * @category Re-exports\n */\n type MultithreadError,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported cancelable multithread operation type.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadOp<unknown, unknown>\n * ```\n *\n * @category Re-exports\n */\n type MultithreadOp,\n} from \"./multithread.types\"\n\n/**\n * Internal runtime shape loaded from the optional \"multithreading\" peer dependency.\n */\ntype MultithreadingRuntime = {\n initRuntime(config: { maxWorkers: number }): void\n shutdown(): void\n move<Args extends unknown[]>(...args: Args): unknown\n spawn<R>(\n payload: unknown,\n fn: (...args: unknown[]) => R | Promise<R>,\n ): {\n join(): Promise<{ ok: boolean; value?: R; error?: Error }>\n abort(): void\n }\n}\n\ntype WorkerLike = (...args: unknown[]) => unknown\ntype WorkerEntrypoint = (...args: unknown[]) => Promise<unknown>\n\ntype InternalCancelController = {\n readonly signal: MultithreadSignal\n isCancelled(): boolean\n cancel(): void\n onCancel(listener: () => void): void\n}\n\nconst CANCELLED_ERROR_MESSAGE = \"@nicolastoulemont/std/multithread/cancelled\"\n\nlet runtimeConfig: { maxWorkers: number } | undefined\nlet runtimeInitialized = false\nlet runtimeImportPromise: Promise<MultithreadingRuntime> | undefined\n\nconst workerEntrypointCache = new WeakMap<object, WorkerEntrypoint>()\n\nconst makeRuntimeUnavailableError = (\n cause?: unknown,\n message = 'Optional peer dependency \"multithreading\" is unavailable. Install it to use Multithread APIs.',\n): MultithreadRuntimeUnavailableError => ({\n _tag: \"MultithreadRuntimeUnavailableError\",\n message,\n cause,\n})\n\nconst makeRuntimeAlreadyInitializedError = (\n message = \"Multithread runtime is already initialized and can no longer be configured.\",\n): MultithreadRuntimeAlreadyInitializedError => ({\n _tag: \"MultithreadRuntimeAlreadyInitializedError\",\n message,\n})\n\nconst makeWorkerExecutionError = (message: string, cause: unknown): MultithreadWorkerExecutionError => ({\n _tag: \"MultithreadWorkerExecutionError\",\n message,\n cause,\n})\n\nconst makeCancelledError = (\n message = \"Multithread operation was cancelled before completion.\",\n): MultithreadCancelledError => ({\n _tag: \"MultithreadCancelledError\",\n message,\n})\n\nconst makeAllFailedError = (message: string, errors: readonly unknown[]): MultithreadAllFailedError => ({\n _tag: \"MultithreadAllFailedError\",\n message,\n errors,\n})\n\nconst getErrorMessage = (cause: unknown): string | undefined =>\n cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : undefined\n\nconst isCancelledCause = (cause: unknown): boolean => {\n const message = getErrorMessage(cause)\n return message === CANCELLED_ERROR_MESSAGE || message === \"Task aborted\"\n}\n\nconst isCallerLocationFailure = (cause: unknown): boolean => {\n const message = getErrorMessage(cause)\n return typeof message === \"string\" && message.startsWith(\"Could not parse coordinates from:\")\n}\n\nconst isResultLike = (value: unknown): value is ResultType<unknown, unknown> => {\n if (typeof value !== \"object\" || value === null || !(\"_tag\" in value)) return false\n const tag = Reflect.get(value, \"_tag\")\n if (tag === \"Ok\") return \"value\" in value\n if (tag === \"Err\") return \"error\" in value\n return false\n}\n\nconst resultOk = <A>(value: A): ResultType<A, never> => ok(value)\nconst resultErr = <E>(error: E): ResultType<never, E> => err(error)\n\nconst normalizeWorkerReturn = <A, E>(value: unknown): ResultType<A, E> => {\n if (isResultLike(value)) {\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- isResultLike confirms runtime shape; generic channels are erased.\n return value as ResultType<A, E>\n }\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Worker return value is user-defined and mapped to generic success type.\n return resultOk(value as A)\n}\n\nconst runFromInputResult = (\n input: unknown,\n execute: (value: unknown) => MultithreadOp<unknown, unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> => {\n if (!isResultLike(input)) {\n return execute(input)\n }\n\n if (input._tag === \"Err\") {\n return Promise.resolve(resultErr(input.error))\n }\n\n return execute(input.value).result()\n}\n\nconst normalizeParallelism = (parallelism: number | undefined, fallback: number): number => {\n if (typeof parallelism !== \"number\" || !Number.isFinite(parallelism)) return fallback\n const rounded = Math.floor(parallelism)\n return rounded > 0 ? rounded : fallback\n}\n\nconst isWorkerLike = (value: unknown): value is WorkerLike => typeof value === \"function\"\n\nconst isParallelOptions = (value: unknown): value is MultithreadParallelOptions =>\n typeof value === \"object\" && value !== null\n\nconst resolveParallelOptions = (value: unknown): MultithreadParallelOptions | undefined =>\n isParallelOptions(value) ? value : undefined\n\nconst getDefaultParallelism = (): number => {\n if (runtimeConfig !== undefined) {\n return runtimeConfig.maxWorkers\n }\n if (typeof navigator !== \"undefined\" && typeof navigator.hardwareConcurrency === \"number\") {\n return normalizeParallelism(navigator.hardwareConcurrency, 4)\n }\n return 4\n}\n\nconst createSharedSignal = (): MultithreadSignal => {\n if (typeof SharedArrayBuffer !== \"function\") return null\n return new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))\n}\n\nconst createCancelController = (): InternalCancelController => {\n const signal = createSharedSignal()\n const listeners = new Set<() => void>()\n let cancelled = false\n\n const isCancelled = (): boolean => cancelled || (signal !== null && Atomics.load(signal, 0) === 1)\n\n const cancel = (): void => {\n if (cancelled) return\n cancelled = true\n\n if (signal !== null) {\n Atomics.store(signal, 0, 1)\n Atomics.notify(signal, 0)\n }\n\n const activeListeners = Array.from(listeners)\n listeners.clear()\n\n for (const listener of activeListeners) {\n try {\n listener()\n } catch {\n // Intentionally ignore listener disposal errors during cancellation fanout.\n }\n }\n }\n\n const onCancel = (listener: () => void): void => {\n if (cancelled) {\n listener()\n return\n }\n listeners.add(listener)\n }\n\n return {\n signal,\n isCancelled,\n cancel,\n onCancel,\n }\n}\n\nconst loadRuntimeModule = async (): Promise<ResultType<MultithreadingRuntime, MultithreadError>> => {\n try {\n runtimeImportPromise ??= import(\"multithreading\") as Promise<MultithreadingRuntime>\n return resultOk(await runtimeImportPromise)\n } catch (cause) {\n return resultErr(makeRuntimeUnavailableError(cause))\n }\n}\n\nconst getRuntime = async (): Promise<ResultType<MultithreadingRuntime, MultithreadError>> => {\n const runtimeResult = await loadRuntimeModule()\n if (runtimeResult._tag === \"Err\") return runtimeResult\n\n const runtime = runtimeResult.value\n\n if (!runtimeInitialized) {\n try {\n if (runtimeConfig !== undefined) {\n runtime.initRuntime(runtimeConfig)\n }\n runtimeInitialized = true\n } catch (cause) {\n return resultErr(makeWorkerExecutionError(\"Failed to initialize multithreading runtime.\", cause))\n }\n }\n\n return resultOk(runtime)\n}\n\nconst createWorkerEntrypoint = <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n): WorkerEntrypoint => {\n const cached = workerEntrypointCache.get(worker)\n if (cached !== undefined) {\n return cached\n }\n\n const source = worker.toString()\n // oxlint-disable-next-line typescript-eslint/no-implied-eval, typescript-eslint/no-unsafe-type-assertion -- Worker code must be reconstructed from serialized callback source and typed at runtime.\n const factory = new Function(\n `\nreturn async function (...__args) {\n const __signal = __args.pop()\n const __isCancelled = () => __signal !== null && Atomics.load(__signal, 0) === 1\n const __throwIfCancelled = () => {\n if (__isCancelled()) {\n throw new Error(${JSON.stringify(CANCELLED_ERROR_MESSAGE)})\n }\n }\n const __ctx = {\n signal: __signal,\n isCancelled: __isCancelled,\n throwIfCancelled: __throwIfCancelled,\n }\n const __worker = (${source})\n return await __worker(...__args, __ctx)\n}\n`,\n ) as () => WorkerEntrypoint\n\n const entrypoint = factory()\n workerEntrypointCache.set(worker, entrypoint)\n return entrypoint\n}\n\nconst createMultithreadOperation = <A, E>(\n execute: (controller: InternalCancelController) => Promise<ResultType<A, E | MultithreadError>>,\n): MultithreadOp<A, E | MultithreadError> => {\n const controller = createCancelController()\n let runPromise: Promise<ResultType<A, E | MultithreadError>> | undefined\n\n const start = (): Promise<ResultType<A, E | MultithreadError>> => {\n if (runPromise !== undefined) return runPromise\n\n if (controller.isCancelled()) {\n runPromise = Promise.resolve(resultErr(makeCancelledError()))\n return runPromise\n }\n\n runPromise = execute(controller)\n .catch((cause: unknown) => resultErr(makeWorkerExecutionError(\"Multithread operation failed.\", cause)))\n .then((result) => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n return result\n })\n\n return runPromise\n }\n\n const then: PromiseLike<ResultType<A, E | MultithreadError>>[\"then\"] = (onfulfilled, onrejected) =>\n start().then(onfulfilled, onrejected)\n\n return {\n _tag: \"MultithreadOp\",\n [FxTypeId]: {\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _A: () => undefined as unknown as A,\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _E: () => undefined as unknown as E | MultithreadError,\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _R: () => undefined as never,\n },\n result: start,\n abort: () => {\n controller.cancel()\n },\n // oxlint-disable-next-line eslint-plugin-unicorn/no-thenable -- MultithreadOp is intentionally PromiseLike for `await op` ergonomics.\n then,\n async *[Symbol.asyncIterator](): AsyncGenerator<E | MultithreadError, A, unknown> {\n const result = await start()\n if (result._tag === \"Err\") {\n yield result.error\n throw new Error(\"Unreachable: Fx.gen should short-circuit on yielded Multithread errors\")\n }\n return result.value\n },\n }\n}\n\nconst runWorkerLocally = async <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n args: Args,\n controller: InternalCancelController,\n): Promise<ResultType<A, E | MultithreadError>> => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const ctx: MultithreadCtx = {\n signal: controller.signal,\n isCancelled: () => controller.isCancelled(),\n throwIfCancelled: () => {\n if (controller.isCancelled()) throw new Error(CANCELLED_ERROR_MESSAGE)\n },\n }\n\n try {\n const value = await worker(...args, ctx)\n\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const normalized = normalizeWorkerReturn<A, E>(value)\n if (normalized._tag === \"Err\") {\n return resultErr(normalized.error)\n }\n\n return resultOk(normalized.value)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Multithread worker failed during execution.\", cause))\n }\n}\n\nconst runDataFirst = <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n args: Args,\n): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const runtimeResult = await getRuntime()\n if (runtimeResult._tag === \"Err\") return resultErr(runtimeResult.error)\n\n const runtime = runtimeResult.value\n const entrypoint = createWorkerEntrypoint(worker)\n\n let joinHandle: ReturnType<MultithreadingRuntime[\"spawn\"]> | undefined\n\n try {\n const movedPayload = runtime.move(...args, controller.signal)\n joinHandle = runtime.spawn(movedPayload, entrypoint)\n controller.onCancel(() => {\n joinHandle?.abort()\n })\n } catch (cause) {\n if (isCallerLocationFailure(cause)) {\n return runWorkerLocally(worker, args, controller)\n }\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Failed to start multithread worker.\", cause))\n }\n\n try {\n const joined = await joinHandle.join()\n\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n if (!joined.ok) {\n const joinError = joined.error ?? new Error(\"Multithread worker returned an unknown error.\")\n if (isCancelledCause(joinError)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Multithread worker failed during execution.\", joinError))\n }\n\n const normalized = normalizeWorkerReturn<A, E>(joined.value)\n if (normalized._tag === \"Err\") {\n return resultErr(normalized.error)\n }\n return resultOk(normalized.value)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Failed to join multithread worker.\", cause))\n }\n })\n\nfunction runOverload<A, E = never>(\n worker: (ctx: MultithreadCtx) => WorkerReturn<A, E>,\n): MultithreadOp<A, E | MultithreadError>\nfunction runOverload<Args extends readonly unknown[], A, E = never>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n ...args: Args\n): MultithreadOp<A, E | MultithreadError>\nfunction runOverload(worker: unknown, ...args: unknown[]): MultithreadOp<unknown, unknown> {\n if (!isWorkerLike(worker)) {\n throw new TypeError(\"Multithread.run expects a worker function as first argument.\")\n }\n return runDataFirst(worker, args)\n}\n\n/**\n * Execute one worker task as a cancelable `MultithreadOp`.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.run((ctx) => (ctx.isCancelled() ? 0 : 42))\n * // => cancelable operation with result() and abort()\n * ```\n *\n * @category Constructors\n */\nexport const run: MultithreadRun = runOverload\n\nfunction taskOverload<A, E = never>(\n worker: (ctx: MultithreadCtx) => WorkerReturn<A, E>,\n): () => MultithreadOp<A, E | MultithreadError>\nfunction taskOverload<Args extends readonly unknown[], A, E = never>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n): (...args: Args) => MultithreadOp<A, E | MultithreadError>\nfunction taskOverload(worker: unknown): (...args: unknown[]) => MultithreadOp<unknown, unknown> {\n if (!isWorkerLike(worker)) {\n throw new TypeError(\"Multithread.task expects a worker function.\")\n }\n return (...args: unknown[]) => runDataFirst(worker, args)\n}\n\n/**\n * Create a reusable worker task factory.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const create = Multithread.task((ctx) => (ctx.isCancelled() ? 0 : 16))\n * const op = create()\n * // => operation that resolves to 16 when executed\n * ```\n *\n * @category Constructors\n */\nexport const task: MultithreadTask = taskOverload\n\nconst executeInParallel = <A, B, E>(\n values: readonly A[],\n createItemOperation: (value: A, index: number) => MultithreadOp<B, E | MultithreadError>,\n parallelism: number,\n controller: InternalCancelController,\n): Promise<ResultType<readonly B[], E | MultithreadError>> => {\n if (values.length === 0) {\n return Promise.resolve(resultOk<readonly B[]>([]))\n }\n\n return new Promise<ResultType<readonly B[], E | MultithreadError>>((resolve) => {\n const operations = new Map<number, MultithreadOp<B, E | MultithreadError>>()\n const output: B[] = []\n\n let inFlight = 0\n let nextIndex = 0\n let completed = 0\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations.values()) {\n operation.abort()\n }\n operations.clear()\n }\n\n const settle = (result: ResultType<readonly B[], E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const handleOperation = (index: number, operation: MultithreadOp<B, E | MultithreadError>): void => {\n void (async () => {\n try {\n const result = await operation.result()\n\n inFlight -= 1\n operations.delete(index)\n\n if (settled) return\n\n if (result._tag === \"Err\") {\n settle(resultErr(result.error))\n return\n }\n\n output[index] = result.value\n completed += 1\n\n if (completed === values.length) {\n settled = true\n resolve(resultOk(output))\n return\n }\n\n launch()\n } catch (cause) {\n inFlight -= 1\n operations.delete(index)\n\n if (settled) return\n\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n settle(resultErr(makeWorkerExecutionError(\"Failed while executing multithread batch.\", cause)))\n }\n })()\n }\n\n const launch = (): void => {\n while (!settled && inFlight < parallelism && nextIndex < values.length) {\n const index = nextIndex\n nextIndex += 1\n\n const operation = createItemOperation(values[index]!, index)\n operations.set(index, operation)\n inFlight += 1\n\n handleOperation(index, operation)\n }\n }\n\n launch()\n })\n}\n\nconst mapDataFirst = <A, B, E>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError> =>\n createMultithreadOperation((controller) => {\n const parallelism = normalizeParallelism(options?.parallelism, getDefaultParallelism())\n return executeInParallel(values, (value, index) => runDataFirst(worker, [value, index]), parallelism, controller)\n })\n\nfunction mapOverload<A, B, E = never>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError>\nfunction mapOverload<A, B, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\nfunction mapOverload<A, B, E = never>(\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\nfunction mapOverload<A, B, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadMapWorker<A, B, E>,\n workerOrOptions?: MultithreadMapWorker<A, B, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) => mapDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions))) as <\n Input extends readonly A[] | ResultType<readonly A[], unknown>,\n >(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.map(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n mapDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n}\n\n/**\n * Map a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.map([1, 2, 3], (value) => value * 2)\n * // => operation that resolves to [2, 4, 6]\n * ```\n *\n * @category Mapping\n */\nexport const map: MultithreadMap = mapOverload\n\nconst forEachDataFirst = <A, E>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<void, E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<void, E | MultithreadError>> => {\n const mapped = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (mapped._tag === \"Err\") return resultErr(mapped.error)\n return resultOk(undefined)\n })\n\nfunction forEachOverload<A, E = never>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<void, E | MultithreadError>\nfunction forEachOverload<A, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<void, E | InputE | MultithreadError>>\nfunction forEachOverload<A, E = never>(\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>\nfunction forEachOverload<A, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadMapWorker<A, unknown, E>,\n workerOrOptions?: MultithreadMapWorker<A, unknown, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<void, E | MultithreadError>\n | Promise<ResultType<void, E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n forEachDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.forEach(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n forEachDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as MultithreadOp<void, E | MultithreadError> | Promise<ResultType<void, E | InputE | MultithreadError>>\n}\n\n/**\n * Run side-effecting parallel work for each item.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.forEach([\"a\", \"b\"], (value) => value.toUpperCase())\n * // => operation that resolves to void after all items complete\n * ```\n *\n * @category Sequencing\n */\nexport const forEach: MultithreadForEach = forEachOverload\n\nconst filterDataFirst = <A, E>(\n values: readonly A[],\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly A[], E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<readonly A[], E | MultithreadError>> => {\n const decisions = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (decisions._tag === \"Err\") return resultErr(decisions.error)\n\n const filtered: A[] = []\n for (let index = 0; index < values.length; index += 1) {\n if (decisions.value[index] === true) {\n filtered.push(values[index]!)\n }\n }\n\n return resultOk(filtered)\n })\n\nfunction filterOverload<A, E = never>(\n values: readonly A[],\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly A[], E | MultithreadError>\nfunction filterOverload<A, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\nfunction filterOverload<A, E = never>(\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>\nfunction filterOverload<A, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadFilterWorker<A, E>,\n workerOrOptions?: MultithreadFilterWorker<A, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly A[], E | MultithreadError>\n | Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n filterDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.filter(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n filterDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly A[], E | MultithreadError>\n | Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\n}\n\n/**\n * Filter a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.filter([1, 2, 3, 4], (value) => value % 2 === 0)\n * // => operation that resolves to [2, 4]\n * ```\n *\n * @category Filtering\n */\nexport const filter: MultithreadFilter = filterOverload\n\nconst flatMapDataFirst = <A, B, E>(\n values: readonly A[],\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<readonly B[], E | MultithreadError>> => {\n const chunks = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (chunks._tag === \"Err\") return resultErr(chunks.error)\n\n const flattened: B[] = []\n for (const chunk of chunks.value) {\n flattened.push(...chunk)\n }\n\n return resultOk(flattened)\n })\n\nfunction flatMapOverload<A, B, E = never>(\n values: readonly A[],\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError>\nfunction flatMapOverload<A, B, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\nfunction flatMapOverload<A, B, E = never>(\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\nfunction flatMapOverload<A, B, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadFlatMapWorker<A, B, E>,\n workerOrOptions?: MultithreadFlatMapWorker<A, B, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n flatMapDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.flatMap(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n flatMapDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n}\n\n/**\n * Flat-map a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.flatMap([1, 2], (value) => [value, value * 10])\n * // => operation that resolves to [1, 10, 2, 20]\n * ```\n *\n * @category Sequencing\n */\nexport const flatMap: MultithreadFlatMap = flatMapOverload\n\nconst raceDataFirst = <A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation((controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (operations.length === 0) {\n return Promise.resolve(resultErr(makeAllFailedError(\"Cannot race an empty list of operations.\", [])))\n }\n\n return new Promise<ResultType<A, E | MultithreadError>>((resolve) => {\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations) {\n operation.abort()\n }\n }\n\n const settle = (result: ResultType<A, E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const watchOperation = (operation: MultithreadOp<A, E>): void => {\n void (async () => {\n try {\n const result = await operation.result()\n settle(result)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n settle(resultErr(makeWorkerExecutionError(\"Multithread race failed.\", cause)))\n }\n })()\n }\n\n for (const operation of operations) {\n watchOperation(operation)\n }\n })\n })\n\nfunction raceOverload<A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError>\nfunction raceOverload<A, E, InputE = never>(\n operations: ResultType<readonly MultithreadOp<A, E>[], InputE>,\n): Promise<ResultType<A, E | InputE | MultithreadError>>\nfunction raceOverload<Ops extends readonly MultithreadOp<unknown, unknown>[]>(\n operations: Ops,\n): MultithreadOp<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | MultithreadError\n>\nfunction raceOverload<Ops extends readonly MultithreadOp<unknown, unknown>[], InputE = never>(\n operations: ResultType<Ops, InputE>,\n): Promise<\n ResultType<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | InputE | MultithreadError\n >\n>\nfunction raceOverload(\n operations: readonly MultithreadOp<unknown, unknown>[] | ResultType<readonly MultithreadOp<unknown, unknown>[], unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> {\n return runFromInputResult(operations, (resolvedOperations) =>\n raceDataFirst(resolvedOperations as readonly MultithreadOp<unknown, unknown>[]),\n )\n}\n\n/**\n * Resolve with the first successfully completed operation.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const fast = Multithread.run(() => 1)\n * const slow = Multithread.run(() => 2)\n * const op = Multithread.race([fast, slow])\n * // => operation that resolves with the first finished result\n * ```\n *\n * @category Combining\n */\nexport const race: MultithreadRace = raceOverload\n\nconst firstSuccessDataFirst = <A, E>(\n operations: readonly MultithreadOp<A, E>[],\n): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation((controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (operations.length === 0) {\n return Promise.resolve(\n resultErr(makeAllFailedError(\"Cannot select a first success from an empty list of operations.\", [])),\n )\n }\n\n return new Promise<ResultType<A, E | MultithreadError>>((resolve) => {\n const failures: unknown[] = Array.from({ length: operations.length })\n let pending = operations.length\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations) {\n operation.abort()\n }\n }\n\n const settle = (result: ResultType<A, E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const watchOperation = (operation: MultithreadOp<A, E>, index: number): void => {\n void (async () => {\n try {\n const result = await operation.result()\n\n if (settled) return\n\n if (result._tag === \"Ok\") {\n settle(resultOk(result.value))\n return\n }\n\n failures[index] = result.error\n pending -= 1\n\n if (pending === 0) {\n settle(\n resultErr(\n makeAllFailedError(\n \"All multithread operations failed before any success was produced.\",\n failures.filter((failure) => failure !== undefined),\n ),\n ),\n )\n }\n } catch (cause) {\n if (settled) return\n\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n failures[index] = makeWorkerExecutionError(\"Multithread operation rejected unexpectedly.\", cause)\n pending -= 1\n\n if (pending === 0) {\n settle(\n resultErr(\n makeAllFailedError(\n \"All multithread operations failed before any success was produced.\",\n failures.filter((failure) => failure !== undefined),\n ),\n ),\n )\n }\n }\n })()\n }\n\n operations.forEach((operation, index) => {\n watchOperation(operation, index)\n })\n })\n })\n\nfunction firstSuccessOverload<A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError>\nfunction firstSuccessOverload<A, E, InputE = never>(\n operations: ResultType<readonly MultithreadOp<A, E>[], InputE>,\n): Promise<ResultType<A, E | InputE | MultithreadError>>\nfunction firstSuccessOverload<Ops extends readonly MultithreadOp<unknown, unknown>[]>(\n operations: Ops,\n): MultithreadOp<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | MultithreadError\n>\nfunction firstSuccessOverload<Ops extends readonly MultithreadOp<unknown, unknown>[], InputE = never>(\n operations: ResultType<Ops, InputE>,\n): Promise<\n ResultType<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | InputE | MultithreadError\n >\n>\nfunction firstSuccessOverload(\n operations: readonly MultithreadOp<unknown, unknown>[] | ResultType<readonly MultithreadOp<unknown, unknown>[], unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> {\n return runFromInputResult(operations, (resolvedOperations) =>\n firstSuccessDataFirst(resolvedOperations as readonly MultithreadOp<unknown, unknown>[]),\n )\n}\n\n/**\n * Return the first successful operation, aggregating failures if none succeed.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n * \n * const fail = Multithread.run(() => Result.err(\"boom\"))\n * const pass = Multithread.run(() => Result.ok(1))\n * const op = Multithread.firstSuccess([fail, pass])\n * // => operation that resolves with 1\n * ```\n *\n * @category Combining\n */\nexport const firstSuccess: MultithreadFirstSuccess = firstSuccessOverload\n\n/**\n * Configure max worker count used by the underlying runtime.\n *\n * Must be called before first multithread operation starts.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const configured = Multithread.configure({ maxWorkers: 4 })\n * // => { _tag: \"Ok\", value: undefined }\n * ```\n *\n * @category Constructors\n */\nexport const configure = (config: { maxWorkers: number }): ResultType<void, MultithreadError> => {\n if (runtimeInitialized) {\n return resultErr(makeRuntimeAlreadyInitializedError())\n }\n\n runtimeConfig = {\n maxWorkers: normalizeParallelism(config.maxWorkers, 1),\n }\n\n return resultOk(undefined)\n}\n\n/**\n * Shutdown worker runtime.\n *\n * This function is idempotent.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const shutdownPromise = Multithread.shutdown()\n * // => Promise<Result<void, MultithreadError>>\n * ```\n *\n * @category Utilities\n */\nexport const shutdown = async (): Promise<ResultType<void, MultithreadError>> => {\n if (!runtimeInitialized) {\n return resultOk(undefined)\n }\n\n const runtimeResult = await loadRuntimeModule()\n if (runtimeResult._tag === \"Err\") {\n runtimeInitialized = false\n return resultErr(runtimeResult.error)\n }\n\n try {\n runtimeResult.value.shutdown()\n return resultOk(undefined)\n } catch (cause) {\n return resultErr(makeWorkerExecutionError(\"Failed to shutdown multithreading runtime.\", cause))\n } finally {\n runtimeInitialized = false\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"multithread-xUUh4eLn.mjs","names":[],"sources":["../src/multithread/multithread.ts"],"sourcesContent":["/**\n * Parallel worker orchestration helpers built on optional `multithreading` runtime.\n *\n * **Mental model**\n * - `MultithreadOp` represents cancelable worker execution.\n * - Use `run`, `task`, and collection combinators (`map`, `forEach`, `race`).\n *\n * **Common tasks**\n * - Execute one worker with `Multithread.run`.\n * - Create reusable tasks with `Multithread.task`.\n * - Process collections in parallel with `Multithread.map` / `forEach`.\n *\n * **Gotchas**\n * - Requires optional `multithreading` peer dependency.\n * - Runtime should be configured before first operation.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.run((ctx) => (ctx.isCancelled() ? 0 : 42))\n * // => cancelable operation with result() and abort()\n * ```\n *\n * @module\n */\nimport { FxTypeId } from \"../fx/fx.types\"\nimport { err, ok } from \"../result/result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport type {\n MultithreadAllFailedError,\n MultithreadCancelledError,\n MultithreadCtx,\n MultithreadError,\n MultithreadFilter,\n MultithreadFilterWorker,\n MultithreadFirstSuccess,\n MultithreadFlatMap,\n MultithreadFlatMapWorker,\n MultithreadForEach,\n MultithreadMap,\n MultithreadMapWorker,\n MultithreadOp,\n MultithreadParallelOptions,\n MultithreadRace,\n MultithreadRun,\n MultithreadRuntimeAlreadyInitializedError,\n MultithreadRuntimeUnavailableError,\n MultithreadSignal,\n MultithreadTask,\n MultithreadWorkerExecutionError,\n WorkerReturn,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported worker context passed to multithread workers.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadCtx\n * ```\n *\n * @category Re-exports\n */\n type MultithreadCtx,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported union of multithread runtime and worker errors.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadError\n * ```\n *\n * @category Re-exports\n */\n type MultithreadError,\n} from \"./multithread.types\"\nexport {\n /**\n * Re-exported cancelable multithread operation type.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Multithread.MultithreadOp<unknown, unknown>\n * ```\n *\n * @category Re-exports\n */\n type MultithreadOp,\n} from \"./multithread.types\"\n\n/**\n * Internal runtime shape loaded from the optional \"multithreading\" peer dependency.\n */\ntype MultithreadingRuntime = {\n initRuntime(config: { maxWorkers: number }): void\n shutdown(): void\n move<Args extends unknown[]>(...args: Args): unknown\n spawn<R>(\n payload: unknown,\n fn: (...args: unknown[]) => R | Promise<R>,\n ): {\n join(): Promise<{ ok: boolean; value?: R; error?: Error }>\n abort(): void\n }\n}\n\ntype WorkerLike = (...args: unknown[]) => unknown\ntype WorkerEntrypoint = (...args: unknown[]) => Promise<unknown>\n\ntype InternalCancelController = {\n readonly signal: MultithreadSignal\n isCancelled(): boolean\n cancel(): void\n onCancel(listener: () => void): void\n}\n\nconst CANCELLED_ERROR_MESSAGE = \"@nicolastoulemont/std/multithread/cancelled\"\n\nlet runtimeConfig: { maxWorkers: number } | undefined\nlet runtimeInitialized = false\nlet runtimeImportPromise: Promise<MultithreadingRuntime> | undefined\n\nconst workerEntrypointCache = new WeakMap<object, WorkerEntrypoint>()\n\nconst makeRuntimeUnavailableError = (\n cause?: unknown,\n message = 'Optional peer dependency \"multithreading\" is unavailable. Install it to use Multithread APIs.',\n): MultithreadRuntimeUnavailableError => ({\n _tag: \"MultithreadRuntimeUnavailableError\",\n message,\n cause,\n})\n\nconst makeRuntimeAlreadyInitializedError = (\n message = \"Multithread runtime is already initialized and can no longer be configured.\",\n): MultithreadRuntimeAlreadyInitializedError => ({\n _tag: \"MultithreadRuntimeAlreadyInitializedError\",\n message,\n})\n\nconst makeWorkerExecutionError = (message: string, cause: unknown): MultithreadWorkerExecutionError => ({\n _tag: \"MultithreadWorkerExecutionError\",\n message,\n cause,\n})\n\nconst makeCancelledError = (\n message = \"Multithread operation was cancelled before completion.\",\n): MultithreadCancelledError => ({\n _tag: \"MultithreadCancelledError\",\n message,\n})\n\nconst makeAllFailedError = (message: string, errors: readonly unknown[]): MultithreadAllFailedError => ({\n _tag: \"MultithreadAllFailedError\",\n message,\n errors,\n})\n\nconst getErrorMessage = (cause: unknown): string | undefined =>\n cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : undefined\n\nconst isCancelledCause = (cause: unknown): boolean => {\n const message = getErrorMessage(cause)\n return message === CANCELLED_ERROR_MESSAGE || message === \"Task aborted\"\n}\n\nconst isCallerLocationFailure = (cause: unknown): boolean => {\n const message = getErrorMessage(cause)\n return typeof message === \"string\" && message.startsWith(\"Could not parse coordinates from:\")\n}\n\nconst isResultLike = (value: unknown): value is ResultType<unknown, unknown> => {\n if (typeof value !== \"object\" || value === null || !(\"_tag\" in value)) return false\n const tag = Reflect.get(value, \"_tag\")\n if (tag === \"Ok\") return \"value\" in value\n if (tag === \"Err\") return \"error\" in value\n return false\n}\n\nconst resultOk = <A>(value: A): ResultType<A, never> => ok(value)\nconst resultErr = <E>(error: E): ResultType<never, E> => err(error)\n\nconst normalizeWorkerReturn = <A, E>(value: unknown): ResultType<A, E> => {\n if (isResultLike(value)) {\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- isResultLike confirms runtime shape; generic channels are erased.\n return value as ResultType<A, E>\n }\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Worker return value is user-defined and mapped to generic success type.\n return resultOk(value as A)\n}\n\nconst runFromInputResult = (\n input: unknown,\n execute: (value: unknown) => MultithreadOp<unknown, unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> => {\n if (!isResultLike(input)) {\n return execute(input)\n }\n\n if (input._tag === \"Err\") {\n return Promise.resolve(resultErr(input.error))\n }\n\n return execute(input.value).result()\n}\n\nconst normalizeParallelism = (parallelism: number | undefined, fallback: number): number => {\n if (typeof parallelism !== \"number\" || !Number.isFinite(parallelism)) return fallback\n const rounded = Math.floor(parallelism)\n return rounded > 0 ? rounded : fallback\n}\n\nconst isWorkerLike = (value: unknown): value is WorkerLike => typeof value === \"function\"\n\nconst isParallelOptions = (value: unknown): value is MultithreadParallelOptions =>\n typeof value === \"object\" && value !== null\n\nconst resolveParallelOptions = (value: unknown): MultithreadParallelOptions | undefined =>\n isParallelOptions(value) ? value : undefined\n\nconst getDefaultParallelism = (): number => {\n if (runtimeConfig !== undefined) {\n return runtimeConfig.maxWorkers\n }\n if (typeof navigator !== \"undefined\" && typeof navigator.hardwareConcurrency === \"number\") {\n return normalizeParallelism(navigator.hardwareConcurrency, 4)\n }\n return 4\n}\n\nconst createSharedSignal = (): MultithreadSignal => {\n if (typeof SharedArrayBuffer !== \"function\") return null\n return new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))\n}\n\nconst createCancelController = (): InternalCancelController => {\n const signal = createSharedSignal()\n const listeners = new Set<() => void>()\n let cancelled = false\n\n const isCancelled = (): boolean => cancelled || (signal !== null && Atomics.load(signal, 0) === 1)\n\n const cancel = (): void => {\n if (cancelled) return\n cancelled = true\n\n if (signal !== null) {\n Atomics.store(signal, 0, 1)\n Atomics.notify(signal, 0)\n }\n\n const activeListeners = Array.from(listeners)\n listeners.clear()\n\n for (const listener of activeListeners) {\n try {\n listener()\n } catch {\n // Intentionally ignore listener disposal errors during cancellation fanout.\n }\n }\n }\n\n const onCancel = (listener: () => void): void => {\n if (cancelled) {\n listener()\n return\n }\n listeners.add(listener)\n }\n\n return {\n signal,\n isCancelled,\n cancel,\n onCancel,\n }\n}\n\nconst loadRuntimeModule = async (): Promise<ResultType<MultithreadingRuntime, MultithreadError>> => {\n try {\n runtimeImportPromise ??= import(\"multithreading\") as Promise<MultithreadingRuntime>\n return resultOk(await runtimeImportPromise)\n } catch (cause) {\n return resultErr(makeRuntimeUnavailableError(cause))\n }\n}\n\nconst getRuntime = async (): Promise<ResultType<MultithreadingRuntime, MultithreadError>> => {\n const runtimeResult = await loadRuntimeModule()\n if (runtimeResult._tag === \"Err\") return runtimeResult\n\n const runtime = runtimeResult.value\n\n if (!runtimeInitialized) {\n try {\n if (runtimeConfig !== undefined) {\n runtime.initRuntime(runtimeConfig)\n }\n runtimeInitialized = true\n } catch (cause) {\n return resultErr(makeWorkerExecutionError(\"Failed to initialize multithreading runtime.\", cause))\n }\n }\n\n return resultOk(runtime)\n}\n\nconst createWorkerEntrypoint = <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n): WorkerEntrypoint => {\n const cached = workerEntrypointCache.get(worker)\n if (cached !== undefined) {\n return cached\n }\n\n const source = worker.toString()\n // oxlint-disable-next-line typescript-eslint/no-implied-eval, typescript-eslint/no-unsafe-type-assertion -- Worker code must be reconstructed from serialized callback source and typed at runtime.\n const factory = new Function(\n `\nreturn async function (...__args) {\n const __signal = __args.pop()\n const __isCancelled = () => __signal !== null && Atomics.load(__signal, 0) === 1\n const __throwIfCancelled = () => {\n if (__isCancelled()) {\n throw new Error(${JSON.stringify(CANCELLED_ERROR_MESSAGE)})\n }\n }\n const __ctx = {\n signal: __signal,\n isCancelled: __isCancelled,\n throwIfCancelled: __throwIfCancelled,\n }\n const __worker = (${source})\n return await __worker(...__args, __ctx)\n}\n`,\n ) as () => WorkerEntrypoint\n\n const entrypoint = factory()\n workerEntrypointCache.set(worker, entrypoint)\n return entrypoint\n}\n\nconst createMultithreadOperation = <A, E>(\n execute: (controller: InternalCancelController) => Promise<ResultType<A, E | MultithreadError>>,\n): MultithreadOp<A, E | MultithreadError> => {\n const controller = createCancelController()\n let runPromise: Promise<ResultType<A, E | MultithreadError>> | undefined\n\n const start = (): Promise<ResultType<A, E | MultithreadError>> => {\n if (runPromise !== undefined) return runPromise\n\n if (controller.isCancelled()) {\n runPromise = Promise.resolve(resultErr(makeCancelledError()))\n return runPromise\n }\n\n runPromise = execute(controller)\n .catch((cause: unknown) => resultErr(makeWorkerExecutionError(\"Multithread operation failed.\", cause)))\n .then((result) => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n return result\n })\n\n return runPromise\n }\n\n const then: PromiseLike<ResultType<A, E | MultithreadError>>[\"then\"] = (onfulfilled, onrejected) =>\n start().then(onfulfilled, onrejected)\n\n return {\n _tag: \"MultithreadOp\",\n [FxTypeId]: {\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _A: () => undefined as unknown as A,\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _E: () => undefined as unknown as E | MultithreadError,\n // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Fx marker channels are phantom-only type metadata.\n _R: () => undefined as never,\n },\n result: start,\n abort: () => {\n controller.cancel()\n },\n // oxlint-disable-next-line eslint-plugin-unicorn/no-thenable -- MultithreadOp is intentionally PromiseLike for `await op` ergonomics.\n then,\n async *[Symbol.asyncIterator](): AsyncGenerator<E | MultithreadError, A, unknown> {\n const result = await start()\n if (result._tag === \"Err\") {\n yield result.error\n throw new Error(\"Unreachable: Fx.gen should short-circuit on yielded Multithread errors\")\n }\n return result.value\n },\n }\n}\n\nconst runWorkerLocally = async <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n args: Args,\n controller: InternalCancelController,\n): Promise<ResultType<A, E | MultithreadError>> => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const ctx: MultithreadCtx = {\n signal: controller.signal,\n isCancelled: () => controller.isCancelled(),\n throwIfCancelled: () => {\n if (controller.isCancelled()) throw new Error(CANCELLED_ERROR_MESSAGE)\n },\n }\n\n try {\n const value = await worker(...args, ctx)\n\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const normalized = normalizeWorkerReturn<A, E>(value)\n if (normalized._tag === \"Err\") {\n return resultErr(normalized.error)\n }\n\n return resultOk(normalized.value)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Multithread worker failed during execution.\", cause))\n }\n}\n\nconst runDataFirst = <Args extends readonly unknown[], A, E>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n args: Args,\n): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n const runtimeResult = await getRuntime()\n if (runtimeResult._tag === \"Err\") return resultErr(runtimeResult.error)\n\n const runtime = runtimeResult.value\n const entrypoint = createWorkerEntrypoint(worker)\n\n let joinHandle: ReturnType<MultithreadingRuntime[\"spawn\"]> | undefined\n\n try {\n const movedPayload = runtime.move(...args, controller.signal)\n joinHandle = runtime.spawn(movedPayload, entrypoint)\n controller.onCancel(() => {\n joinHandle?.abort()\n })\n } catch (cause) {\n if (isCallerLocationFailure(cause)) {\n return runWorkerLocally(worker, args, controller)\n }\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Failed to start multithread worker.\", cause))\n }\n\n try {\n const joined = await joinHandle.join()\n\n if (controller.isCancelled()) {\n return resultErr(makeCancelledError())\n }\n\n if (!joined.ok) {\n const joinError = joined.error ?? new Error(\"Multithread worker returned an unknown error.\")\n if (isCancelledCause(joinError)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Multithread worker failed during execution.\", joinError))\n }\n\n const normalized = normalizeWorkerReturn<A, E>(joined.value)\n if (normalized._tag === \"Err\") {\n return resultErr(normalized.error)\n }\n return resultOk(normalized.value)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n return resultErr(makeCancelledError())\n }\n return resultErr(makeWorkerExecutionError(\"Failed to join multithread worker.\", cause))\n }\n })\n\nfunction runOverload<A, E = never>(\n worker: (ctx: MultithreadCtx) => WorkerReturn<A, E>,\n): MultithreadOp<A, E | MultithreadError>\nfunction runOverload<Args extends readonly unknown[], A, E = never>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n ...args: Args\n): MultithreadOp<A, E | MultithreadError>\nfunction runOverload(worker: unknown, ...args: unknown[]): MultithreadOp<unknown, unknown> {\n if (!isWorkerLike(worker)) {\n throw new TypeError(\"Multithread.run expects a worker function as first argument.\")\n }\n return runDataFirst(worker, args)\n}\n\n/**\n * Execute one worker task as a cancelable `MultithreadOp`.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.run((ctx) => (ctx.isCancelled() ? 0 : 42))\n * // => cancelable operation with result() and abort()\n * ```\n *\n * @category Constructors\n */\nexport const run: MultithreadRun = runOverload\n\nfunction taskOverload<A, E = never>(\n worker: (ctx: MultithreadCtx) => WorkerReturn<A, E>,\n): () => MultithreadOp<A, E | MultithreadError>\nfunction taskOverload<Args extends readonly unknown[], A, E = never>(\n worker: (...args: [...Args, MultithreadCtx]) => WorkerReturn<A, E>,\n): (...args: Args) => MultithreadOp<A, E | MultithreadError>\nfunction taskOverload(worker: unknown): (...args: unknown[]) => MultithreadOp<unknown, unknown> {\n if (!isWorkerLike(worker)) {\n throw new TypeError(\"Multithread.task expects a worker function.\")\n }\n return (...args: unknown[]) => runDataFirst(worker, args)\n}\n\n/**\n * Create a reusable worker task factory.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const create = Multithread.task((ctx) => (ctx.isCancelled() ? 0 : 16))\n * const op = create()\n * // => operation that resolves to 16 when executed\n * ```\n *\n * @category Constructors\n */\nexport const task: MultithreadTask = taskOverload\n\nconst executeInParallel = <A, B, E>(\n values: readonly A[],\n createItemOperation: (value: A, index: number) => MultithreadOp<B, E | MultithreadError>,\n parallelism: number,\n controller: InternalCancelController,\n): Promise<ResultType<readonly B[], E | MultithreadError>> => {\n if (values.length === 0) {\n return Promise.resolve(resultOk<readonly B[]>([]))\n }\n\n return new Promise<ResultType<readonly B[], E | MultithreadError>>((resolve) => {\n const operations = new Map<number, MultithreadOp<B, E | MultithreadError>>()\n const output: B[] = []\n\n let inFlight = 0\n let nextIndex = 0\n let completed = 0\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations.values()) {\n operation.abort()\n }\n operations.clear()\n }\n\n const settle = (result: ResultType<readonly B[], E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const handleOperation = (index: number, operation: MultithreadOp<B, E | MultithreadError>): void => {\n void (async () => {\n try {\n const result = await operation.result()\n\n inFlight -= 1\n operations.delete(index)\n\n if (settled) return\n\n if (result._tag === \"Err\") {\n settle(resultErr(result.error))\n return\n }\n\n output[index] = result.value\n completed += 1\n\n if (completed === values.length) {\n settled = true\n resolve(resultOk(output))\n return\n }\n\n launch()\n } catch (cause) {\n inFlight -= 1\n operations.delete(index)\n\n if (settled) return\n\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n settle(resultErr(makeWorkerExecutionError(\"Failed while executing multithread batch.\", cause)))\n }\n })()\n }\n\n const launch = (): void => {\n while (!settled && inFlight < parallelism && nextIndex < values.length) {\n const index = nextIndex\n nextIndex += 1\n\n const operation = createItemOperation(values[index]!, index)\n operations.set(index, operation)\n inFlight += 1\n\n handleOperation(index, operation)\n }\n }\n\n launch()\n })\n}\n\nconst mapDataFirst = <A, B, E>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError> =>\n createMultithreadOperation((controller) => {\n const parallelism = normalizeParallelism(options?.parallelism, getDefaultParallelism())\n return executeInParallel(values, (value, index) => runDataFirst(worker, [value, index]), parallelism, controller)\n })\n\nfunction mapOverload<A, B, E = never>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError>\nfunction mapOverload<A, B, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\nfunction mapOverload<A, B, E = never>(\n worker: MultithreadMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\nfunction mapOverload<A, B, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadMapWorker<A, B, E>,\n workerOrOptions?: MultithreadMapWorker<A, B, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n mapDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.map(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n mapDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n}\n\n/**\n * Map a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.map([1, 2, 3], (value) => value * 2)\n * // => operation that resolves to [2, 4, 6]\n * ```\n *\n * @category Mapping\n */\nexport const map: MultithreadMap = mapOverload\n\nconst forEachDataFirst = <A, E>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<void, E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<void, E | MultithreadError>> => {\n const mapped = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (mapped._tag === \"Err\") return resultErr(mapped.error)\n return resultOk(undefined)\n })\n\nfunction forEachOverload<A, E = never>(\n values: readonly A[],\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<void, E | MultithreadError>\nfunction forEachOverload<A, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<void, E | InputE | MultithreadError>>\nfunction forEachOverload<A, E = never>(\n worker: MultithreadMapWorker<A, unknown, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>\nfunction forEachOverload<A, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadMapWorker<A, unknown, E>,\n workerOrOptions?: MultithreadMapWorker<A, unknown, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<void, E | MultithreadError>\n | Promise<ResultType<void, E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n forEachDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<void, E | ResultInputE | MultithreadError>>\n : MultithreadOp<void, E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.forEach(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n forEachDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as MultithreadOp<void, E | MultithreadError> | Promise<ResultType<void, E | InputE | MultithreadError>>\n}\n\n/**\n * Run side-effecting parallel work for each item.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.forEach([\"a\", \"b\"], (value) => value.toUpperCase())\n * // => operation that resolves to void after all items complete\n * ```\n *\n * @category Sequencing\n */\nexport const forEach: MultithreadForEach = forEachOverload\n\nconst filterDataFirst = <A, E>(\n values: readonly A[],\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly A[], E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<readonly A[], E | MultithreadError>> => {\n const decisions = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (decisions._tag === \"Err\") return resultErr(decisions.error)\n\n const filtered: A[] = []\n for (let index = 0; index < values.length; index += 1) {\n if (decisions.value[index] === true) {\n filtered.push(values[index]!)\n }\n }\n\n return resultOk(filtered)\n })\n\nfunction filterOverload<A, E = never>(\n values: readonly A[],\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly A[], E | MultithreadError>\nfunction filterOverload<A, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\nfunction filterOverload<A, E = never>(\n worker: MultithreadFilterWorker<A, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>\nfunction filterOverload<A, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadFilterWorker<A, E>,\n workerOrOptions?: MultithreadFilterWorker<A, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly A[], E | MultithreadError>\n | Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n filterDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly A[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly A[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.filter(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n filterDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly A[], E | MultithreadError>\n | Promise<ResultType<readonly A[], E | InputE | MultithreadError>>\n}\n\n/**\n * Filter a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.filter([1, 2, 3, 4], (value) => value % 2 === 0)\n * // => operation that resolves to [2, 4]\n * ```\n *\n * @category Filtering\n */\nexport const filter: MultithreadFilter = filterOverload\n\nconst flatMapDataFirst = <A, B, E>(\n values: readonly A[],\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError> =>\n createMultithreadOperation(async (controller): Promise<ResultType<readonly B[], E | MultithreadError>> => {\n const chunks = await executeInParallel(\n values,\n (value, index) => runDataFirst(worker, [value, index]),\n normalizeParallelism(options?.parallelism, getDefaultParallelism()),\n controller,\n )\n\n if (chunks._tag === \"Err\") return resultErr(chunks.error)\n\n const flattened: B[] = []\n for (const chunk of chunks.value) {\n flattened.push(...chunk)\n }\n\n return resultOk(flattened)\n })\n\nfunction flatMapOverload<A, B, E = never>(\n values: readonly A[],\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): MultithreadOp<readonly B[], E | MultithreadError>\nfunction flatMapOverload<A, B, E = never, InputE = never>(\n values: ResultType<readonly A[], InputE>,\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\nfunction flatMapOverload<A, B, E = never>(\n worker: MultithreadFlatMapWorker<A, B, E>,\n options?: MultithreadParallelOptions,\n): <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\nfunction flatMapOverload<A, B, E = never, InputE = never>(\n valuesOrWorker: readonly A[] | ResultType<readonly A[], InputE> | MultithreadFlatMapWorker<A, B, E>,\n workerOrOptions?: MultithreadFlatMapWorker<A, B, E> | MultithreadParallelOptions,\n options?: MultithreadParallelOptions,\n):\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n | (<Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>) {\n if (typeof valuesOrWorker === \"function\") {\n const curriedOptions = resolveParallelOptions(workerOrOptions)\n return ((values: readonly A[] | ResultType<readonly A[], unknown>) =>\n runFromInputResult(values, (resolvedValues) =>\n flatMapDataFirst(resolvedValues as readonly A[], valuesOrWorker, curriedOptions),\n )) as <Input extends readonly A[] | ResultType<readonly A[], unknown>>(\n values: Input,\n ) => Input extends ResultType<readonly A[], infer ResultInputE>\n ? Promise<ResultType<readonly B[], E | ResultInputE | MultithreadError>>\n : MultithreadOp<readonly B[], E | MultithreadError>\n }\n\n if (typeof workerOrOptions !== \"function\") {\n throw new TypeError(\"Multithread.flatMap(values, worker, options) requires a worker function.\")\n }\n\n return runFromInputResult(valuesOrWorker, (resolvedValues) =>\n flatMapDataFirst(resolvedValues as readonly A[], workerOrOptions, options),\n ) as\n | MultithreadOp<readonly B[], E | MultithreadError>\n | Promise<ResultType<readonly B[], E | InputE | MultithreadError>>\n}\n\n/**\n * Flat-map a collection in parallel.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const op = Multithread.flatMap([1, 2], (value) => [value, value * 10])\n * // => operation that resolves to [1, 10, 2, 20]\n * ```\n *\n * @category Sequencing\n */\nexport const flatMap: MultithreadFlatMap = flatMapOverload\n\nconst raceDataFirst = <A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation((controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (operations.length === 0) {\n return Promise.resolve(resultErr(makeAllFailedError(\"Cannot race an empty list of operations.\", [])))\n }\n\n return new Promise<ResultType<A, E | MultithreadError>>((resolve) => {\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations) {\n operation.abort()\n }\n }\n\n const settle = (result: ResultType<A, E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const watchOperation = (operation: MultithreadOp<A, E>): void => {\n void (async () => {\n try {\n const result = await operation.result()\n settle(result)\n } catch (cause) {\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n settle(resultErr(makeWorkerExecutionError(\"Multithread race failed.\", cause)))\n }\n })()\n }\n\n for (const operation of operations) {\n watchOperation(operation)\n }\n })\n })\n\nfunction raceOverload<A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError>\nfunction raceOverload<A, E, InputE = never>(\n operations: ResultType<readonly MultithreadOp<A, E>[], InputE>,\n): Promise<ResultType<A, E | InputE | MultithreadError>>\nfunction raceOverload<Ops extends readonly MultithreadOp<unknown, unknown>[]>(\n operations: Ops,\n): MultithreadOp<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | MultithreadError\n>\nfunction raceOverload<Ops extends readonly MultithreadOp<unknown, unknown>[], InputE = never>(\n operations: ResultType<Ops, InputE>,\n): Promise<\n ResultType<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | InputE | MultithreadError\n >\n>\nfunction raceOverload(\n operations:\n | readonly MultithreadOp<unknown, unknown>[]\n | ResultType<readonly MultithreadOp<unknown, unknown>[], unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> {\n return runFromInputResult(operations, (resolvedOperations) =>\n raceDataFirst(resolvedOperations as readonly MultithreadOp<unknown, unknown>[]),\n )\n}\n\n/**\n * Resolve with the first successfully completed operation.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const fast = Multithread.run(() => 1)\n * const slow = Multithread.run(() => 2)\n * const op = Multithread.race([fast, slow])\n * // => operation that resolves with the first finished result\n * ```\n *\n * @category Combining\n */\nexport const race: MultithreadRace = raceOverload\n\nconst firstSuccessDataFirst = <A, E>(\n operations: readonly MultithreadOp<A, E>[],\n): MultithreadOp<A, E | MultithreadError> =>\n createMultithreadOperation((controller): Promise<ResultType<A, E | MultithreadError>> => {\n if (operations.length === 0) {\n return Promise.resolve(\n resultErr(makeAllFailedError(\"Cannot select a first success from an empty list of operations.\", [])),\n )\n }\n\n return new Promise<ResultType<A, E | MultithreadError>>((resolve) => {\n const failures: unknown[] = Array.from({ length: operations.length })\n let pending = operations.length\n let settled = false\n\n const abortAll = (): void => {\n for (const operation of operations) {\n operation.abort()\n }\n }\n\n const settle = (result: ResultType<A, E | MultithreadError>): void => {\n if (settled) return\n settled = true\n abortAll()\n resolve(result)\n }\n\n controller.onCancel(() => {\n settle(resultErr(makeCancelledError()))\n })\n\n const watchOperation = (operation: MultithreadOp<A, E>, index: number): void => {\n void (async () => {\n try {\n const result = await operation.result()\n\n if (settled) return\n\n if (result._tag === \"Ok\") {\n settle(resultOk(result.value))\n return\n }\n\n failures[index] = result.error\n pending -= 1\n\n if (pending === 0) {\n settle(\n resultErr(\n makeAllFailedError(\n \"All multithread operations failed before any success was produced.\",\n failures.filter((failure) => failure !== undefined),\n ),\n ),\n )\n }\n } catch (cause) {\n if (settled) return\n\n if (controller.isCancelled() || isCancelledCause(cause)) {\n settle(resultErr(makeCancelledError()))\n return\n }\n\n failures[index] = makeWorkerExecutionError(\"Multithread operation rejected unexpectedly.\", cause)\n pending -= 1\n\n if (pending === 0) {\n settle(\n resultErr(\n makeAllFailedError(\n \"All multithread operations failed before any success was produced.\",\n failures.filter((failure) => failure !== undefined),\n ),\n ),\n )\n }\n }\n })()\n }\n\n operations.forEach((operation, index) => {\n watchOperation(operation, index)\n })\n })\n })\n\nfunction firstSuccessOverload<A, E>(operations: readonly MultithreadOp<A, E>[]): MultithreadOp<A, E | MultithreadError>\nfunction firstSuccessOverload<A, E, InputE = never>(\n operations: ResultType<readonly MultithreadOp<A, E>[], InputE>,\n): Promise<ResultType<A, E | InputE | MultithreadError>>\nfunction firstSuccessOverload<Ops extends readonly MultithreadOp<unknown, unknown>[]>(\n operations: Ops,\n): MultithreadOp<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | MultithreadError\n>\nfunction firstSuccessOverload<Ops extends readonly MultithreadOp<unknown, unknown>[], InputE = never>(\n operations: ResultType<Ops, InputE>,\n): Promise<\n ResultType<\n Ops[number] extends MultithreadOp<infer A, unknown> ? A : never,\n (Ops[number] extends MultithreadOp<unknown, infer OpE> ? OpE : never) | InputE | MultithreadError\n >\n>\nfunction firstSuccessOverload(\n operations:\n | readonly MultithreadOp<unknown, unknown>[]\n | ResultType<readonly MultithreadOp<unknown, unknown>[], unknown>,\n): MultithreadOp<unknown, unknown> | Promise<ResultType<unknown, unknown>> {\n return runFromInputResult(operations, (resolvedOperations) =>\n firstSuccessDataFirst(resolvedOperations as readonly MultithreadOp<unknown, unknown>[]),\n )\n}\n\n/**\n * Return the first successful operation, aggregating failures if none succeed.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n *\n * const fail = Multithread.run(() => Result.err(\"boom\"))\n * const pass = Multithread.run(() => Result.ok(1))\n * const op = Multithread.firstSuccess([fail, pass])\n * // => operation that resolves with 1\n * ```\n *\n * @category Combining\n */\nexport const firstSuccess: MultithreadFirstSuccess = firstSuccessOverload\n\n/**\n * Configure max worker count used by the underlying runtime.\n *\n * Must be called before first multithread operation starts.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const configured = Multithread.configure({ maxWorkers: 4 })\n * // => { _tag: \"Ok\", value: undefined }\n * ```\n *\n * @category Constructors\n */\nexport const configure = (config: { maxWorkers: number }): ResultType<void, MultithreadError> => {\n if (runtimeInitialized) {\n return resultErr(makeRuntimeAlreadyInitializedError())\n }\n\n runtimeConfig = {\n maxWorkers: normalizeParallelism(config.maxWorkers, 1),\n }\n\n return resultOk(undefined)\n}\n\n/**\n * Shutdown worker runtime.\n *\n * This function is idempotent.\n *\n * @example\n * ```ts\n * import { Multithread } from \"@nicolastoulemont/std\"\n *\n * const shutdownPromise = Multithread.shutdown()\n * // => Promise<Result<void, MultithreadError>>\n * ```\n *\n * @category Utilities\n */\nexport const shutdown = async (): Promise<ResultType<void, MultithreadError>> => {\n if (!runtimeInitialized) {\n return resultOk(undefined)\n }\n\n const runtimeResult = await loadRuntimeModule()\n if (runtimeResult._tag === \"Err\") {\n runtimeInitialized = false\n return resultErr(runtimeResult.error)\n }\n\n try {\n runtimeResult.value.shutdown()\n return resultOk(undefined)\n } catch (cause) {\n return resultErr(makeWorkerExecutionError(\"Failed to shutdown multithreading runtime.\", cause))\n } finally {\n runtimeInitialized = false\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { t as option_d_exports } from "../index-Dm2dFysv.mjs";
1
+ import { t as option_d_exports } from "../index-UzMbg1dh.mjs";
2
2
  export { option_d_exports as Option };
@@ -1 +1 @@
1
- import{r as e}from"../option-Qt1H-u7c.mjs";export{e as Option};
1
+ import{r as e}from"../option-Tfbo4wty.mjs";export{e as Option};
@@ -1,2 +1,2 @@
1
- import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";import{t as n}from"./dual-CZhzZslG.mjs";import{n as r}from"./flow-D8_tllWl.mjs";import{t as i}from"./pipeable-COGyGMUV.mjs";import{t as a}from"./option.types-DRUm2QiI.mjs";var o=e({NoSuchElementError:()=>s,all:()=>_,filter:()=>g,flatMap:()=>p,fromNullable:()=>S,fromTry:()=>C,isNone:()=>d,isSome:()=>u,map:()=>f,match:()=>b,none:()=>l,orElse:()=>h,some:()=>c,tap:()=>m,unwrapOr:()=>v,unwrapOrElse:()=>y});const s=a,c=e=>({_tag:`Some`,value:e,[t]:{_A:()=>e,_E:()=>void 0,_R:()=>void 0},pipe:i,*[Symbol.iterator](){return e}}),l=()=>({_tag:`None`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},pipe:i,*[Symbol.iterator](){throw yield new s,Error(`Unreachable: Fx.gen should short-circuit on NoSuchElementError`)}}),u=e=>e._tag===`Some`,d=e=>e._tag===`None`,f=n(2,(e,t)=>{if(e._tag===`None`)return e;let n=t(e.value);return r(n)?Promise.resolve(n).then(c):c(n)}),p=n(2,(e,t)=>e._tag===`Some`?t(e.value):e),m=n(2,(e,t)=>{if(e._tag===`None`)return e;let n=t(e.value);return r(n)?Promise.resolve(n).then(()=>e):e}),h=n(2,(e,t)=>e._tag===`Some`?e:t()),g=n(2,(e,t)=>e._tag===`None`||t(e.value)?e:l()),_=e=>{if(Array.isArray(e)){let t=[];for(let n of e){if(n._tag===`None`)return n;t.push(n.value)}return c(t)}let t={};for(let[n,r]of Object.entries(e)){let e=r;if(e._tag===`None`)return r;t[n]=e.value}return c(t)},v=n(2,(e,t)=>e._tag===`Some`?e.value:t),y=n(2,(e,t)=>e._tag===`Some`?e.value:t()),b=n(2,(e,t)=>e._tag===`Some`?t.Some(e.value):t.None()),x=e=>e!=null,S=e=>x(e)?c(e):l(),C=e=>{try{let t=e();return r(t)?Promise.resolve(t).then(c).catch(()=>l()):c(t)}catch{return l()}};export{c as i,l as n,o as r,S as t};
2
- //# sourceMappingURL=option-Qt1H-u7c.mjs.map
1
+ import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";import{t as n}from"./dual-CZhzZslG.mjs";import{n as r}from"./flow-D8_tllWl.mjs";import{t as i}from"./pipeable-COGyGMUV.mjs";import{t as a}from"./option.types-D1mm0zUb.mjs";var o=e({NoSuchElementError:()=>s,all:()=>_,filter:()=>g,flatMap:()=>p,fromNullable:()=>S,fromTry:()=>C,isNone:()=>d,isSome:()=>u,map:()=>f,match:()=>b,none:()=>l,orElse:()=>h,some:()=>c,tap:()=>m,unwrapOr:()=>v,unwrapOrElse:()=>y});const s=a,c=e=>({_tag:`Some`,value:e,[t]:{_A:()=>e,_E:()=>void 0,_R:()=>void 0},pipe:i,*[Symbol.iterator](){return e}}),l=()=>({_tag:`None`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},pipe:i,*[Symbol.iterator](){throw yield new s,Error(`Unreachable: Fx.gen should short-circuit on NoSuchElementError`)}}),u=e=>e._tag===`Some`,d=e=>e._tag===`None`,f=n(2,(e,t)=>{if(e._tag===`None`)return e;let n=t(e.value);return r(n)?Promise.resolve(n).then(c):c(n)}),p=n(2,(e,t)=>e._tag===`Some`?t(e.value):e),m=n(2,(e,t)=>{if(e._tag===`None`)return e;let n=t(e.value);return r(n)?Promise.resolve(n).then(()=>e):e}),h=n(2,(e,t)=>e._tag===`Some`?e:t()),g=n(2,(e,t)=>e._tag===`None`||t(e.value)?e:l()),_=e=>{if(Array.isArray(e)){let t=[];for(let n of e){if(n._tag===`None`)return n;t.push(n.value)}return c(t)}let t={};for(let[n,r]of Object.entries(e)){let e=r;if(e._tag===`None`)return r;t[n]=e.value}return c(t)},v=n(2,(e,t)=>e._tag===`Some`?e.value:t),y=n(2,(e,t)=>e._tag===`Some`?e.value:t()),b=n(2,(e,t)=>e._tag===`Some`?t.Some(e.value):t.None()),x=e=>e!=null,S=e=>x(e)?c(e):l(),C=e=>{try{let t=e();return r(t)?Promise.resolve(t).then(c).catch(()=>l()):c(t)}catch{return l()}};export{c as i,l as n,o as r,S as t};
2
+ //# sourceMappingURL=option-Tfbo4wty.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option-Tfbo4wty.mjs","names":["NoSuchElementErrorCtor","values"],"sources":["../src/option/option.ts"],"sourcesContent":["/**\n * Optional value primitives for modeling presence (`Some`) and absence (`None`).\n *\n * **Mental model**\n * - `Option<A>` is either a value or no value.\n * - Prefer `Option` when missing data is expected and not exceptional.\n *\n * **Common tasks**\n * - Construct with `Option.some`, `Option.none`, `Option.fromNullable`.\n * - Transform with `Option.map`, `Option.flatMap`, `Option.filter`.\n * - Extract with `Option.unwrapOr`, `Option.match`.\n *\n * **Gotchas**\n * - `Option.none` short-circuits in `Fx.gen`.\n * - Use `Option.match` for exhaustive branch handling.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const name = Option.fromNullable(\"Ada\")\n * const upper = Option.map(name, (value) => value.toUpperCase())\n * ```\n *\n * @module\n */\nimport { FxTypeId } from \"../fx/fx.types\"\nimport { dual } from \"../shared/dual\"\nimport { isPromise } from \"../shared/is-promise\"\nimport { pipeMethod } from \"../shared/pipeable\"\nimport { NoSuchElementError as NoSuchElementErrorCtor } from \"./option.types\"\nimport type {\n Option as OptionType,\n OptionAll,\n OptionFlatMap,\n OptionMap,\n OptionMatch,\n OptionTap,\n OptionOrElse,\n OptionFilter,\n OptionUnwrapOr,\n OptionUnwrapOrElse,\n FromTryReturn,\n} from \"./option.types\"\n\n/**\n * Re-exported error type used when yielding `Option.none()` in `Fx.gen`.\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const error = new Option.NoSuchElementError()\n * // => error.name === \"NoSuchElementError\"\n * ```\n *\n * @category Re-exports\n */\nexport const NoSuchElementError = NoSuchElementErrorCtor\n\n/**\n * Re-exported `NoSuchElementError` instance type.\n *\n * @example\n * ```ts\n * import type { Option } from \"@nicolastoulemont/std\"\n *\n * type Example = Option.NoSuchElementError\n * ```\n *\n * @category Re-exports\n */\nexport type NoSuchElementError = InstanceType<typeof NoSuchElementErrorCtor>\n\n/**\n * Re-exported `Option` type.\n *\n * @example\n * ```ts\n * import type { Option } from \"@nicolastoulemont/std\"\n *\n * type Example = Option.Option<unknown>\n * ```\n *\n * @category Re-exports\n */\nexport type Option<T> = OptionType<T>\n\n/* oxlint-disable no-unsafe-type-assertion -- Option runtime values carry erased Fx phantom channels that require explicit marker assertions. */\n\n// ============================================================================\n// Constructors\n// ============================================================================\n\n/**\n * Create an Option with a value.\n *\n * @param value - The value to wrap\n * @returns An Option with `_tag: \"Some\"`\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const value = Option.some(42)\n * // => { _tag: \"Some\", value: 42 }\n * ```\n *\n * @category Constructors\n */\nexport const some = <T>(value: T): OptionType<T> => ({\n _tag: \"Some\",\n value,\n [FxTypeId]: {\n _A: () => value,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n pipe: pipeMethod,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<NoSuchElementError, T, unknown> {\n return value\n },\n})\n\n/**\n * Create an Option with no value.\n *\n * @returns An Option with `_tag: \"None\"`\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const value = Option.none<number>()\n * // => { _tag: \"None\" }\n * ```\n *\n * @category Constructors\n */\nexport const none = <T = never>(): OptionType<T> => ({\n _tag: \"None\",\n [FxTypeId]: {\n _A: () => undefined as never,\n _E: () => undefined as unknown as NoSuchElementError,\n _R: () => undefined as never,\n },\n pipe: pipeMethod,\n *[Symbol.iterator](): Generator<NoSuchElementError, never, unknown> {\n yield new NoSuchElementError()\n throw new Error(\"Unreachable: Fx.gen should short-circuit on NoSuchElementError\")\n },\n})\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if an Option has a value.\n *\n * @param option - The Option to check\n * @returns true if the Option is some\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const value = Option.isSome(Option.some(1))\n * // => true\n * ```\n *\n * @category Guards\n */\nexport const isSome = <T>(option: OptionType<T>): option is Extract<OptionType<T>, { _tag: \"Some\" }> =>\n option._tag === \"Some\"\n\n/**\n * isNone utility.\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const value = Option.isNone(Option.none())\n * // => true\n * ```\n *\n * @category Guards\n */\nexport const isNone = <T>(option: OptionType<T>): option is Extract<OptionType<T>, { _tag: \"None\" }> =>\n option._tag === \"None\"\n\n// ============================================================================\n// Transformations (curried for pipe)\n// ============================================================================\n\n/**\n * Transform the value of an Option.\n * If the Option is none, it passes through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `map(option, fn)`\n * - Data-last: `pipe(option, map(fn))`\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<U>\n * - Async fn: returns Promise<Option<U>>\n *\n * @param fn - Function to transform the value\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.some(2)\n * const dataFirst = Option.map(input, (n) => n + 1)\n * // => { _tag: \"Some\", value: 3 }\n *\n * const dataLast = Option.map((n: number) => n + 1)(input)\n * // => { _tag: \"Some\", value: 3 }\n * ```\n *\n * @category Mapping\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const map: OptionMap = dual(2, (option: OptionType<unknown>, fn: (value: unknown) => unknown) => {\n if (option._tag === \"None\") return option as any\n const mapped = fn(option.value)\n if (isPromise(mapped)) {\n return Promise.resolve(mapped).then(some) as any\n }\n return some(mapped) as any\n})\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Chain operations that return Options.\n * If the Option is none, it passes through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `flatMap(option, fn)`\n * - Data-last: `pipe(option, flatMap(fn))`\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<U>\n * - Async fn: returns Promise<Option<U>>\n *\n * @param fn - Function that takes a value and returns an Option (or Promise<Option>)\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.some(2)\n * const dataFirst = Option.flatMap(input, (n) => Option.some(n + 1))\n * // => { _tag: \"Some\", value: 3 }\n *\n * const dataLast = Option.flatMap((n: number) => Option.some(n + 1))(input)\n * // => { _tag: \"Some\", value: 3 }\n * ```\n *\n * @category Sequencing\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const flatMap: OptionFlatMap = dual(2, (option: OptionType<unknown>, fn: (value: unknown) => unknown) =>\n option._tag === \"Some\" ? fn(option.value) : option,\n)\n\n/**\n * Perform a side effect on the value without modifying the Option.\n * Useful for debugging, logging, or other side effects in a pipeline.\n * If the Option is none, the function is not called.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `tap(option, fn)`\n * - Data-last: `pipe(option, tap(fn))`\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<T>\n * - Async fn: returns Promise<Option<T>>\n *\n * @param fn - Function to call with the value (return value is ignored)\n * @returns A function that takes an Option and returns the same Option\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * let seen = 0\n * const input = Option.some(2)\n * const dataFirst = Option.tap(input, (n) => {\n * seen = n\n * })\n * // => { _tag: \"Some\", value: 2 }\n *\n * const dataLast = Option.tap((n: number) => {\n * seen = n\n * })(input)\n * // => { _tag: \"Some\", value: 2 }\n * ```\n *\n * @category Sequencing\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tap: OptionTap = dual(2, (option: OptionType<unknown>, fn: (value: unknown) => unknown) => {\n if (option._tag === \"None\") return option as any\n const sideEffect = fn(option.value)\n if (isPromise(sideEffect)) {\n return Promise.resolve(sideEffect).then(() => option) as any\n }\n return option as any\n})\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Recover from none by providing an alternative Option.\n * If the Option is some, it passes through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `orElse(option, fn)`\n * - Data-last: `pipe(option, orElse(fn))`\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<T | U>\n * - Async fn: returns Promise<Option<T | U>>\n *\n * @param fn - Function that returns an alternative Option\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.none<number>()\n * const dataFirst = Option.orElse(input, () => Option.some(0))\n * // => { _tag: \"Some\", value: 0 }\n *\n * const dataLast = Option.orElse(() => Option.some(0))(input)\n * // => { _tag: \"Some\", value: 0 }\n * ```\n *\n * @category Combining\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const orElse: OptionOrElse = dual(2, (option: OptionType<unknown>, fn: () => unknown) =>\n option._tag === \"Some\" ? option : fn(),\n)\n\n/**\n * Filter an Option based on a predicate.\n * If the predicate returns false, converts to none.\n * If the Option is already none, it passes through unchanged.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `filter(option, predicate)`\n * - Data-last: `pipe(option, filter(predicate))`\n *\n * @param predicate - Function that returns true to keep the value\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.some(3)\n * const dataFirst = Option.filter(input, (n) => n > 0)\n * // => { _tag: \"Some\", value: 3 }\n *\n * const dataLast = Option.filter((n: number) => n > 0)(input)\n * // => { _tag: \"Some\", value: 3 }\n * ```\n *\n * @category Filtering\n */\nexport const filter: OptionFilter = dual(2, (option: OptionType<unknown>, predicate: (value: unknown) => boolean) => {\n if (option._tag === \"None\") return option\n return predicate(option.value) ? option : none()\n})\n\n// ============================================================================\n// Combinators\n// ============================================================================\n\n/**\n * Combine multiple Options into a single Option.\n * Supports both array and object inputs.\n *\n * - If all Options are some, returns some with all values\n * - If any Option is none, returns none (short-circuits)\n *\n * For arrays of 1-6 elements, tuple types are inferred automatically.\n * For longer arrays, use `as const` to preserve tuple structure.\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const combined = Option.all([Option.some(1), Option.some(2)] as const)\n * // => { _tag: \"Some\", value: [1, 2] }\n * ```\n *\n * @category Combining\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument -- Required for handling union types in overloaded function */\nexport const all: OptionAll = (options: any): any => {\n if (Array.isArray(options)) {\n const values: unknown[] = []\n for (const option of options) {\n if (option._tag === \"None\") return option\n values.push(option.value)\n }\n return some(values)\n }\n\n const values: Record<string, unknown> = {}\n for (const [key, option] of Object.entries(options)) {\n const o = option as OptionType<unknown>\n if (o._tag === \"None\") return option\n values[key] = o.value\n }\n return some(values)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion */\n\n// ============================================================================\n// Extraction\n// ============================================================================\n\n/**\n * Get the value or a default value.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `unwrapOr(option, defaultValue)`\n * - Data-last: `pipe(option, unwrapOr(defaultValue))`\n *\n * Uses NoInfer to prevent type inference from the default value.\n *\n * @param defaultValue - Value to return if the Option is none\n * @returns A function that takes an Option and returns the value or default\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.none<number>()\n * const dataFirst = Option.unwrapOr(input, 0)\n * // => 0\n *\n * const dataLast = Option.unwrapOr(0)(input)\n * // => 0\n * ```\n *\n * @category Getters\n */\nexport const unwrapOr: OptionUnwrapOr = dual(\n 2,\n <T>(option: OptionType<T>, defaultValue: NoInfer<T>): T => (option._tag === \"Some\" ? option.value : defaultValue),\n)\n\n/**\n * Get the value or compute a value.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `unwrapOrElse(option, fn)`\n * - Data-last: `pipe(option, unwrapOrElse(fn))`\n *\n * @param fn - Function to compute a value\n * @returns A function that takes an Option and returns the value or computed value\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.none<number>()\n * const dataFirst = Option.unwrapOrElse(input, () => 0)\n * // => 0\n *\n * const dataLast = Option.unwrapOrElse(() => 0)(input)\n * // => 0\n * ```\n *\n * @category Getters\n */\nexport const unwrapOrElse: OptionUnwrapOrElse = dual(\n 2,\n <T>(option: OptionType<T>, fn: () => T): T => (option._tag === \"Some\" ? option.value : fn()),\n)\n\n/**\n * Pattern match on an Option, handling both some and none cases.\n *\n * Supports both data-first and data-last calling styles:\n * - Data-first: `match(option, { Some: ..., None: ... })`\n * - Data-last: `pipe(option, match({ Some: ..., None: ... }))`\n *\n * @param handlers - Object with `Some` and `None` handlers\n * @returns A function that takes an Option and returns the handler result\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const input = Option.some(2)\n * const dataFirst = Option.match(input, {\n * Some: (value) => `some:${value}` ,\n * None: () => \"none\" ,\n * })\n * // => \"some:2\"\n *\n * const dataLast = Option.match({\n * Some: (value: number) => `some:${value}` ,\n * None: () => \"none\" ,\n * })(input)\n * // => \"some:2\"\n * ```\n *\n * @category Pattern Matching\n */\nexport const match: OptionMatch = dual(\n 2,\n <T, U>(option: OptionType<T>, handlers: { Some: (value: T) => U; None: () => U }): U =>\n option._tag === \"Some\" ? handlers.Some(option.value) : handlers.None(),\n)\n\n// ============================================================================\n// Conversions\n// ============================================================================\n\n/**\n * Convert a nullable value to an Option.\n * `null` and `undefined` become `Option.none()`, other values become `Option.some(value)`.\n * The return type narrows to `Option<NonNullable<T>>`.\n *\n * @param value - The value to convert\n * @returns An Option\n *\n * @example\n * ```ts\n * fromNullable(42) // { _tag: \"Some\", value: 42 }\n * fromNullable(null) // { _tag: \"None\" }\n * fromNullable(undefined) // { _tag: \"None\" }\n *\n * const maybeName = \"Alice\" as string | undefined\n * const option = fromNullable(maybeName) // Option<string>\n * ```\n */\nconst isNonNullable = <T>(value: T): value is NonNullable<T> => value !== null && value !== undefined\n\n/**\n * fromNullable utility.\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const value = Option.fromNullable(\"Ada\")\n * // => { _tag: \"Some\", value: \"Ada\" }\n * ```\n *\n * @category Conversions\n */\nexport const fromNullable = <T>(value: T): OptionType<NonNullable<T>> => (isNonNullable(value) ? some(value) : none())\n\n/**\n * Wrap a function that might throw into an Option.\n * Supports both sync and async functions with automatic type inference.\n *\n * - Sync fn: returns Option<T>\n * - Async fn: returns Promise<Option<T>>\n *\n * **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),\n * you should add an explicit return type annotation. This is because TypeScript's\n * conditional types cannot determine if `any` is a Promise or not, resulting in a\n * union type `Promise<Option<unknown>> | Option<any>` that won't work\n * with Option utilities like `isSome` or `isNone`.\n *\n * @param fn - Function that might throw (sync or async)\n * @returns An Option with the return value or none\n *\n * @example\n * ```ts\n * import { Option } from \"@nicolastoulemont/std\"\n *\n * const parsed = Option.fromTry(() => Number.parseInt(\"42\", 10))\n * // => { _tag: \"Some\", value: 42 }\n * ```\n *\n * @category Conversions\n */\n/* oxlint-disable no-explicit-any, no-unsafe-type-assertion -- Required for conditional return type */\nexport const fromTry = <T>(fn: () => T): FromTryReturn<T> => {\n try {\n const result = fn()\n if (isPromise(result)) {\n return Promise.resolve(result)\n .then(some)\n .catch(() => none()) as unknown as FromTryReturn<T>\n }\n return some(result) as unknown as FromTryReturn<T>\n } catch {\n return none() as unknown as FromTryReturn<T>\n }\n}\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"qeA4DA,MAAa,EAAqBA,EAoDrB,EAAW,IAA6B,CACnD,KAAM,OACN,SACC,GAAW,CACV,OAAU,EACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CACD,KAAM,EAEN,EAAE,OAAO,WAAuD,CAC9D,OAAO,GAEV,EAiBY,OAAwC,CACnD,KAAM,QACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CACD,KAAM,EACN,EAAE,OAAO,WAA2D,CAElE,MADA,MAAM,IAAI,EACA,MAAM,iEAAiE,EAEpF,EAsBY,EAAa,GACxB,EAAO,OAAS,OAeL,EAAa,GACxB,EAAO,OAAS,OAoCL,EAAiB,EAAK,GAAI,EAA6B,IAAoC,CACtG,GAAI,EAAO,OAAS,OAAQ,OAAO,EACnC,IAAM,EAAS,EAAG,EAAO,MAAM,CAI/B,OAHI,EAAU,EAAO,CACZ,QAAQ,QAAQ,EAAO,CAAC,KAAK,EAAK,CAEpC,EAAK,EAAO,EACnB,CAiCW,EAAyB,EAAK,GAAI,EAA6B,IAC1E,EAAO,OAAS,OAAS,EAAG,EAAO,MAAM,CAAG,EAC7C,CAsCY,EAAiB,EAAK,GAAI,EAA6B,IAAoC,CACtG,GAAI,EAAO,OAAS,OAAQ,OAAO,EACnC,IAAM,EAAa,EAAG,EAAO,MAAM,CAInC,OAHI,EAAU,EAAW,CAChB,QAAQ,QAAQ,EAAW,CAAC,SAAW,EAAO,CAEhD,GACP,CAiCW,EAAuB,EAAK,GAAI,EAA6B,IACxE,EAAO,OAAS,OAAS,EAAS,GAAI,CACvC,CA4BY,EAAuB,EAAK,GAAI,EAA6B,IACpE,EAAO,OAAS,QACb,EAAU,EAAO,MAAM,CADK,EACO,GAAM,CAChD,CA2BW,EAAkB,GAAsB,CACnD,GAAI,MAAM,QAAQ,EAAQ,CAAE,CAC1B,IAAMC,EAAoB,EAAE,CAC5B,IAAK,IAAM,KAAU,EAAS,CAC5B,GAAI,EAAO,OAAS,OAAQ,OAAO,EACnC,EAAO,KAAK,EAAO,MAAM,CAE3B,OAAO,EAAKA,EAAO,CAGrB,IAAM,EAAkC,EAAE,CAC1C,IAAK,GAAM,CAAC,EAAK,KAAW,OAAO,QAAQ,EAAQ,CAAE,CACnD,IAAM,EAAI,EACV,GAAI,EAAE,OAAS,OAAQ,OAAO,EAC9B,EAAO,GAAO,EAAE,MAElB,OAAO,EAAK,EAAO,EAkCR,EAA2B,EACtC,GACI,EAAuB,IAAiC,EAAO,OAAS,OAAS,EAAO,MAAQ,EACrG,CA0BY,EAAmC,EAC9C,GACI,EAAuB,IAAoB,EAAO,OAAS,OAAS,EAAO,MAAQ,GAAI,CAC5F,CAgCY,EAAqB,EAChC,GACO,EAAuB,IAC5B,EAAO,OAAS,OAAS,EAAS,KAAK,EAAO,MAAM,CAAG,EAAS,MAAM,CACzE,CAwBK,EAAoB,GAAsC,GAAU,KAe7D,EAAmB,GAA0C,EAAc,EAAM,CAAG,EAAK,EAAM,CAAG,GAAM,CA6BxG,EAAc,GAAkC,CAC3D,GAAI,CACF,IAAM,EAAS,GAAI,CAMnB,OALI,EAAU,EAAO,CACZ,QAAQ,QAAQ,EAAO,CAC3B,KAAK,EAAK,CACV,UAAY,GAAM,CAAC,CAEjB,EAAK,EAAO,MACb,CACN,OAAO,GAAM"}
@@ -0,0 +1,2 @@
1
+ var e=class extends Error{_tag=`NoSuchElementError`;constructor(){super(`Option is None - no element present`),this.name=`NoSuchElementError`}};export{e as t};
2
+ //# sourceMappingURL=option.types-D1mm0zUb.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option.types-D1mm0zUb.mjs","names":[],"sources":["../src/option/option.types.ts"],"sourcesContent":["import type { Fx } from \"../fx/fx.types\"\nimport type { Pipeable } from \"../shared/pipeable\"\n\n/* oxlint-disable no-unsafe-type-assertion -- Option types expose Fx phantom channels through compile-time-only marker fields. */\n\n// ============================================================================\n// NoSuchElementError\n// ============================================================================\n\n/**\n * Error thrown when attempting to access a value from None.\n * Used as the error type when Option is yielded in Fx.gen().\n *\n * When you yield* Option.none() in Fx.gen(), the computation short-circuits\n * with this error, which becomes part of the error union type.\n *\n * This is the typed error channel for `Option.none()` in Fx computations.\n */\nexport class NoSuchElementError extends Error {\n readonly _tag = \"NoSuchElementError\"\n\n constructor() {\n super(\"Option is None - no element present\")\n this.name = \"NoSuchElementError\"\n }\n}\n\n// ============================================================================\n// Option Variant Types\n// ============================================================================\n\n/**\n * Represents an Option with a value.\n */\ntype Some<T> = {\n readonly _tag: \"Some\"\n readonly value: T\n}\n\n/**\n * Represents an Option with no value.\n */\ntype None = {\n readonly _tag: \"None\"\n}\n\n// ============================================================================\n// Option Type\n// ============================================================================\n\n/**\n * A discriminated union representing either a value (Some) or absence (None).\n * Uses _tag discriminator for unified API compatibility.\n * Compatible with ts-pattern for exhaustive matching.\n *\n * Implements Fx protocol: Option<T> is Fx<T, NoSuchElementError, never>\n * - Yielding Some in Fx.gen() returns the value\n * - Yielding None in Fx.gen() short-circuits with NoSuchElementError\n *\n * When yielded in a generator, yields NoSuchElementError\n * for proper type inference in both gen() and Fx.gen().\n */\nexport type Option<T> = (Some<T> | None) &\n Fx<T, NoSuchElementError> &\n Pipeable & {\n [Symbol.iterator](): Generator<NoSuchElementError, T, unknown>\n }\n\n/**\n * Compute the return type of `fromTry` based on whether fn returns a Promise.\n * - If fn returns Promise<T>, result is Promise<Option<T>>\n * - If fn returns T, result is Option<T>\n */\nexport type FromTryReturn<T> = T extends Promise<infer U> ? Promise<Option<U>> : Option<T>\n\n// ============================================================================\n// All/Combine types\n// ============================================================================\n\n/**\n * Extract the value type from an Option.\n * Uses structural matching to extract the value type from the Some branch.\n */\ntype OptionValue<O> = O extends { readonly _tag: \"Some\"; readonly value: infer T } ? T : never\n\n/**\n * Overloaded all() type with explicit tuple arities for better inference.\n * Provides tuple overloads for 1-6 elements so `as const` is not required.\n */\nexport type OptionAll = {\n // Tuple overloads (1-6 elements)\n <A>(options: readonly [Option<A>]): Option<[A]>\n <A, B>(options: readonly [Option<A>, Option<B>]): Option<[A, B]>\n <A, B, C>(options: readonly [Option<A>, Option<B>, Option<C>]): Option<[A, B, C]>\n <A, B, C, D>(options: readonly [Option<A>, Option<B>, Option<C>, Option<D>]): Option<[A, B, C, D]>\n <A, B, C, D, E>(options: readonly [Option<A>, Option<B>, Option<C>, Option<D>, Option<E>]): Option<[A, B, C, D, E]>\n <A, B, C, D, E, F>(\n options: readonly [Option<A>, Option<B>, Option<C>, Option<D>, Option<E>, Option<F>],\n ): Option<[A, B, C, D, E, F]>\n\n // Array fallback (longer tuples need `as const`)\n <T extends readonly Option<unknown>[]>(options: T): Option<{ -readonly [K in keyof T]: OptionValue<T[K]> }>\n\n // Object form\n <T extends Record<string, Option<unknown>>>(options: T): Option<{ -readonly [K in keyof T]: OptionValue<T[K]> }>\n}\n\n// ============================================================================\n// Function Interfaces for improved pipe inference\n// ============================================================================\n\n/**\n * Interface for flatMap - using method syntax improves generic inference in pipe chains.\n * Supports both data-first and data-last (curried) calling styles via dual().\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionFlatMap = {\n // Data-first overloads (async first)\n <A, B>(option: Option<A>, fn: (value: A) => Promise<Option<B>>): Promise<Option<B>>\n <A, B>(option: Option<A>, fn: (value: A) => Option<B>): Option<B>\n // Data-last overloads (curried for pipe)\n <A, B>(fn: (value: A) => Promise<Option<B>>): (option: Option<A>) => Promise<Option<B>>\n <A, B>(fn: (value: A) => Option<B>): (option: Option<A>) => Option<B>\n}\n\n/**\n * Interface for map function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionMap = {\n // Data-first overloads (async first)\n <A, B>(option: Option<A>, fn: (value: A) => Promise<B>): Promise<Option<B>>\n <A, B>(option: Option<A>, fn: (value: A) => B): Option<B>\n // Data-last overloads (curried for pipe)\n <A, B>(fn: (value: A) => Promise<B>): (option: Option<A>) => Promise<Option<B>>\n <A, B>(fn: (value: A) => B): (option: Option<A>) => Option<B>\n}\n\n/* oxlint-enable no-unsafe-type-assertion */\n\n/**\n * Interface for tap function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n */\nexport type OptionTap = {\n // Data-first overload\n <A, R>(option: Option<A>, fn: (value: A) => R): R extends Promise<unknown> ? Promise<Option<A>> : Option<A>\n // Data-last overload (curried for pipe)\n <A, R>(fn: (value: A) => R): (option: Option<A>) => R extends Promise<unknown> ? Promise<Option<A>> : Option<A>\n}\n\n/**\n * Interface for orElse function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionOrElse = {\n // Data-first overloads (async first)\n <A, B>(option: Option<A>, fn: () => Promise<Option<B>>): Promise<Option<A | B>>\n <A, B>(option: Option<A>, fn: () => Option<B>): Option<A | B>\n // Data-last overloads (curried for pipe)\n <A, B>(fn: () => Promise<Option<B>>): (option: Option<A>) => Promise<Option<A | B>>\n <A, B>(fn: () => Option<B>): (option: Option<A>) => Option<A | B>\n}\n\n/**\n * Interface for filter function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n */\nexport type OptionFilter = {\n // Data-first overload\n <A>(option: Option<A>, predicate: (value: A) => boolean): Option<A>\n // Data-last overload (curried for pipe)\n <A>(predicate: (value: A) => boolean): (option: Option<A>) => Option<A>\n}\n\n/**\n * Interface for unwrapOr function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n * Uses NoInfer to prevent type inference from the default value.\n */\nexport type OptionUnwrapOr = {\n // Data-first overload\n <T>(option: Option<T>, defaultValue: NoInfer<T>): T\n // Data-last overload (curried for pipe)\n <T>(defaultValue: NoInfer<T>): (option: Option<T>) => T\n}\n\n/**\n * Interface for unwrapOrElse function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n */\nexport type OptionUnwrapOrElse = {\n // Data-first overload\n <T>(option: Option<T>, fn: () => T): T\n // Data-last overload (curried for pipe)\n <T>(fn: () => T): (option: Option<T>) => T\n}\n\n/**\n * Interface for match function.\n * Supports both data-first and data-last (curried) calling styles via dual().\n */\nexport type OptionMatch = {\n // Data-first overload\n <T, U>(option: Option<T>, handlers: { Some: (value: T) => U; None: () => U }): U\n // Data-last overload (curried for pipe)\n <T, U>(handlers: { Some: (value: T) => U; None: () => U }): (option: Option<T>) => U\n}\n"],"mappings":"AAkBA,IAAa,EAAb,cAAwC,KAAM,CAC5C,KAAgB,qBAEhB,aAAc,CACZ,MAAM,sCAAsC,CAC5C,KAAK,KAAO"}
@@ -1,4 +1,4 @@
1
- import { c as FxTypeId, i as Fx } from "./fx.types-DeEWEltG.mjs";
1
+ import { i as Fx } from "./fx.types-DeEWEltG.mjs";
2
2
  import { t as Pipeable } from "./pipeable-rfqacPxZ.mjs";
3
3
 
4
4
  //#region src/option/option.types.d.ts
@@ -10,15 +10,10 @@ import { t as Pipeable } from "./pipeable-rfqacPxZ.mjs";
10
10
  * When you yield* Option.none() in Fx.gen(), the computation short-circuits
11
11
  * with this error, which becomes part of the error union type.
12
12
  *
13
- * Implements Fx protocol so it can be yielded in Fx.gen() directly.
13
+ * This is the typed error channel for `Option.none()` in Fx computations.
14
14
  */
15
- declare class NoSuchElementError extends Error implements Fx<never, NoSuchElementError> {
15
+ declare class NoSuchElementError extends Error {
16
16
  readonly _tag = "NoSuchElementError";
17
- readonly [FxTypeId]: {
18
- _A: () => never;
19
- _E: () => NoSuchElementError;
20
- _R: () => never;
21
- };
22
17
  constructor();
23
18
  }
24
19
  /**
@@ -43,7 +38,7 @@ type None = {
43
38
  * - Yielding Some in Fx.gen() returns the value
44
39
  * - Yielding None in Fx.gen() short-circuits with NoSuchElementError
45
40
  *
46
- * When yielded in a generator, yields NoSuchElementError (which implements Fx)
41
+ * When yielded in a generator, yields NoSuchElementError
47
42
  * for proper type inference in both gen() and Fx.gen().
48
43
  */
49
44
  type Option<T> = (Some<T> | None) & Fx<T, NoSuchElementError> & Pipeable & {
@@ -159,4 +154,4 @@ type OptionMatch = {
159
154
  };
160
155
  //#endregion
161
156
  export { OptionFilter as a, OptionMatch as c, OptionUnwrapOr as d, OptionUnwrapOrElse as f, OptionAll as i, OptionOrElse as l, NoSuchElementError as n, OptionFlatMap as o, Option as r, OptionMap as s, FromTryReturn as t, OptionTap as u };
162
- //# sourceMappingURL=option.types-DlAb6Sr0.d.mts.map
157
+ //# sourceMappingURL=option.types-qPevEZQd.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option.types-qPevEZQd.d.mts","names":[],"sources":["../src/option/option.types.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"order-D5c4QChk.mjs","names":[],"sources":["../src/order/order.ts"],"sourcesContent":["/**\n * Ordering combinators and instances for deterministic sorting and comparisons.\n *\n * **Mental model**\n * - `Order<A>` compares two values and returns `-1 | 0 | 1`.\n * - Compose reusable comparators with `by`, `merge`, and `reverse`.\n *\n * **Common tasks**\n * - Use built-ins like `Order.number`, `Order.string`, `Order.date`.\n * - Build custom orders with `Order.make`, `Order.by`, `Order.struct`.\n * - Sort with `Order.sort`, `Order.sortWith`, `Order.sortBy`.\n *\n * **Gotchas**\n * - Orders should be total and stable for predictable sorting.\n * - `Order.merge` uses lexicographic tie-breaking.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const byAge = Order.by(Order.number, (user: { age: number }) => user.age)\n * const sorted = Order.sort([{ age: 2 }, { age: 1 }], byAge)\n * ```\n *\n * @module\n */\nimport { dual } from \"../shared/dual\"\nimport type { Order as OrderType, OrderBounds, Ordering as OrderingType } from \"./order.types\"\n\n/**\n * Re-exported `Order` type.\n *\n * @example\n * ```ts\n * import type { Order } from \"@nicolastoulemont/std\"\n *\n * type Example = Order.Order<unknown>\n * ```\n *\n * @category Re-exports\n */\nexport type Order<A> = OrderType<A>\n\n/**\n * Re-exported `Ordering` type.\n *\n * @example\n * ```ts\n * import type { Order } from \"@nicolastoulemont/std\"\n *\n * type Example = Order.Ordering\n * ```\n *\n * @category Re-exports\n */\nexport type Ordering = OrderingType\n\n/**\n * Create an `Order` from a comparison function.\n *\n * The created order short-circuits identical references (`===`) to `0`.\n *\n * @param compare - Comparison function returning `-1 | 0 | 1`\n * @returns An order function\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const byLength = Order.make<string>((self, that) =>\n * self.length < that.length ? -1 : self.length > that.length ? 1 : 0,\n * )\n * const result = byLength(\"a\", \"bbb\")\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function make<A>(compare: (self: A, that: A) => Ordering): OrderType<A> {\n return (self, that) => (self === that ? 0 : compare(self, that))\n}\n\n/**\n * `Order` instance for strings (lexicographic, case-sensitive).\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.string(\"a\", \"b\")\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const string: OrderType<string> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for numbers.\n *\n * - `NaN` equals `NaN`\n * - `NaN` is less than any non-`NaN`\n * - `0` equals `-0`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.number(1, 2)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const number: OrderType<number> = make((self, that) => {\n if (Number.isNaN(self) && Number.isNaN(that)) return 0\n if (Number.isNaN(self)) return -1\n if (Number.isNaN(that)) return 1\n return self < that ? -1 : 1\n})\n\n/**\n * `Order` instance for booleans where `false < true`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.boolean(false, true)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const boolean: OrderType<boolean> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for bigints.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.bigint(1n, 2n)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const bigint: OrderType<bigint> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for dates based on `getTime()`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.date(new Date(\"2024-01-01\"), new Date(\"2024-01-02\"))\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const date: OrderType<Date> = make((self, that) => number(self.getTime(), that.getTime()))\n\n/**\n * Create an order that treats all values as equal.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.alwaysEqual<number>()\n * const result = compare(1, 2)\n * // => 0\n * ```\n *\n * @category Constructors\n */\nexport function alwaysEqual<A>(): OrderType<A> {\n return make(() => 0)\n}\n\n/**\n * Reverse an existing order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const desc = Order.reverse(Order.number)\n * const result = desc(1, 2)\n * // => 1\n * ```\n *\n * @category Combinators\n */\nexport function reverse<A>(order: OrderType<A>): OrderType<A> {\n return make((self, that) => order(that, self))\n}\n\n/**\n * Map inputs before comparison.\n *\n * Supports data-first and data-last styles:\n * - `by(order, project)`\n * - `pipe(order, by(project))`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * type User = { age: number }\n * const dataFirst = Order.by(Order.number, (user: User) => user.age)\n * const compareFirst = dataFirst({ age: 1 }, { age: 2 })\n * // => -1\n * \n * const dataLast = Order.by((user: User) => user.age)(Order.number)\n * const compareLast = dataLast({ age: 1 }, { age: 2 })\n * // => -1\n * ```\n *\n * @category Combinators\n */\nexport const by: {\n <B, A>(project: (value: B) => A): (order: OrderType<A>) => OrderType<B>\n <A, B>(order: OrderType<A>, project: (value: B) => A): OrderType<B>\n} = dual(\n 2,\n <A, B>(order: OrderType<A>, project: (value: B) => A): OrderType<B> =>\n make((self, that) => order(project(self), project(that))),\n)\n\nconst mergeBinary = <A>(self: OrderType<A>, that: OrderType<A>): OrderType<A> =>\n make((a, b) => {\n const result = self(a, b)\n if (result !== 0) return result\n return that(a, b)\n })\n\nconst mergeAll = <A>(orders: Iterable<OrderType<A>>): OrderType<A> => {\n const all = Array.from(orders)\n if (all.length === 0) return alwaysEqual()\n if (all.length === 1) return all[0]!\n\n return make((a, b) => {\n for (const order of all) {\n const result = order(a, b)\n if (result !== 0) return result\n }\n return 0\n })\n}\n\nfunction mergeOverload<A>(that: OrderType<A>): (self: OrderType<A>) => OrderType<A>\nfunction mergeOverload<A>(self: OrderType<A>, that: OrderType<A>): OrderType<A>\nfunction mergeOverload<A>(orders: Iterable<OrderType<A>>): OrderType<A>\nfunction mergeOverload<A>(\n selfOrThatOrOrders: OrderType<A> | Iterable<OrderType<A>>,\n that?: OrderType<A>,\n): ((self: OrderType<A>) => OrderType<A>) | OrderType<A> {\n if (that !== undefined) {\n if (typeof selfOrThatOrOrders !== \"function\") {\n throw new TypeError(\"Order.merge(self, that) requires two order functions\")\n }\n return mergeBinary(selfOrThatOrOrders, that)\n }\n\n if (typeof selfOrThatOrOrders === \"function\") {\n return (self: OrderType<A>) => mergeBinary(self, selfOrThatOrOrders)\n }\n\n return mergeAll(selfOrThatOrOrders)\n}\n\n/**\n * Merge orders lexicographically.\n *\n * Supports three forms:\n * - `merge(self, that)`\n * - `merge(that)(self)`\n * - `merge([order1, order2, ...])`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * type User = { first: string; last: string }\n * const byLast = Order.by(Order.string, (user: User) => user.last)\n * const byFirst = Order.by(Order.string, (user: User) => user.first)\n * const compare = Order.merge([byLast, byFirst])({ first: \"Ada\", last: \"Lovelace\" }, { first: \"Alan\", last: \"Turing\" })\n * // => -1\n * ```\n *\n * @category Combining\n */\nexport const merge: {\n <A>(that: OrderType<A>): (self: OrderType<A>) => OrderType<A>\n <A>(self: OrderType<A>, that: OrderType<A>): OrderType<A>\n <A>(orders: Iterable<OrderType<A>>): OrderType<A>\n} = mergeOverload\n\n/**\n * Create an order for tuples, compared left-to-right.\n */\ntype TupleOrders<Elements extends ReadonlyArray<unknown>> = {\n readonly [K in keyof Elements]: OrderType<Elements[K]>\n}\n\n/**\n * tuple utility.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.tuple([Order.string, Order.number] as const)([\"a\", 1], [\"a\", 2])\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function tuple<const Elements extends ReadonlyArray<unknown>>(\n orders: TupleOrders<Elements>,\n): OrderType<Elements> {\n return make((self, that) => {\n for (let i = 0; i < orders.length; i++) {\n const order = orders[i]!\n const result = order(self[i], that[i])\n if (result !== 0) return result\n }\n return 0\n })\n}\n\n/**\n * Create an order for arrays.\n *\n * Arrays are compared element-by-element, then by length when all compared\n * elements are equal.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.array(Order.number)([1, 2], [1, 3])\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function array<A>(order: OrderType<A>): OrderType<readonly A[]> {\n return make((self, that) => {\n const minLength = Math.min(self.length, that.length)\n for (let i = 0; i < minLength; i++) {\n const result = order(self[i]!, that[i]!)\n if (result !== 0) return result\n }\n return number(self.length, that.length)\n })\n}\n\n/**\n * Create an order for objects by key order in `fields`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.struct<{ id: number; name: string }>({\n * id: Order.number,\n * name: Order.string,\n * })({ id: 1, name: \"a\" }, { id: 1, name: \"b\" })\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function struct<const R extends Record<string, unknown>>(fields: {\n readonly [K in keyof R]: OrderType<R[K]>\n}): OrderType<R> {\n const keys = Object.keys(fields) as Array<keyof R>\n\n return make((self, that) => {\n for (const key of keys) {\n const result = fields[key](self[key], that[key])\n if (result !== 0) return result\n }\n return 0\n })\n}\n\n/**\n * Test strict less-than using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.lessThan(Order.number)(1, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const lessThan = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) === -1)\n\n/**\n * Test less-than-or-equal using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.lessThanOrEqual(Order.number)(2, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const lessThanOrEqual = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) !== 1)\n\n/**\n * Test strict greater-than using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.greaterThan(Order.number)(3, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const greaterThan = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) === 1)\n\n/**\n * Test greater-than-or-equal using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.greaterThanOrEqual(Order.number)(2, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const greaterThanOrEqual = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) !== -1)\n\n/**\n * Get the minimum of two values.\n *\n * If equal, returns the first argument.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.min(Order.number)(3, 5)\n * // => 3\n * ```\n *\n * @category Combinators\n */\nexport const min = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => A\n (self: A, that: A): A\n} => dual(2, (self: A, that: A) => (self === that || order(self, that) < 1 ? self : that))\n\n/**\n * Get the maximum of two values.\n *\n * If equal, returns the first argument.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.max(Order.number)(3, 5)\n * // => 5\n * ```\n *\n * @category Combinators\n */\nexport const max = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => A\n (self: A, that: A): A\n} => dual(2, (self: A, that: A) => (self === that || order(self, that) > -1 ? self : that))\n\n/**\n * Clamp a value to inclusive bounds.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.clamp(Order.number)(7, { minimum: 0, maximum: 5 })\n * // => 5\n * ```\n *\n * @category Combinators\n */\nexport const clamp = <A>(\n order: OrderType<A>,\n): {\n (bounds: OrderBounds<A>): (self: A) => A\n (self: A, bounds: OrderBounds<A>): A\n} => dual(2, (self: A, bounds: OrderBounds<A>): A => min(order)(bounds.maximum, max(order)(bounds.minimum, self)))\n\n/**\n * Check whether a value is within inclusive bounds.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const isBetween = Order.between(Order.number)(3, { minimum: 0, maximum: 5 })\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const between = <A>(\n order: OrderType<A>,\n): {\n (bounds: OrderBounds<A>): (self: A) => boolean\n (self: A, bounds: OrderBounds<A>): boolean\n} =>\n dual(\n 2,\n (self: A, bounds: OrderBounds<A>): boolean =>\n !lessThan(order)(self, bounds.minimum) && !greaterThan(order)(self, bounds.maximum),\n )\n\n/**\n * Sort an iterable by an order, returning a new array.\n *\n * Supports data-first and data-last styles.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const values = [3, 1, 2]\n * const dataFirst = Order.sort(values, Order.number)\n * // => [1, 2, 3]\n * \n * const dataLast = Order.sort(Order.number)(values)\n * // => [1, 2, 3]\n * ```\n *\n * @category Utilities\n */\nexport const sort: {\n <B>(order: OrderType<B>): <A extends B>(input: Iterable<A>) => A[]\n <A extends B, B>(input: Iterable<A>, order: OrderType<B>): A[]\n} = dual(2, <A extends B, B>(input: Iterable<A>, order: OrderType<B>): A[] => {\n const output = Array.from(input)\n output.sort((self, that) => order(self, that))\n return output\n})\n\n/**\n * Sort an iterable by a projected value.\n *\n * Supports data-first and data-last styles.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const users = [{ age: 2 }, { age: 1 }]\n * const dataFirst = Order.sortWith(users, (user) => user.age, Order.number)\n * // => [{ age: 1 }, { age: 2 }]\n *\n * const dataLast = Order.sortWith((user: { age: number }) => user.age, Order.number)(users)\n * // => [{ age: 1 }, { age: 2 }]\n * ```\n *\n * @category Utilities\n */\nexport const sortWith: {\n <A, B>(project: (value: A) => B, order: OrderType<B>): (input: Iterable<A>) => A[]\n <A, B>(input: Iterable<A>, project: (value: A) => B, order: OrderType<B>): A[]\n} = dual(3, <A, B>(input: Iterable<A>, project: (value: A) => B, order: OrderType<B>): A[] => {\n const output = Array.from(input, (value) => [value, project(value)] as const)\n output.sort(([, a], [, b]) => order(a, b))\n return output.map(([value]) => value)\n})\n\n/**\n * Sort an iterable by multiple orders, in sequence.\n *\n * - first order has highest priority\n * - ties are broken by subsequent orders\n * - no orders returns a shallow copy preserving iteration order\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const users = [{ age: 2, name: \"b\" }, { age: 1, name: \"a\" }]\n * const sorted = Order.sortBy(Order.by(Order.number, (user: { age: number; name: string }) => user.age))(users)\n * // => [{ age: 1, name: \"a\" }, { age: 2, name: \"b\" }]\n * ```\n *\n * @category Utilities\n */\nexport const sortBy = <A>(...orders: readonly OrderType<A>[]) => {\n if (orders.length === 0) {\n return (input: Iterable<A>): A[] => Array.from(input)\n }\n\n const merged = merge(orders)\n return (input: Iterable<A>): A[] => sort(input, merged)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"order-D5c4QChk.mjs","names":[],"sources":["../src/order/order.ts"],"sourcesContent":["/**\n * Ordering combinators and instances for deterministic sorting and comparisons.\n *\n * **Mental model**\n * - `Order<A>` compares two values and returns `-1 | 0 | 1`.\n * - Compose reusable comparators with `by`, `merge`, and `reverse`.\n *\n * **Common tasks**\n * - Use built-ins like `Order.number`, `Order.string`, `Order.date`.\n * - Build custom orders with `Order.make`, `Order.by`, `Order.struct`.\n * - Sort with `Order.sort`, `Order.sortWith`, `Order.sortBy`.\n *\n * **Gotchas**\n * - Orders should be total and stable for predictable sorting.\n * - `Order.merge` uses lexicographic tie-breaking.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const byAge = Order.by(Order.number, (user: { age: number }) => user.age)\n * const sorted = Order.sort([{ age: 2 }, { age: 1 }], byAge)\n * ```\n *\n * @module\n */\nimport { dual } from \"../shared/dual\"\nimport type { Order as OrderType, OrderBounds, Ordering as OrderingType } from \"./order.types\"\n\n/**\n * Re-exported `Order` type.\n *\n * @example\n * ```ts\n * import type { Order } from \"@nicolastoulemont/std\"\n *\n * type Example = Order.Order<unknown>\n * ```\n *\n * @category Re-exports\n */\nexport type Order<A> = OrderType<A>\n\n/**\n * Re-exported `Ordering` type.\n *\n * @example\n * ```ts\n * import type { Order } from \"@nicolastoulemont/std\"\n *\n * type Example = Order.Ordering\n * ```\n *\n * @category Re-exports\n */\nexport type Ordering = OrderingType\n\n/**\n * Create an `Order` from a comparison function.\n *\n * The created order short-circuits identical references (`===`) to `0`.\n *\n * @param compare - Comparison function returning `-1 | 0 | 1`\n * @returns An order function\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const byLength = Order.make<string>((self, that) =>\n * self.length < that.length ? -1 : self.length > that.length ? 1 : 0,\n * )\n * const result = byLength(\"a\", \"bbb\")\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function make<A>(compare: (self: A, that: A) => Ordering): OrderType<A> {\n return (self, that) => (self === that ? 0 : compare(self, that))\n}\n\n/**\n * `Order` instance for strings (lexicographic, case-sensitive).\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.string(\"a\", \"b\")\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const string: OrderType<string> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for numbers.\n *\n * - `NaN` equals `NaN`\n * - `NaN` is less than any non-`NaN`\n * - `0` equals `-0`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.number(1, 2)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const number: OrderType<number> = make((self, that) => {\n if (Number.isNaN(self) && Number.isNaN(that)) return 0\n if (Number.isNaN(self)) return -1\n if (Number.isNaN(that)) return 1\n return self < that ? -1 : 1\n})\n\n/**\n * `Order` instance for booleans where `false < true`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.boolean(false, true)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const boolean: OrderType<boolean> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for bigints.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.bigint(1n, 2n)\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const bigint: OrderType<bigint> = make((self, that) => (self < that ? -1 : 1))\n\n/**\n * `Order` instance for dates based on `getTime()`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.date(new Date(\"2024-01-01\"), new Date(\"2024-01-02\"))\n * // => -1\n * ```\n *\n * @category Instances\n */\nexport const date: OrderType<Date> = make((self, that) => number(self.getTime(), that.getTime()))\n\n/**\n * Create an order that treats all values as equal.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.alwaysEqual<number>()\n * const result = compare(1, 2)\n * // => 0\n * ```\n *\n * @category Constructors\n */\nexport function alwaysEqual<A>(): OrderType<A> {\n return make(() => 0)\n}\n\n/**\n * Reverse an existing order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const desc = Order.reverse(Order.number)\n * const result = desc(1, 2)\n * // => 1\n * ```\n *\n * @category Combinators\n */\nexport function reverse<A>(order: OrderType<A>): OrderType<A> {\n return make((self, that) => order(that, self))\n}\n\n/**\n * Map inputs before comparison.\n *\n * Supports data-first and data-last styles:\n * - `by(order, project)`\n * - `pipe(order, by(project))`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * type User = { age: number }\n * const dataFirst = Order.by(Order.number, (user: User) => user.age)\n * const compareFirst = dataFirst({ age: 1 }, { age: 2 })\n * // => -1\n *\n * const dataLast = Order.by((user: User) => user.age)(Order.number)\n * const compareLast = dataLast({ age: 1 }, { age: 2 })\n * // => -1\n * ```\n *\n * @category Combinators\n */\nexport const by: {\n <B, A>(project: (value: B) => A): (order: OrderType<A>) => OrderType<B>\n <A, B>(order: OrderType<A>, project: (value: B) => A): OrderType<B>\n} = dual(\n 2,\n <A, B>(order: OrderType<A>, project: (value: B) => A): OrderType<B> =>\n make((self, that) => order(project(self), project(that))),\n)\n\nconst mergeBinary = <A>(self: OrderType<A>, that: OrderType<A>): OrderType<A> =>\n make((a, b) => {\n const result = self(a, b)\n if (result !== 0) return result\n return that(a, b)\n })\n\nconst mergeAll = <A>(orders: Iterable<OrderType<A>>): OrderType<A> => {\n const all = Array.from(orders)\n if (all.length === 0) return alwaysEqual()\n if (all.length === 1) return all[0]!\n\n return make((a, b) => {\n for (const order of all) {\n const result = order(a, b)\n if (result !== 0) return result\n }\n return 0\n })\n}\n\nfunction mergeOverload<A>(that: OrderType<A>): (self: OrderType<A>) => OrderType<A>\nfunction mergeOverload<A>(self: OrderType<A>, that: OrderType<A>): OrderType<A>\nfunction mergeOverload<A>(orders: Iterable<OrderType<A>>): OrderType<A>\nfunction mergeOverload<A>(\n selfOrThatOrOrders: OrderType<A> | Iterable<OrderType<A>>,\n that?: OrderType<A>,\n): ((self: OrderType<A>) => OrderType<A>) | OrderType<A> {\n if (that !== undefined) {\n if (typeof selfOrThatOrOrders !== \"function\") {\n throw new TypeError(\"Order.merge(self, that) requires two order functions\")\n }\n return mergeBinary(selfOrThatOrOrders, that)\n }\n\n if (typeof selfOrThatOrOrders === \"function\") {\n return (self: OrderType<A>) => mergeBinary(self, selfOrThatOrOrders)\n }\n\n return mergeAll(selfOrThatOrOrders)\n}\n\n/**\n * Merge orders lexicographically.\n *\n * Supports three forms:\n * - `merge(self, that)`\n * - `merge(that)(self)`\n * - `merge([order1, order2, ...])`\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * type User = { first: string; last: string }\n * const byLast = Order.by(Order.string, (user: User) => user.last)\n * const byFirst = Order.by(Order.string, (user: User) => user.first)\n * const compare = Order.merge([byLast, byFirst])({ first: \"Ada\", last: \"Lovelace\" }, { first: \"Alan\", last: \"Turing\" })\n * // => -1\n * ```\n *\n * @category Combining\n */\nexport const merge: {\n <A>(that: OrderType<A>): (self: OrderType<A>) => OrderType<A>\n <A>(self: OrderType<A>, that: OrderType<A>): OrderType<A>\n <A>(orders: Iterable<OrderType<A>>): OrderType<A>\n} = mergeOverload\n\n/**\n * Create an order for tuples, compared left-to-right.\n */\ntype TupleOrders<Elements extends ReadonlyArray<unknown>> = {\n readonly [K in keyof Elements]: OrderType<Elements[K]>\n}\n\n/**\n * tuple utility.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.tuple([Order.string, Order.number] as const)([\"a\", 1], [\"a\", 2])\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function tuple<const Elements extends ReadonlyArray<unknown>>(\n orders: TupleOrders<Elements>,\n): OrderType<Elements> {\n return make((self, that) => {\n for (let i = 0; i < orders.length; i++) {\n const order = orders[i]!\n const result = order(self[i], that[i])\n if (result !== 0) return result\n }\n return 0\n })\n}\n\n/**\n * Create an order for arrays.\n *\n * Arrays are compared element-by-element, then by length when all compared\n * elements are equal.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.array(Order.number)([1, 2], [1, 3])\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function array<A>(order: OrderType<A>): OrderType<readonly A[]> {\n return make((self, that) => {\n const minLength = Math.min(self.length, that.length)\n for (let i = 0; i < minLength; i++) {\n const result = order(self[i]!, that[i]!)\n if (result !== 0) return result\n }\n return number(self.length, that.length)\n })\n}\n\n/**\n * Create an order for objects by key order in `fields`.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const compare = Order.struct<{ id: number; name: string }>({\n * id: Order.number,\n * name: Order.string,\n * })({ id: 1, name: \"a\" }, { id: 1, name: \"b\" })\n * // => -1\n * ```\n *\n * @category Constructors\n */\nexport function struct<const R extends Record<string, unknown>>(fields: {\n readonly [K in keyof R]: OrderType<R[K]>\n}): OrderType<R> {\n const keys = Object.keys(fields) as Array<keyof R>\n\n return make((self, that) => {\n for (const key of keys) {\n const result = fields[key](self[key], that[key])\n if (result !== 0) return result\n }\n return 0\n })\n}\n\n/**\n * Test strict less-than using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.lessThan(Order.number)(1, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const lessThan = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) === -1)\n\n/**\n * Test less-than-or-equal using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.lessThanOrEqual(Order.number)(2, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const lessThanOrEqual = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) !== 1)\n\n/**\n * Test strict greater-than using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.greaterThan(Order.number)(3, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const greaterThan = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) === 1)\n\n/**\n * Test greater-than-or-equal using an order.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const result = Order.greaterThanOrEqual(Order.number)(2, 2)\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const greaterThanOrEqual = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => boolean\n (self: A, that: A): boolean\n} => dual(2, (self: A, that: A) => order(self, that) !== -1)\n\n/**\n * Get the minimum of two values.\n *\n * If equal, returns the first argument.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.min(Order.number)(3, 5)\n * // => 3\n * ```\n *\n * @category Combinators\n */\nexport const min = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => A\n (self: A, that: A): A\n} => dual(2, (self: A, that: A) => (self === that || order(self, that) < 1 ? self : that))\n\n/**\n * Get the maximum of two values.\n *\n * If equal, returns the first argument.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.max(Order.number)(3, 5)\n * // => 5\n * ```\n *\n * @category Combinators\n */\nexport const max = <A>(\n order: OrderType<A>,\n): {\n (that: A): (self: A) => A\n (self: A, that: A): A\n} => dual(2, (self: A, that: A) => (self === that || order(self, that) > -1 ? self : that))\n\n/**\n * Clamp a value to inclusive bounds.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const value = Order.clamp(Order.number)(7, { minimum: 0, maximum: 5 })\n * // => 5\n * ```\n *\n * @category Combinators\n */\nexport const clamp = <A>(\n order: OrderType<A>,\n): {\n (bounds: OrderBounds<A>): (self: A) => A\n (self: A, bounds: OrderBounds<A>): A\n} => dual(2, (self: A, bounds: OrderBounds<A>): A => min(order)(bounds.maximum, max(order)(bounds.minimum, self)))\n\n/**\n * Check whether a value is within inclusive bounds.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const isBetween = Order.between(Order.number)(3, { minimum: 0, maximum: 5 })\n * // => true\n * ```\n *\n * @category Predicates\n */\nexport const between = <A>(\n order: OrderType<A>,\n): {\n (bounds: OrderBounds<A>): (self: A) => boolean\n (self: A, bounds: OrderBounds<A>): boolean\n} =>\n dual(\n 2,\n (self: A, bounds: OrderBounds<A>): boolean =>\n !lessThan(order)(self, bounds.minimum) && !greaterThan(order)(self, bounds.maximum),\n )\n\n/**\n * Sort an iterable by an order, returning a new array.\n *\n * Supports data-first and data-last styles.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const values = [3, 1, 2]\n * const dataFirst = Order.sort(values, Order.number)\n * // => [1, 2, 3]\n *\n * const dataLast = Order.sort(Order.number)(values)\n * // => [1, 2, 3]\n * ```\n *\n * @category Utilities\n */\nexport const sort: {\n <B>(order: OrderType<B>): <A extends B>(input: Iterable<A>) => A[]\n <A extends B, B>(input: Iterable<A>, order: OrderType<B>): A[]\n} = dual(2, <A extends B, B>(input: Iterable<A>, order: OrderType<B>): A[] => {\n const output = Array.from(input)\n output.sort((self, that) => order(self, that))\n return output\n})\n\n/**\n * Sort an iterable by a projected value.\n *\n * Supports data-first and data-last styles.\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const users = [{ age: 2 }, { age: 1 }]\n * const dataFirst = Order.sortWith(users, (user) => user.age, Order.number)\n * // => [{ age: 1 }, { age: 2 }]\n *\n * const dataLast = Order.sortWith((user: { age: number }) => user.age, Order.number)(users)\n * // => [{ age: 1 }, { age: 2 }]\n * ```\n *\n * @category Utilities\n */\nexport const sortWith: {\n <A, B>(project: (value: A) => B, order: OrderType<B>): (input: Iterable<A>) => A[]\n <A, B>(input: Iterable<A>, project: (value: A) => B, order: OrderType<B>): A[]\n} = dual(3, <A, B>(input: Iterable<A>, project: (value: A) => B, order: OrderType<B>): A[] => {\n const output = Array.from(input, (value) => [value, project(value)] as const)\n output.sort(([, a], [, b]) => order(a, b))\n return output.map(([value]) => value)\n})\n\n/**\n * Sort an iterable by multiple orders, in sequence.\n *\n * - first order has highest priority\n * - ties are broken by subsequent orders\n * - no orders returns a shallow copy preserving iteration order\n *\n * @example\n * ```ts\n * import { Order } from \"@nicolastoulemont/std\"\n *\n * const users = [{ age: 2, name: \"b\" }, { age: 1, name: \"a\" }]\n * const sorted = Order.sortBy(Order.by(Order.number, (user: { age: number; name: string }) => user.age))(users)\n * // => [{ age: 1, name: \"a\" }, { age: 2, name: \"b\" }]\n * ```\n *\n * @category Utilities\n */\nexport const sortBy = <A>(...orders: readonly OrderType<A>[]) => {\n if (orders.length === 0) {\n return (input: Iterable<A>): A[] => Array.from(input)\n }\n\n const merged = merge(orders)\n return (input: Iterable<A>): A[] => sort(input, merged)\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- import{t as e}from"../provide-B_SqJpCd.mjs";export{e as Provide};
1
+ import{t as e}from"../provide-BmSM3Ruy.mjs";export{e as Provide};
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./chunk-C934ptG5.mjs";import{t}from"./fx.types-Bg-Mmdm5.mjs";import{r as n}from"./result-BEzV0DYC.mjs";import{n as r,t as i}from"./service-resolution-C19smeaO.mjs";import{n as a,t as o}from"./fx.runtime-DclEDyjY.mjs";import{t as s}from"./scope-D_kzd1nT.mjs";var c=class{cache=new Map;getOrBuild(e,r,a){let o=this.cache.get(e);if(o?.context)return{_tag:`SyncFx`,[t]:{_A:()=>o.context,_E:()=>void 0,_R:()=>void 0},run:()=>n(o.context),*[Symbol.iterator](){return o.context}};if(o?.promise)return{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},run:async()=>n(await o.promise),async*[Symbol.asyncIterator](){return await o.promise}};this.cache.set(e,{building:!0});let s=e.build(this,r),c=this.cache;if(s._tag===`AsyncFx`){let r=(async()=>{let t=s[Symbol.asyncIterator](),n=await t.next();for(;n.done!==!0;){let e=n.value,r=i(e);if(r===void 0)throw e;let o=a._services.get(r.key);if(o===void 0)throw Error(`Service "${r.key}" not found during layer build`);n=await t.next(o)}let r=n.value;return c.set(e,{context:r}),r})();return this.cache.set(e,{promise:r}),{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},run:async()=>{try{return n(await r)}catch(e){return{ok:!1,error:e,*[Symbol.iterator](){throw yield e,Error(`Unreachable`)}}}},async*[Symbol.asyncIterator](){try{return await r}catch(e){throw yield e,Error(`Unreachable`,{cause:e})}}}}return{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},run:()=>{let t=s[Symbol.iterator](),r=t.next();for(;r.done!==!0;){let e=r.value,n=i(e);if(n===void 0)return{ok:!1,error:e,*[Symbol.iterator](){throw yield e,Error(`Unreachable`)}};let o=a._services.get(n.key);if(o===void 0)throw Error(`Service "${n.key}" not found during layer build`);r=t.next(o)}let o=r.value;return c.set(e,{context:o}),n(o)},*[Symbol.iterator](){let t=s[Symbol.iterator](),n=t.next();for(;n.done!==!0;){let e=n.value,r=i(e);if(r===void 0)throw yield e,Error(`Unreachable`);let o=a._services.get(r.key);if(o===void 0)throw Error(`Service "${r.key}" not found during layer build`);n=t.next(o)}return c.set(e,{context:n.value}),n.value}}}clear(){this.cache.clear()}get size(){return this.cache.size}},l=e({context:()=>d,layer:()=>u,service:()=>f});function u(e){return i=>{let l=e.build(new c,s())._tag,u=()=>{let t=new c,n=s();return{scope:n,layerBuildFx:e.build(t,n)}};return l===`AsyncFx`||i._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let{scope:e,layerBuildFx:t}=u();try{let e;if(t._tag===`AsyncFx`){let n=t[Symbol.asyncIterator](),r=await n.next();for(;r.done!==!0;)yield r.value,r=await n.next(void 0);e=r.value}else{let n=t[Symbol.iterator](),r=n.next();for(;r.done!==!0;)yield r.value,r=n.next(void 0);e=r.value}if(i._tag===`AsyncFx`){let t=i[Symbol.asyncIterator](),n=await t.next();for(;n.done!==!0;){let i=n.value,a=r(e,i);if(a!==void 0){n=await t.next(a);continue}let o=yield i;n=await t.next(o)}return n.value}let n=i[Symbol.iterator](),a=n.next();for(;a.done!==!0;){let t=a.value,i=r(e,t);if(i!==void 0){a=n.next(i);continue}let o=yield t;a=n.next(o)}return a.value}finally{let t=e.close(n(void 0));t._tag===`AsyncFx`?await o(t):a(t)}}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let{scope:e,layerBuildFx:t}=u();if(t._tag===`AsyncFx`)throw Error(`Provide.layer sync execution encountered an async layer build. Ensure async layers are treated as async at composition time.`);try{let e=t[Symbol.iterator](),n=e.next();for(;n.done!==!0;)yield n.value,n=e.next(void 0);let a=n.value,o=i[Symbol.iterator](),s=o.next();for(;s.done!==!0;){let e=s.value,t=r(a,e);if(t!==void 0){s=o.next(t);continue}let n=yield e;s=o.next(n)}return s.value}finally{a(e.close(n(void 0)))}}}}}const d=e=>n=>n._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let t=n[Symbol.asyncIterator](),r=await t.next();for(;r.done!==!0;){let n=r.value,a=i(n);if(a===void 0){yield n,r=await t.next(void 0);continue}let o=e._services.get(a.key);if(o===void 0)throw Error(`Service "${a.key}" not found`);r=await t.next(o)}return r.value}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let t=n[Symbol.iterator](),r=t.next();for(;r.done!==!0;){let n=r.value,a=i(n);if(a===void 0){yield n,r=t.next(void 0);continue}let o=e._services.get(a.key);if(o===void 0)throw Error(`Service "${a.key}" not found`);r=t.next(o)}return r.value}},f=(e,n)=>r=>r._tag===`AsyncFx`?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){let t=r[Symbol.asyncIterator](),a=await t.next();for(;a.done!==!0;){let r=a.value;if(i(r)?.key===e.key)a=await t.next(n);else{let e=yield r;a=await t.next(e)}}return a.value}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){let t=r[Symbol.iterator](),a=t.next();for(;a.done!==!0;){let r=a.value;if(i(r)?.key===e.key)a=t.next(n);else{let e=yield r;a=t.next(e)}}return a.value}};export{l as t};
2
+ //# sourceMappingURL=provide-BmSM3Ruy.mjs.map