@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
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
//#region src/predicate/predicate.types.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* A predicate function that tests a value and returns a boolean.
|
|
4
|
-
*
|
|
5
|
-
* @template T - The type of value being tested
|
|
6
|
-
*/
|
|
7
|
-
type Predicate$1<T> = (value: T) => boolean;
|
|
8
|
-
/**
|
|
9
|
-
* A refinement predicate that narrows type T to subtype U.
|
|
10
|
-
* This is a type guard - when it returns true, TypeScript knows
|
|
11
|
-
* the value is of the narrower type U.
|
|
12
|
-
*
|
|
13
|
-
* @template T - The base type
|
|
14
|
-
* @template U - The narrower type (must extend T)
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```ts
|
|
18
|
-
* // Built-in refinement
|
|
19
|
-
* const isString: Refinement<unknown, string> = (v): v is string =>
|
|
20
|
-
* typeof v === "string"
|
|
21
|
-
*
|
|
22
|
-
* // Usage with filter
|
|
23
|
-
* const mixed: (string | number)[] = ["a", 1, "b", 2]
|
|
24
|
-
* const strings: string[] = mixed.filter(isString)
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
type Refinement<T, U extends T> = (value: T) => value is U;
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/predicate/predicate.d.ts
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Predicate namespace containing composable boolean functions.
|
|
33
|
-
*
|
|
34
|
-
* Predicates are functions that test values and return booleans.
|
|
35
|
-
* This namespace provides combinators to build complex predicates
|
|
36
|
-
* from simple ones, with support for type guards (refinements).
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* import { Predicate, pipe } from "@repo/std"
|
|
41
|
-
*
|
|
42
|
-
* // Basic predicates
|
|
43
|
-
* const isPositive = (n: number) => n > 0
|
|
44
|
-
* const isEven = (n: number) => n % 2 === 0
|
|
45
|
-
*
|
|
46
|
-
* // Combine with and/or
|
|
47
|
-
* const isPositiveEven = Predicate.and(isPositive, isEven)
|
|
48
|
-
* const isZeroOrNegative = Predicate.or(Predicate.equals(0), Predicate.not(isPositive))
|
|
49
|
-
*
|
|
50
|
-
* // Array predicates
|
|
51
|
-
* const allPositive = Predicate.all(isPositive)
|
|
52
|
-
* const hasNegative = Predicate.some(Predicate.not(isPositive))
|
|
53
|
-
*
|
|
54
|
-
* // Use with filter
|
|
55
|
-
* [1, 2, 3, 4, 5].filter(isPositiveEven) // [2, 4]
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
declare const Predicate: {
|
|
59
|
-
readonly not: <T>(predicate: Predicate$1<T>) => Predicate$1<T>;
|
|
60
|
-
readonly and: <T>(...predicates: readonly Predicate$1<T>[]) => Predicate$1<T>;
|
|
61
|
-
readonly or: <T>(...predicates: readonly Predicate$1<T>[]) => Predicate$1<T>;
|
|
62
|
-
readonly all: <T>(predicate: Predicate$1<T>) => Predicate$1<readonly T[]>;
|
|
63
|
-
readonly some: <T>(predicate: Predicate$1<T>) => Predicate$1<readonly T[]>;
|
|
64
|
-
readonly none: <T>(predicate: Predicate$1<T>) => Predicate$1<readonly T[]>;
|
|
65
|
-
readonly andRefinement: <T, U extends T>(...refinements: readonly Refinement<T, U>[]) => Refinement<T, U>;
|
|
66
|
-
readonly orRefinement: <T, U extends T>(...refinements: readonly Refinement<T, U>[]) => Refinement<T, U>;
|
|
67
|
-
readonly constant: <T>(value: boolean) => Predicate$1<T>;
|
|
68
|
-
readonly equals: <T>(expected: T) => Predicate$1<T>;
|
|
69
|
-
};
|
|
70
|
-
//#endregion
|
|
71
|
-
export { Predicate$1 as n, Refinement as r, Predicate as t };
|
|
72
|
-
//# sourceMappingURL=index-DbfMra4p.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DbfMra4p.d.mts","names":[],"sources":["../src/predicate/predicate.types.ts","../src/predicate/predicate.ts"],"sourcesContent":[],"mappings":";;AAKA;AAqBA;;;AAAgE,KArBpD,WAqBoD,CAAA,CAAA,CAAA,GAAA,CAAA,KAAA,EArB7B,CAqB6B,EAAA,GAAA,OAAA;;;;;AC8QhE;;;;;;;;;;;;;;;AA5L4E,KDlFhE,UCkFgE,CAAA,CAAA,EAAA,UDlFxC,CCkFwC,CAAA,GAAA,CAAA,KAAA,EDlF3B,CCkF2B,EAAA,GAAA,KAAA,IDlFZ,CCkFY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4L/D;+BAlRqB,YAAc,OAAK,YAAc;4CA0BpB,YAAc,SAAO,YAAc;2CA8BpC,YAAc,SAAO,YAAc;+BA8B/C,YAAc,OAAK,qBAAuB;gCAsBzC,YAAc,OAAK,qBAAuB;gCAuB1C,YAAc,OAAK,qBAAuB;wCA8BlC,4BAA4B,WAAW,GAAG,SAAO,WAAW,GAAG;uCA8BhE,4BAA4B,WAAW,GAAG,SAAO,WAAW,GAAG;4CA0B5D,YAAc;iCA0BvB,MAAI,YAAc"}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["resultErr","resultOk","gen","result","service","impl","ctx","gen","layerGen","layerResult","gen","gen","fxGen","fxResult","resultErr"],"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","../src/std.ts"],"sourcesContent":["import { ok as resultOk, err as resultErr } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport type { Fx as FxType, SyncFx, AsyncFx, FxGenerator, AsyncFxGenerator, ServiceRequest } from \"./fx.types\"\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 A - The success value type\n * @template E - The error type\n * @template R - The required services type\n * @param generatorFn - A function that returns a sync generator\n * @returns SyncFx<A, E, R>\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: Fx<User[], DatabaseError, Database | Logger>\n *\n * // Execute later with dependencies provided\n * const result = pipe(getUser(\"123\"), provide(AppLayer)).run()\n * ```\n */\nfunction fxGen<A, E, R>(generatorFn: () => FxGenerator<A, E, R>): SyncFx<A, E, R>\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 A - The success value type\n * @template E - The error type\n * @template R - The required services type\n * @param generatorFn - A function that returns an async generator\n * @returns AsyncFx<A, E, R>\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: Fx<unknown, Error, Logger>\n * ```\n */\nfunction fxGen<A, E, R>(generatorFn: () => AsyncFxGenerator<A, E, R>): AsyncFx<A, E, R>\n\n/**\n * Implementation of unified Fx.gen function.\n * Detects sync vs async generator and returns appropriate computation type.\n */\nfunction fxGen<A, E, R>(\n generatorFn: () => FxGenerator<A, E, R> | AsyncFxGenerator<A, E, R>,\n): SyncFx<A, E, R> | AsyncFx<A, E, R> {\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 run: async () => {\n const gen = generatorFn() as AsyncFxGenerator<A, E, R>\n const result = await gen.next()\n\n if (result.done !== true) {\n // Yielded value is either an error or service request\n const yielded = result.value\n if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"ServiceRequest\"\n ) {\n throw new Error(`Service \"${yielded.serviceKey}\" not provided. Use provide() to inject services.`)\n }\n return resultErr(yielded as E)\n }\n\n return resultOk(result.value)\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<R>, A, unknown> {\n const gen = generatorFn() as AsyncFxGenerator<A, E, R>\n let result = await gen.next()\n\n while (!result.done) {\n // Pass through yields (errors or service requests)\n const injected = yield result.value\n result = await gen.next(injected)\n }\n\n return result.value\n },\n } as AsyncFx<A, E, R>\n }\n\n // Sync generator\n return {\n _tag: \"SyncFx\",\n run: () => {\n const gen = generatorFn() as FxGenerator<A, E, R>\n const result = gen.next()\n\n if (result.done !== true) {\n const yielded = result.value\n if (typeof yielded === \"object\" && yielded !== null && \"_tag\" in yielded && yielded._tag === \"ServiceRequest\") {\n throw new Error(`Service \"${yielded.serviceKey}\" not provided. Use provide() to inject services.`)\n }\n return resultErr(yielded as E)\n }\n\n return resultOk(result.value)\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<R>, A, unknown> {\n const gen = generatorFn() as FxGenerator<A, E, R>\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 } as SyncFx<A, E, R>\n}\n\n// ============================================================================\n// Fx.fn - Execute computations immediately\n// ============================================================================\n\n/**\n * Execute a sync computation immediately and return the result.\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>\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, never>\n * // result = { ok: true, value: 30 }\n * ```\n */\nfunction fxFn<A, E>(generatorFn: () => FxGenerator<A, E, never>): Result<A, E>\n\n/**\n * Execute an async computation immediately and return a Promise of the result.\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>>\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>>\n * ```\n */\nfunction fxFn<A, E>(generatorFn: () => AsyncFxGenerator<A, E, never>): Promise<Result<A, E>>\n\n/**\n * Execute a sync computation with service dependencies immediately.\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>\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, never>\n * ```\n */\nfunction fxFn<A, E, E2, R>(\n generatorFn: () => FxGenerator<A, E, R>,\n provider: (fx: FxType<A, E, R>) => FxType<A, E | E2, never>,\n): Result<A, E | E2>\n\n/**\n * Execute an async computation with service dependencies immediately.\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>>\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, never>>\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: FxType<A, E, R>) => FxType<A, E | E2, never>,\n): Promise<Result<A, E | E2>>\n\n/**\n * Implementation of Fx.fn.\n */\nfunction fxFn<A, E, E2, R>(\n generatorFn: () => FxGenerator<A, E, R> | AsyncFxGenerator<A, E, R>,\n provider?: (fx: FxType<A, E, R>) => FxType<A, E | E2, never>,\n): Result<A, E | E2> | Promise<Result<A, E | E2>> {\n const testGen = generatorFn()\n const isAsync = Symbol.asyncIterator in testGen\n\n // If a provider is given, create the Fx, apply provider, then run\n if (provider) {\n if (isAsync) {\n const fx: AsyncFx<A, E, R> = {\n _tag: \"AsyncFx\",\n run: async () => {\n throw new Error(\"Should not be called directly - use provider\")\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<R>, A, unknown> {\n const gen = generatorFn() as AsyncFxGenerator<A, E, R>\n let result = await gen.next()\n\n while (!result.done) {\n const injected = yield result.value\n result = await gen.next(injected)\n }\n\n return result.value\n },\n }\n\n const provided = provider(fx)\n return provided.run()\n } else {\n const fx: SyncFx<A, E, R> = {\n _tag: \"SyncFx\",\n run: () => {\n throw new Error(\"Should not be called directly - use provider\")\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<R>, A, unknown> {\n const gen = generatorFn() as FxGenerator<A, E, R>\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 const provided = provider(fx)\n return provided.run()\n }\n }\n\n // No provider - execute directly (R must be never)\n if (isAsync) {\n return (async () => {\n const gen = generatorFn() as AsyncFxGenerator<A, E, never>\n let result = await gen.next()\n\n while (!result.done) {\n // For fn() without provider, there should be no service requests (R = never)\n // Only errors can be yielded\n return resultErr(result.value as E)\n }\n\n return resultOk(result.value)\n })()\n }\n\n const gen = generatorFn() as FxGenerator<A, E, never>\n let result = gen.next()\n\n while (!result.done) {\n return resultErr(result.value as E)\n }\n\n return resultOk(result.value)\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 ok = fxOk\nexport const err = fxErr\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.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 = pipe(myWorkflow, provide(AppLayer)).run()\n * ```\n */\nexport const Fx = {\n gen: fxGen,\n fn: fxFn,\n ok: fxOk,\n err: fxErr,\n} as const\n","import type { ServiceRequest } 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 */\nexport type ServiceClass<Self, Key extends string = string> = {\n readonly _tag: \"Service\"\n readonly key: Key\n readonly _Self: Self // Phantom type\n\n /**\n * Yielding the service class in a gen computation\n * returns the service instance from context.\n */\n [Symbol.iterator](): Generator<ServiceRequest<Self>, 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 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 /**\n * Yielding the class returns a ServiceRequest.\n * The runtime intercepts this and provides the actual service instance.\n */\n static *[Symbol.iterator](): Generator<ServiceRequest<Self>, Self, Self> {\n const serviceInstance = yield {\n _tag: \"ServiceRequest\",\n _service: undefined as unknown as Self,\n serviceKey: key,\n }\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 return {\n _tag: \"Service\",\n key,\n _Self: undefined as unknown as S,\n *[Symbol.iterator](): Generator<ServiceRequest<S>, S, S> {\n const serviceInstance = yield {\n _tag: \"ServiceRequest\",\n _service: undefined as unknown as S,\n serviceKey: key,\n }\n return serviceInstance\n },\n }\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 readonly _Services: Services // Phantom type for tracking available 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 { ok } from \"../result/result\"\nimport { Context } from \"./context\"\nimport type { Fx, SyncFx, AsyncFx, ServiceRequest } from \"./fx.types\"\nimport type { Layer as LayerType, MergeROut, MergeError, UnprovidedDeps } 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 */\n// oxlint-disable-next-line no-redundant-type-constituents\nconst layerOk = <S>(service: ServiceClass<S>, impl: S): LayerType<S, never> => ({\n _tag: \"Layer\",\n _ROut: undefined as unknown as S,\n _E: undefined as never,\n _RIn: undefined as never,\n build: (): Fx<Context<S>, never> => ({\n _tag: \"SyncFx\",\n run: () => ok(Context.make(service, impl)),\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> => ({\n _tag: \"Layer\",\n _ROut: undefined as never,\n _E: undefined as unknown as E,\n _RIn: undefined as never,\n build: (): Fx<Context, E> => ({\n _tag: \"SyncFx\",\n run: () => ({\n ok: false,\n error,\n *[Symbol.iterator]() {\n yield error\n throw new Error(\"Unreachable\")\n },\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 */\nconst layerFx =\n <S>(service: ServiceClass<S>) =>\n <E, R>(fx: Fx<S, E, R>): LayerType<S, E, R> => ({\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 build: (): Fx<Context<S>, E, R> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n run: async () => {\n throw new Error(\"Layer build should use iterator\")\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<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 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 run: () => {\n throw new Error(\"Layer build should use iterator\")\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<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 * Create a scoped layer (with resource cleanup).\n */\nconst layerScoped =\n <S>(service: ServiceClass<S>) =>\n <E, R>(fx: Fx<S, E, R | ScopeService>): LayerType<S, E, ExcludeScope<R>> => ({\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 build: (_memoMap, scope): Fx<Context<S>, E, ExcludeScope<R>> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n run: async () => {\n throw new Error(\"Layer build should use iterator\")\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === \"@std/Scope\"\n ) {\n result = await gen.next(scope)\n } else {\n const value = yield yielded as E | ServiceRequest<ExcludeScope<R>>\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 run: () => {\n throw new Error(\"Layer build should use iterator\")\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === \"@std/Scope\"\n ) {\n result = gen.next(scope)\n } else {\n const value = yield yielded as E | ServiceRequest<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// Layer Composition\n// ============================================================================\n\n/**\n * Provide dependencies to a layer and merge outputs.\n */\nconst layerProvide =\n <DepsROut, DepsE, DepsRIn>(deps: LayerType<DepsROut, DepsE, DepsRIn>) =>\n <ROut, E, RIn extends DepsROut>(layer: LayerType<ROut, E, RIn>): LayerType<ROut | DepsROut, E | DepsE, DepsRIn> => ({\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 build: (memoMap, scope): Fx<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 run: async () => {\n throw new Error(\"Layer build should use iterator\")\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n E | DepsE | ServiceRequest<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 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 === \"ServiceRequest\"\n ) {\n const service = depsCtx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n layerResult = await layerGen.next(service)\n continue\n }\n }\n const value = yield yielded as E | ServiceRequest<DepsRIn>\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 === \"ServiceRequest\"\n ) {\n const service = depsCtx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n layerResult = layerGen.next(service)\n continue\n }\n }\n const value = yield yielded as E | ServiceRequest<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 run: () => {\n throw new Error(\"Layer build should use iterator\")\n },\n *[Symbol.iterator](): Generator<E | DepsE | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = depsCtx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n layerResult = syncGen.next(service)\n continue\n }\n }\n const value = yield yielded as E | ServiceRequest<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 * Merge multiple layers with automatic dependency resolution.\n */\nconst layerMerge = <L extends LayerType<unknown, unknown, unknown>[]>(\n ...layers: L\n): LayerType<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>> => ({\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 build: (memoMap, scope): Fx<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 run: async () => {\n throw new Error(\"Layer build should use iterator\")\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<\n MergeError<L> | ServiceRequest<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 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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n result = await gen.next(service)\n continue\n }\n }\n const value = yield yielded as MergeError<L> | ServiceRequest<UnprovidedDeps<L>>\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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n }\n const value = yield yielded as MergeError<L> | ServiceRequest<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 run: () => {\n throw new Error(\"Layer build should use iterator\")\n },\n *[Symbol.iterator](): Generator<\n MergeError<L> | ServiceRequest<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 !== \"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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n result = gen.next(service)\n continue\n }\n }\n const value = yield yielded as MergeError<L> | ServiceRequest<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// 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 { ok } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport type { SyncFx, AsyncFx, ServiceRequest } 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, never> | AsyncFx<void, never>): SyncFx<void, never>\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, never> | AsyncFx<void, never>\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, never> | AsyncFx<void, never>\n const finalizers: Finalizer[] = []\n let closed = false\n const children: ScopeService[] = []\n\n const scope: ScopeService = {\n addFinalizer(finalizer: Finalizer): SyncFx<void, never> {\n return {\n _tag: \"SyncFx\",\n get run() {\n return (() => {\n if (!closed) {\n finalizers.push(finalizer)\n }\n return ok(undefined)\n }) as () => Result<void, never>\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<ServiceRequest<never>, void, unknown> {\n if (!closed) {\n finalizers.push(finalizer)\n }\n },\n } as SyncFx<void, never>\n },\n\n close(exit: Result<unknown, unknown>): SyncFx<void, never> | AsyncFx<void, never> {\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 get run() {\n return (async () => {\n if (closed) return ok(undefined)\n closed = true\n\n // Close children first (in reverse order)\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n if (childClose._tag === \"AsyncFx\") {\n await (childClose.run as () => Promise<Result<void, never>>)()\n } else {\n ;(childClose.run as () => Result<void, never>)()\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 await (fx.run as () => Promise<Result<void, never>>)()\n } else {\n ;(fx.run as () => Result<void, never>)()\n }\n }\n\n return ok(undefined)\n }) as () => Promise<Result<void, never>>\n },\n // oxlint-disable-next-line require-yield\n async *[Symbol.asyncIterator](): AsyncGenerator<ServiceRequest<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 await (childClose.run as () => Promise<Result<void, never>>)()\n } else {\n ;(childClose.run as () => Result<void, never>)()\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 await (fx.run as () => Promise<Result<void, never>>)()\n } else {\n ;(fx.run as () => Result<void, never>)()\n }\n }\n },\n } as AsyncFx<void, never>\n }\n\n // Sync version\n return {\n _tag: \"SyncFx\",\n get run() {\n return (() => {\n if (closed) return ok(undefined)\n closed = true\n\n // Close children first\n for (const child of [...children].toReversed()) {\n const childClose = child.close(exit)\n ;(childClose.run as () => Result<void, never>)()\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n // oxlint-disable-next-line no-redundant-type-constituents\n ;(fx.run as () => Result<void, never>)()\n }\n\n return ok(undefined)\n }) as () => Result<void, never>\n },\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<ServiceRequest<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 ;(childClose.run as () => Result<void, never>)()\n }\n\n // Run finalizers in LIFO order\n const reversed = [...finalizers].toReversed()\n for (const finalizer of reversed) {\n const fx = finalizer()\n ;(fx.run as () => Result<void, never>)()\n }\n },\n } as SyncFx<void, never>\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 type { Fx, SyncFx, AsyncFx, ServiceRequest } from \"./fx.types\"\nimport type { Layer } from \"./layer.types\"\nimport type { ScopeService } from \"./scope\"\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 An Fx producing the layer's context\n */\n getOrBuild<ROut, E, RIn>(layer: Layer<ROut, E, RIn>, scope: ScopeService, deps: Context<RIn>): Fx<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 run: () => ok(cached.context as Context<ROut>),\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<E | ServiceRequest<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 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<E | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = deps._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(\n `Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found during layer build`,\n )\n }\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 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<E | ServiceRequest<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 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 === \"ServiceRequest\"\n ) {\n const service = deps._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(\n `Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found during layer build`,\n )\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<E | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = deps._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(\n `Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found during layer build`,\n )\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, err as resultErr } from \"../result/result\"\nimport type { Result } from \"../result/result.types\"\nimport type { Context } from \"./context\"\nimport type { Fx, SyncFx, AsyncFx, ServiceRequest } 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 * Provide a layer to an Fx computation, resolving all service requirements.\n * Creates a new scope for resource management.\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 = pipe(\n * updateDocumentWorkflow(userId, docId, data),\n * provide(AppLayer)\n * ).run()\n * ```\n */\nexport const provide =\n <ROut, E2>(layer: Layer<ROut, E2>) =>\n <A, E, R extends ROut>(fx: Fx<A, E, R>): Fx<A, E | E2, never> => {\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 get run() {\n return (async () => {\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 // Layer should have no requirements, but handle just in case\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 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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n fxResult = await fxGen.next(service)\n } else {\n // It's an error\n return resultErr(yielded as E)\n }\n }\n\n return ok(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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n fxResult = fxGen.next(service)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(fxResult.value)\n } finally {\n // Close scope\n const closeResult = scope.close({ _tag: \"Success\", value: undefined })\n if (closeResult._tag === \"AsyncFx\") {\n await (closeResult.run as () => Promise<Result<void, never>>)()\n } else {\n ;(closeResult.run as () => Result<void, never>)()\n }\n }\n }) as () => Promise<Result<A, E | E2>>\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | E2 | ServiceRequest<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 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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n fxResult = await fxGen.next(service)\n continue\n }\n }\n\n // Pass through (error or unsatisfied service)\n const value = yield yielded as E | ServiceRequest<Exclude<R, ROut>>\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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\n }\n\n const value = yield yielded as E | ServiceRequest<Exclude<R, ROut>>\n fxResult = fxGen.next(value)\n }\n\n return fxResult.value\n } finally {\n const closeResult = scope.close({ _tag: \"Success\", value: undefined })\n if (closeResult._tag === \"AsyncFx\") {\n await (closeResult.run as () => Promise<Result<void, never>>)()\n } else {\n ;(closeResult.run as () => Result<void, never>)()\n }\n }\n },\n } as AsyncFx<A, E | E2>\n }\n\n // Both sync\n return {\n _tag: \"SyncFx\",\n get run() {\n return (() => {\n try {\n // Build the layer\n const layerGen = layerBuildFx[Symbol.iterator]()\n let layerResult = layerGen.next()\n\n while (!layerResult.done) {\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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n fxResult = fxGen.next(service)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(fxResult.value)\n } finally {\n const closeResult = scope.close({ _tag: \"Success\", value: undefined })\n ;(closeResult.run as () => Result<void, never>)()\n }\n }) as () => Result<A, E | E2>\n },\n *[Symbol.iterator](): Generator<E | E2 | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service !== undefined) {\n fxResult = fxGen.next(service)\n continue\n }\n }\n\n const value = yield yielded as E | ServiceRequest<Exclude<R, ROut>>\n fxResult = fxGen.next(value)\n }\n\n return fxResult.value\n } finally {\n const closeResult = scope.close({ _tag: \"Success\", value: undefined })\n ;(closeResult.run as () => Result<void, never>)()\n }\n },\n } as SyncFx<A, E | E2>\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 = pipe(\n * myWorkflow,\n * provideContext(ctx)\n * ).run()\n * ```\n */\nexport const provideContext =\n <R>(ctx: Context<R>) =>\n <A, E>(fx: Fx<A, E, R>): Fx<A, E> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n get run() {\n return (async () => {\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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n result = await gen.next(service)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(result.value)\n }) as () => Promise<Result<A, E>>\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n result = await gen.next(service)\n } else {\n yield yielded as E\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 get run() {\n return (() => {\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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n }\n result = gen.next(service)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(result.value)\n }) as () => Result<A, E>\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<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 === \"ServiceRequest\"\n ) {\n const service = ctx._services.get((yielded as ServiceRequest<unknown>).serviceKey)\n if (service === undefined) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" 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 = pipe(\n * myWorkflow,\n * provideService(Config, configImpl),\n * provideService(Logger, loggerImpl),\n * ).run()\n * ```\n */\nexport const provideService =\n <S>(service: ServiceClass<S>, impl: S) =>\n <A, E, R>(fx: Fx<A, E, R | S>): Fx<A, E, Exclude<R, S>> => {\n if (fx._tag === \"AsyncFx\") {\n return {\n _tag: \"AsyncFx\",\n get run() {\n return (async () => {\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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === service.key\n ) {\n result = await gen.next(impl)\n } else if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"ServiceRequest\"\n ) {\n // Can't resolve - throw\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(result.value)\n }) as () => Promise<Result<A, E>>\n },\n async *[Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === service.key\n ) {\n result = await gen.next(impl)\n } else {\n const value = yield yielded as E | ServiceRequest<Exclude<R, S>>\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 get run() {\n return (() => {\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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === service.key\n ) {\n result = gen.next(impl)\n } else if (\n typeof yielded === \"object\" &&\n yielded !== null &&\n \"_tag\" in yielded &&\n yielded._tag === \"ServiceRequest\"\n ) {\n throw new Error(`Service \"${(yielded as ServiceRequest<unknown>).serviceKey}\" not found`)\n } else {\n return resultErr(yielded as E)\n }\n }\n\n return ok(result.value)\n }) as () => Result<A, E>\n },\n *[Symbol.iterator](): Generator<E | ServiceRequest<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 === \"ServiceRequest\" &&\n (yielded as ServiceRequest<unknown>).serviceKey === service.key\n ) {\n result = gen.next(impl)\n } else {\n const value = yield yielded as E | ServiceRequest<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","import { data, record } from \"./adt\"\nimport { Brand } from \"./brand\"\nimport { array, struct, tagged, tuple } from \"./data\"\nimport { Either } from \"./either\"\nimport { Err, TaggedError } from \"./err\"\nimport { flow } from \"./flow\"\nimport { fn } from \"./fn\"\nimport { Fx, Service, Layer, Context, Scope, provide } from \"./fx\"\nimport { gen } from \"./gen\"\nimport { Option } from \"./option\"\nimport { pipe } from \"./pipe\"\nimport { Predicate } from \"./predicate\"\nimport { Result } from \"./result\"\n\n/**\n * Main Std namespace containing all utility functions and types.\n */\nexport const Std = {\n array,\n data,\n flow,\n fn,\n gen,\n pipe,\n record,\n struct,\n tagged,\n tuple,\n // Spreading the result utilities since we want to make it a 1st class citizen\n ...Result,\n Option,\n Either,\n Err,\n TaggedError,\n Predicate,\n Brand,\n // Fx - Dependency injection system\n Fx,\n Service,\n Layer,\n Context,\n Scope,\n provide,\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"is-promise-BEl3eGZg.mjs","names":[],"sources":["../src/shared/is-promise.ts"],"sourcesContent":["/**\n * Check if a value is a Promise.\n */\nexport function isPromise(value: unknown): value is Promise<unknown> {\n return value instanceof Promise\n}\n"],"mappings":";;;;AAGA,SAAgB,UAAU,OAA2C;AACnE,QAAO,iBAAiB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"option-CKHDOVea.mjs","names":["NoneValue","values"],"sources":["../src/option/option.types.ts","../src/option/option.ts"],"sourcesContent":["import type { Yieldable } from \"../gen/gen.types\"\n\n// ============================================================================\n// None Type\n// ============================================================================\n\n/**\n * Marker type for Option's absence in the Do computation context.\n * When an Option is yielded in Do, None becomes part of the error union.\n */\nexport type None = { readonly __typename: \"None\" }\n\n/**\n * Singleton None value.\n */\nexport const None: None = { __typename: \"None\" }\n\n// ============================================================================\n// Option Type\n// ============================================================================\n\n/**\n * A discriminated union representing either a value (some) or absence (none).\n * Compatible with ts-pattern for exhaustive matching.\n * Implements Yieldable protocol for use in Do computations with yield*.\n */\nexport type Option<T> = Yieldable<T, None> & ({ readonly some: true; readonly value: T } | { readonly some: false })\n\n// ============================================================================\n// Async-aware transformation types\n// ============================================================================\n\n/**\n * Compute the return type of `map` based on whether fn returns a Promise.\n * - If fn returns Promise<U>, result is Promise<Option<U>>\n * - If fn returns U, result is Option<U>\n */\nexport type MapReturn<FnReturn> = FnReturn extends Promise<infer U> ? Promise<Option<U>> : Option<FnReturn>\n\n/**\n * Compute the return type of `flatMap` based on whether fn returns a Promise.\n * - If fn returns Promise<Option<U>>, result is Promise<Option<U>>\n * - If fn returns Option<U>, result is Option<U>\n */\nexport type FlatMapReturn<FnReturn> =\n FnReturn extends Promise<Option<infer U>> ? Promise<Option<U>> : FnReturn extends Option<infer U> ? Option<U> : never\n\n/**\n * Compute the return type of `tap` based on whether fn returns a Promise.\n * - If fn returns Promise<any>, result is Promise<Option<T>>\n * - If fn returns any, result is Option<T>\n * The result value is always unchanged.\n */\n// oxlint-disable-next-line no-explicit-any\nexport type TapReturn<FnReturn, T> = FnReturn extends Promise<any> ? Promise<Option<T>> : Option<T>\n\n/**\n * Compute the return type of `orElse` based on whether fn returns a Promise.\n * - If fn returns Promise<Option<U>>, result is Promise<Option<T | U>>\n * - If fn returns Option<U>, result is Option<T | U>\n */\nexport type OrElseReturn<FnReturn, T> =\n FnReturn extends Promise<Option<infer U>>\n ? Promise<Option<T | U>>\n : FnReturn extends Option<infer U>\n ? Option<T | U>\n : never\n\n/**\n * Compute the return type of `fromTry` based on whether fn returns a Promise.\n * - If fn returns Promise<T>, result is Promise<Option<T>>\n * - If fn returns T, result is Option<T>\n */\nexport type FromTryReturn<T> = T extends Promise<infer U> ? Promise<Option<U>> : Option<T>\n\n// ============================================================================\n// All/Combine types\n// ============================================================================\n\n/**\n * Extract the value type from an Option.\n * Uses structural matching to extract the value type from the some branch.\n */\nexport type OptionValue<O> = O extends { readonly some: true; readonly value: infer T } ? T : never\n\n/**\n * Compute return type for `all` with array input.\n * Preserves tuple structure and extracts value types from each position.\n */\nexport type AllArrayReturn<T extends readonly Option<unknown>[]> = Option<{\n -readonly [K in keyof T]: OptionValue<T[K]>\n}>\n\n/**\n * Compute return type for `all` with object input.\n * Preserves object structure and extracts value types from each key.\n */\nexport type AllObjectReturn<T extends Record<string, Option<unknown>>> = Option<{\n -readonly [K in keyof T]: OptionValue<T[K]>\n}>\n\n// ============================================================================\n// Function Interfaces for improved pipe inference\n// ============================================================================\n\n/**\n * Interface for flatMap - using method syntax improves generic inference in pipe chains.\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionFlatMap = {\n <A, B>(fn: (value: A) => Promise<Option<B>>): (option: Option<A>) => Promise<Option<B>>\n <A, B>(fn: (value: A) => Option<B>): (option: Option<A>) => Option<B>\n}\n\n/**\n * Interface for map function.\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionMap = {\n <A, B>(fn: (value: A) => Promise<B>): (option: Option<A>) => Promise<Option<B>>\n <A, B>(fn: (value: A) => B): (option: Option<A>) => Option<B>\n}\n\n/**\n * Interface for tap function.\n */\nexport type OptionTap = {\n <A, R>(fn: (value: A) => R): (option: Option<A>) => R extends Promise<unknown> ? Promise<Option<A>> : Option<A>\n}\n\n/**\n * Interface for orElse function.\n * Note: Async overload must come first for proper overload resolution.\n */\nexport type OptionOrElse = {\n <A, B>(fn: () => Promise<Option<B>>): (option: Option<A>) => Promise<Option<A | B>>\n <A, B>(fn: () => Option<B>): (option: Option<A>) => Option<A | B>\n}\n\n/**\n * Interface for filter function.\n */\nexport type OptionFilter = {\n <A>(predicate: (value: A) => boolean): (option: Option<A>) => Option<A>\n}\n","import { isPromise } from \"../shared/is-promise\"\nimport { None as NoneValue } from \"./option.types\"\nimport type {\n AllArrayReturn,\n AllObjectReturn,\n Option as OptionType,\n OptionFlatMap,\n OptionMap,\n OptionTap,\n OptionOrElse,\n OptionFilter,\n None,\n FromTryReturn,\n} from \"./option.types\"\n\n// ============================================================================\n// Constructors\n// ============================================================================\n\n/**\n * Create an Option with a value.\n *\n * @param value - The value to wrap\n * @returns An Option with some: true\n *\n * @example\n * ```ts\n * some(42) // { some: true, value: 42 }\n * ```\n */\nexport const some = <T>(value: T): OptionType<T> => ({\n some: true,\n value,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<None, T, unknown> {\n return value\n },\n})\n\n/**\n * Create an Option with no value.\n *\n * @returns An Option with some: false\n *\n * @example\n * ```ts\n * none() // { some: false }\n * ```\n */\nexport const none = <T>(): OptionType<T> => ({\n some: false,\n *[Symbol.iterator](): Generator<None, never, unknown> {\n yield NoneValue\n throw new Error(\"Unreachable: Do should short-circuit on None\")\n },\n})\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if an Option has a value.\n *\n * @param option - The Option to check\n * @returns true if the Option is some\n *\n * @example\n * ```ts\n * const option = some(42)\n * if (isSome(option)) {\n * console.log(option.value) // TypeScript knows value exists\n * }\n * ```\n */\nexport const isSome = <T>(option: OptionType<T>): option is Extract<OptionType<T>, { some: true }> => option.some\n\n/**\n * Check if an Option has no value.\n *\n * @param option - The Option to check\n * @returns true if the Option is none\n *\n * @example\n * ```ts\n * const option = none()\n * if (isNone(option)) {\n * console.log('No value') // TypeScript knows value doesn't exist\n * }\n * ```\n */\nexport const isNone = <T>(option: OptionType<T>): option is Extract<OptionType<T>, { some: false }> => !option.some\n\n// ============================================================================\n// Transformations (curried for pipe)\n// ============================================================================\n\n/**\n * Transform the value of an Option.\n * If the Option is none, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<U>\n * - Async fn: returns Promise<Option<U>>\n *\n * @param fn - Function to transform the value\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * some(5),\n * map(n => n * 2)\n * ) // { some: true, value: 10 }\n *\n * // Async usage\n * await pipe(\n * some(userId),\n * map(async id => await fetchName(id))\n * ) // Promise<Option<string>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const map: OptionMap = (fn) => (option) => {\n if (!option.some) return option as any\n const mapped = fn(option.value)\n if (mapped instanceof Promise) {\n return mapped.then(some) as any\n }\n return some(mapped) as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Chain operations that return Options.\n * If the Option is none, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<U>\n * - Async fn: returns Promise<Option<U>>\n *\n * @param fn - Function that takes a value and returns an Option (or Promise<Option>)\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * const findUser = (id: number) =>\n * id > 0 ? some({ id, name: 'Alice' }) : none()\n *\n * // Sync usage\n * pipe(\n * some(10),\n * flatMap(id => findUser(id))\n * ) // { some: true, value: { id: 10, name: 'Alice' } }\n *\n * // Async usage\n * await pipe(\n * some(userId),\n * flatMap(async id => some(await fetchUser(id)))\n * ) // Promise<Option<User>>\n * ```\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const flatMap: OptionFlatMap = (fn) => (option) => (option.some ? fn(option.value) : option) as any\n\n/**\n * Perform a side effect on the value without modifying the Option.\n * Useful for debugging, logging, or other side effects in a pipeline.\n * If the Option is none, the function is not called.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<T>\n * - Async fn: returns Promise<Option<T>>\n *\n * @param fn - Function to call with the value (return value is ignored)\n * @returns A function that takes an Option and returns the same Option\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * some(42),\n * tap(console.log), // logs 42\n * map(n => n * 2)\n * ) // { some: true, value: 84 }\n *\n * // Async usage\n * await pipe(\n * some(42),\n * tap(async v => await logToServer(v)),\n * map(n => n * 2)\n * ) // Promise<Option<84>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tap: OptionTap = (fn) => (option) => {\n if (!option.some) return option as any\n const sideEffect = fn(option.value)\n if (sideEffect instanceof Promise) {\n return sideEffect.then(() => option) as any\n }\n return option as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Recover from none by providing an alternative Option.\n * If the Option is some, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Option<T | U>\n * - Async fn: returns Promise<Option<T | U>>\n *\n * @param fn - Function that returns an alternative Option\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * // Sync recovery\n * pipe(\n * none(),\n * orElse(() => some(defaultValue))\n * ) // { some: true, value: defaultValue }\n *\n * // Async recovery\n * await pipe(\n * none(),\n * orElse(async () => some(await fetchFromAPI()))\n * ) // Promise<Option<T>>\n *\n * // Chain multiple fallbacks\n * pipe(\n * none(),\n * orElse(() => tryCache()),\n * orElse(() => tryAPI()),\n * orElse(() => some(fallback))\n * )\n * ```\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const orElse: OptionOrElse = (fn) => (option) => (option.some ? option : fn()) as any\n\n/**\n * Filter an Option based on a predicate.\n * If the predicate returns false, converts to none.\n * If the Option is already none, it passes through unchanged.\n *\n * @param predicate - Function that returns true to keep the value\n * @returns A function that takes an Option and returns a new Option\n *\n * @example\n * ```ts\n * pipe(\n * some(5),\n * filter(n => n > 10)\n * ) // { some: false }\n *\n * pipe(\n * some(15),\n * filter(n => n > 10)\n * ) // { some: true, value: 15 }\n *\n * // With complex validation\n * pipe(\n * some(user),\n * filter(u => u.age >= 18)\n * )\n * ```\n */\nexport const filter: OptionFilter = (predicate) => (option) => {\n if (!option.some) return option\n return predicate(option.value) ? option : none()\n}\n\n// ============================================================================\n// Combinators\n// ============================================================================\n\n/**\n * Combine multiple Options into a single Option.\n * Supports both array and object inputs.\n *\n * - If all Options are some, returns some with all values\n * - If any Option is none, returns none (short-circuits)\n *\n * @example\n * ```ts\n * // Array form (use `as const` for tuple types) - returns Option<[number, string]>\n * const [num, str] = pipe(\n * Option.all([parseNumber(input), parseString(other)] as const),\n * Option.unwrapOr([0, ''])\n * )\n *\n * // Object form - returns Option<{ user: User, config: Config }>\n * pipe(\n * Option.all({ user: findUser(id), config: loadConfig() }),\n * Option.tap(({ user, config }) => console.log(user.name, config.theme))\n * )\n * ```\n */\nexport function all<T extends readonly OptionType<unknown>[]>(options: T): AllArrayReturn<T>\nexport function all<T extends Record<string, OptionType<unknown>>>(options: T): AllObjectReturn<T>\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument -- Required for handling union types in overloaded function */\nexport function all(options: any): any {\n if (Array.isArray(options)) {\n const values: unknown[] = []\n for (const option of options) {\n if (!option.some) return option\n values.push(option.value)\n }\n return some(values)\n }\n\n const values: Record<string, unknown> = {}\n for (const [key, option] of Object.entries(options)) {\n const o = option as OptionType<unknown>\n if (!o.some) return option\n values[key] = o.value\n }\n return some(values)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion */\n\n// ============================================================================\n// Extraction\n// ============================================================================\n\n/**\n * Get the value or a default value.\n *\n * @param defaultValue - Value to return if the Option is none\n * @returns A function that takes an Option and returns the value or default\n *\n * @example\n * ```ts\n * pipe(some(42), unwrapOr(0)) // 42\n * pipe(none(), unwrapOr(0)) // 0\n * ```\n */\nexport const unwrapOr =\n <T>(defaultValue: T) =>\n (option: OptionType<T>): T =>\n option.some ? option.value : defaultValue\n\n/**\n * Get the value or compute a value.\n *\n * @param fn - Function to compute a value\n * @returns A function that takes an Option and returns the value or computed value\n *\n * @example\n * ```ts\n * pipe(\n * none(),\n * unwrapOrElse(() => generateDefault())\n * ) // generateDefault()\n * ```\n */\nexport const unwrapOrElse =\n <T>(fn: () => T) =>\n (option: OptionType<T>): T =>\n option.some ? option.value : fn()\n\n/**\n * Pattern match on an Option, handling both some and none cases.\n *\n * @param handlers - Object with some and none handlers\n * @returns A function that takes an Option and returns the handler result\n *\n * @example\n * ```ts\n * pipe(\n * some(42),\n * match({\n * some: n => `Got ${n}`,\n * none: () => 'No value'\n * })\n * ) // 'Got 42'\n * ```\n */\nexport const match =\n <T, U>(handlers: { some: (value: T) => U; none: () => U }) =>\n (option: OptionType<T>): U =>\n option.some ? handlers.some(option.value) : handlers.none()\n\n// ============================================================================\n// Conversions\n// ============================================================================\n\n/**\n * Convert a nullable value to an Option.\n * null and undefined become none, other values become some.\n *\n * @param value - The value to convert\n * @returns An Option\n *\n * @example\n * ```ts\n * fromNullable(42) // { some: true, value: 42 }\n * fromNullable(null) // { some: false }\n * fromNullable(undefined) // { some: false }\n * ```\n */\nexport const fromNullable = <T>(value: T | null | undefined): OptionType<T> =>\n value === null || value === undefined ? none<T>() : some(value)\n\n/**\n * Wrap a function that might throw into an Option.\n * Supports both sync and async functions with automatic type inference.\n *\n * - Sync fn: returns Option<T>\n * - Async fn: returns Promise<Option<T>>\n *\n * **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),\n * you should add an explicit return type annotation. This is because TypeScript's\n * conditional types cannot determine if `any` is a Promise or not, resulting in a\n * union type `Promise<Option<unknown>> | Option<any>` that won't work\n * with Option utilities like `isSome` or `isNone`.\n *\n * @param fn - Function that might throw (sync or async)\n * @returns An Option with the return value or none\n *\n * @example\n * ```ts\n * // Sync usage\n * fromTry(() => JSON.parse('{\"valid\": true}'))\n * // { some: true, value: { valid: true } }\n *\n * fromTry(() => JSON.parse('not json'))\n * // { some: false }\n *\n * // When fn returns `any`, add explicit return type:\n * fromTry((): unknown => JSON.parse(input))\n * fromTry((): MyType => JSON.parse(input))\n *\n * // Async usage\n * await fromTry(async () => await fetch('/api/user'))\n * // Promise<Option<Response>>\n *\n * await fromTry(async () => {\n * throw new Error('network error')\n * })\n * // Promise<{ some: false }>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-type-assertion -- Required for conditional return type */\nexport const fromTry = <T>(fn: () => T): FromTryReturn<T> => {\n try {\n const result = fn()\n if (isPromise(result)) {\n return result.then(some).catch(() => none()) as unknown as FromTryReturn<T>\n }\n return some(result) as unknown as FromTryReturn<T>\n } catch {\n return none() as unknown as FromTryReturn<T>\n }\n}\n\n// ============================================================================\n// Namespace\n// ============================================================================\n\n/**\n * Option namespace containing all utility functions for working with Option types.\n *\n * Option represents either the presence (some) or absence (none) of a value.\n * Use this for optional values without needing to track why the value is missing.\n *\n * @see {@link Result} for success/failure with error information\n * @see {@link Either} for two valid outcomes\n *\n * @example\n * ```ts\n * import { Option, pipe } from '@repo/std'\n * import type { Option as OptionType } from '@repo/std'\n *\n * const findUser = (id: number): OptionType<User> =>\n * id > 0 ? Option.some({ id, name: 'Alice' }) : Option.none()\n *\n * const result = pipe(\n * Option.some(10),\n * Option.flatMap(findUser),\n * Option.map(user => user.name),\n * Option.unwrapOr('Unknown')\n * )\n * ```\n */\nexport const Option = {\n some,\n none,\n isSome,\n isNone,\n map,\n flatMap,\n tap,\n orElse,\n filter,\n all,\n unwrapOr,\n unwrapOrElse,\n match,\n fromNullable,\n fromTry,\n} as const\n"],"mappings":";;;;;;AAeA,MAAa,OAAa,EAAE,YAAY,QAAQ;;;;;;;;;;;;;;;ACehD,MAAa,QAAW,WAA6B;CACnD,MAAM;CACN;CAEA,EAAE,OAAO,YAAyC;AAChD,SAAO;;CAEV;;;;;;;;;;;AAYD,MAAa,cAAgC;CAC3C,MAAM;CACN,EAAE,OAAO,YAA6C;AACpD,QAAMA;AACN,QAAM,IAAI,MAAM,+CAA+C;;CAElE;;;;;;;;;;;;;;;AAoBD,MAAa,UAAa,WAA4E,OAAO;;;;;;;;;;;;;;;AAgB7G,MAAa,UAAa,WAA6E,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiC/G,MAAa,OAAkB,QAAQ,WAAW;AAChD,KAAI,CAAC,OAAO,KAAM,QAAO;CACzB,MAAM,SAAS,GAAG,OAAO,MAAM;AAC/B,KAAI,kBAAkB,QACpB,QAAO,OAAO,KAAK,KAAK;AAE1B,QAAO,KAAK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCrB,MAAa,WAA0B,QAAQ,WAAY,OAAO,OAAO,GAAG,OAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC5F,MAAa,OAAkB,QAAQ,WAAW;AAChD,KAAI,CAAC,OAAO,KAAM,QAAO;CACzB,MAAM,aAAa,GAAG,OAAO,MAAM;AACnC,KAAI,sBAAsB,QACxB,QAAO,WAAW,WAAW,OAAO;AAEtC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCT,MAAa,UAAwB,QAAQ,WAAY,OAAO,OAAO,SAAS,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BpF,MAAa,UAAwB,eAAe,WAAW;AAC7D,KAAI,CAAC,OAAO,KAAM,QAAO;AACzB,QAAO,UAAU,OAAO,MAAM,GAAG,SAAS,MAAM;;AAgClD,SAAgB,IAAI,SAAmB;AACrC,KAAI,MAAM,QAAQ,QAAQ,EAAE;EAC1B,MAAMC,WAAoB,EAAE;AAC5B,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,CAAC,OAAO,KAAM,QAAO;AACzB,YAAO,KAAK,OAAO,MAAM;;AAE3B,SAAO,KAAKA,SAAO;;CAGrB,MAAM,SAAkC,EAAE;AAC1C,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,QAAQ,EAAE;EACnD,MAAM,IAAI;AACV,MAAI,CAAC,EAAE,KAAM,QAAO;AACpB,SAAO,OAAO,EAAE;;AAElB,QAAO,KAAK,OAAO;;;;;;;;;;;;;;AAoBrB,MAAa,YACP,kBACH,WACC,OAAO,OAAO,OAAO,QAAQ;;;;;;;;;;;;;;;AAgBjC,MAAa,gBACP,QACH,WACC,OAAO,OAAO,OAAO,QAAQ,IAAI;;;;;;;;;;;;;;;;;;AAmBrC,MAAa,SACJ,cACN,WACC,OAAO,OAAO,SAAS,KAAK,OAAO,MAAM,GAAG,SAAS,MAAM;;;;;;;;;;;;;;;AAoB/D,MAAa,gBAAmB,UAC9B,UAAU,QAAQ,UAAU,SAAY,MAAS,GAAG,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CjE,MAAa,WAAc,OAAkC;AAC3D,KAAI;EACF,MAAM,SAAS,IAAI;AACnB,MAAI,UAAU,OAAO,CACnB,QAAO,OAAO,KAAK,KAAK,CAAC,YAAY,MAAM,CAAC;AAE9C,SAAO,KAAK,OAAO;SACb;AACN,SAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCjB,MAAa,SAAS;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { y as Yieldable } from "./result.types-Bd8a43Fg.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/option/option.types.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Marker type for Option's absence in the Do computation context.
|
|
7
|
-
* When an Option is yielded in Do, None becomes part of the error union.
|
|
8
|
-
*/
|
|
9
|
-
type None = {
|
|
10
|
-
readonly __typename: "None";
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Singleton None value.
|
|
14
|
-
*/
|
|
15
|
-
declare const None: None;
|
|
16
|
-
/**
|
|
17
|
-
* A discriminated union representing either a value (some) or absence (none).
|
|
18
|
-
* Compatible with ts-pattern for exhaustive matching.
|
|
19
|
-
* Implements Yieldable protocol for use in Do computations with yield*.
|
|
20
|
-
*/
|
|
21
|
-
type Option<T> = Yieldable<T, None> & ({
|
|
22
|
-
readonly some: true;
|
|
23
|
-
readonly value: T;
|
|
24
|
-
} | {
|
|
25
|
-
readonly some: false;
|
|
26
|
-
});
|
|
27
|
-
/**
|
|
28
|
-
* Compute the return type of `fromTry` based on whether fn returns a Promise.
|
|
29
|
-
* - If fn returns Promise<T>, result is Promise<Option<T>>
|
|
30
|
-
* - If fn returns T, result is Option<T>
|
|
31
|
-
*/
|
|
32
|
-
type FromTryReturn<T> = T extends Promise<infer U> ? Promise<Option<U>> : Option<T>;
|
|
33
|
-
/**
|
|
34
|
-
* Extract the value type from an Option.
|
|
35
|
-
* Uses structural matching to extract the value type from the some branch.
|
|
36
|
-
*/
|
|
37
|
-
type OptionValue<O> = O extends {
|
|
38
|
-
readonly some: true;
|
|
39
|
-
readonly value: infer T;
|
|
40
|
-
} ? T : never;
|
|
41
|
-
/**
|
|
42
|
-
* Compute return type for `all` with array input.
|
|
43
|
-
* Preserves tuple structure and extracts value types from each position.
|
|
44
|
-
*/
|
|
45
|
-
type AllArrayReturn<T extends readonly Option<unknown>[]> = Option<{ -readonly [K in keyof T]: OptionValue<T[K]> }>;
|
|
46
|
-
/**
|
|
47
|
-
* Compute return type for `all` with object input.
|
|
48
|
-
* Preserves object structure and extracts value types from each key.
|
|
49
|
-
*/
|
|
50
|
-
type AllObjectReturn<T extends Record<string, Option<unknown>>> = Option<{ -readonly [K in keyof T]: OptionValue<T[K]> }>;
|
|
51
|
-
/**
|
|
52
|
-
* Interface for flatMap - using method syntax improves generic inference in pipe chains.
|
|
53
|
-
* Note: Async overload must come first for proper overload resolution.
|
|
54
|
-
*/
|
|
55
|
-
type OptionFlatMap = {
|
|
56
|
-
<A, B>(fn: (value: A) => Promise<Option<B>>): (option: Option<A>) => Promise<Option<B>>;
|
|
57
|
-
<A, B>(fn: (value: A) => Option<B>): (option: Option<A>) => Option<B>;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Interface for map function.
|
|
61
|
-
* Note: Async overload must come first for proper overload resolution.
|
|
62
|
-
*/
|
|
63
|
-
type OptionMap = {
|
|
64
|
-
<A, B>(fn: (value: A) => Promise<B>): (option: Option<A>) => Promise<Option<B>>;
|
|
65
|
-
<A, B>(fn: (value: A) => B): (option: Option<A>) => Option<B>;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Interface for tap function.
|
|
69
|
-
*/
|
|
70
|
-
type OptionTap = {
|
|
71
|
-
<A, R>(fn: (value: A) => R): (option: Option<A>) => R extends Promise<unknown> ? Promise<Option<A>> : Option<A>;
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Interface for orElse function.
|
|
75
|
-
* Note: Async overload must come first for proper overload resolution.
|
|
76
|
-
*/
|
|
77
|
-
type OptionOrElse = {
|
|
78
|
-
<A, B>(fn: () => Promise<Option<B>>): (option: Option<A>) => Promise<Option<A | B>>;
|
|
79
|
-
<A, B>(fn: () => Option<B>): (option: Option<A>) => Option<A | B>;
|
|
80
|
-
};
|
|
81
|
-
/**
|
|
82
|
-
* Interface for filter function.
|
|
83
|
-
*/
|
|
84
|
-
type OptionFilter = {
|
|
85
|
-
<A>(predicate: (value: A) => boolean): (option: Option<A>) => Option<A>;
|
|
86
|
-
};
|
|
87
|
-
//#endregion
|
|
88
|
-
export { Option as a, OptionMap as c, None as i, OptionOrElse as l, AllObjectReturn as n, OptionFilter as o, FromTryReturn as r, OptionFlatMap as s, AllArrayReturn as t, OptionTap as u };
|
|
89
|
-
//# sourceMappingURL=option.types-eqVODMIy.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"option.types-eqVODMIy.d.mts","names":[],"sources":["../src/option/option.types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"result-C5tPWR60.mjs","names":["values"],"sources":["../src/result/result.ts"],"sourcesContent":["import { isPromise } from \"../shared/is-promise\"\nimport type {\n AllArrayReturn,\n AllObjectReturn,\n FromTryReturn,\n Result as ResultType,\n ResultFlatMap,\n ResultMap,\n ResultMapErr,\n ResultTap,\n ResultOrElse,\n ResultFilter,\n} from \"./result.types\"\n\n// ============================================================================\n// Constructors\n// ============================================================================\n\n/**\n * Create a successful Result.\n *\n * @param value - The success value\n * @returns A Result with ok: true\n *\n * @example\n * ```ts\n * ok(42) // { ok: true, value: 42 }\n * ```\n */\nexport const ok = <T>(value: T): ResultType<T, never> => ({\n ok: true,\n value,\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, T, unknown> {\n return value\n },\n})\n\n/**\n * Create an error Result.\n *\n * @param error - The error value\n * @returns A Result with ok: false\n *\n * @example\n * ```ts\n * err('something went wrong') // { ok: false, error: 'something went wrong' }\n * ```\n */\nexport const err = <E>(error: E): ResultType<never, E> => ({\n ok: false,\n error,\n *[Symbol.iterator](): Generator<E, never, unknown> {\n yield error\n throw new Error(\"Unreachable: Do should short-circuit on error\")\n },\n})\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a Result is successful.\n *\n * @param result - The Result to check\n * @returns true if the Result is ok\n *\n * @example\n * ```ts\n * const result = ok(42)\n * if (isOk(result)) {\n * console.log(result.value) // TypeScript knows value exists\n * }\n * ```\n */\nexport const isOk = <T, E>(result: ResultType<T, E>): result is Extract<ResultType<T, E>, { ok: true }> => result.ok\n\n/**\n * Check if a Result is an error.\n *\n * @param result - The Result to check\n * @returns true if the Result is an error\n *\n * @example\n * ```ts\n * const result = err('oops')\n * if (isErr(result)) {\n * console.log(result.error) // TypeScript knows error exists\n * }\n * ```\n */\nexport const isErr = <T, E>(result: ResultType<T, E>): result is Extract<ResultType<T, E>, { ok: false }> => !result.ok\n\n// ============================================================================\n// Transformations (curried for pipe)\n// ============================================================================\n\n/**\n * Transform the success value of a Result.\n * If the Result is an error, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<U, E>\n * - Async fn: returns Promise<Result<U, E>>\n *\n * @param fn - Function to transform the success value\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * ok(5),\n * map(n => n * 2)\n * ) // { ok: true, value: 10 }\n *\n * // Async usage\n * await pipe(\n * ok(userId),\n * map(async id => await fetchName(id))\n * ) // Promise<Result<string, E>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const map: ResultMap = (fn) => (result) => {\n if (!result.ok) return result as any\n const mapped = fn(result.value)\n if (mapped instanceof Promise) {\n return mapped.then(ok) as any\n }\n return ok(mapped) as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Transform the error value of a Result.\n * If the Result is successful, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T, F>\n * - Async fn: returns Promise<Result<T, F>>\n *\n * @param fn - Function to transform the error value\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * err({ code: 404 }),\n * mapErr(e => `Error: ${e.code}`)\n * ) // { ok: false, error: 'Error: 404' }\n *\n * // Async usage\n * await pipe(\n * err(errorCode),\n * mapErr(async code => await translateError(code))\n * ) // Promise<Result<T, string>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const mapErr: ResultMapErr = (fn) => (result) => {\n if (result.ok) return result as any\n const mapped = fn(result.error)\n if (mapped instanceof Promise) {\n return mapped.then(err) as any\n }\n return err(mapped) as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Chain operations that return Results.\n * If the Result is an error, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<U, E | E2>\n * - Async fn: returns Promise<Result<U, E | E2>>\n *\n * @param fn - Function that takes a value and returns a Result (or Promise<Result>)\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * const divide = (a: number, b: number) =>\n * b === 0 ? err('division by zero') : ok(a / b)\n *\n * // Sync usage\n * pipe(\n * ok(10),\n * flatMap(n => divide(n, 2))\n * ) // { ok: true, value: 5 }\n *\n * // Async usage\n * await pipe(\n * ok(userId),\n * flatMap(async id => ok(await fetchUser(id)))\n * ) // Promise<Result<User, E>>\n * ```\n */\n\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const flatMap: ResultFlatMap = (fn) => (result) => (result.ok ? fn(result.value) : result) as any\n\n/**\n * Perform a side effect on the success value without modifying the Result.\n * Useful for debugging, logging, or other side effects in a pipeline.\n * If the Result is an error, the function is not called.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T, E>\n * - Async fn: returns Promise<Result<T, E>>\n *\n * @param fn - Function to call with the success value (return value is ignored)\n * @returns A function that takes a Result and returns the same Result\n *\n * @example\n * ```ts\n * // Sync usage\n * pipe(\n * ok(42),\n * tap(console.log), // logs 42\n * map(n => n * 2)\n * ) // { ok: true, value: 84 }\n *\n * // Async usage\n * await pipe(\n * ok(42),\n * tap(async v => await logToServer(v)),\n * map(n => n * 2)\n * ) // Promise<Result<84, E>>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types in curried functions */\nexport const tap: ResultTap = (fn) => (result) => {\n if (!result.ok) return result as any\n const sideEffect = fn(result.value)\n if (sideEffect instanceof Promise) {\n return sideEffect.then(() => result) as any\n }\n return result as any\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-type-assertion */\n\n/**\n * Recover from an error by providing an alternative Result.\n * If the Result is successful, it passes through unchanged.\n *\n * Supports both sync and async functions:\n * - Sync fn: returns Result<T | U, E2>\n * - Async fn: returns Promise<Result<T | U, E2>>\n *\n * @param fn - Function that takes the error and returns an alternative Result\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * // Sync recovery\n * pipe(\n * err('cache miss'),\n * orElse(() => ok(defaultValue))\n * ) // { ok: true, value: defaultValue }\n *\n * // Async recovery\n * await pipe(\n * err('cache miss'),\n * orElse(async () => ok(await fetchFromAPI()))\n * ) // Promise<Result<T, E2>>\n *\n * // Chain multiple fallbacks\n * pipe(\n * err('not found'),\n * orElse(() => tryCache()),\n * orElse(() => tryAPI()),\n * orElse(() => ok(fallback))\n * )\n * ```\n */\n// oxlint-disable-next-line no-explicit-any, no-unsafe-return, no-unsafe-type-assertion -- Required for overloaded return types\nexport const orElse: ResultOrElse = (fn) => (result) => (result.ok ? result : fn(result.error)) as any\n\n/**\n * Filter a successful Result based on a predicate.\n * If the predicate returns false, converts the success to an error.\n * If the Result is already an error, it passes through unchanged.\n *\n * @param predicate - Function that returns true to keep the value\n * @param onFail - Function that creates the error when predicate fails\n * @returns A function that takes a Result and returns a new Result\n *\n * @example\n * ```ts\n * pipe(\n * ok(5),\n * filter(n => n > 10, n => `${n} is too small`)\n * ) // { ok: false, error: '5 is too small' }\n *\n * pipe(\n * ok(15),\n * filter(n => n > 10, n => `${n} is too small`)\n * ) // { ok: true, value: 15 }\n *\n * // With complex validation\n * pipe(\n * ok(user),\n * filter(u => u.age >= 18, u => ({ code: 'UNDERAGE', user: u }))\n * )\n * ```\n */\nexport const filter: ResultFilter = (predicate, onFail) => (result) => {\n if (!result.ok) return result\n return predicate(result.value) ? result : err(onFail(result.value))\n}\n\n// ============================================================================\n// Combinators\n// ============================================================================\n\n/**\n * Combine multiple Results into a single Result.\n * Supports both array and object inputs.\n *\n * - If all Results are ok, returns ok with all values\n * - If any Result is an error, returns the first error (short-circuits)\n *\n * @example\n * ```ts\n * // Array form (use `as const` for tuple types) - returns Result<[number, string], E>\n * const [num, str] = pipe(\n * Result.all([parseNumber(input), parseString(other)] as const),\n * Result.unwrapOr([0, ''])\n * )\n *\n * // Object form - returns Result<{ user: User, config: Config }, E>\n * pipe(\n * Result.all({ user: fetchUser(id), config: loadConfig() }),\n * Result.tap(({ user, config }) => console.log(user.name, config.theme))\n * )\n * ```\n */\nexport function all<T extends readonly ResultType<unknown, unknown>[]>(results: T): AllArrayReturn<T>\nexport function all<T extends Record<string, ResultType<unknown, unknown>>>(results: T): AllObjectReturn<T>\n/* oxlint-disable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument -- Required for handling union types in overloaded function */\nexport function all(results: any): any {\n if (Array.isArray(results)) {\n const values: unknown[] = []\n for (const result of results) {\n if (!result.ok) return result\n values.push(result.value)\n }\n return ok(values)\n }\n\n const values: Record<string, unknown> = {}\n for (const [key, result] of Object.entries(results)) {\n const r = result as ResultType<unknown, unknown>\n if (!r.ok) return result\n values[key] = r.value\n }\n return ok(values)\n}\n/* oxlint-enable no-explicit-any, no-unsafe-return, no-unsafe-member-access, strict-boolean-expressions, no-unsafe-type-assertion, no-unsafe-argument */\n\n// ============================================================================\n// Extraction\n// ============================================================================\n\n/**\n * Get the success value or a default value.\n *\n * @param defaultValue - Value to return if the Result is an error\n * @returns A function that takes a Result and returns the value or default\n *\n * @example\n * ```ts\n * pipe(ok(42), unwrapOr(0)) // 42\n * pipe(err('oops'), unwrapOr(0)) // 0\n * ```\n */\nexport const unwrapOr =\n <T>(defaultValue: T) =>\n <E>(result: ResultType<T, E>): T =>\n result.ok ? result.value : defaultValue\n\n/**\n * Get the success value or compute a value from the error.\n *\n * @param fn - Function to compute a value from the error\n * @returns A function that takes a Result and returns the value or computed value\n *\n * @example\n * ```ts\n * pipe(\n * err({ code: 404 }),\n * unwrapOrElse(e => `Error ${e.code}`)\n * ) // 'Error 404'\n * ```\n */\nexport const unwrapOrElse =\n <E, T>(fn: (error: E) => T) =>\n (result: ResultType<T, E>): T =>\n result.ok ? result.value : fn(result.error)\n\n/**\n * Pattern match on a Result, handling both success and error cases.\n *\n * @param handlers - Object with ok and err handlers\n * @returns A function that takes a Result and returns the handler result\n *\n * @example\n * ```ts\n * pipe(\n * ok(42),\n * match({\n * ok: n => `Got ${n}`,\n * err: e => `Error: ${e}`\n * })\n * ) // 'Got 42'\n * ```\n */\nexport const match =\n <T, E, U>(handlers: { ok: (value: T) => U; err: (error: E) => U }) =>\n (result: ResultType<T, E>): U =>\n result.ok ? handlers.ok(result.value) : handlers.err(result.error)\n\n// ============================================================================\n// Error Boundary\n// ============================================================================\n\n/**\n * Wrap a function that might throw into a Result.\n * Supports both sync and async functions with automatic type inference.\n *\n * - Sync fn: returns Result<T, Error>\n * - Async fn: returns Promise<Result<T, Error>>\n *\n * **Note on `any` return types:** If your function returns `any` (e.g., `JSON.parse`),\n * you should add an explicit return type annotation. This is because TypeScript's\n * conditional types cannot determine if `any` is a Promise or not, resulting in a\n * union type `Promise<Result<unknown, Error>> | Result<any, Error>` that won't work\n * with Result utilities like `isOk` or `isErr`.\n *\n * @param fn - Function that might throw (sync or async)\n * @returns A Result with the return value or the caught error\n *\n * @example\n * ```ts\n * // Sync usage\n * fromTry(() => JSON.parse('{\"valid\": true}'))\n * // { ok: true, value: { valid: true } }\n *\n * fromTry(() => JSON.parse('not json'))\n * // { ok: false, error: SyntaxError }\n *\n * // When fn returns `any`, add explicit return type:\n * fromTry((): unknown => JSON.parse(input))\n * fromTry((): MyType => JSON.parse(input))\n *\n * // Async usage\n * await fromTry(async () => await fetch('/api/user'))\n * // Promise<Result<Response, Error>>\n *\n * await fromTry(async () => {\n * throw new Error('network error')\n * })\n * // Promise<{ ok: false, error: Error }>\n * ```\n */\n/* oxlint-disable no-explicit-any, no-unsafe-type-assertion -- Required for conditional return type */\nexport const fromTry = <T>(fn: () => T): FromTryReturn<T> => {\n try {\n const result = fn()\n if (isPromise(result)) {\n return result\n .then(ok)\n .catch((e) => err(e instanceof Error ? e : new Error(String(e)))) as unknown as FromTryReturn<T>\n }\n return ok(result) as unknown as FromTryReturn<T>\n } catch (e) {\n return err(e instanceof Error ? e : new Error(String(e))) as unknown as FromTryReturn<T>\n }\n}\n/* oxlint-enable no-explicit-any, no-unsafe-type-assertion */\n\n// ============================================================================\n// Namespace\n// ============================================================================\n\n/**\n * Result namespace containing all utility functions for working with Result types.\n *\n * Result represents either success (ok) or failure (err). Use this for operations\n * that can fail with typed errors.\n *\n * @see {@link Option} for presence/absence semantics (no error information)\n * @see {@link Either} for two valid outcomes (not just success/failure)\n *\n * @example\n * ```ts\n * import { Result, pipe } from '@repo/std'\n * import type { Result as ResultType } from '@repo/std'\n *\n * const divide = (a: number, b: number): ResultType<number, string> =>\n * b === 0 ? Result.err('division by zero') : Result.ok(a / b)\n *\n * const result = pipe(\n * divide(10, 2),\n * Result.map(n => n * 2),\n * Result.unwrapOr(0)\n * )\n * ```\n */\nexport const Result = {\n ok,\n err,\n isOk,\n isErr,\n map,\n mapErr,\n flatMap,\n tap,\n orElse,\n filter,\n all,\n unwrapOr,\n unwrapOrElse,\n match,\n fromTry,\n} as const\n"],"mappings":"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"}
|