@nicolastoulemont/std 0.8.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +391 -40
- package/dist/brand/index.d.mts +1 -1
- package/dist/brand/index.mjs +1 -1
- package/dist/{brand-DZgGDrAe.mjs → brand-DP-C92GS.mjs} +2 -2
- package/dist/{brand-DZgGDrAe.mjs.map → brand-DP-C92GS.mjs.map} +1 -1
- package/dist/{brand.types-B3NDX1vo.d.mts → brand.types-C_7QgCA4.d.mts} +1 -1
- package/dist/{brand.types-B3NDX1vo.d.mts.map → brand.types-C_7QgCA4.d.mts.map} +1 -1
- package/dist/context/index.d.mts +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/{context-0xDbwtpx.mjs → context-7oKePrBY.mjs} +2 -2
- package/dist/{context-0xDbwtpx.mjs.map → context-7oKePrBY.mjs.map} +1 -1
- package/dist/{context-B2dWloPl.d.mts → context-B9oWzbwF.d.mts} +2 -2
- package/dist/{context-B2dWloPl.d.mts.map → context-B9oWzbwF.d.mts.map} +1 -1
- package/dist/data/index.d.mts +1 -1
- package/dist/data/index.mjs +1 -1
- package/dist/data-W10ldR5l.mjs +2 -0
- package/dist/data-W10ldR5l.mjs.map +1 -0
- package/dist/{dual-fN6OUwN_.mjs → dual-CZhzZslG.mjs} +1 -1
- package/dist/{dual-fN6OUwN_.mjs.map → dual-CZhzZslG.mjs.map} +1 -1
- package/dist/duration/index.d.mts +1 -1
- package/dist/duration/index.mjs +1 -1
- package/dist/{duration-CYoDHcOR.mjs → duration-Dwtjy95Z.mjs} +2 -2
- package/dist/{duration-CYoDHcOR.mjs.map → duration-Dwtjy95Z.mjs.map} +1 -1
- package/dist/either/index.d.mts +1 -1
- package/dist/either/index.mjs +1 -1
- package/dist/{either-G7uOu4Ar.mjs → either-B2TvVY_j.mjs} +2 -2
- package/dist/{either-G7uOu4Ar.mjs.map → either-B2TvVY_j.mjs.map} +1 -1
- package/dist/exit-DOdhmr81.d.mts +67 -0
- package/dist/exit-DOdhmr81.d.mts.map +1 -0
- package/dist/fiber/index.d.mts +2 -0
- package/dist/fiber/index.mjs +1 -0
- package/dist/fiber-CZsyrDdd.mjs +2 -0
- package/dist/fiber-CZsyrDdd.mjs.map +1 -0
- package/dist/{flow-CNyLsPGb.mjs → flow-D8_tllWl.mjs} +1 -1
- package/dist/{flow-CNyLsPGb.mjs.map → flow-D8_tllWl.mjs.map} +1 -1
- package/dist/functions/index.mjs +1 -1
- package/dist/functions-DmOZ7O4j.mjs +2 -0
- package/dist/{functions-ByAk682_.mjs.map → functions-DmOZ7O4j.mjs.map} +1 -1
- package/dist/fx/index.d.mts +1 -1
- package/dist/fx/index.mjs +1 -1
- package/dist/fx-DXBw4iYX.mjs +2 -0
- package/dist/fx-DXBw4iYX.mjs.map +1 -0
- package/dist/fx.runtime-B2_rL7h_.mjs +2 -0
- package/dist/fx.runtime-B2_rL7h_.mjs.map +1 -0
- package/dist/fx.runtime-BuIElLpZ.d.mts +16 -0
- package/dist/fx.runtime-BuIElLpZ.d.mts.map +1 -0
- package/dist/{fx.types-DyQVgTS8.mjs → fx.types-Bg-Mmdm5.mjs} +1 -1
- package/dist/{fx.types-DyQVgTS8.mjs.map → fx.types-Bg-Mmdm5.mjs.map} +1 -1
- package/dist/{fx.types-BdN1EWxr.d.mts → fx.types-CpFKa-Jj.d.mts} +1 -1
- package/dist/{fx.types-BdN1EWxr.d.mts.map → fx.types-CpFKa-Jj.d.mts.map} +1 -1
- package/dist/{index-DCUGtEcj.d.mts → index-5QkUtJ-4.d.mts} +4 -4
- package/dist/{index-DCUGtEcj.d.mts.map → index-5QkUtJ-4.d.mts.map} +1 -1
- package/dist/{index-C4DOLLaU.d.mts → index-B3xia3Jl.d.mts} +82 -58
- package/dist/index-B3xia3Jl.d.mts.map +1 -0
- package/dist/{index-CIvNgjsx.d.mts → index-B4rHoUK4.d.mts} +2 -2
- package/dist/{index-CIvNgjsx.d.mts.map → index-B4rHoUK4.d.mts.map} +1 -1
- package/dist/{index-BA0EsFxS.d.mts → index-BDUhDs4D.d.mts} +3 -3
- package/dist/{index-BA0EsFxS.d.mts.map → index-BDUhDs4D.d.mts.map} +1 -1
- package/dist/{index-CNTYbcY9.d.mts → index-BZ1-IrU_.d.mts} +1 -1
- package/dist/{index-CNTYbcY9.d.mts.map → index-BZ1-IrU_.d.mts.map} +1 -1
- package/dist/{index-uE3S3Krx.d.mts → index-BZP6t2h9.d.mts} +5 -5
- package/dist/{index-uE3S3Krx.d.mts.map → index-BZP6t2h9.d.mts.map} +1 -1
- package/dist/{index-D8rDE60Y.d.mts → index-Bu-z5Xoq.d.mts} +1 -1
- package/dist/index-Bu-z5Xoq.d.mts.map +1 -0
- package/dist/index-C8KMi_I9.d.mts +226 -0
- package/dist/index-C8KMi_I9.d.mts.map +1 -0
- package/dist/{index-dCRymj_g.d.mts → index-CfXGmPMY.d.mts} +5 -5
- package/dist/{index-dCRymj_g.d.mts.map → index-CfXGmPMY.d.mts.map} +1 -1
- package/dist/index-Cv48HmyO.d.mts +59 -0
- package/dist/index-Cv48HmyO.d.mts.map +1 -0
- package/dist/{index-B2Z7-XGR.d.mts → index-D-KxgnwF.d.mts} +59 -34
- package/dist/index-D-KxgnwF.d.mts.map +1 -0
- package/dist/{index-DR7hzXU4.d.mts → index-DLkMqvw4.d.mts} +137 -29
- package/dist/index-DLkMqvw4.d.mts.map +1 -0
- package/dist/index-DlWm_PwP.d.mts +436 -0
- package/dist/index-DlWm_PwP.d.mts.map +1 -0
- package/dist/{index-B0flvtFB.d.mts → index-DogEz6WQ.d.mts} +2 -2
- package/dist/{index-B0flvtFB.d.mts.map → index-DogEz6WQ.d.mts.map} +1 -1
- package/dist/{index-crtzMG48.d.mts → index-XxPUUAGQ.d.mts} +41 -6
- package/dist/index-XxPUUAGQ.d.mts.map +1 -0
- package/dist/{index-BqJ1GWAF.d.mts → index-pC80zLHb.d.mts} +2 -2
- package/dist/{index-BqJ1GWAF.d.mts.map → index-pC80zLHb.d.mts.map} +1 -1
- package/dist/index.d.mts +23 -20
- package/dist/index.mjs +1 -1
- package/dist/layer/index.d.mts +1 -1
- package/dist/layer/index.mjs +1 -1
- package/dist/layer-BmrPWBkT.mjs +2 -0
- package/dist/layer-BmrPWBkT.mjs.map +1 -0
- package/dist/{layer.types-BB0MrvLg.d.mts → layer.types-DsCTjICW.d.mts} +4 -4
- package/dist/{layer.types-BB0MrvLg.d.mts.map → layer.types-DsCTjICW.d.mts.map} +1 -1
- package/dist/log/index.d.mts +2 -0
- package/dist/log/index.mjs +1 -0
- package/dist/log-Bh8G5umo.mjs +2 -0
- package/dist/log-Bh8G5umo.mjs.map +1 -0
- package/dist/multithread/index.d.mts +1 -1
- package/dist/multithread/index.mjs +1 -1
- package/dist/multithread-CovZ2ioL.mjs +21 -0
- package/dist/multithread-CovZ2ioL.mjs.map +1 -0
- package/dist/option/index.d.mts +1 -1
- package/dist/option/index.mjs +1 -1
- package/dist/{option-C2iCxAuJ.mjs → option-BlyP5LA2.mjs} +2 -2
- package/dist/{option-C2iCxAuJ.mjs.map → option-BlyP5LA2.mjs.map} +1 -1
- package/dist/{option.types-D9hrKcfa.d.mts → option.types-DLp3QpFE.d.mts} +3 -3
- package/dist/{option.types-D9hrKcfa.d.mts.map → option.types-DLp3QpFE.d.mts.map} +1 -1
- package/dist/{option.types-CbY_swma.mjs → option.types-bFFSErJ-.mjs} +1 -1
- package/dist/{option.types-CbY_swma.mjs.map → option.types-bFFSErJ-.mjs.map} +1 -1
- package/dist/order/index.d.mts +1 -1
- package/dist/order/index.mjs +1 -1
- package/dist/{order-BXOBEKvB.mjs → order-VTXpppmI.mjs} +2 -2
- package/dist/{order-BXOBEKvB.mjs.map → order-VTXpppmI.mjs.map} +1 -1
- package/dist/{pipeable-BIrevC0D.d.mts → pipeable-BY9yPsNK.d.mts} +1 -1
- package/dist/{pipeable-BIrevC0D.d.mts.map → pipeable-BY9yPsNK.d.mts.map} +1 -1
- package/dist/pipeable-COGyGMUV.mjs +2 -0
- package/dist/{pipeable-Dp1_23zH.mjs.map → pipeable-COGyGMUV.mjs.map} +1 -1
- package/dist/predicate/index.d.mts +1 -1
- package/dist/predicate/index.mjs +1 -1
- package/dist/{predicate-D_1SsIi4.mjs → predicate-8hY-0Ocv.mjs} +2 -2
- package/dist/{predicate-D_1SsIi4.mjs.map → predicate-8hY-0Ocv.mjs.map} +1 -1
- package/dist/provide/index.d.mts +1 -1
- package/dist/provide/index.mjs +1 -1
- package/dist/provide-K-6oXtLm.mjs +2 -0
- package/dist/provide-K-6oXtLm.mjs.map +1 -0
- package/dist/queue/index.d.mts +1 -1
- package/dist/queue/index.mjs +1 -1
- package/dist/{queue-apiEOlRD.mjs → queue-CeEIUHcY.mjs} +2 -2
- package/dist/{queue-apiEOlRD.mjs.map → queue-CeEIUHcY.mjs.map} +1 -1
- package/dist/result/index.d.mts +1 -1
- package/dist/result/index.mjs +1 -1
- package/dist/{result-D3VY0qBG.mjs → result-C74pRN2x.mjs} +2 -2
- package/dist/{result-D3VY0qBG.mjs.map → result-C74pRN2x.mjs.map} +1 -1
- package/dist/{result.types-BKzChyWY.d.mts → result.types-CnhiVFEV.d.mts} +3 -3
- package/dist/{result.types-BKzChyWY.d.mts.map → result.types-CnhiVFEV.d.mts.map} +1 -1
- package/dist/schedule/index.d.mts +1 -1
- package/dist/schedule/index.mjs +1 -1
- package/dist/{schedule-C6iN3oMt.mjs → schedule-ChcIgvd5.mjs} +2 -2
- package/dist/{schedule-C6iN3oMt.mjs.map → schedule-ChcIgvd5.mjs.map} +1 -1
- package/dist/{schedule-D2651VJY.d.mts → schedule-DiidMLcl.d.mts} +3 -3
- package/dist/{schedule-D2651VJY.d.mts.map → schedule-DiidMLcl.d.mts.map} +1 -1
- package/dist/schema/index.d.mts +1 -1
- package/dist/schema/index.mjs +1 -1
- package/dist/schema-CT_wO7tN.mjs +2 -0
- package/dist/schema-CT_wO7tN.mjs.map +1 -0
- package/dist/scope/index.d.mts +1 -1
- package/dist/scope/index.mjs +1 -1
- package/dist/{scope-CuM3CzwG.d.mts → scope-7bLTmdRX.d.mts} +4 -4
- package/dist/scope-7bLTmdRX.d.mts.map +1 -0
- package/dist/scope-D2AqJy7j.mjs +2 -0
- package/dist/scope-D2AqJy7j.mjs.map +1 -0
- package/dist/service/index.d.mts +1 -1
- package/dist/service/index.mjs +1 -1
- package/dist/{service-D8mr0wwg.d.mts → service-C4xUfS_M.d.mts} +2 -2
- package/dist/{service-D8mr0wwg.d.mts.map → service-C4xUfS_M.d.mts.map} +1 -1
- package/dist/{service-CWAIEH46.mjs → service-DHkeorS3.mjs} +2 -2
- package/dist/{service-CWAIEH46.mjs.map → service-DHkeorS3.mjs.map} +1 -1
- package/dist/trace/index.d.mts +2 -0
- package/dist/trace/index.mjs +1 -0
- package/dist/trace-ByjppUes.mjs +2 -0
- package/dist/trace-ByjppUes.mjs.map +1 -0
- package/dist/trace-D_7sjH22.d.mts +375 -0
- package/dist/trace-D_7sjH22.d.mts.map +1 -0
- package/package.json +13 -5
- package/dist/adt/index.d.mts +0 -2
- package/dist/adt/index.mjs +0 -1
- package/dist/adt-CPG_sa8q.mjs +0 -2
- package/dist/adt-CPG_sa8q.mjs.map +0 -1
- package/dist/data-BHYPdqWZ.mjs +0 -2
- package/dist/data-BHYPdqWZ.mjs.map +0 -1
- package/dist/discriminator.types-C-ygT2S1.d.mts +0 -7
- package/dist/discriminator.types-C-ygT2S1.d.mts.map +0 -1
- package/dist/equality-BX6BUidG.mjs +0 -2
- package/dist/equality-BX6BUidG.mjs.map +0 -1
- package/dist/functions-ByAk682_.mjs +0 -2
- package/dist/fx-DUXDxwsU.mjs +0 -2
- package/dist/fx-DUXDxwsU.mjs.map +0 -1
- package/dist/fx.runtime-jQxh77s3.mjs +0 -2
- package/dist/fx.runtime-jQxh77s3.mjs.map +0 -1
- package/dist/index-B2Z7-XGR.d.mts.map +0 -1
- package/dist/index-B41_sFR6.d.mts +0 -64
- package/dist/index-B41_sFR6.d.mts.map +0 -1
- package/dist/index-C4DOLLaU.d.mts.map +0 -1
- package/dist/index-C6W3_n_Q.d.mts +0 -458
- package/dist/index-C6W3_n_Q.d.mts.map +0 -1
- package/dist/index-D8rDE60Y.d.mts.map +0 -1
- package/dist/index-DR7hzXU4.d.mts.map +0 -1
- package/dist/index-crtzMG48.d.mts.map +0 -1
- package/dist/layer-CKtH7TRL.mjs +0 -2
- package/dist/layer-CKtH7TRL.mjs.map +0 -1
- package/dist/multithread-Cyc8Bz45.mjs +0 -19
- package/dist/multithread-Cyc8Bz45.mjs.map +0 -1
- package/dist/pipeable-Dp1_23zH.mjs +0 -2
- package/dist/provide--yZE8x-n.mjs +0 -2
- package/dist/provide--yZE8x-n.mjs.map +0 -1
- package/dist/schema-DstB1_VK.mjs +0 -2
- package/dist/schema-DstB1_VK.mjs.map +0 -1
- package/dist/schema.shared-Bjyroa6b.mjs +0 -2
- package/dist/schema.shared-Bjyroa6b.mjs.map +0 -1
- package/dist/schema.types-E1pjcc0Y.d.mts +0 -62
- package/dist/schema.types-E1pjcc0Y.d.mts.map +0 -1
- package/dist/scope-CuM3CzwG.d.mts.map +0 -1
- package/dist/scope-gVt4PESc.mjs +0 -2
- package/dist/scope-gVt4PESc.mjs.map +0 -1
- package/dist/service-resolution-BefYr4nR.mjs +0 -2
- package/dist/service-resolution-BefYr4nR.mjs.map +0 -1
- /package/dist/{chunk-oQKkju2G.mjs → chunk-6rpU2rUb.mjs} +0 -0
- /package/dist/{option-CXXiA1w-.mjs → option-BqAUkJ8e.mjs} +0 -0
- /package/dist/{result-xFLfwriM.mjs → result-B5WbPg8C.mjs} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"multithread-Cyc8Bz45.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 = Multithread.MultithreadCtx\n * ```\n *\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 = Multithread.MultithreadError\n * ```\n *\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 = Multithread.MultithreadOp<unknown, unknown>\n * ```\n *\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 */\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 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./fx.types-DyQVgTS8.mjs";import{i as n}from"./result-D3VY0qBG.mjs";import{n as r,t as i}from"./service-resolution-BefYr4nR.mjs";import{n as a,t as o}from"./fx.runtime-jQxh77s3.mjs";import{t as s}from"./scope-gVt4PESc.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--yZE8x-n.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provide--yZE8x-n.mjs","names":["layer","service","layer","makeScope","fxGen","fxResult","service"],"sources":["../src/provide/memo-map.ts","../src/provide/provide.ts"],"sourcesContent":["import type { Context } from \"../context/context\"\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"../fx/fx.types\"\nimport type { Layer } from \"../layer/layer.types\"\nimport { ok } from \"../result/result\"\nimport type { ScopeService } from \"../scope/scope\"\nimport { asServiceRequest } from \"../service/service-resolution\"\n\n/* oxlint-disable no-unsafe-type-assertion, only-throw-error -- MemoMap bridges erased generic Fx channels and re-emits typed domain errors from generator boundaries. */\n\n// ============================================================================\n// MemoMap\n// ============================================================================\n\ntype AnyLayer = Layer<unknown, unknown, unknown>\n\n/**\n * MemoMap caches built layers so each layer is only built once.\n * Multiple dependents share the same service instance.\n *\n * This implements the \"service singleton\" pattern where a service\n * is instantiated once and shared across all consumers.\n *\n * @example\n * ```ts\n * // Database is built once, shared by DocumentService and TeamService\n * const AppLayer = Layer.merge(\n * ConfigLive,\n * LoggerLive,\n * DatabaseLive, // Built once\n * DocumentServiceLive, // Uses shared Database\n * TeamServiceLive, // Uses same Database instance\n * )\n * ```\n */\nexport class MemoMap {\n private cache = new Map<\n AnyLayer,\n {\n promise?: Promise<Context<unknown>>\n context?: Context<unknown>\n building?: boolean\n }\n >()\n\n /**\n * Get a cached context or build the layer if not cached.\n *\n * @param layer - The layer to get or build\n * @param scope - The scope for resource management\n * @param deps - Context containing the layer's dependencies\n * @returns A RunnableFx producing the layer's context\n */\n getOrBuild<ROut, E, RIn>(\n layer: Layer<ROut, E, RIn>,\n scope: ScopeService,\n deps: Context<RIn>,\n ): RunnableFx<Context<ROut>, E> {\n const cached = this.cache.get(layer as AnyLayer)\n\n // Already built - return cached context\n if (cached?.context) {\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => cached.context as Context<ROut>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n run: () => ok(cached.context as Context<ROut>),\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<FxYield<E, never>, Context<ROut>, unknown> {\n return cached.context as Context<ROut>\n },\n } as SyncFx<Context<ROut>, E>\n }\n\n // Building in progress (async) - wait for it\n if (cached?.promise) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<ROut>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n run: async () => {\n const ctx = await cached.promise!\n return ok(ctx as Context<ROut>)\n },\n // oxlint-disable-next-line require-yield\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, never>, Context<ROut>, unknown> {\n const ctx = await cached.promise!\n return ctx as Context<ROut>\n },\n } as AsyncFx<Context<ROut>, E>\n }\n\n // Need to build - mark as building\n this.cache.set(layer as AnyLayer, { building: true })\n\n // Build the layer with provided dependencies\n const buildFx = layer.build(this, scope)\n const cacheRef = this.cache\n\n // Determine if async\n if (buildFx._tag === \"AsyncFx\") {\n // Create a promise for the build\n const buildPromise = (async () => {\n const gen = buildFx[Symbol.asyncIterator]()\n let result = await gen.next()\n\n // Resolve service requests from deps\n while (result.done !== true) {\n const yielded = result.value\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest === undefined) {\n // It's an error - rethrow\n throw yielded\n }\n const service = deps._services.get(serviceRequest.key)\n if (service === undefined) {\n throw new Error(`Service \"${serviceRequest.key}\" not found during layer build`)\n }\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n }\n\n const ctx = result.value\n cacheRef.set(layer as AnyLayer, { context: ctx })\n return ctx\n })()\n\n this.cache.set(layer as AnyLayer, { promise: buildPromise })\n\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<ROut>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n run: async () => {\n try {\n const ctx = await buildPromise\n return ok(ctx)\n } catch (e) {\n return {\n ok: false,\n error: e as E,\n *[Symbol.iterator]() {\n yield e as E\n throw new Error(\"Unreachable\")\n },\n }\n }\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, never>, Context<ROut>, unknown> {\n try {\n const ctx = await buildPromise\n return ctx\n } catch (e) {\n yield e as E\n throw new Error(\"Unreachable\", { cause: e })\n }\n },\n } as AsyncFx<Context<ROut>, E>\n }\n\n // Sync build\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<ROut>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n run: () => {\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n\n // Resolve service requests from deps\n while (result.done !== true) {\n const yielded = result.value\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest === undefined) {\n // It's an error\n return {\n ok: false,\n error: yielded as E,\n *[Symbol.iterator]() {\n yield yielded as E\n throw new Error(\"Unreachable\")\n },\n }\n }\n const service = deps._services.get(serviceRequest.key)\n if (service === undefined) {\n throw new Error(`Service \"${serviceRequest.key}\" not found during layer build`)\n }\n result = gen.next(service)\n }\n\n const ctx = result.value\n cacheRef.set(layer as AnyLayer, { context: ctx })\n return ok(ctx)\n },\n *[Symbol.iterator](): Generator<FxYield<E, never>, Context<ROut>, unknown> {\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n\n // Resolve service requests from deps\n while (result.done !== true) {\n const yielded = result.value\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest === undefined) {\n // It's an error - yield it\n yield yielded as E\n throw new Error(\"Unreachable\")\n }\n const service = deps._services.get(serviceRequest.key)\n if (service === undefined) {\n throw new Error(`Service \"${serviceRequest.key}\" not found during layer build`)\n }\n result = gen.next(service)\n }\n\n cacheRef.set(layer as AnyLayer, { context: result.value })\n return result.value\n },\n } as SyncFx<Context<ROut>, E>\n }\n\n /**\n * Clear the cache.\n * Useful for testing.\n */\n clear(): void {\n this.cache.clear()\n }\n\n /**\n * Get the number of cached layers.\n */\n get size(): number {\n return this.cache.size\n }\n}\n\n/* oxlint-enable no-unsafe-type-assertion, only-throw-error */\n","import type { Context } from \"../context/context\"\nimport { runSync, runAsync } from \"../fx/fx.runtime\"\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"../fx/fx.types\"\nimport type { Layer } from \"../layer/layer.types\"\nimport { ok } from \"../result/result\"\nimport { make as makeScope } from \"../scope/scope\"\nimport type { ServiceClass } from \"../service/service\"\nimport { asServiceRequest, resolveService } from \"../service/service-resolution\"\nimport { MemoMap } from \"./memo-map\"\n\n/* oxlint-disable no-unsafe-type-assertion -- layer/service re-thread generic Fx channels through runtime service injection points. */\n\n// ============================================================================\n// Provide Layer\n// ============================================================================\n\n/**\n * Extract the value type from an Fx.\n */\ntype FxValueType<F> = F extends RunnableFx<infer A, unknown, unknown> ? A : never\n\n/**\n * Extract the error type from an Fx.\n */\ntype FxErrorType<F> = F extends RunnableFx<unknown, infer E, unknown> ? E : never\n\n/**\n * Type for the result of provide based on layer sync and fx type.\n * Uses infer to extract A and E from the actual Fx type.\n * - Sync layer + SyncFx → SyncFx\n * - Sync layer + AsyncFx → AsyncFx\n * - Async layer + any fx → AsyncFx\n * - Unknown sync layer + any fx → RunnableFx (fallback)\n */\ntype ProvideResult<\n E2,\n LayerSync extends boolean,\n Fx extends RunnableFx<unknown, unknown, unknown>,\n> = LayerSync extends true\n ? Fx[\"_tag\"] extends \"SyncFx\"\n ? SyncFx<FxValueType<Fx>, FxErrorType<Fx> | E2>\n : AsyncFx<FxValueType<Fx>, FxErrorType<Fx> | E2>\n : LayerSync extends false\n ? AsyncFx<FxValueType<Fx>, FxErrorType<Fx> | E2>\n : RunnableFx<FxValueType<Fx>, FxErrorType<Fx> | E2>\n\n/**\n * Provide a layer to an Fx computation, resolving all service requirements.\n * Creates a new scope for resource management.\n *\n * Type preservation:\n * - Sync layer + SyncFx → SyncFx\n * - Sync layer + AsyncFx → AsyncFx\n * - Async layer + any fx → AsyncFx\n * - Unknown sync layer + any fx → RunnableFx (fallback)\n *\n * @param layer - The layer providing services (must have no external requirements)\n * @returns A function that takes an Fx and returns an Fx with dependencies resolved\n *\n * @example\n * ```ts\n * import { Fx, Layer, Provide, Service } from \"@nicolastoulemont/std\"\n *\n * const Port = Service.tag<number>(\"Port\")\n * const portLayer = Layer.ok(Port, 3000)\n * const readPort = Fx.gen(function* () {\n * return yield* Port\n * })\n * const provided = Provide.layer(portLayer)(readPort)\n * const exit = Fx.run(provided)\n * // => { _tag: \"Ok\", value: 3000 }\n * ```\n */\nexport function layer<ROut, E2, LayerSync extends boolean>(\n layer: Layer<ROut, E2, never, LayerSync>,\n): <Fx extends RunnableFx<unknown, unknown, ROut>>(fx: Fx) => ProvideResult<E2, LayerSync, Fx>\nexport function layer<ROut, E2>(layer: Layer<ROut, E2>) {\n return <A, E, R extends ROut>(fx: RunnableFx<A, E, R>): RunnableFx<A, E | E2> => {\n // Build mode selection should remain stable for this wrapper,\n // while actual layer state (scope + memoization) must be per-execution.\n const layerBuildTag = layer.build(new MemoMap(), makeScope())._tag\n\n const createRunLayerState = (): {\n readonly scope: ReturnType<typeof makeScope>\n readonly layerBuildFx: ReturnType<typeof layer.build>\n } => {\n const memoMap = new MemoMap()\n const scope = makeScope()\n return {\n scope,\n layerBuildFx: layer.build(memoMap, scope),\n }\n }\n\n if (layerBuildTag === \"AsyncFx\" || fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E | E2,\n _R: () => undefined as never,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E | E2, Exclude<R, ROut>>, A, unknown> {\n const { scope, layerBuildFx } = createRunLayerState()\n\n try {\n // Build the layer\n let ctx: Context<ROut>\n\n if (layerBuildFx._tag === \"AsyncFx\") {\n const gen = layerBuildFx[Symbol.asyncIterator]()\n let result = await gen.next()\n\n while (result.done !== true) {\n yield result.value as E2\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(undefined)\n }\n ctx = result.value\n } else {\n const gen = layerBuildFx[Symbol.iterator]()\n let result = gen.next()\n\n while (result.done !== true) {\n yield result.value as E2\n result = gen.next(undefined)\n }\n ctx = result.value\n }\n\n // Run the fx with the context\n if (fx._tag === \"AsyncFx\") {\n const fxGen = fx[Symbol.asyncIterator]()\n let fxResult = await fxGen.next()\n\n while (fxResult.done !== true) {\n const yielded = fxResult.value\n\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n fxResult = await fxGen.next(service)\n continue\n }\n\n // Pass through (error or unsatisfied service)\n const value = yield yielded as FxYield<E, Exclude<R, ROut>>\n // oxlint-disable-next-line no-await-in-loop\n fxResult = await fxGen.next(value)\n }\n\n return fxResult.value\n }\n\n // Sync fx\n const fxGen = fx[Symbol.iterator]()\n let fxResult = fxGen.next()\n\n while (fxResult.done !== true) {\n const yielded = fxResult.value\n\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\n\n const value = yield yielded as FxYield<E, Exclude<R, ROut>>\n fxResult = fxGen.next(value)\n }\n\n return fxResult.value\n } finally {\n const closeResult = scope.close(ok(undefined))\n if (closeResult._tag === \"AsyncFx\") {\n await runAsync(closeResult)\n } else {\n runSync(closeResult)\n }\n }\n },\n } as AsyncFx<A, E | E2>\n }\n\n // Both sync\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E | E2,\n _R: () => undefined as never,\n },\n *[Symbol.iterator](): Generator<FxYield<E | E2, Exclude<R, ROut>>, A, unknown> {\n const { scope, layerBuildFx } = createRunLayerState()\n\n if (layerBuildFx._tag === \"AsyncFx\") {\n throw new Error(\n \"Provide.layer sync execution encountered an async layer build. Ensure async layers are treated as async at composition time.\",\n )\n }\n\n try {\n // Build the layer\n const layerGen = layerBuildFx[Symbol.iterator]()\n let layerResult = layerGen.next()\n\n while (layerResult.done !== true) {\n yield layerResult.value as E2\n layerResult = layerGen.next(undefined)\n }\n\n const ctx = layerResult.value\n\n // Run the fx with the context\n const fxGen = fx[Symbol.iterator]()\n let fxResult = fxGen.next()\n\n while (fxResult.done !== true) {\n const yielded = fxResult.value\n\n const service = resolveService(ctx, yielded)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\n\n const value = yield yielded as FxYield<E, Exclude<R, ROut>>\n fxResult = fxGen.next(value)\n }\n\n return fxResult.value\n } finally {\n const closeResult = scope.close(ok(undefined))\n // In sync-only branch, closeResult is always SyncFx\n runSync(closeResult as SyncFx<void>)\n }\n },\n } as SyncFx<A, E | E2>\n }\n}\n\n// ============================================================================\n// Provide Context\n// ============================================================================\n\n/**\n * Provide a context directly to an Fx computation.\n *\n * @param ctx - The context containing services\n * @returns A function that takes an Fx and returns an Fx with dependencies resolved\n *\n * @example\n * ```ts\n * import { Context, Fx, Provide, Service } from \"@nicolastoulemont/std\"\n *\n * const Port = Service.tag<number>(\"Port\")\n * const ctx = Context.make(Port, 3000)\n * const readPort = Fx.gen(function* () {\n * return yield* Port\n * })\n * const provided = Provide.context(ctx)(readPort)\n * const exit = Fx.run(provided)\n * // => { _tag: \"Ok\", value: 3000 }\n * ```\n */\nexport const context =\n <R>(ctx: Context<R>) =>\n <A, E>(fx: RunnableFx<A, E, R>): RunnableFx<A, E> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, never>, A, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n\n while (result.done !== true) {\n const yielded = result.value\n\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest === undefined) {\n yield yielded as E\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(undefined)\n continue\n }\n const service = ctx._services.get(serviceRequest.key)\n if (service === undefined) {\n throw new Error(`Service \"${serviceRequest.key}\" not found`)\n }\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n }\n\n return result.value\n },\n } as AsyncFx<A, E>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E,\n _R: () => undefined as never,\n },\n *[Symbol.iterator](): Generator<FxYield<E, never>, A, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n\n while (result.done !== true) {\n const yielded = result.value\n\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest === undefined) {\n yield yielded as E\n result = gen.next(undefined)\n continue\n }\n const service = ctx._services.get(serviceRequest.key)\n if (service === undefined) {\n throw new Error(`Service \"${serviceRequest.key}\" not found`)\n }\n result = gen.next(service)\n }\n\n return result.value\n },\n } as SyncFx<A, E>\n }\n\n// ============================================================================\n// Provide Service\n// ============================================================================\n\n/**\n * Provide a single service to an Fx computation.\n *\n * @param service - The service class (tag)\n * @param impl - The service implementation\n * @returns A function that takes an Fx and returns an Fx with the service provided\n *\n * @example\n * ```ts\n * import { Fx, Provide, Service } from \"@nicolastoulemont/std\"\n *\n * const Port = Service.tag<number>(\"Port\")\n * const readPort = Fx.gen(function* () {\n * return yield* Port\n * })\n * const provided = Provide.service(Port, 3000)(readPort)\n * const exit = Fx.run(provided)\n * // => { _tag: \"Ok\", value: 3000 }\n * ```\n */\nexport const service =\n <S>(service: ServiceClass<S>, impl: S) =>\n <A, E, R>(fx: RunnableFx<A, E, R | S>): RunnableFx<A, E, Exclude<R, S>> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as Exclude<R, S>,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, Exclude<R, S>>, A, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n\n while (result.done !== true) {\n const yielded = result.value\n\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest?.key === service.key) {\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(impl)\n } else {\n const value = yield yielded as FxYield<E, Exclude<R, S>>\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n }\n\n return result.value\n },\n } as AsyncFx<A, E, Exclude<R, S>>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as A,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as Exclude<R, S>,\n },\n *[Symbol.iterator](): Generator<FxYield<E, Exclude<R, S>>, A, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n\n while (result.done !== true) {\n const yielded = result.value\n\n const serviceRequest = asServiceRequest(yielded)\n if (serviceRequest?.key === service.key) {\n result = gen.next(impl)\n } else {\n const value = yield yielded as FxYield<E, Exclude<R, S>>\n result = gen.next(value)\n }\n }\n\n return result.value\n },\n } as SyncFx<A, E, Exclude<R, S>>\n }\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"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"}
|
package/dist/schema-DstB1_VK.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./dual-fN6OUwN_.mjs";import{n}from"./flow-CNyLsPGb.mjs";import{t as r}from"./result-D3VY0qBG.mjs";import{n as i,r as a,t as o}from"./schema.shared-Bjyroa6b.mjs";var s=e({is:()=>f,parse:()=>c,refine:()=>u});function c(e){return t=>{try{let a=e[`~standard`].validate(t);return n(a)?Promise.resolve(a).then(e=>i(e),e=>r(o(e))):i(a)}catch(e){return r(o(e))}}}const l=t(2,(e,t)=>a(t,e,`Schema.refine()`)._tag===`Ok`);function u(...e){return l(...e)}const d=t(2,(e,t)=>a(t,e,`Schema.is()`)._tag===`Ok`);function f(...e){return d(...e)}export{s as t};
|
|
2
|
-
//# sourceMappingURL=schema-DstB1_VK.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema-DstB1_VK.mjs","names":["Result.err"],"sources":["../src/schema/schema.ts"],"sourcesContent":["import { Result } from \"../result\"\nimport type { Result as ResultType } from \"../result/result.types\"\n/**\n * Standard Schema-backed parsing and refinement helpers.\n *\n * **Mental model**\n * - `Schema.parse` is for boundary validation and parsing.\n * - `Schema.is` is a sync-only proof guard for direct in-memory checks.\n * - `Schema.refine` is the reusable preserved-shape guard for higher-order APIs like `Array.filter`.\n *\n * **Common tasks**\n * - Parse loose external data into validated subtypes.\n * - Use `Schema.is` for direct control-flow checks against already-typed values.\n * - Reuse a schema as a preserved-shape predicate with `Schema.refine`.\n * - Name reusable narrowed types with `Schema.Refine<Base, typeof schema>` or exact schema outputs with `Schema.Infer<typeof schema>`.\n *\n * **Gotchas**\n * - `Schema.parse` may be sync or async based on the schema type you preserve.\n * - `Schema.refine` and `Schema.is` support both data-first and data-last styles.\n * - `Schema.refine` and `Schema.is` are sync-only.\n * - `Schema.is` and `Schema.refine` must only be used with proof schemas that validate the current value in place.\n * - Transforms, defaults, coercions, and other output-changing schemas should use `Schema.parse`.\n * - `Schema.is` narrows `unknown` to the exact schema output, but in direct control flow TypeScript preserves the current value shape.\n * - `Schema.refine` exists for the cases where you need that preserved shape to survive higher-order APIs like `Array.filter`.\n *\n * @module\n */\nimport { dual } from \"../shared/dual\"\nimport { isPromise } from \"../shared/is-promise\"\nimport { toThrownValidationError, toValidationResult, validateSync } from \"./schema.shared\"\nimport type {\n Input,\n Output,\n Refine as Refined,\n SyncRefinementSchema,\n SyncSchema,\n ValidationError,\n} from \"./schema.types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\nexport type {\n Infer,\n Input,\n Output,\n Refine,\n RefinementSchema,\n SyncRefinementSchema,\n SyncSchema,\n ValidationError,\n ValidationIssue,\n} from \"./schema.types\"\n\n/**\n * Create a schema-backed parser.\n *\n * For sync schemas the returned parser is sync.\n * For general Standard Schema values the returned parser is async.\n */\nexport function parse<S extends SyncSchema>(schema: S): (value: Input<S>) => ResultType<Output<S>, ValidationError>\nexport function parse<S extends StandardSchemaV1>(\n schema: S,\n): (value: Input<S>) => Promise<ResultType<Output<S>, ValidationError>>\nexport function parse<S extends StandardSchemaV1>(schema: S) {\n return (value: Input<S>) => {\n try {\n const result = schema[\"~standard\"].validate(value)\n\n if (isPromise(result)) {\n return Promise.resolve(result).then(\n (validated) => toValidationResult(validated),\n (error) => Result.err(toThrownValidationError(error)),\n )\n }\n\n return toValidationResult(result)\n } catch (error) {\n return Result.err(toThrownValidationError(error))\n }\n }\n}\n\nexport type RefineFn = {\n <S extends SyncSchema, Base extends Input<S>>(value: Base, schema: S): value is Refined<Base, S>\n <S extends SyncSchema>(schema: S): <Base extends Input<S>>(value: Base) => value is Refined<Base, S>\n}\n\nexport type Is = {\n <Base, Sub extends Base>(value: Base, schema: SyncRefinementSchema<Base, Sub>): value is Sub\n <S extends SyncSchema>(value: unknown, schema: S): value is Output<S>\n <Base, Sub extends Base>(schema: SyncRefinementSchema<Base, Sub>): (value: Base) => value is Sub\n <S extends SyncSchema>(schema: S): (value: unknown) => value is Output<S>\n}\n\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- dual() requires a single implementation signature */\nconst refineImpl = dual(2, (value: unknown, schema: SyncSchema) => {\n return validateSync(schema, value, \"Schema.refine()\")._tag === \"Ok\"\n}) as RefineFn\n\n/**\n * Create a sync-only schema-backed reusable type guard that preserves the original value shape.\n *\n * Use this when a schema validates only a subset of a broader in-memory value\n * and you need the preserved shape to survive higher-order APIs like\n * `Array.filter`. The narrowed type is `Base & Output<typeof schema>`, not the\n * exact schema output.\n *\n * Supports both data-first and data-last styles:\n * - Data-first: `Schema.refine(value, schema)`\n * - Data-last: `Schema.refine(schema)(value)`\n *\n * Only use this with sync proof schemas that validate properties already\n * present on the original value. Transforms, defaults, and coercions are not\n * safe here because they can change the schema output without changing the\n * original input value.\n */\nexport function refine<S extends SyncSchema, Base extends Input<S>>(value: Base, schema: S): value is Refined<Base, S>\nexport function refine<S extends SyncSchema>(schema: S): <Base extends Input<S>>(value: Base) => value is Refined<Base, S>\nexport function refine(...args: [value: unknown, schema: SyncSchema] | [schema: SyncSchema]) {\n return (refineImpl as (...args: [unknown, SyncSchema] | [SyncSchema]) => boolean | ((value: unknown) => boolean))(...args)\n}\n\nconst isImpl = dual(2, (value: unknown, schema: SyncSchema) => {\n return validateSync(schema, value, \"Schema.is()\")._tag === \"Ok\"\n}) as Is\n\n/**\n * Create a sync-only schema-backed proof guard.\n *\n * On `unknown` values this narrows to the exact schema output. On already-typed\n * values, TypeScript preserves the current shape during direct control-flow\n * checks. Use `Schema.refine` when that preserved shape must survive\n * higher-order APIs like `Array.filter`.\n *\n * Supports both data-first and data-last styles:\n * - Data-first: `Schema.is(value, schema)`\n * - Data-last: `Schema.is(schema)(value)`\n */\nexport function is<Base, Sub extends Base>(value: Base, schema: SyncRefinementSchema<Base, Sub>): value is Sub\nexport function is<S extends SyncSchema>(value: unknown, schema: S): value is Output<S>\nexport function is<Base, Sub extends Base>(schema: SyncRefinementSchema<Base, Sub>): (value: Base) => value is Sub\nexport function is<S extends SyncSchema>(schema: S): (value: unknown) => value is Output<S>\nexport function is(...args: [value: unknown, schema: SyncSchema] | [schema: SyncSchema]) {\n return (isImpl as (...args: [unknown, SyncSchema] | [SyncSchema]) => boolean | ((value: unknown) => boolean))(...args)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n"],"mappings":"qQA8DA,SAAgB,EAAkC,EAAW,CAC3D,MAAQ,IAAoB,CAC1B,GAAI,CACF,IAAM,EAAS,EAAO,aAAa,SAAS,EAAM,CASlD,OAPI,EAAU,EAAO,CACZ,QAAQ,QAAQ,EAAO,CAAC,KAC5B,GAAc,EAAmB,EAAU,CAC3C,GAAUA,EAAW,EAAwB,EAAM,CAAC,CACtD,CAGI,EAAmB,EAAO,OAC1B,EAAO,CACd,OAAOA,EAAW,EAAwB,EAAM,CAAC,GAkBvD,MAAM,EAAa,EAAK,GAAI,EAAgB,IACnC,EAAa,EAAQ,EAAO,kBAAkB,CAAC,OAAS,KAC/D,CAqBF,SAAgB,EAAO,GAAG,EAAmE,CAC3F,OAAQ,EAA0G,GAAG,EAAK,CAG5H,MAAM,EAAS,EAAK,GAAI,EAAgB,IAC/B,EAAa,EAAQ,EAAO,cAAc,CAAC,OAAS,KAC3D,CAkBF,SAAgB,EAAG,GAAG,EAAmE,CACvF,OAAQ,EAAsG,GAAG,EAAK"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./flow-CNyLsPGb.mjs";import{i as t,t as n}from"./result-D3VY0qBG.mjs";function r(e){return typeof e==`object`&&e&&`key`in e?e.key:e}function i(e){return e.map(e=>({message:e.message,path:e.path?.map(r)}))}function a(e){return e.issues?n({issues:i(e.issues)}):t(e.value)}function o(e){return e instanceof Error&&e.message.length>0?e.message:typeof e==`string`&&e.length>0?e:`Schema validation failed.`}function s(e){return{issues:[{message:o(e)}]}}function c(t,n,r){let i=t[`~standard`].validate(n);if(e(i))throw TypeError(`Async validation is not supported in ${r}.`);return a(i)}export{a as n,c as r,s as t};
|
|
2
|
-
//# sourceMappingURL=schema.shared-Bjyroa6b.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.shared-Bjyroa6b.mjs","names":["Result.err","Result.ok"],"sources":["../src/schema/schema.shared.ts"],"sourcesContent":["import { Result } from \"../result\"\nimport type { Result as ResultType } from \"../result/result.types\"\nimport { isPromise } from \"../shared/is-promise\"\nimport type { ValidationError, ValidationIssue } from \"./schema.types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\nfunction normalizePathSegment(segment: PropertyKey | { readonly key: PropertyKey }): PropertyKey {\n return typeof segment === \"object\" && segment !== null && \"key\" in segment ? segment.key : segment\n}\n\nfunction normalizeIssues(\n issues: NonNullable<StandardSchemaV1.Result<unknown>[\"issues\"]>,\n): ReadonlyArray<ValidationIssue> {\n return issues.map((issue) => ({\n message: issue.message,\n path: issue.path?.map(normalizePathSegment),\n }))\n}\n\nexport function toValidationResult<T>(result: StandardSchemaV1.Result<T>): ResultType<T, ValidationError> {\n if (result.issues) {\n return Result.err({ issues: normalizeIssues(result.issues) })\n }\n\n return Result.ok(result.value)\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.length > 0) {\n return error.message\n }\n\n if (typeof error === \"string\" && error.length > 0) {\n return error\n }\n\n return \"Schema validation failed.\"\n}\n\nexport function toThrownValidationError(error: unknown): ValidationError {\n return {\n issues: [{ message: toErrorMessage(error) }],\n }\n}\n\nexport function validateSync<T>(\n schema: StandardSchemaV1<unknown, T>,\n value: unknown,\n operation: string,\n): ResultType<T, ValidationError> {\n const result = schema[\"~standard\"].validate(value)\n\n if (isPromise(result)) {\n throw new TypeError(`Async validation is not supported in ${operation}.`)\n }\n\n return toValidationResult(result)\n}\n"],"mappings":"yFAMA,SAAS,EAAqB,EAAmE,CAC/F,OAAO,OAAO,GAAY,UAAY,GAAoB,QAAS,EAAU,EAAQ,IAAM,EAG7F,SAAS,EACP,EACgC,CAChC,OAAO,EAAO,IAAK,IAAW,CAC5B,QAAS,EAAM,QACf,KAAM,EAAM,MAAM,IAAI,EAAqB,CAC5C,EAAE,CAGL,SAAgB,EAAsB,EAAoE,CAKxG,OAJI,EAAO,OACFA,EAAW,CAAE,OAAQ,EAAgB,EAAO,OAAO,CAAE,CAAC,CAGxDC,EAAU,EAAO,MAAM,CAGhC,SAAS,EAAe,EAAwB,CAS9C,OARI,aAAiB,OAAS,EAAM,QAAQ,OAAS,EAC5C,EAAM,QAGX,OAAO,GAAU,UAAY,EAAM,OAAS,EACvC,EAGF,4BAGT,SAAgB,EAAwB,EAAiC,CACvE,MAAO,CACL,OAAQ,CAAC,CAAE,QAAS,EAAe,EAAM,CAAE,CAAC,CAC7C,CAGH,SAAgB,EACd,EACA,EACA,EACgC,CAChC,IAAM,EAAS,EAAO,aAAa,SAAS,EAAM,CAElD,GAAI,EAAU,EAAO,CACnB,MAAU,UAAU,wCAAwC,EAAU,GAAG,CAG3E,OAAO,EAAmB,EAAO"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { h as Prettify } from "./result.types-BKzChyWY.mjs";
|
|
2
|
-
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
-
|
|
4
|
-
//#region src/schema/schema.types.d.ts
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Infer the input type from a Standard Schema.
|
|
8
|
-
*/
|
|
9
|
-
type Input<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["input"];
|
|
10
|
-
/**
|
|
11
|
-
* Infer the output type from a Standard Schema.
|
|
12
|
-
*/
|
|
13
|
-
type Output<S extends StandardSchemaV1> = NonNullable<S["~standard"]["types"]>["output"];
|
|
14
|
-
/**
|
|
15
|
-
* Infer the validated output type from a Standard Schema.
|
|
16
|
-
*
|
|
17
|
-
* This matches the exact schema output used by `Schema.parse()` and by
|
|
18
|
-
* `Schema.is()` when the starting value is `unknown`.
|
|
19
|
-
*/
|
|
20
|
-
type Infer<S extends StandardSchemaV1> = Output<S>;
|
|
21
|
-
/**
|
|
22
|
-
* Compute the base-shape-preserving narrowed type used by `Schema.refine()`.
|
|
23
|
-
*
|
|
24
|
-
* This preserves fields already present on the base value while intersecting in
|
|
25
|
-
* the schema-proven output fields. This is also the shape TypeScript derives in
|
|
26
|
-
* direct control-flow checks when `Schema.is()` is used on an already-typed
|
|
27
|
-
* value.
|
|
28
|
-
*/
|
|
29
|
-
type Refine<Base, S extends StandardSchemaV1> = Base extends Input<S> ? Base extends unknown ? Prettify<Base & Output<S>> : never : never;
|
|
30
|
-
/**
|
|
31
|
-
* Normalized validation issue shape used across std modules.
|
|
32
|
-
*/
|
|
33
|
-
type ValidationIssue = {
|
|
34
|
-
readonly message: string;
|
|
35
|
-
readonly path?: ReadonlyArray<PropertyKey> | undefined;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Validation error containing normalized schema issues.
|
|
39
|
-
*/
|
|
40
|
-
type ValidationError = {
|
|
41
|
-
readonly issues: ReadonlyArray<ValidationIssue>;
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Standard Schema subtype with sync-only validation.
|
|
45
|
-
* Callers can preserve sync parse inference by annotating schemas with this type.
|
|
46
|
-
*/
|
|
47
|
-
type SyncSchema<TInput = unknown, TOutput = TInput> = Omit<StandardSchemaV1<TInput, TOutput>, "~standard"> & {
|
|
48
|
-
readonly "~standard": Omit<StandardSchemaV1<TInput, TOutput>["~standard"], "validate"> & {
|
|
49
|
-
validate: (value: unknown) => StandardSchemaV1.Result<TOutput>;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Schema whose validated output is a refinement of a broader base type.
|
|
54
|
-
*/
|
|
55
|
-
type RefinementSchema<Base, Sub extends Base> = StandardSchemaV1<Base, Sub>;
|
|
56
|
-
/**
|
|
57
|
-
* Sync-only refinement schema for building type guards.
|
|
58
|
-
*/
|
|
59
|
-
type SyncRefinementSchema<Base, Sub extends Base> = SyncSchema<Base, Sub>;
|
|
60
|
-
//#endregion
|
|
61
|
-
export { RefinementSchema as a, ValidationError as c, Refine as i, ValidationIssue as l, Input as n, SyncRefinementSchema as o, Output as r, SyncSchema as s, Infer as t };
|
|
62
|
-
//# sourceMappingURL=schema.types-E1pjcc0Y.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.types-E1pjcc0Y.d.mts","names":[],"sources":["../src/schema/schema.types.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAA4B,KAAhB,KAAgB,CAAA,UAAA,gBAAA,CAAA,GAAoB,WAApB,CAAgC,CAAhC,CAAA,WAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CAAA,OAAA,CAAA;;;;AAKhB,KAAA,MAAM,CAAA,UAAW,gBAAX,CAAA,GAA+B,WAA/B,CAA2C,CAA3C,CAAA,WAAA,CAAA,CAAA,OAAA,CAAA,CAAA,CAAA,QAAA,CAAA;;;;;AAQlB;;AAAuD,KAA3C,KAA2C,CAAA,UAA3B,gBAA2B,CAAA,GAAP,MAAO,CAAA,CAAA,CAAA;;;AAUvD;;;;;;AAEe,KAFH,MAEG,CAAA,IAAA,EAAA,UAFoB,gBAEpB,CAAA,GAFwC,IAExC,SAFqD,KAErD,CAF2D,CAE3D,CAAA,GADX,IACW,SAAA,OAAA,GAAT,QAAS,CAAA,IAAA,GAAO,MAAP,CAAc,CAAd,CAAA,CAAA,GAAA,KAAA,GAAA,KAAA;;;;AAAD,KAOF,eAAA,GAPE;EAOF,SAAA,OAAA,EAAe,MAAA;EAQf,SAAA,IAAA,CAAA,EANM,aAMS,CANK,WAOC,CAAA,GAAA,SAAd;AAOnB,CAAA;;;;AAAkE,KARtD,eAAA,GAQsD;EAAL,SAAA,MAAA,EAP1C,aAO0C,CAP5B,eAO4B,CAAA;CACf;;;;;AACZ,KAFtB,UAEuC,CAAA,SAAA,OAAA,EAAA,UAFA,MAEA,CAAA,GAFU,IAEV,CAFe,gBAEf,CAFgC,MAEhC,EAFwC,OAExC,CAAA,EAAA,WAAA,CAAA,GAAA;EAAM,SAAA,WAAA,EADjC,IACiC,CAD5B,gBAC4B,CADX,MACW,EADH,OACG,CAAA,CAAA,WAAA,CAAA,EAAA,UAAA,CAAA,GAAA;IAO7C,QAAA,EAAA,CAAA,KAAgB,EAAA,OAAA,EAAA,GAPM,gBAAA,CAAiB,MAOvB,CAP8B,OAO9B,CAAA;EAAmB,CAAA;CAAyB;;;;AAK5D,KALA,gBAKoB,CAAA,IAAA,EAAA,YALe,IAKf,CAAA,GALuB,gBAKvB,CALwC,IAKxC,EAL8C,GAK9C,CAAA;;;;AAA2B,KAA/C,oBAA+C,CAAA,IAAA,EAAA,YAAR,IAAQ,CAAA,GAAA,UAAA,CAAW,IAAX,EAAiB,GAAjB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-CuM3CzwG.d.mts","names":[],"sources":["../src/scope/scope.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;AAqDA;;;AAQ+D,KARnD,YAAA,GAQmD;EAQjD;;;;;AA0Bd;AA4HA;EAAsC,YAAA,CAAA,SAAA,EAAA,GAAA,GA9JN,MA8JM,CAAA,IAAA,CAAA,GA9JS,OA8JT,CAAA,IAAA,CAAA,CAAA,EA9JyB,MA8JzB,CAAA,IAAA,CAAA;EAAG;;;;;;cAtJ3B,2BAA2B,eAAe;;;;;;;UAQ9C;;;;;;;;;;;;;;;;;iBAkBM,IAAA,CAAA,GAAQ;;;;;;;;;;;;KA4HZ,kBAAkB,QAAQ,GAAG"}
|
package/dist/scope-gVt4PESc.mjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./chunk-oQKkju2G.mjs";import{t}from"./fx.types-DyQVgTS8.mjs";import{n,t as r}from"./fx.runtime-jQxh77s3.mjs";var i=e({make:()=>a});function a(){let e=[],i=!1,o=[];return{addFinalizer(n){return{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){i||e.push(n)}}},close(a){return e.some(e=>e()._tag===`AsyncFx`)?{_tag:`AsyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},async*[Symbol.asyncIterator](){if(i)return;i=!0;for(let e of[...o].toReversed()){let t=e.close(a);t._tag===`AsyncFx`?await r(t):n(t)}let t=[...e].toReversed();for(let e of t){let t=e();t._tag===`AsyncFx`?await r(t):n(t)}}}:{_tag:`SyncFx`,[t]:{_A:()=>void 0,_E:()=>void 0,_R:()=>void 0},*[Symbol.iterator](){if(i)return;i=!0;for(let e of[...o].toReversed())n(e.close(a));let t=[...e].toReversed();for(let e of t)n(e())}}},fork(){let e=a();return o.push(e),e}}}export{i as n,a as t};
|
|
2
|
-
//# sourceMappingURL=scope-gVt4PESc.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-gVt4PESc.mjs","names":[],"sources":["../src/scope/scope.ts"],"sourcesContent":["/**\n * Scope lifecycle management for registering and running finalizers.\n *\n * **Mental model**\n * - A scope tracks cleanup actions and executes them in LIFO order.\n * - `Layer.scoped` and `Provide.layer` rely on scope semantics.\n *\n * **Common tasks**\n * - Create scopes with `Scope.make`.\n * - Register cleanup with `scope.addFinalizer`.\n * - Close scopes with `scope.close`.\n *\n * **Gotchas**\n * - Child scopes close before parent finalizers.\n * - Async finalizers force async scope close.\n *\n * **Quickstart**\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n *\n * const scope = Scope.make()\n * const closeFx = scope.close(Result.ok(undefined))\n * // => SyncFx<void> | AsyncFx<void>\n * ```\n *\n * @module\n */\nimport { runSync, runAsync } from \"../fx/fx.runtime\"\nimport { FxTypeId } from \"../fx/fx.types\"\nimport type { SyncFx, AsyncFx, FxYield } from \"../fx/fx.types\"\nimport type { Result } from \"../result/result.types\"\n\n/* oxlint-disable no-unsafe-type-assertion -- Scope encodes Fx phantom type slots and sync/async branch narrowing via assertions. */\n\n// ============================================================================\n// Scope Service\n// ============================================================================\n\n/**\n * Scope manages resource lifecycles with finalizers.\n * Finalizers run in LIFO (Last In, First Out) order when the scope closes.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Scope\n * ```\n */\nexport type ScopeService = {\n /**\n * Add a finalizer to be run when the scope closes.\n * Finalizers are run in LIFO order.\n *\n * @param finalizer - A function that returns an Fx to run on cleanup\n * @returns An Fx that completes when the finalizer is registered\n */\n addFinalizer(finalizer: () => SyncFx<void> | AsyncFx<void>): SyncFx<void>\n\n /**\n * Close the scope, running all finalizers in LIFO order.\n *\n * @param exit - The exit status of the computation\n * @returns An Fx that completes when all finalizers have run\n */\n close(exit: Result<unknown, unknown>): SyncFx<void> | AsyncFx<void>\n\n /**\n * Fork a child scope.\n * The child scope will be closed when the parent scope closes.\n *\n * @returns A new child scope\n */\n fork(): ScopeService\n}\n\n/**\n * Create a new Scope instance.\n * This is the concrete implementation of the ScopeService interface.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * import { Result } from \"@nicolastoulemont/std\"\n *\n * const scope = Scope.make()\n * const closeFx = scope.close(Result.ok(undefined))\n * // => SyncFx<void> | AsyncFx<void>\n * ```\n */\nexport function make(): ScopeService {\n type Finalizer = () => SyncFx<void> | AsyncFx<void>\n const finalizers: Finalizer[] = []\n let closed = false\n const children: ScopeService[] = []\n\n const scope: ScopeService = {\n addFinalizer(finalizer: Finalizer): SyncFx<void> {\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<FxYield<never, never>, void, unknown> {\n if (!closed) {\n finalizers.push(finalizer)\n }\n },\n } as SyncFx<void>\n },\n\n close(exit: Result<unknown, unknown>): SyncFx<void> | AsyncFx<void> {\n // Check if any finalizer is async\n const hasAsyncFinalizer = finalizers.some((f) => {\n const fx = f()\n return fx._tag === \"AsyncFx\"\n })\n\n if (hasAsyncFinalizer) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<never, never>, void, unknown> {\n if (closed) return\n closed = true\n\n // Close children first\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n if (childClose._tag === \"AsyncFx\") {\n // oxlint-disable-next-line no-await-in-loop\n await runAsync(childClose)\n } else {\n runSync(childClose)\n }\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n if (fx._tag === \"AsyncFx\") {\n // oxlint-disable-next-line no-await-in-loop\n await runAsync(fx)\n } else {\n runSync(fx)\n }\n }\n },\n } as AsyncFx<void>\n }\n\n // Sync version\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as void,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<FxYield<never, never>, void, unknown> {\n if (closed) return\n closed = true\n\n // Close children first\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n runSync(childClose as SyncFx<void>)\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n runSync(fx as SyncFx<void>)\n }\n },\n } as SyncFx<void>\n },\n\n fork(): ScopeService {\n const child = make()\n children.push(child)\n return child\n },\n }\n\n return scope\n}\n\n// ============================================================================\n// Helper Types\n// ============================================================================\n\n/**\n * Type utility to exclude Scope from requirements.\n * Used by Layer.scoped to auto-provide Scope.\n *\n * @example\n * ```ts\n * import { Scope } from \"@nicolastoulemont/std\"\n *\n * type Example = typeof Scope\n * ```\n */\nexport type ExcludeScope<R> = Exclude<R, ScopeService>\n\n/* oxlint-enable no-unsafe-type-assertion */\n"],"mappings":"sJA+FA,SAAgB,GAAqB,CAEnC,IAAM,EAA0B,EAAE,CAC9B,EAAS,GACP,EAA2B,EAAE,CAsGnC,MApG4B,CAC1B,aAAa,EAAoC,CAC/C,MAAO,CACL,KAAM,UACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,EAAE,OAAO,WAA6D,CAC/D,GACH,EAAW,KAAK,EAAU,EAG/B,EAGH,MAAM,EAA8D,CA+ClE,OA7C0B,EAAW,KAAM,GAC9B,GAAG,CACJ,OAAS,UACnB,CAGO,CACL,KAAM,WACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,OAAQ,OAAO,gBAAuE,CACpF,GAAI,EAAQ,OACZ,EAAS,GAGT,IAAK,IAAM,IAAS,CAAC,GAAG,EAAS,CAAC,YAAY,CAAE,CAC9C,IAAM,EAAa,EAAM,MAAM,EAAK,CAChC,EAAW,OAAS,UAEtB,MAAM,EAAS,EAAW,CAE1B,EAAQ,EAAW,CAKvB,IAAM,EAAW,CAAC,GAAG,EAAW,CAAC,YAAY,CAC7C,IAAK,IAAM,KAAa,EAAU,CAChC,IAAM,EAAK,GAAW,CAClB,EAAG,OAAS,UAEd,MAAM,EAAS,EAAG,CAElB,EAAQ,EAAG,GAIlB,CAII,CACL,KAAM,UACL,GAAW,CACV,OAAU,IAAA,GACV,OAAU,IAAA,GACV,OAAU,IAAA,GACX,CAED,EAAE,OAAO,WAA6D,CACpE,GAAI,EAAQ,OACZ,EAAS,GAGT,IAAK,IAAM,IAAS,CAAC,GAAG,EAAS,CAAC,YAAY,CAE5C,EADmB,EAAM,MAAM,EAAK,CACD,CAIrC,IAAM,EAAW,CAAC,GAAG,EAAW,CAAC,YAAY,CAC7C,IAAK,IAAM,KAAa,EAEtB,EADW,GAAW,CACK,EAGhC,EAGH,MAAqB,CACnB,IAAM,EAAQ,GAAM,CAEpB,OADA,EAAS,KAAK,EAAM,CACb,GAEV"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function e(e){return typeof e==`object`&&!!e&&`_tag`in e&&e._tag===`Service`&&`key`in e&&typeof e.key==`string`}function t(t){return e(t)?t:void 0}function n(e,n){let r=t(n);if(r!==void 0)return e._services.get(r.key)}export{n,t};
|
|
2
|
-
//# sourceMappingURL=service-resolution-BefYr4nR.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service-resolution-BefYr4nR.mjs","names":[],"sources":["../src/service/service-resolution.ts"],"sourcesContent":["import type { Context } from \"../context/context\"\n\ntype ServiceRequest = {\n _tag: \"Service\"\n key: string\n}\n\n/**\n * Narrow an unknown yielded value to a service request.\n */\nfunction isServiceRequest(value: unknown): value is ServiceRequest {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"_tag\" in value &&\n value._tag === \"Service\" &&\n \"key\" in value &&\n typeof value.key === \"string\"\n )\n}\n\nexport function asServiceRequest(value: unknown) {\n return isServiceRequest(value) ? value : undefined\n}\n\n/**\n * Resolve a yielded service request from a context.\n */\nexport function resolveService<R>(ctx: Context<R>, value: unknown) {\n const request = asServiceRequest(value)\n if (request === undefined) return undefined\n return ctx._services.get(request.key)\n}\n"],"mappings":"AAUA,SAAS,EAAiB,EAAyC,CACjE,OACE,OAAO,GAAU,YACjB,GACA,SAAU,GACV,EAAM,OAAS,WACf,QAAS,GACT,OAAO,EAAM,KAAQ,SAIzB,SAAgB,EAAiB,EAAgB,CAC/C,OAAO,EAAiB,EAAM,CAAG,EAAQ,IAAA,GAM3C,SAAgB,EAAkB,EAAiB,EAAgB,CACjE,IAAM,EAAU,EAAiB,EAAM,CACnC,OAAY,IAAA,GAChB,OAAO,EAAI,UAAU,IAAI,EAAQ,IAAI"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|