@nicolastoulemont/std 0.3.0 → 0.4.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/dist/adt/index.d.mts +1 -1
- package/dist/adt/index.mjs +1 -1
- package/dist/{adt-DraJkmij.mjs → adt-DH37Pprw.mjs} +53 -53
- package/dist/adt-DH37Pprw.mjs.map +1 -0
- package/dist/{apply-fn.types-CXDoeA7D.d.mts → apply-fn.types-0g_9eXRy.d.mts} +1 -1
- package/dist/{apply-fn.types-CXDoeA7D.d.mts.map → apply-fn.types-0g_9eXRy.d.mts.map} +1 -1
- package/dist/brand/index.d.mts +2 -2
- package/dist/brand/index.mjs +2 -2
- package/dist/{brand-CTaxGuU9.mjs → brand-BqcqFXj5.mjs} +6 -6
- package/dist/{brand-CTaxGuU9.mjs.map → brand-BqcqFXj5.mjs.map} +1 -1
- package/dist/chunk-DRYujVrt.mjs +18 -0
- package/dist/data/index.d.mts +1 -1
- package/dist/data/index.mjs +1 -1
- package/dist/{data-DgzWI4R_.mjs → data-Cg8ySt6-.mjs} +13 -13
- package/dist/data-Cg8ySt6-.mjs.map +1 -0
- package/dist/discriminator.types-D-UbMmAD.d.mts +7 -0
- package/dist/discriminator.types-D-UbMmAD.d.mts.map +1 -0
- package/dist/either/index.d.mts +2 -2
- package/dist/either/index.mjs +2 -2
- package/dist/{either-CnOBUH7a.mjs → either-jkBX8xS1.mjs} +181 -44
- package/dist/either-jkBX8xS1.mjs.map +1 -0
- package/dist/{equality-YMebYwm1.mjs → equality-C2l3BIi8.mjs} +28 -28
- package/dist/equality-C2l3BIi8.mjs.map +1 -0
- package/dist/err/index.d.mts +2 -2
- package/dist/err/index.mjs +2 -2
- package/dist/{err-BqQApH9r.mjs → err-BM-svBaK.mjs} +20 -13
- package/dist/err-BM-svBaK.mjs.map +1 -0
- package/dist/flow/index.d.mts +1 -1
- package/dist/flow/index.mjs +1 -1
- package/dist/{flow-pRdnqmMY.mjs → flow-D4cE0EAg.mjs} +10 -3
- package/dist/flow-D4cE0EAg.mjs.map +1 -0
- package/dist/fx/index.d.mts +3 -0
- package/dist/fx/index.mjs +4 -0
- package/dist/fx-B-0MxGTM.mjs +1306 -0
- package/dist/fx-B-0MxGTM.mjs.map +1 -0
- package/dist/fx.types-DpIQILok.mjs +13 -0
- package/dist/fx.types-DpIQILok.mjs.map +1 -0
- package/dist/fx.types-aTmhyidu.d.mts +133 -0
- package/dist/fx.types-aTmhyidu.d.mts.map +1 -0
- package/dist/index-BO6bxBeo.d.mts +457 -0
- package/dist/index-BO6bxBeo.d.mts.map +1 -0
- package/dist/{index-tkgTLCoq.d.mts → index-BOrJQBPO.d.mts} +2 -2
- package/dist/{index-tkgTLCoq.d.mts.map → index-BOrJQBPO.d.mts.map} +1 -1
- package/dist/{index-zC2zAtZY.d.mts → index-CLlcoy8B.d.mts} +2 -2
- package/dist/{index-zC2zAtZY.d.mts.map → index-CLlcoy8B.d.mts.map} +1 -1
- package/dist/index-CLspOlBH.d.mts +737 -0
- package/dist/index-CLspOlBH.d.mts.map +1 -0
- package/dist/{index-BR7takNf.d.mts → index-CQxzD1YM.d.mts} +63 -24
- package/dist/index-CQxzD1YM.d.mts.map +1 -0
- package/dist/index-ClxPiGP9.d.mts +886 -0
- package/dist/index-ClxPiGP9.d.mts.map +1 -0
- package/dist/index-Cydt5ocm.d.mts +221 -0
- package/dist/index-Cydt5ocm.d.mts.map +1 -0
- package/dist/index-D5tzehjf.d.mts +476 -0
- package/dist/index-D5tzehjf.d.mts.map +1 -0
- package/dist/{index-BCrD3pEs.d.mts → index-EmWRCTY3.d.mts} +18 -18
- package/dist/index-EmWRCTY3.d.mts.map +1 -0
- package/dist/{index-Cp_4sFun.d.mts → index-FySViSfh.d.mts} +136 -41
- package/dist/index-FySViSfh.d.mts.map +1 -0
- package/dist/index-USQPafrR.d.mts +288 -0
- package/dist/index-USQPafrR.d.mts.map +1 -0
- package/dist/index.d.mts +27 -789
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -1391
- package/dist/option/index.d.mts +3 -3
- package/dist/option/index.mjs +3 -2
- package/dist/{option-CKHDOVea.mjs → option-C2QpGffy.mjs} +149 -29
- package/dist/option-C2QpGffy.mjs.map +1 -0
- package/dist/option.types-BiAiZ8Ks.mjs +33 -0
- package/dist/option.types-BiAiZ8Ks.mjs.map +1 -0
- package/dist/option.types-CVvowfmd.d.mts +165 -0
- package/dist/option.types-CVvowfmd.d.mts.map +1 -0
- package/dist/pipe/index.d.mts +1 -1
- package/dist/pipe/index.mjs +1 -1
- package/dist/{pipe-GYxZNkPB.mjs → pipe-BF4G4SLo.mjs} +2 -2
- package/dist/{pipe-GYxZNkPB.mjs.map → pipe-BF4G4SLo.mjs.map} +1 -1
- package/dist/pipeable-DYNrUps7.mjs +92 -0
- package/dist/pipeable-DYNrUps7.mjs.map +1 -0
- package/dist/pipeable-Dr0d_q4F.d.mts +27 -0
- package/dist/pipeable-Dr0d_q4F.d.mts.map +1 -0
- package/dist/predicate/index.d.mts +2 -2
- package/dist/predicate/index.mjs +2 -2
- package/dist/{predicate-BZkZmo-W.mjs → predicate-Dt9Qsbav.mjs} +2 -2
- package/dist/{predicate-BZkZmo-W.mjs.map → predicate-Dt9Qsbav.mjs.map} +1 -1
- package/dist/result/index.d.mts +3 -3
- package/dist/result/index.mjs +2 -2
- package/dist/{result-C5tPWR60.mjs → result-DhYA-J-M.mjs} +158 -38
- package/dist/result-DhYA-J-M.mjs.map +1 -0
- package/dist/result.types-_W95221K.d.mts +150 -0
- package/dist/result.types-_W95221K.d.mts.map +1 -0
- package/package.json +1 -9
- package/dist/adt-DraJkmij.mjs.map +0 -1
- package/dist/data-DgzWI4R_.mjs.map +0 -1
- package/dist/discriminator.types-DCkkrCj4.d.mts +0 -7
- package/dist/discriminator.types-DCkkrCj4.d.mts.map +0 -1
- package/dist/either-CnOBUH7a.mjs.map +0 -1
- package/dist/equality/index.d.mts +0 -86
- package/dist/equality/index.d.mts.map +0 -1
- package/dist/equality/index.mjs +0 -3
- package/dist/equality-YMebYwm1.mjs.map +0 -1
- package/dist/err-BqQApH9r.mjs.map +0 -1
- package/dist/flow-pRdnqmMY.mjs.map +0 -1
- package/dist/fn/index.d.mts +0 -2
- package/dist/fn/index.mjs +0 -3
- package/dist/fn-DFHj-EVA.mjs +0 -10
- package/dist/fn-DFHj-EVA.mjs.map +0 -1
- package/dist/gen/index.d.mts +0 -3
- package/dist/gen/index.mjs +0 -3
- package/dist/gen-DF-FXNdy.mjs +0 -99
- package/dist/gen-DF-FXNdy.mjs.map +0 -1
- package/dist/index-B3z7T6Dz.d.mts +0 -57
- package/dist/index-B3z7T6Dz.d.mts.map +0 -1
- package/dist/index-BCrD3pEs.d.mts.map +0 -1
- package/dist/index-BFhV56qy.d.mts +0 -105
- package/dist/index-BFhV56qy.d.mts.map +0 -1
- package/dist/index-BLG9B4bn.d.mts +0 -116
- package/dist/index-BLG9B4bn.d.mts.map +0 -1
- package/dist/index-BR7takNf.d.mts.map +0 -1
- package/dist/index-BiFc2xWF.d.mts +0 -211
- package/dist/index-BiFc2xWF.d.mts.map +0 -1
- package/dist/index-BwVaI5d0.d.mts +0 -79
- package/dist/index-BwVaI5d0.d.mts.map +0 -1
- package/dist/index-CckxkaUd.d.mts +0 -80
- package/dist/index-CckxkaUd.d.mts.map +0 -1
- package/dist/index-Cp_4sFun.d.mts.map +0 -1
- package/dist/index-DbfMra4p.d.mts +0 -72
- package/dist/index-DbfMra4p.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/is-promise-BEl3eGZg.mjs +0 -11
- package/dist/is-promise-BEl3eGZg.mjs.map +0 -1
- package/dist/option-CKHDOVea.mjs.map +0 -1
- package/dist/option.types-eqVODMIy.d.mts +0 -89
- package/dist/option.types-eqVODMIy.d.mts.map +0 -1
- package/dist/result-C5tPWR60.mjs.map +0 -1
- package/dist/result.types-Bd8a43Fg.d.mts +0 -174
- package/dist/result.types-Bd8a43Fg.d.mts.map +0 -1
- /package/dist/{result-D7XJ96pv.mjs → result-BmqdTN5o.mjs} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fx-B-0MxGTM.mjs","names":["isServiceClass","resultErr","resultOk","gen","service","impl","ctx","gen","layerGen","layerResult","ok","gen","gen","fxGen","fxResult","ok"],"sources":["../src/fx/fx.ts","../src/fx/service.ts","../src/fx/context.ts","../src/fx/layer.ts","../src/fx/scope.ts","../src/fx/memo-map.ts","../src/fx/provide.ts"],"sourcesContent":["import { NoSuchElementError } from \"../option/option.types\"\nimport { ok as resultOk, err as resultErr } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport { FxTypeId } from \"./fx.types\"\nimport type {\n RunnableFx,\n SyncFx,\n AsyncFx,\n Fx as FxProtocol,\n FxError,\n FxRequirements,\n FxGenerator,\n AsyncFxGenerator,\n} from \"./fx.types\"\n\n// ============================================================================\n// FxDefect - Wraps unexpected thrown exceptions\n// ============================================================================\n\n/**\n * Represents an unexpected thrown exception (defect) caught during Fx execution.\n * Wraps the original thrown value and provides access to it via `.defect`.\n *\n * @example\n * ```ts\n * const result = Fx.run(myComputation)\n * if (!result.ok && isFxDefect(result.error)) {\n * console.error(\"Unexpected defect:\", result.error.defect)\n * }\n * ```\n */\nexport class FxDefect extends Error {\n readonly _tag = \"FxDefect\" as const\n readonly defect: unknown\n\n constructor(thrown: unknown) {\n super(thrown instanceof Error ? thrown.message : String(thrown))\n this.name = \"FxDefect\"\n this.defect = thrown\n if (thrown instanceof Error) {\n this.cause = thrown\n }\n }\n}\n\n/**\n * Type guard to check if an error is an FxDefect (unexpected thrown exception).\n */\nexport const isFxDefect = (error: unknown): error is FxDefect => error instanceof FxDefect\n\n// ============================================================================\n// Fx.run - Execute computations\n// ============================================================================\n\n/**\n * Execute a sync Fx computation and return the result.\n * Catches unexpected thrown exceptions and wraps them as FxDefect in the error channel.\n * Only available when R = never (all dependencies provided).\n *\n * @param fx - The sync computation to execute\n * @returns Result<A, E | FxDefect>\n */\nfunction fxRun<A, E>(fx: SyncFx<A, E>): Result<A, E | FxDefect>\n\n/**\n * Execute an async Fx computation and return a Promise of the result.\n * Catches unexpected thrown exceptions and wraps them as FxDefect in the error channel.\n * Only available when R = never (all dependencies provided).\n *\n * @param fx - The async computation to execute\n * @returns Promise<Result<A, E | FxDefect>>\n */\nfunction fxRun<A, E>(fx: AsyncFx<A, E>): Promise<Result<A, E | FxDefect>>\n\n/**\n * Execute an Fx computation (union type).\n * Returns Result for sync, Promise<Result> for async.\n * Catches unexpected thrown exceptions and wraps them as FxDefect.\n */\nfunction fxRun<A, E>(fx: RunnableFx<A, E>): Result<A, E | FxDefect> | Promise<Result<A, E | FxDefect>>\n\n/**\n * Implementation of Fx.run.\n * Detects sync vs async and executes appropriately.\n */\nfunction fxRun<A, E>(fx: RunnableFx<A, E>): Result<A, E | FxDefect> | Promise<Result<A, E | FxDefect>> {\n if (fx._tag === \"AsyncFx\") {\n return runAsync(fx)\n }\n return runSync(fx)\n}\n\n/**\n * Check if a value is a ServiceClass (yielded for service injection).\n */\nfunction isServiceClass(value: unknown): value is { _tag: \"Service\"; key: string } {\n return typeof value === \"object\" && value !== null && \"_tag\" in value && value._tag === \"Service\"\n}\n\n/**\n * Internal helper to run a sync Fx computation.\n * Wraps execution in try-catch to capture unexpected thrown exceptions as FxDefect.\n */\nfunction runSync<A, E>(fx: SyncFx<A, E>): Result<A, E | FxDefect> {\n try {\n const gen = fx[Symbol.iterator]()\n const result = gen.next()\n\n if (result.done !== true) {\n const yielded = result.value as unknown\n // Check for ServiceClass (which is what gets yielded now)\n if (isServiceClass(yielded)) {\n return resultErr(\n new FxDefect(new Error(`Service \"${yielded.key}\" not provided. Use provide() to inject services.`)),\n )\n }\n // Check for NoSuchElementError (from Option.none())\n if (yielded instanceof NoSuchElementError) {\n return resultErr(yielded as E)\n }\n // Check for Result.err - return it directly (it's already a valid Result)\n if (typeof yielded === \"object\" && yielded !== null && \"ok\" in yielded && yielded.ok === false) {\n return yielded as Result<A, E>\n }\n // Otherwise it's a raw error (shouldn't happen with proper types, but handle for safety)\n return resultErr(yielded as E)\n }\n\n return resultOk(result.value)\n } catch (thrown) {\n return resultErr(new FxDefect(thrown))\n }\n}\n\n/**\n * Internal helper to run an async Fx computation.\n * Wraps execution in try-catch to capture unexpected thrown exceptions as FxDefect.\n */\nasync function runAsync<A, E>(fx: AsyncFx<A, E>): Promise<Result<A, E | FxDefect>> {\n try {\n const gen = fx[Symbol.asyncIterator]()\n const result = await gen.next()\n\n if (result.done !== true) {\n const yielded = result.value as unknown\n // Check for ServiceClass (which is what gets yielded now)\n if (isServiceClass(yielded)) {\n return resultErr(\n new FxDefect(new Error(`Service \"${yielded.key}\" not provided. Use provide() to inject services.`)),\n )\n }\n // Check for NoSuchElementError (from Option.none())\n if (yielded instanceof NoSuchElementError) {\n return resultErr(yielded as E)\n }\n // Check for Result.err - return it directly (it's already a valid Result)\n if (typeof yielded === \"object\" && yielded !== null && \"ok\" in yielded && yielded.ok === false) {\n return yielded as Result<A, E>\n }\n // Otherwise it's a raw error (shouldn't happen with proper types, but handle for safety)\n return resultErr(yielded as E)\n }\n\n return resultOk(result.value)\n } catch (thrown) {\n return resultErr(new FxDefect(thrown))\n }\n}\n\n// ============================================================================\n// Fx.gen - Create composable computations\n// ============================================================================\n\n/**\n * Create a composable computation from a sync generator function.\n * Returns a SyncFx that can be stored, passed around, and executed later.\n *\n * @template Yielded - The type of values yielded by the generator (must implement Fx protocol)\n * @template A - The success value type\n * @param generatorFn - A function that returns a sync generator\n * @returns SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n *\n * @example\n * ```ts\n * const getUser = (id: string) => Fx.gen(function* () {\n * const db = yield* Database\n * const logger = yield* Logger\n *\n * logger.info(`Fetching user ${id}`)\n * return yield* db.query<User>(`SELECT * FROM users WHERE id = '${id}'`)\n * })\n * // Type: SyncFx<User[], DatabaseError, Database | Logger>\n *\n * // Execute later with dependencies provided\n * const result = pipe(getUser(\"123\"), provide(AppLayer)).run()\n * ```\n */\nfunction fxGen<Yielded extends FxProtocol<unknown, unknown, unknown>, A>(\n generatorFn: () => Generator<Yielded, A, unknown>,\n): SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n\n/**\n * Create a composable computation from an async generator function.\n * Returns an AsyncFx that can be stored, passed around, and executed later.\n *\n * @template Yielded - The type of values yielded by the generator (must implement Fx protocol)\n * @template A - The success value type\n * @param generatorFn - A function that returns an async generator\n * @returns AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n *\n * @example\n * ```ts\n * const fetchData = (url: string) => Fx.gen(async function* () {\n * const logger = yield* Logger\n *\n * logger.info(`Fetching ${url}`)\n * const response = await fetch(url)\n * return yield* Result.fromTry(async () => await response.json())\n * })\n * // Type: AsyncFx<unknown, Error, Logger>\n * ```\n */\nfunction fxGen<Yielded extends FxProtocol<unknown, unknown, unknown>, A>(\n generatorFn: () => AsyncGenerator<Yielded, A, unknown>,\n): AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n\n/**\n * Create a composable computation from a sync generator function that takes parameters.\n * Returns a factory function that, when called with parameters, produces a SyncFx.\n *\n * @template P - The parameter types (must be non-empty)\n * @template Yielded - The type of values yielded by the generator (must implement Fx protocol)\n * @template A - The success value type\n * @param generatorFn - A function that takes parameters and returns a sync generator\n * @returns A factory function that produces SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n *\n * @example\n * ```ts\n * const getUser = Fx.gen(function* ({userId}: {userId: string}) {\n * const db = yield* Database\n * return yield* db.query(`SELECT * FROM users WHERE id = '${userId}'`)\n * })\n * // Type: (params: {userId: string}) => SyncFx<...>\n *\n * const result = Fx.run(pipe(getUser({userId: \"123\"}), provide(DbLayer)))\n * ```\n */\nfunction fxGen<P extends [unknown, ...unknown[]], Yielded extends FxProtocol<unknown, unknown, unknown>, A>(\n generatorFn: (...params: P) => Generator<Yielded, A, unknown>,\n): (...params: P) => SyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n\n/**\n * Create a composable computation from an async generator function that takes parameters.\n * Returns a factory function that, when called with parameters, produces an AsyncFx.\n *\n * @template P - The parameter types (must be non-empty)\n * @template Yielded - The type of values yielded by the generator (must implement Fx protocol)\n * @template A - The success value type\n * @param generatorFn - A function that takes parameters and returns an async generator\n * @returns A factory function that produces AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n *\n * @example\n * ```ts\n * const fetchUser = Fx.gen(async function* ({url}: {url: string}) {\n * const response = await fetch(url)\n * return yield* Result.fromTry(async () => await response.json())\n * })\n * // Type: (params: {url: string}) => AsyncFx<...>\n * ```\n */\nfunction fxGen<P extends [unknown, ...unknown[]], Yielded extends FxProtocol<unknown, unknown, unknown>, A>(\n generatorFn: (...params: P) => AsyncGenerator<Yielded, A, unknown>,\n): (...params: P) => AsyncFx<A, FxError<Yielded>, FxRequirements<Yielded>>\n\n/**\n * Implementation of unified Fx.gen function.\n * Detects sync vs async generator and returns appropriate computation type.\n * For parameterized generators (length > 0), returns a factory function.\n */\n// oxlint-disable-next-line no-explicit-any\nfunction fxGen(generatorFn: (...args: any[]) => any): any {\n if (generatorFn.length > 0) {\n return (...params: unknown[]) => fxGen(() => generatorFn(...params))\n }\n\n // Check if we're dealing with async generator\n const testGen = generatorFn()\n const isAsync = Symbol.asyncIterator in testGen\n\n if (isAsync) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined,\n _E: () => undefined,\n _R: () => undefined,\n },\n // oxlint-disable-next-line no-explicit-any\n async *[Symbol.asyncIterator](): AsyncGenerator<any, any, unknown> {\n const gen = generatorFn()\n let result = await gen.next()\n\n while (!result.done) {\n // Pass through yields (errors or services as Fx values)\n const injected = yield result.value\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(injected)\n }\n\n return result.value\n },\n }\n }\n\n // Sync generator\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined,\n _E: () => undefined,\n _R: () => undefined,\n },\n // oxlint-disable-next-line no-explicit-any\n *[Symbol.iterator](): Generator<any, any, unknown> {\n const gen = generatorFn()\n let result = gen.next()\n\n while (!result.done) {\n const injected = yield result.value\n result = gen.next(injected)\n }\n\n return result.value\n },\n }\n}\n\n// ============================================================================\n// Fx.fn - Execute computations immediately\n// ============================================================================\n\n/**\n * Execute a sync computation immediately and return the result.\n * Catches unexpected thrown exceptions and wraps them as FxDefect.\n * For computations without service dependencies.\n *\n * @template A - The success value type\n * @template E - The error type\n * @param generatorFn - A function that returns a sync generator\n * @returns Result<A, E | FxDefect>\n *\n * @example\n * ```ts\n * const result = Fx.fn(function* () {\n * const a = yield* Result.ok(10)\n * const b = yield* Result.ok(20)\n * return a + b\n * })\n * // Type: Result<number, FxDefect>\n * // result = { ok: true, value: 30 }\n * ```\n */\nfunction fxFn<A, E>(generatorFn: () => FxGenerator<A, E, never>): Result<A, E | FxDefect>\n\n/**\n * Execute an async computation immediately and return a Promise of the result.\n * Catches unexpected thrown exceptions and wraps them as FxDefect.\n * For computations without service dependencies.\n *\n * @template A - The success value type\n * @template E - The error type\n * @param generatorFn - A function that returns an async generator\n * @returns Promise<Result<A, E | FxDefect>>\n *\n * @example\n * ```ts\n * const result = await Fx.fn(async function* () {\n * const response = await fetch(\"/api/users\")\n * const data = yield* Result.fromTry(async () => await response.json())\n * return data\n * })\n * // Type: Promise<Result<unknown, Error | FxDefect>>\n * ```\n */\nfunction fxFn<A, E>(generatorFn: () => AsyncFxGenerator<A, E, never>): Promise<Result<A, E | FxDefect>>\n\n/**\n * Execute a sync computation with service dependencies immediately.\n * Catches unexpected thrown exceptions and wraps them as FxDefect.\n * The second argument is required when the computation has service requirements (R ≠ never).\n *\n * @template A - The success value type\n * @template E - The error type from the computation\n * @template E2 - The error type from the provider (layer)\n * @template R - The required services type\n * @param generatorFn - A function that returns a sync generator with service requirements\n * @param provider - A function that provides the services (e.g., provide(AppLayer))\n * @returns Result<A, E | E2 | FxDefect>\n *\n * @example\n * ```ts\n * const result = Fx.fn(function* () {\n * const config = yield* Config\n * const logger = yield* Logger\n * logger.info(`DB URL: ${config.dbUrl}`)\n * return config.dbUrl\n * }, provide(AppLayer))\n * // Type: Result<string, FxDefect>\n * ```\n */\nfunction fxFn<A, E, E2, R>(\n generatorFn: () => FxGenerator<A, E, R>,\n provider: (fx: RunnableFx<A, E, R>) => RunnableFx<A, E | E2>,\n): Result<A, E | E2 | FxDefect>\n\n/**\n * Execute an async computation with service dependencies immediately.\n * Catches unexpected thrown exceptions and wraps them as FxDefect.\n * The second argument is required when the computation has service requirements (R ≠ never).\n *\n * @template A - The success value type\n * @template E - The error type from the computation\n * @template E2 - The error type from the provider (layer)\n * @template R - The required services type\n * @param generatorFn - A function that returns an async generator with service requirements\n * @param provider - A function that provides the services (e.g., provide(AppLayer))\n * @returns Promise<Result<A, E | E2 | FxDefect>>\n *\n * @example\n * ```ts\n * const result = await Fx.fn(async function* () {\n * const config = yield* Config\n * await doAsyncWork()\n * return config.dbUrl\n * }, provide(AppLayer))\n * // Type: Promise<Result<string, FxDefect>>\n * ```\n */\n// oxlint-disable-next-line no-redundant-type-constituents\nfunction fxFn<A, E, E2, R>(\n generatorFn: () => AsyncFxGenerator<A, E, R>,\n provider: (fx: RunnableFx<A, E, R>) => RunnableFx<A, E | E2>,\n): Promise<Result<A, E | E2 | FxDefect>>\n\n/**\n * Implementation of Fx.fn.\n * Reuses fxGen() for Fx creation and fxRun() for execution to ensure consistent behavior.\n */\nfunction fxFn<A, E, E2, R>(\n generatorFn: () => FxGenerator<A, E, R> | AsyncFxGenerator<A, E, R>,\n provider?: (fx: RunnableFx<A, E, R>) => RunnableFx<A, E | E2>,\n): Result<A, E | E2 | FxDefect> | Promise<Result<A, E | E2 | FxDefect>> {\n // Create the Fx using fxGen (single source of truth for Fx creation)\n // Type cast needed because fxGen infers E/R from yielded Fx values,\n // while fxFn receives E/R as explicit type parameters\n // oxlint-disable-next-line no-explicit-any\n const fx = fxGen(generatorFn as any) as RunnableFx<A, E, R>\n\n if (provider) {\n // Apply provider and run\n const provided = provider(fx)\n return fxRun(provided as RunnableFx<A, E | E2>) as\n | Result<A, E | E2 | FxDefect>\n | Promise<Result<A, E | E2 | FxDefect>>\n }\n\n // No provider - run directly (R must be never at the type level)\n return fxRun(fx as RunnableFx<A, E | E2>) as Result<A, E | E2 | FxDefect> | Promise<Result<A, E | E2 | FxDefect>>\n}\n\n// ============================================================================\n// Fx.ok / Fx.err - Convenience aliases\n// ============================================================================\n\n/**\n * Convenience alias for Result.ok.\n * Creates a successful Result that can be yielded in an Fx computation.\n *\n * @param value - The success value\n * @returns Result<T, never>\n *\n * @example\n * ```ts\n * const workflow = Fx.gen(function* () {\n * const value = yield* Fx.ok(42)\n * return value * 2\n * })\n * ```\n */\nconst fxOk = resultOk\n\n/**\n * Convenience alias for Result.err.\n * Creates an error Result that can be yielded in an Fx computation.\n *\n * @param error - The error value\n * @returns Result<never, E>\n *\n * @example\n * ```ts\n * const workflow = Fx.gen(function* () {\n * const config = yield* Config\n *\n * if (!config.dbUrl) {\n * return yield* Fx.err(new ValidationError({ field: \"dbUrl\" }))\n * }\n *\n * return config.dbUrl\n * })\n * ```\n */\nconst fxErr = resultErr\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n// Export individual functions\nexport const gen = fxGen\nexport const fn = fxFn\nexport const run = fxRun\nexport const ok = fxOk\nexport const err = fxErr\n\n// Export internal helpers for use in other modules (provide, scope)\nexport { runSync, runAsync }\n\n/**\n * Fx namespace containing utilities for creating and running effectful computations.\n *\n * Fx provides a minimal API inspired by Effect.ts:\n * - `Fx.gen()` - Create composable computations with service dependencies\n * - `Fx.fn()` - Execute computations immediately\n * - `Fx.run()` - Execute a computation (when all dependencies are provided)\n * - `Fx.ok()` - Create successful results (alias for Result.ok)\n * - `Fx.err()` - Create error results (alias for Result.err)\n *\n * @example\n * ```ts\n * import { Fx, Service, Layer, provide, pipe } from \"@repo/std\"\n *\n * // Define services\n * class Config extends Service<Config>()(\"Config\") {\n * readonly dbUrl!: string\n * }\n *\n * class Logger extends Service<Logger>()(\"Logger\") {\n * readonly info!: (msg: string) => void\n * }\n *\n * // Create layers\n * const ConfigLive = Layer.ok(Config, { dbUrl: \"postgres://...\" })\n * const LoggerLive = Layer.fx(Logger)(\n * Fx.gen(function* () {\n * const config = yield* Config\n * return { info: (msg) => console.log(`[${config.dbUrl}] ${msg}`) }\n * })\n * )\n *\n * // Create workflow\n * const myWorkflow = Fx.gen(function* () {\n * const logger = yield* Logger\n * logger.info(\"Hello from Fx!\")\n * return \"done\"\n * })\n *\n * // Compose and run\n * const AppLayer = pipe(ConfigLive, Layer.provide(LoggerLive))\n * const result = Fx.run(pipe(myWorkflow, provide(AppLayer)))\n * ```\n */\nexport const Fx = {\n gen: fxGen,\n fn: fxFn,\n run: fxRun,\n ok: fxOk,\n err: fxErr,\n} as const\n","import { FxTypeId } from \"./fx.types\"\nimport type { Fx } from \"./fx.types\"\n\n// ============================================================================\n// Service Class Types\n// ============================================================================\n\n/**\n * The interface returned by Service()().\n * Acts as both a type tag and a runtime lookup key.\n * Implements Fx protocol with E = never (no errors) and R = Self (requires itself).\n * When yielded, yields itself (as Fx) for proper type inference.\n */\nexport type ServiceClass<Self, Key extends string = string> = Fx<Self, never, Self> & {\n readonly _tag: \"Service\"\n readonly key: Key\n // Phantom type\n readonly _Self: Self\n\n /**\n * Yielding the service class in a gen computation\n * returns the service instance from context.\n * Yields the ServiceClass itself (which implements Fx) for type inference.\n */\n [Symbol.iterator](): Generator<ServiceClass<Self, Key>, Self, unknown>\n}\n\n/**\n * Extract the service type from a ServiceClass.\n */\nexport type ServiceOf<T> = T extends ServiceClass<infer S> ? S : never\n\n/**\n * Extract the key from a ServiceClass.\n */\nexport type ServiceKey<T> = T extends ServiceClass<unknown, infer K> ? K : never\n\n// ============================================================================\n// Service Factory\n// ============================================================================\n\n/**\n * Define a service with a unique key.\n * The returned class acts as both a type and a runtime tag for lookup.\n *\n * Usage follows a double-invocation pattern:\n * - First call provides the Self type parameter\n * - Second call provides the unique key\n *\n * @example\n * ```ts\n * class Config extends Service<Config>()(\"Config\") {\n * readonly dbUrl!: string\n * readonly logLevel!: \"debug\" | \"info\" | \"error\"\n * }\n *\n * class Logger extends Service<Logger>()(\"Logger\") {\n * readonly info!: (msg: string) => void\n * readonly error!: (msg: string) => void\n * }\n *\n * // Use in Fx.gen:\n * const workflow = Fx.gen(function* () {\n * const config = yield* Config\n * const logger = yield* Logger\n * logger.info(`DB URL: ${config.dbUrl}`)\n * })\n * ```\n */\nexport function Service<Self>(): <Key extends string>(key: Key) => ServiceClass<Self, Key> & (new () => Self) {\n return <Key extends string>(key: Key): ServiceClass<Self, Key> & (new () => Self) => {\n // Create the base class with proper prototype\n // oxlint-disable-next-line typescript/no-extraneous-class\n const ServiceBase = class {\n static readonly _tag = \"Service\" as const\n static readonly key: Key = key\n static readonly _Self: Self = undefined as unknown as Self\n\n static readonly [FxTypeId] = {\n _A: () => undefined as unknown as Self,\n _E: () => undefined as never,\n _R: () => undefined as unknown as Self,\n };\n\n /**\n * Yielding the class returns the class itself (for type inference).\n * The runtime intercepts this and provides the actual service instance.\n */\n static *[Symbol.iterator](): Generator<typeof ServiceBase, Self, Self> {\n // Yield the class itself - it implements Fx<Self, never, Self>\n // The runtime will recognize ServiceClass and inject the service\n const serviceInstance = yield ServiceBase\n return serviceInstance\n }\n }\n\n // Return with correct typing\n return ServiceBase as unknown as ServiceClass<Self, Key> & (new () => Self)\n }\n}\n\n/**\n * Create a service tag without class syntax.\n * Useful for simple services that don't need class inheritance.\n *\n * @example\n * ```ts\n * interface ConfigService {\n * readonly dbUrl: string\n * readonly logLevel: \"debug\" | \"info\" | \"error\"\n * }\n *\n * const Config = serviceTag<ConfigService>(\"Config\")\n *\n * // Use in Fx.gen:\n * const workflow = Fx.gen(function* () {\n * const config = yield* Config\n * console.log(config.dbUrl)\n * })\n * ```\n */\nexport function serviceTag<S>(key: string): ServiceClass<S> {\n const tag: ServiceClass<S> = {\n _tag: \"Service\",\n key,\n _Self: undefined as unknown as S,\n [FxTypeId]: {\n _A: () => undefined as unknown as S,\n _E: () => undefined as never,\n _R: () => undefined as unknown as S,\n },\n *[Symbol.iterator](): Generator<ServiceClass<S>, S, S> {\n // Yield the tag itself - it implements Fx<S, never, S>\n // The runtime will recognize ServiceClass and inject the service\n const serviceInstance = yield tag\n return serviceInstance\n },\n }\n return tag\n}\n\n/**\n * Check if a value is a ServiceClass.\n */\nexport const isServiceClass = (value: unknown): value is ServiceClass<unknown> =>\n typeof value === \"object\" && value !== null && \"_tag\" in value && value._tag === \"Service\"\n","import type { ServiceClass } from \"./service\"\n\n// ============================================================================\n// Context Type\n// ============================================================================\n\n/**\n * Context<Services> is an immutable map storing service implementations.\n * The Services type parameter tracks which services are available.\n */\nexport type Context<Services = never> = {\n readonly _tag: \"Context\"\n readonly _services: ReadonlyMap<string, unknown>\n // Phantom type for tracking available services\n readonly _Services: Services\n}\n\n// ============================================================================\n// Context Constructors\n// ============================================================================\n\n/**\n * Create an empty context with no services.\n */\nconst empty = (): Context => ({\n _tag: \"Context\",\n _services: new Map(),\n _Services: undefined as never,\n})\n\n/**\n * Create a context with a single service.\n *\n * @param service - The service class (tag)\n * @param impl - The service implementation\n * @returns A context containing the service\n *\n * @example\n * ```ts\n * const ctx = Context.make(Config, { dbUrl: \"postgres://...\", logLevel: \"info\" })\n * ```\n */\nconst make = <S>(service: ServiceClass<S>, impl: S): Context<S> => ({\n _tag: \"Context\",\n _services: new Map([[service.key, impl]]),\n _Services: undefined as unknown as S,\n})\n\n// ============================================================================\n// Context Operations\n// ============================================================================\n\n/**\n * Add a service to an existing context (returns new context).\n * Curried for use with pipe.\n *\n * @param service - The service class (tag)\n * @param impl - The service implementation\n * @returns A function that takes a context and returns a new context with the service added\n *\n * @example\n * ```ts\n * const ctx = pipe(\n * Context.empty(),\n * Context.add(Config, configImpl),\n * Context.add(Logger, loggerImpl),\n * )\n * ```\n */\nconst add =\n <S>(service: ServiceClass<S>, impl: S) =>\n <Existing>(ctx: Context<Existing>): Context<Existing | S> => ({\n _tag: \"Context\",\n _services: new Map([...ctx._services, [service.key, impl]]),\n _Services: undefined as unknown as Existing | S,\n })\n\n/**\n * Merge two contexts together.\n * If both contexts have the same service, the second context's implementation wins.\n *\n * @param a - First context\n * @param b - Second context\n * @returns A new context with services from both\n *\n * @example\n * ```ts\n * const ctx = Context.merge(configContext, loggerContext)\n * ```\n */\nconst merge = <A, B>(a: Context<A>, b: Context<B>): Context<A | B> => ({\n _tag: \"Context\",\n _services: new Map([...a._services, ...b._services]),\n _Services: undefined as unknown as A | B,\n})\n\n/**\n * Get a service from a context.\n * Throws if the service is not found.\n *\n * @param service - The service class (tag)\n * @returns The service implementation\n * @throws Error if service not found\n *\n * @example\n * ```ts\n * const config = Context.get(ctx, Config)\n * ```\n */\n// Use overload to handle both curried and uncurried calls\nfunction get<S>(ctx: Context<S>, service: ServiceClass<S>): S\nfunction get<S>(service: ServiceClass<S>): (ctx: Context<S>) => S\nfunction get<S>(\n ctxOrService: Context<S> | ServiceClass<S>,\n maybeService?: ServiceClass<S>,\n): S | ((ctx: Context<S>) => S) {\n // Curried form: get(service)(ctx)\n if (maybeService === undefined) {\n const service = ctxOrService as ServiceClass<S>\n return (ctx: Context<S>): S => {\n const impl = ctx._services.get(service.key)\n if (impl === undefined) {\n throw new Error(\n `Service \"${service.key}\" not found in context. Available services: [${[...ctx._services.keys()].join(\", \")}]`,\n )\n }\n return impl as S\n }\n }\n\n // Uncurried form: get(ctx, service)\n const ctx = ctxOrService as Context<S>\n const service = maybeService\n const impl = ctx._services.get(service.key)\n if (impl === undefined) {\n throw new Error(\n `Service \"${service.key}\" not found in context. Available services: [${[...ctx._services.keys()].join(\", \")}]`,\n )\n }\n return impl as S\n}\n\n/**\n * Unsafely get a service from a context by key string.\n * Used internally by the runtime when resolving ServiceRequests.\n * Returns undefined if not found (caller should handle).\n */\nconst unsafeGet = (ctx: Context<unknown>, key: string): unknown => ctx._services.get(key)\n\n/**\n * Check if a context contains a specific service.\n *\n * @param ctx - The context to check\n * @param service - The service class (tag)\n * @returns true if the service is in the context\n */\nconst has = <S>(ctx: Context<unknown>, service: ServiceClass<S>): boolean => ctx._services.has(service.key)\n\n/**\n * Get all service keys in a context.\n */\nconst keys = (ctx: Context<unknown>): string[] => [...ctx._services.keys()]\n\n/**\n * Get the size (number of services) in a context.\n */\nconst size = (ctx: Context<unknown>): number => ctx._services.size\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a value is a Context.\n */\nconst isContext = (value: unknown): value is Context<unknown> =>\n typeof value === \"object\" && value !== null && \"_tag\" in value && value._tag === \"Context\"\n\n// ============================================================================\n// Context Namespace\n// ============================================================================\n\n/**\n * Context namespace containing utilities for managing service contexts.\n *\n * A Context is an immutable map of services that can be provided to Fx computations.\n * Services are identified by their unique keys.\n *\n * @example\n * ```ts\n * import { Context, Service } from \"@repo/std\"\n *\n * class Config extends Service<Config>()(\"Config\") {\n * readonly dbUrl!: string\n * }\n *\n * class Logger extends Service<Logger>()(\"Logger\") {\n * readonly info!: (msg: string) => void\n * }\n *\n * // Create a context with services\n * const ctx = pipe(\n * Context.empty(),\n * Context.add(Config, { dbUrl: \"postgres://...\" }),\n * Context.add(Logger, { info: console.log }),\n * )\n *\n * // Or use make and merge\n * const configCtx = Context.make(Config, { dbUrl: \"postgres://...\" })\n * const loggerCtx = Context.make(Logger, { info: console.log })\n * const fullCtx = Context.merge(configCtx, loggerCtx)\n * ```\n */\nexport const Context = {\n empty,\n make,\n add,\n merge,\n get,\n unsafeGet,\n has,\n keys,\n size,\n isContext,\n} as const\n","import { Context } from \"./context\"\nimport { FxTypeId } from \"./fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"./fx.types\"\nimport type { Layer as LayerType, MergeROut, MergeError, UnprovidedDeps, AllSync } from \"./layer.types\"\nimport type { ScopeService, ExcludeScope } from \"./scope\"\nimport type { ServiceClass } from \"./service\"\n\n/**\n * Create a layer from a synchronous value (no dependencies).\n */\nconst layerOk = <S>(service: ServiceClass<S>, impl: S): LayerType<S, never, never, true> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as never,\n _RIn: undefined as never,\n _Sync: undefined as unknown as true,\n build: (): SyncFx<Context<S>, never> => ({\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<S>,\n _E: () => undefined as never,\n _R: () => undefined as never,\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, Context<S>, unknown> {\n return Context.make(service, impl)\n },\n }),\n})\n\n/**\n * Create a layer that always fails with an error.\n */\nconst layerErr = <E>(error: E): LayerType<never, E, never, true> => ({\n _tag: \"Layer\",\n _ROut: undefined as never,\n _E: undefined as unknown as E,\n _RIn: undefined as never,\n _Sync: undefined as unknown as true,\n build: (): SyncFx<Context, E> => ({\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as never,\n _E: () => error,\n _R: () => undefined as never,\n },\n *[Symbol.iterator](): Generator<E, never, unknown> {\n yield error\n throw new Error(\"Unreachable\")\n },\n }),\n})\n\n/**\n * Create a layer from an Fx computation (can have dependencies).\n * The Sync type parameter is inferred from the input fx:\n * - SyncFx input → Layer with Sync=true\n * - AsyncFx input → Layer with Sync=false\n */\nfunction layerFx<S>(service: ServiceClass<S>): {\n <E, R>(fx: SyncFx<S, E, R>): LayerType<S, E, R, true>\n <E, R>(fx: AsyncFx<S, E, R>): LayerType<S, E, R, false>\n <E, R>(fx: RunnableFx<S, E, R>): LayerType<S, E, R, boolean>\n}\nfunction layerFx<S>(service: ServiceClass<S>) {\n return <E, R>(fx: RunnableFx<S, E, R>): LayerType<S, E, R, boolean> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as unknown as E,\n _RIn: undefined as unknown as R,\n _Sync: undefined as unknown as boolean,\n build: (): RunnableFx<Context<S>, E, R> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as R,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, Context<S>, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n while (!result.done) {\n const value = yield result.value\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n return Context.make(service, result.value)\n },\n } as AsyncFx<Context<S>, E, R>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as R,\n },\n *[Symbol.iterator](): Generator<FxYield<E, R>, Context<S>, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n while (!result.done) {\n const value = yield result.value\n result = gen.next(value)\n }\n return Context.make(service, result.value)\n },\n } as SyncFx<Context<S>, E, R>\n },\n })\n}\n\n/**\n * Create a scoped layer (with resource cleanup).\n * The Sync type parameter is inferred from the input fx.\n */\nfunction layerScoped<S>(service: ServiceClass<S>): {\n <E, R>(fx: SyncFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, true>\n <E, R>(fx: AsyncFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, false>\n <E, R>(fx: RunnableFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, boolean>\n}\nfunction layerScoped<S>(service: ServiceClass<S>) {\n return <E, R>(fx: RunnableFx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>, boolean> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as unknown as E,\n _RIn: undefined as unknown as ExcludeScope<R>,\n _Sync: undefined as unknown as boolean,\n build: (_memoMap, scope): RunnableFx<Context<S>, E, ExcludeScope<R>> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as ExcludeScope<R>,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, ExcludeScope<R>>, Context<S>, unknown> {\n const gen = fx[Symbol.asyncIterator]()\n let result = await gen.next()\n while (!result.done) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded &&\n (yielded as ServiceClass<unknown>).key === \"@std/Scope\"\n ) {\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(scope)\n } else {\n const value = yield yielded as FxYield<E, ExcludeScope<R>>\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n }\n return Context.make(service, result.value)\n },\n } as AsyncFx<Context<S>, E, ExcludeScope<R>>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<S>,\n _E: () => undefined as unknown as E,\n _R: () => undefined as unknown as ExcludeScope<R>,\n },\n *[Symbol.iterator](): Generator<FxYield<E, ExcludeScope<R>>, Context<S>, unknown> {\n const gen = fx[Symbol.iterator]()\n let result = gen.next()\n while (!result.done) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded &&\n (yielded as ServiceClass<unknown>).key === \"@std/Scope\"\n ) {\n result = gen.next(scope)\n } else {\n const value = yield yielded as FxYield<E, ExcludeScope<R>>\n result = gen.next(value)\n }\n }\n return Context.make(service, result.value)\n },\n } as SyncFx<Context<S>, E, ExcludeScope<R>>\n },\n })\n}\n\n// ============================================================================\n// Layer Composition\n// ============================================================================\n\n/**\n * Provide dependencies to a layer and merge outputs.\n * Sync is preserved only if both the deps layer and the consuming layer are sync.\n */\nfunction layerProvide<DepsROut, DepsE, DepsRIn, DepsSync extends boolean>(\n deps: LayerType<DepsROut, DepsE, DepsRIn, DepsSync>,\n): {\n <ROut, E, RIn extends DepsROut, LayerSync extends boolean>(\n layer: LayerType<ROut, E, RIn, LayerSync>,\n ): LayerType<ROut | DepsROut, E | DepsE, DepsRIn, LayerSync extends true ? DepsSync : false>\n}\nfunction layerProvide<DepsROut, DepsE, DepsRIn>(deps: LayerType<DepsROut, DepsE, DepsRIn, boolean>) {\n return <ROut, E, RIn extends DepsROut>(\n layer: LayerType<ROut, E, RIn, boolean>,\n ): LayerType<ROut | DepsROut, E | DepsE, DepsRIn, boolean> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as ROut | DepsROut,\n _E: undefined as unknown as E | DepsE,\n _RIn: undefined as unknown as DepsRIn,\n _Sync: undefined as unknown as boolean,\n build: (memoMap, scope): RunnableFx<Context<ROut | DepsROut>, E | DepsE, DepsRIn> => {\n const depsBuildFx = deps.build(memoMap, scope)\n\n if (depsBuildFx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<ROut | DepsROut>,\n _E: () => undefined as unknown as E | DepsE,\n _R: () => undefined as unknown as DepsRIn,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n FxYield<E | DepsE, DepsRIn>,\n Context<ROut | DepsROut>,\n unknown\n > {\n const depsGen = depsBuildFx[Symbol.asyncIterator]()\n let depsResult = await depsGen.next()\n while (!depsResult.done) {\n const value = yield depsResult.value\n // oxlint-disable-next-line no-await-in-loop\n depsResult = await depsGen.next(value)\n }\n const depsCtx = depsResult.value\n\n const layerBuildFx = layer.build(memoMap, scope)\n if (layerBuildFx._tag === \"AsyncFx\") {\n const layerGen = layerBuildFx[Symbol.asyncIterator]()\n let layerResult = await layerGen.next()\n while (!layerResult.done) {\n const yielded = layerResult.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = depsCtx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n layerResult = await layerGen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n // oxlint-disable-next-line no-await-in-loop\n layerResult = await layerGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n }\n\n const layerGen = layerBuildFx[Symbol.iterator]()\n let layerResult = layerGen.next()\n while (!layerResult.done) {\n const yielded = layerResult.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = depsCtx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n layerResult = layerGen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n layerResult = layerGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n },\n } as AsyncFx<Context<ROut | DepsROut>, E | DepsE, DepsRIn>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<ROut | DepsROut>,\n _E: () => undefined as unknown as E | DepsE,\n _R: () => undefined as unknown as DepsRIn,\n },\n *[Symbol.iterator](): Generator<FxYield<E | DepsE, DepsRIn>, Context<ROut | DepsROut>, unknown> {\n const depsGen = depsBuildFx[Symbol.iterator]()\n let depsResult = depsGen.next()\n while (!depsResult.done) {\n const value = yield depsResult.value\n depsResult = depsGen.next(value)\n }\n const depsCtx = depsResult.value\n\n const layerBuildFx = layer.build(memoMap, scope)\n if (layerBuildFx._tag === \"SyncFx\") {\n const syncGen = layerBuildFx[Symbol.iterator]()\n let layerResult = syncGen.next()\n while (!layerResult.done) {\n const yielded = layerResult.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = depsCtx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n layerResult = syncGen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<E, DepsRIn>\n layerResult = syncGen.next(value)\n }\n return Context.merge(depsCtx, layerResult.value)\n }\n throw new Error(\"Cannot use async layer in sync context\")\n },\n } as SyncFx<Context<ROut | DepsROut>, E | DepsE, DepsRIn>\n },\n })\n}\n\n/**\n * Merge multiple layers with automatic dependency resolution.\n * The merged layer is sync only if ALL input layers are sync.\n */\nfunction layerMerge<L extends LayerType<unknown, unknown, unknown, boolean>[]>(\n ...layers: L\n): LayerType<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>, AllSync<L>>\nfunction layerMerge<L extends LayerType<unknown, unknown, unknown, boolean>[]>(\n ...layers: L\n): LayerType<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>, boolean> {\n return {\n _tag: \"Layer\",\n _ROut: undefined as unknown as MergeROut<L>,\n _E: undefined as unknown as MergeError<L>,\n _RIn: undefined as unknown as UnprovidedDeps<L>,\n _Sync: undefined as unknown as boolean,\n build: (memoMap, scope): RunnableFx<Context<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>> => {\n const hasAsync = layers.some((l) => l.build(memoMap, scope)._tag === \"AsyncFx\")\n\n if (hasAsync) {\n return {\n _tag: \"AsyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<MergeROut<L>>,\n _E: () => undefined as unknown as MergeError<L>,\n _R: () => undefined as unknown as UnprovidedDeps<L>,\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n FxYield<MergeError<L>, UnprovidedDeps<L>>,\n Context<MergeROut<L>>,\n unknown\n > {\n let ctx = Context.empty() as Context<unknown>\n for (const layer of layers) {\n const buildFx = layer.build(memoMap, scope)\n if (buildFx._tag === \"AsyncFx\") {\n const gen = buildFx[Symbol.asyncIterator]()\n // oxlint-disable-next-line no-await-in-loop\n let result = await gen.next()\n while (!result.done) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n } else {\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n while (!result.done) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n result = gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n }\n }\n return ctx as Context<MergeROut<L>>\n },\n } as AsyncFx<Context<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>>\n }\n\n return {\n _tag: \"SyncFx\",\n [FxTypeId]: {\n _A: () => undefined as unknown as Context<MergeROut<L>>,\n _E: () => undefined as unknown as MergeError<L>,\n _R: () => undefined as unknown as UnprovidedDeps<L>,\n },\n *[Symbol.iterator](): Generator<FxYield<MergeError<L>, UnprovidedDeps<L>>, Context<MergeROut<L>>, unknown> {\n let ctx = Context.empty() as Context<unknown>\n for (const layer of layers) {\n const buildFx = layer.build(memoMap, scope)\n if (buildFx._tag !== \"SyncFx\") {\n throw new Error(\"Expected sync layer in sync context\")\n }\n const gen = buildFx[Symbol.iterator]()\n let result = gen.next()\n while (!result.done) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n }\n const value = yield yielded as FxYield<MergeError<L>, UnprovidedDeps<L>>\n result = gen.next(value)\n }\n ctx = Context.merge(ctx, result.value)\n }\n return ctx as Context<MergeROut<L>>\n },\n } as SyncFx<Context<MergeROut<L>>, MergeError<L>, UnprovidedDeps<L>>\n },\n }\n}\n\n// ============================================================================\n// Layer Namespace\n// ============================================================================\n\nexport const Layer = {\n ok: layerOk,\n err: layerErr,\n fx: layerFx,\n scoped: layerScoped,\n provide: layerProvide,\n merge: layerMerge,\n} as const\n","import type { Result } from \"../result/result.types\"\nimport { runSync, runAsync } from \"./fx\"\nimport { FxTypeId } from \"./fx.types\"\nimport type { SyncFx, AsyncFx, FxYield } from \"./fx.types\"\nimport { Service } from \"./service\"\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 * const DatabaseLive = Layer.scoped(Database)(\n * Fx.gen(function* () {\n * const scope = yield* Scope\n *\n * const connection = createConnection()\n *\n * // Register cleanup - runs when scope closes\n * yield* scope.addFinalizer(() =>\n * Fx.gen(function* () {\n * connection.close()\n * })\n * )\n *\n * return { query: (sql) => connection.query(sql) }\n * })\n * )\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// Create the Scope service tag\nclass ScopeTag extends Service<ScopeService>()(\"@std/Scope\") {}\nexport { ScopeTag as Scope }\n\n// ============================================================================\n// Scope Implementation\n// ============================================================================\n\n/**\n * Create a new Scope instance.\n * This is the concrete implementation of the ScopeService interface.\n */\nexport function createScope(): 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 = createScope()\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 */\nexport type ExcludeScope<R> = Exclude<R, ScopeService>\n","import { ok } from \"../result/result\"\nimport type { Context } from \"./context\"\nimport { FxTypeId } from \"./fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"./fx.types\"\nimport type { Layer } from \"./layer.types\"\nimport type { ScopeService } from \"./scope\"\nimport type { ServiceClass } from \"./service\"\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) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = deps._services.get((yielded as ServiceClass<unknown>).key)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceClass<unknown>).key}\" not found during layer build`)\n }\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n } else {\n // It's an error - rethrow\n throw yielded\n }\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) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = deps._services.get((yielded as ServiceClass<unknown>).key)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceClass<unknown>).key}\" not found during layer build`)\n }\n result = gen.next(service)\n } else {\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 }\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) {\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = deps._services.get((yielded as ServiceClass<unknown>).key)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceClass<unknown>).key}\" not found during layer build`)\n }\n result = gen.next(service)\n } else {\n // It's an error - yield it\n yield yielded as E\n throw new Error(\"Unreachable\")\n }\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/**\n * Create a new MemoMap instance.\n */\nexport const createMemoMap = (): MemoMap => new MemoMap()\n","import { ok } from \"../result/result\"\nimport type { Context } from \"./context\"\nimport { runSync, runAsync } from \"./fx\"\nimport { FxTypeId } from \"./fx.types\"\nimport type { RunnableFx, SyncFx, AsyncFx, FxYield } from \"./fx.types\"\nimport type { Layer } from \"./layer.types\"\nimport { MemoMap } from \"./memo-map\"\nimport { createScope } from \"./scope\"\nimport type { ServiceClass } from \"./service\"\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 * const result = Fx.run(pipe(\n * updateDocumentWorkflow(userId, docId, data),\n * provide(AppLayer)\n * ))\n * ```\n */\nexport function provide<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 provide<ROut, E2>(layer: Layer<ROut, E2>) {\n return <A, E, R extends ROut>(fx: RunnableFx<A, E, R>): RunnableFx<A, E | E2> => {\n // Determine if the layer or fx is async\n const memoMap = new MemoMap()\n const scope = createScope()\n const layerBuildFx = layer.build(memoMap, scope)\n\n if (layerBuildFx._tag === \"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 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) {\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) {\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) {\n const yielded = fxResult.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n // oxlint-disable-next-line no-await-in-loop\n fxResult = await fxGen.next(service)\n continue\n }\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) {\n const yielded = fxResult.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\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 try {\n // Build the layer\n const layerGen = layerBuildFx[Symbol.iterator]()\n let layerResult = layerGen.next()\n\n while (!layerResult.done) {\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) {\n const yielded = fxResult.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\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, never>)\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 * const ctx = Context.make(Config, configImpl)\n * const result = Fx.run(pipe(\n * myWorkflow,\n * provideContext(ctx)\n * ))\n * ```\n */\nexport const provideContext =\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) {\n const yielded = result.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceClass<unknown>).key}\" not found`)\n }\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(service)\n } else {\n yield yielded as E\n // oxlint-disable-next-line no-await-in-loop\n result = await gen.next(undefined)\n }\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) {\n const yielded = result.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded\n ) {\n const service = ctx._services.get((yielded as ServiceClass<unknown>).key)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceClass<unknown>).key}\" not found`)\n }\n result = gen.next(service)\n } else {\n yield yielded as E\n result = gen.next(undefined)\n }\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 * const result = Fx.run(pipe(\n * myWorkflow,\n * provideService(Config, configImpl),\n * provideService(Logger, loggerImpl),\n * ))\n * ```\n */\nexport const provideService =\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) {\n const yielded = result.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded &&\n (yielded as ServiceClass<unknown>).key === service.key\n ) {\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) {\n const yielded = result.value\n\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"Service\" &&\n \"key\" in yielded &&\n (yielded as ServiceClass<unknown>).key === service.key\n ) {\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"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/fx/fx.types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Unique symbol for Fx type identification.
|
|
4
|
+
*/
|
|
5
|
+
const FxTypeId = Symbol.for("@repo/std/fx/FxTypeId");
|
|
6
|
+
/**
|
|
7
|
+
* Check if a value is a ServiceRequest.
|
|
8
|
+
*/
|
|
9
|
+
const isServiceRequest = (value) => typeof value === "object" && value !== null && "_tag" in value && value._tag === "ServiceRequest";
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { isServiceRequest as n, FxTypeId as t };
|
|
13
|
+
//# sourceMappingURL=fx.types-DpIQILok.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fx.types-DpIQILok.mjs","names":[],"sources":["../src/fx/fx.types.ts"],"sourcesContent":["// ============================================================================\n// Service Request\n// ============================================================================\n\n/**\n * Unique symbol for Fx type identification.\n */\nexport const FxTypeId: unique symbol = Symbol.for(\"@repo/std/fx/FxTypeId\")\nexport type FxTypeId = typeof FxTypeId\n\n/**\n * Fx<A, E, R> is the base protocol for all effect types.\n * Explicitly carries type parameters for proper inference in generators.\n *\n * @template A - Success value type\n * @template E - Error type\n * @template R - Requirements type (services needed)\n */\nexport type Fx<out A, out E = never, out R = never> = {\n readonly [FxTypeId]: {\n readonly _A: () => A\n readonly _E: () => E\n readonly _R: () => R\n }\n}\n\n/**\n * ServiceRequest is yielded when accessing a service via yield*.\n * The runtime intercepts these and injects the service from context.\n * Implements Fx protocol with A=S, E=never, R=S (requires service S to produce S).\n */\nexport type ServiceRequest<S> = Fx<S, never, S> & {\n readonly _tag: \"ServiceRequest\"\n /** Phantom type for service identification */\n readonly _service: S\n readonly serviceKey: string\n}\n\n/**\n * Check if a value is a ServiceRequest.\n */\nexport const isServiceRequest = (value: unknown): value is ServiceRequest<unknown> =>\n typeof value === \"object\" && value !== null && \"_tag\" in value && value._tag === \"ServiceRequest\"\n\n/**\n * Extract the success type from an Fx.\n */\nexport type FxValue<T> = T extends Fx<infer A, unknown, unknown> ? A : never\n\n/**\n * Extract the error type from an Fx.\n */\nexport type FxError<T> = T extends Fx<unknown, infer E, unknown> ? E : never\n\n/**\n * Extract the requirements type from an Fx.\n */\nexport type FxRequirements<T> = T extends Fx<unknown, unknown, infer R> ? R : never\n\n// ============================================================================\n// Core Fx Types\n// ============================================================================\n\n/**\n * The type yielded by Fx generators at runtime.\n *\n * This union represents what flows through generator yield points:\n * - E: Error values that propagate through the computation\n * - ServiceClass<R>: Service requests that get intercepted and resolved from context\n *\n * Used for generator type annotations in Fx.gen(), provide(), and Layer implementations.\n */\nexport type FxYield<E, R> = E | ServiceClass<R>\n\n/**\n * ServiceClass type imported for FxYield.\n * This is a structural type that matches service classes.\n */\ntype ServiceClass<S> = Fx<S, never, S> & { _tag: \"Service\"; key: string }\n\n/**\n * SyncFx<A, E, R> represents a synchronous computation that:\n * - Produces a value of type A on success\n * - May fail with an error of type E\n * - Requires services of type R to run\n *\n * Use Fx.run() to execute when R = never (all dependencies provided).\n */\nexport type SyncFx<A, E = never, R = never> = Fx<A, E, R> & {\n readonly _tag: \"SyncFx\"\n\n /**\n * Iterator for yield* support in gen computations.\n * Yields error Results or ServiceClasses for service injection.\n */\n [Symbol.iterator](): Generator<FxYield<E, R>, A, unknown>\n}\n\n/**\n * AsyncFx<A, E, R> represents an asynchronous computation that:\n * - Produces a value of type A on success\n * - May fail with an error of type E\n * - Requires services of type R to run\n *\n * Use Fx.run() to execute when R = never (all dependencies provided).\n */\nexport type AsyncFx<A, E = never, R = never> = Fx<A, E, R> & {\n readonly _tag: \"AsyncFx\"\n\n /**\n * Async iterator for yield* support in async gen computations.\n * Yields error Results or ServiceClasses for service injection.\n */\n [Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, A, unknown>\n}\n\n/**\n * RunnableFx<A, E, R> is a union of executable Fx types (sync or async).\n * Use this for functions that execute effects like Fx.run().\n */\nexport type RunnableFx<A, E = never, R = never> = SyncFx<A, E, R> | AsyncFx<A, E, R>\n\n// ============================================================================\n// Type Extractors\n// ============================================================================\n\n/**\n * Extract the success type from an Fx.\n * @deprecated Use FxValue instead\n */\nexport type FxSuccess<T> = T extends Fx<infer A, unknown, unknown> ? A : never\n\n// ============================================================================\n// Generator Types for Fx\n// ============================================================================\n\n/**\n * Sync generator type for Fx.gen.\n * Yields error Results or ServiceClasses, returns value of type A.\n */\nexport type FxGenerator<A, E, R> = Generator<FxYield<E, R>, A, unknown>\n\n/**\n * Async generator type for Fx.gen.\n * Yields error Results or ServiceClasses, returns value of type A.\n */\nexport type AsyncFxGenerator<A, E, R> = AsyncGenerator<FxYield<E, R>, A, unknown>\n\n// ============================================================================\n// Yieldable Types (for compatibility with existing gen module)\n// ============================================================================\n\n/**\n * FxYieldable extends the existing Yieldable protocol to support Fx values.\n */\nexport type FxYieldable<A, E = never, R = never> = Fx<A, E, R> & {\n [Symbol.iterator](): Generator<FxYield<E, R>, A, unknown>\n}\n\n/**\n * AsyncFxYieldable for async computations with Fx values.\n */\nexport type AsyncFxYieldable<A, E = never, R = never> = Fx<A, E, R> & {\n [Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, A, unknown>\n}\n"],"mappings":";;;;AAOA,MAAa,WAA0B,OAAO,IAAI,wBAAwB;;;;AAkC1E,MAAa,oBAAoB,UAC/B,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,SAAS,MAAM,SAAS"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
//#region src/fx/fx.types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Unique symbol for Fx type identification.
|
|
4
|
+
*/
|
|
5
|
+
declare const FxTypeId: unique symbol;
|
|
6
|
+
type FxTypeId = typeof FxTypeId;
|
|
7
|
+
/**
|
|
8
|
+
* Fx<A, E, R> is the base protocol for all effect types.
|
|
9
|
+
* Explicitly carries type parameters for proper inference in generators.
|
|
10
|
+
*
|
|
11
|
+
* @template A - Success value type
|
|
12
|
+
* @template E - Error type
|
|
13
|
+
* @template R - Requirements type (services needed)
|
|
14
|
+
*/
|
|
15
|
+
type Fx<out A, out E = never, out R = never> = {
|
|
16
|
+
readonly [FxTypeId]: {
|
|
17
|
+
readonly _A: () => A;
|
|
18
|
+
readonly _E: () => E;
|
|
19
|
+
readonly _R: () => R;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* ServiceRequest is yielded when accessing a service via yield*.
|
|
24
|
+
* The runtime intercepts these and injects the service from context.
|
|
25
|
+
* Implements Fx protocol with A=S, E=never, R=S (requires service S to produce S).
|
|
26
|
+
*/
|
|
27
|
+
type ServiceRequest<S> = Fx<S, never, S> & {
|
|
28
|
+
readonly _tag: "ServiceRequest";
|
|
29
|
+
/** Phantom type for service identification */
|
|
30
|
+
readonly _service: S;
|
|
31
|
+
readonly serviceKey: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Check if a value is a ServiceRequest.
|
|
35
|
+
*/
|
|
36
|
+
declare const isServiceRequest: (value: unknown) => value is ServiceRequest<unknown>;
|
|
37
|
+
/**
|
|
38
|
+
* Extract the success type from an Fx.
|
|
39
|
+
*/
|
|
40
|
+
type FxValue<T> = T extends Fx<infer A, unknown, unknown> ? A : never;
|
|
41
|
+
/**
|
|
42
|
+
* Extract the error type from an Fx.
|
|
43
|
+
*/
|
|
44
|
+
type FxError<T> = T extends Fx<unknown, infer E, unknown> ? E : never;
|
|
45
|
+
/**
|
|
46
|
+
* Extract the requirements type from an Fx.
|
|
47
|
+
*/
|
|
48
|
+
type FxRequirements<T> = T extends Fx<unknown, unknown, infer R> ? R : never;
|
|
49
|
+
/**
|
|
50
|
+
* The type yielded by Fx generators at runtime.
|
|
51
|
+
*
|
|
52
|
+
* This union represents what flows through generator yield points:
|
|
53
|
+
* - E: Error values that propagate through the computation
|
|
54
|
+
* - ServiceClass<R>: Service requests that get intercepted and resolved from context
|
|
55
|
+
*
|
|
56
|
+
* Used for generator type annotations in Fx.gen(), provide(), and Layer implementations.
|
|
57
|
+
*/
|
|
58
|
+
type FxYield<E, R> = E | ServiceClass<R>;
|
|
59
|
+
/**
|
|
60
|
+
* ServiceClass type imported for FxYield.
|
|
61
|
+
* This is a structural type that matches service classes.
|
|
62
|
+
*/
|
|
63
|
+
type ServiceClass<S> = Fx<S, never, S> & {
|
|
64
|
+
_tag: "Service";
|
|
65
|
+
key: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* SyncFx<A, E, R> represents a synchronous computation that:
|
|
69
|
+
* - Produces a value of type A on success
|
|
70
|
+
* - May fail with an error of type E
|
|
71
|
+
* - Requires services of type R to run
|
|
72
|
+
*
|
|
73
|
+
* Use Fx.run() to execute when R = never (all dependencies provided).
|
|
74
|
+
*/
|
|
75
|
+
type SyncFx<A, E = never, R = never> = Fx<A, E, R> & {
|
|
76
|
+
readonly _tag: "SyncFx";
|
|
77
|
+
/**
|
|
78
|
+
* Iterator for yield* support in gen computations.
|
|
79
|
+
* Yields error Results or ServiceClasses for service injection.
|
|
80
|
+
*/
|
|
81
|
+
[Symbol.iterator](): Generator<FxYield<E, R>, A, unknown>;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* AsyncFx<A, E, R> represents an asynchronous computation that:
|
|
85
|
+
* - Produces a value of type A on success
|
|
86
|
+
* - May fail with an error of type E
|
|
87
|
+
* - Requires services of type R to run
|
|
88
|
+
*
|
|
89
|
+
* Use Fx.run() to execute when R = never (all dependencies provided).
|
|
90
|
+
*/
|
|
91
|
+
type AsyncFx<A, E = never, R = never> = Fx<A, E, R> & {
|
|
92
|
+
readonly _tag: "AsyncFx";
|
|
93
|
+
/**
|
|
94
|
+
* Async iterator for yield* support in async gen computations.
|
|
95
|
+
* Yields error Results or ServiceClasses for service injection.
|
|
96
|
+
*/
|
|
97
|
+
[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, A, unknown>;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* RunnableFx<A, E, R> is a union of executable Fx types (sync or async).
|
|
101
|
+
* Use this for functions that execute effects like Fx.run().
|
|
102
|
+
*/
|
|
103
|
+
type RunnableFx<A, E = never, R = never> = SyncFx<A, E, R> | AsyncFx<A, E, R>;
|
|
104
|
+
/**
|
|
105
|
+
* Extract the success type from an Fx.
|
|
106
|
+
* @deprecated Use FxValue instead
|
|
107
|
+
*/
|
|
108
|
+
type FxSuccess<T> = T extends Fx<infer A, unknown, unknown> ? A : never;
|
|
109
|
+
/**
|
|
110
|
+
* Sync generator type for Fx.gen.
|
|
111
|
+
* Yields error Results or ServiceClasses, returns value of type A.
|
|
112
|
+
*/
|
|
113
|
+
type FxGenerator<A, E, R> = Generator<FxYield<E, R>, A, unknown>;
|
|
114
|
+
/**
|
|
115
|
+
* Async generator type for Fx.gen.
|
|
116
|
+
* Yields error Results or ServiceClasses, returns value of type A.
|
|
117
|
+
*/
|
|
118
|
+
type AsyncFxGenerator<A, E, R> = AsyncGenerator<FxYield<E, R>, A, unknown>;
|
|
119
|
+
/**
|
|
120
|
+
* FxYieldable extends the existing Yieldable protocol to support Fx values.
|
|
121
|
+
*/
|
|
122
|
+
type FxYieldable<A, E = never, R = never> = Fx<A, E, R> & {
|
|
123
|
+
[Symbol.iterator](): Generator<FxYield<E, R>, A, unknown>;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* AsyncFxYieldable for async computations with Fx values.
|
|
127
|
+
*/
|
|
128
|
+
type AsyncFxYieldable<A, E = never, R = never> = Fx<A, E, R> & {
|
|
129
|
+
[Symbol.asyncIterator](): AsyncGenerator<FxYield<E, R>, A, unknown>;
|
|
130
|
+
};
|
|
131
|
+
//#endregion
|
|
132
|
+
export { FxError as a, FxSuccess as c, FxYield as d, FxYieldable as f, isServiceRequest as g, SyncFx as h, Fx as i, FxTypeId as l, ServiceRequest as m, AsyncFxGenerator as n, FxGenerator as o, RunnableFx as p, AsyncFxYieldable as r, FxRequirements as s, AsyncFx as t, FxValue as u };
|
|
133
|
+
//# sourceMappingURL=fx.types-aTmhyidu.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fx.types-aTmhyidu.d.mts","names":[],"sources":["../src/fx/fx.types.ts"],"sourcesContent":[],"mappings":"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"}
|