@nicolastoulemont/std 0.2.0 → 0.3.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/index.d.mts CHANGED
@@ -13,6 +13,633 @@ import { t as pipe } from "./index-zC2zAtZY.mjs";
13
13
  import { n as Predicate$1, r as Refinement, t as Predicate } from "./index-DbfMra4p.mjs";
14
14
  import { n as all$2, t as Result } from "./index-BwVaI5d0.mjs";
15
15
 
16
+ //#region src/fx/fx.types.d.ts
17
+ /**
18
+ * ServiceRequest is yielded when accessing a service via yield*.
19
+ * The runtime intercepts these and injects the service from context.
20
+ */
21
+ type ServiceRequest<S> = {
22
+ readonly _tag: "ServiceRequest";
23
+ /** Phantom type for service identification */
24
+ readonly _service: S;
25
+ readonly serviceKey: string;
26
+ };
27
+ /**
28
+ * Exit represents the outcome of a computation.
29
+ * Either success with a value or failure with an error.
30
+ */
31
+ /**
32
+ * SyncFx<A, E, R> represents a synchronous computation that:
33
+ * - Produces a value of type A on success
34
+ * - May fail with an error of type E
35
+ * - Requires services of type R to run
36
+ *
37
+ * When R = never, .run() returns Result<A, E> directly.
38
+ */
39
+ type SyncFx<A, E = never, R = never> = {
40
+ readonly _tag: "SyncFx";
41
+ /**
42
+ * Execute the computation synchronously.
43
+ * Only available when R = never (all dependencies provided).
44
+ */
45
+ run: () => Result$1<A, E>;
46
+ /**
47
+ * Iterator for yield* support in gen computations.
48
+ * Yields either errors or service requests.
49
+ */
50
+ [Symbol.iterator](): Generator<E | ServiceRequest<R>, A, unknown>;
51
+ };
52
+ /**
53
+ * AsyncFx<A, E, R> represents an asynchronous computation that:
54
+ * - Produces a value of type A on success
55
+ * - May fail with an error of type E
56
+ * - Requires services of type R to run
57
+ *
58
+ * When R = never, .run() returns Promise<Result<A, E>>.
59
+ */
60
+ type AsyncFx<A, E = never, R = never> = {
61
+ readonly _tag: "AsyncFx";
62
+ /**
63
+ * Execute the computation asynchronously.
64
+ * Only available when R = never (all dependencies provided).
65
+ */
66
+ run: () => Promise<Result$1<A, E>>;
67
+ /**
68
+ * Async iterator for yield* support in async gen computations.
69
+ * Yields either errors or service requests.
70
+ */
71
+ [Symbol.asyncIterator](): AsyncGenerator<E | ServiceRequest<R>, A, unknown>;
72
+ };
73
+ /**
74
+ * Fx<A, E, R> is a union of sync and async computations.
75
+ * Use this as the general type for computations.
76
+ */
77
+ type Fx$1<A, E = never, R = never> = SyncFx<A, E, R> | AsyncFx<A, E, R>;
78
+ /**
79
+ * Extract the success type from an Fx.
80
+ */
81
+ type FxSuccess<T> = T extends Fx$1<infer A, unknown, unknown> ? A : never;
82
+ /**
83
+ * Extract the error type from an Fx.
84
+ */
85
+ type FxError<T> = T extends Fx$1<unknown, infer E, unknown> ? E : never;
86
+ /**
87
+ * Extract the requirements type from an Fx.
88
+ */
89
+ type FxRequirements<T> = T extends Fx$1<unknown, unknown, infer R> ? R : never;
90
+ /**
91
+ * Sync generator type for Fx.gen.
92
+ * Yields errors or service requests, returns value of type A.
93
+ */
94
+ type FxGenerator<A, E, R> = Generator<E | ServiceRequest<R>, A, unknown>;
95
+ /**
96
+ * Async generator type for Fx.gen.
97
+ * Yields errors or service requests, returns value of type A.
98
+ */
99
+ type AsyncFxGenerator<A, E, R> = AsyncGenerator<E | ServiceRequest<R>, A, unknown>;
100
+ //#endregion
101
+ //#region src/fx/fx.d.ts
102
+ /**
103
+ * Create a composable computation from a sync generator function.
104
+ * Returns a SyncFx that can be stored, passed around, and executed later.
105
+ *
106
+ * @template A - The success value type
107
+ * @template E - The error type
108
+ * @template R - The required services type
109
+ * @param generatorFn - A function that returns a sync generator
110
+ * @returns SyncFx<A, E, R>
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * const getUser = (id: string) => Fx.gen(function* () {
115
+ * const db = yield* Database
116
+ * const logger = yield* Logger
117
+ *
118
+ * logger.info(`Fetching user ${id}`)
119
+ * return yield* db.query<User>(`SELECT * FROM users WHERE id = '${id}'`)
120
+ * })
121
+ * // Type: Fx<User[], DatabaseError, Database | Logger>
122
+ *
123
+ * // Execute later with dependencies provided
124
+ * const result = pipe(getUser("123"), provide(AppLayer)).run()
125
+ * ```
126
+ */
127
+ declare function fxGen<A, E, R>(generatorFn: () => FxGenerator<A, E, R>): SyncFx<A, E, R>;
128
+ /**
129
+ * Create a composable computation from an async generator function.
130
+ * Returns an AsyncFx that can be stored, passed around, and executed later.
131
+ *
132
+ * @template A - The success value type
133
+ * @template E - The error type
134
+ * @template R - The required services type
135
+ * @param generatorFn - A function that returns an async generator
136
+ * @returns AsyncFx<A, E, R>
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * const fetchData = (url: string) => Fx.gen(async function* () {
141
+ * const logger = yield* Logger
142
+ *
143
+ * logger.info(`Fetching ${url}`)
144
+ * const response = await fetch(url)
145
+ * return yield* Result.fromTry(async () => await response.json())
146
+ * })
147
+ * // Type: Fx<unknown, Error, Logger>
148
+ * ```
149
+ */
150
+ declare function fxGen<A, E, R>(generatorFn: () => AsyncFxGenerator<A, E, R>): AsyncFx<A, E, R>;
151
+ /**
152
+ * Execute a sync computation immediately and return the result.
153
+ * For computations without service dependencies.
154
+ *
155
+ * @template A - The success value type
156
+ * @template E - The error type
157
+ * @param generatorFn - A function that returns a sync generator
158
+ * @returns Result<A, E>
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const result = Fx.fn(function* () {
163
+ * const a = yield* Result.ok(10)
164
+ * const b = yield* Result.ok(20)
165
+ * return a + b
166
+ * })
167
+ * // Type: Result<number, never>
168
+ * // result = { ok: true, value: 30 }
169
+ * ```
170
+ */
171
+ declare function fxFn<A, E>(generatorFn: () => FxGenerator<A, E, never>): Result$1<A, E>;
172
+ /**
173
+ * Execute an async computation immediately and return a Promise of the result.
174
+ * For computations without service dependencies.
175
+ *
176
+ * @template A - The success value type
177
+ * @template E - The error type
178
+ * @param generatorFn - A function that returns an async generator
179
+ * @returns Promise<Result<A, E>>
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * const result = await Fx.fn(async function* () {
184
+ * const response = await fetch("/api/users")
185
+ * const data = yield* Result.fromTry(async () => await response.json())
186
+ * return data
187
+ * })
188
+ * // Type: Promise<Result<unknown, Error>>
189
+ * ```
190
+ */
191
+ declare function fxFn<A, E>(generatorFn: () => AsyncFxGenerator<A, E, never>): Promise<Result$1<A, E>>;
192
+ /**
193
+ * Execute a sync computation with service dependencies immediately.
194
+ * The second argument is required when the computation has service requirements (R ≠ never).
195
+ *
196
+ * @template A - The success value type
197
+ * @template E - The error type from the computation
198
+ * @template E2 - The error type from the provider (layer)
199
+ * @template R - The required services type
200
+ * @param generatorFn - A function that returns a sync generator with service requirements
201
+ * @param provider - A function that provides the services (e.g., provide(AppLayer))
202
+ * @returns Result<A, E | E2>
203
+ *
204
+ * @example
205
+ * ```ts
206
+ * const result = Fx.fn(function* () {
207
+ * const config = yield* Config
208
+ * const logger = yield* Logger
209
+ * logger.info(`DB URL: ${config.dbUrl}`)
210
+ * return config.dbUrl
211
+ * }, provide(AppLayer))
212
+ * // Type: Result<string, never>
213
+ * ```
214
+ */
215
+ declare function fxFn<A, E, E2, R>(generatorFn: () => FxGenerator<A, E, R>, provider: (fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>): Result$1<A, E | E2>;
216
+ /**
217
+ * Execute an async computation with service dependencies immediately.
218
+ * The second argument is required when the computation has service requirements (R ≠ never).
219
+ *
220
+ * @template A - The success value type
221
+ * @template E - The error type from the computation
222
+ * @template E2 - The error type from the provider (layer)
223
+ * @template R - The required services type
224
+ * @param generatorFn - A function that returns an async generator with service requirements
225
+ * @param provider - A function that provides the services (e.g., provide(AppLayer))
226
+ * @returns Promise<Result<A, E | E2>>
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * const result = await Fx.fn(async function* () {
231
+ * const config = yield* Config
232
+ * await doAsyncWork()
233
+ * return config.dbUrl
234
+ * }, provide(AppLayer))
235
+ * // Type: Promise<Result<string, never>>
236
+ * ```
237
+ */
238
+ declare function fxFn<A, E, E2, R>(generatorFn: () => AsyncFxGenerator<A, E, R>, provider: (fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>): Promise<Result$1<A, E | E2>>;
239
+ /**
240
+ * Fx namespace containing utilities for creating and running effectful computations.
241
+ *
242
+ * Fx provides a minimal API inspired by Effect.ts:
243
+ * - `Fx.gen()` - Create composable computations with service dependencies
244
+ * - `Fx.fn()` - Execute computations immediately
245
+ * - `Fx.ok()` - Create successful results (alias for Result.ok)
246
+ * - `Fx.err()` - Create error results (alias for Result.err)
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * import { Fx, Service, Layer, provide, pipe } from "@repo/std"
251
+ *
252
+ * // Define services
253
+ * class Config extends Service<Config>()("Config") {
254
+ * readonly dbUrl!: string
255
+ * }
256
+ *
257
+ * class Logger extends Service<Logger>()("Logger") {
258
+ * readonly info!: (msg: string) => void
259
+ * }
260
+ *
261
+ * // Create layers
262
+ * const ConfigLive = Layer.ok(Config, { dbUrl: "postgres://..." })
263
+ * const LoggerLive = Layer.fx(Logger)(
264
+ * Fx.gen(function* () {
265
+ * const config = yield* Config
266
+ * return { info: (msg) => console.log(`[${config.dbUrl}] ${msg}`) }
267
+ * })
268
+ * )
269
+ *
270
+ * // Create workflow
271
+ * const myWorkflow = Fx.gen(function* () {
272
+ * const logger = yield* Logger
273
+ * logger.info("Hello from Fx!")
274
+ * return "done"
275
+ * })
276
+ *
277
+ * // Compose and run
278
+ * const AppLayer = pipe(ConfigLive, Layer.provide(LoggerLive))
279
+ * const result = pipe(myWorkflow, provide(AppLayer)).run()
280
+ * ```
281
+ */
282
+ declare const Fx: {
283
+ readonly gen: typeof fxGen;
284
+ readonly fn: typeof fxFn;
285
+ readonly ok: <T>(value: T) => Result$1<T, never>;
286
+ readonly err: <E>(error: E) => Result$1<never, E>;
287
+ };
288
+ //#endregion
289
+ //#region src/fx/service.d.ts
290
+ /**
291
+ * The interface returned by Service()().
292
+ * Acts as both a type tag and a runtime lookup key.
293
+ */
294
+ type ServiceClass<Self, Key extends string = string> = {
295
+ readonly _tag: "Service";
296
+ readonly key: Key;
297
+ readonly _Self: Self;
298
+ /**
299
+ * Yielding the service class in a gen computation
300
+ * returns the service instance from context.
301
+ */
302
+ [Symbol.iterator](): Generator<ServiceRequest<Self>, Self, unknown>;
303
+ };
304
+ /**
305
+ * Extract the service type from a ServiceClass.
306
+ */
307
+ type ServiceOf<T> = T extends ServiceClass<infer S> ? S : never;
308
+ /**
309
+ * Define a service with a unique key.
310
+ * The returned class acts as both a type and a runtime tag for lookup.
311
+ *
312
+ * Usage follows a double-invocation pattern:
313
+ * - First call provides the Self type parameter
314
+ * - Second call provides the unique key
315
+ *
316
+ * @example
317
+ * ```ts
318
+ * class Config extends Service<Config>()("Config") {
319
+ * readonly dbUrl!: string
320
+ * readonly logLevel!: "debug" | "info" | "error"
321
+ * }
322
+ *
323
+ * class Logger extends Service<Logger>()("Logger") {
324
+ * readonly info!: (msg: string) => void
325
+ * readonly error!: (msg: string) => void
326
+ * }
327
+ *
328
+ * // Use in Fx.gen:
329
+ * const workflow = Fx.gen(function* () {
330
+ * const config = yield* Config
331
+ * const logger = yield* Logger
332
+ * logger.info(`DB URL: ${config.dbUrl}`)
333
+ * })
334
+ * ```
335
+ */
336
+ declare function Service<Self>(): <Key extends string>(key: Key) => ServiceClass<Self, Key> & (new () => Self);
337
+ /**
338
+ * Create a service tag without class syntax.
339
+ * Useful for simple services that don't need class inheritance.
340
+ *
341
+ * @example
342
+ * ```ts
343
+ * interface ConfigService {
344
+ * readonly dbUrl: string
345
+ * readonly logLevel: "debug" | "info" | "error"
346
+ * }
347
+ *
348
+ * const Config = serviceTag<ConfigService>("Config")
349
+ *
350
+ * // Use in Fx.gen:
351
+ * const workflow = Fx.gen(function* () {
352
+ * const config = yield* Config
353
+ * console.log(config.dbUrl)
354
+ * })
355
+ * ```
356
+ */
357
+ declare function serviceTag<S>(key: string): ServiceClass<S>;
358
+ //#endregion
359
+ //#region src/fx/context.d.ts
360
+ /**
361
+ * Context<Services> is an immutable map storing service implementations.
362
+ * The Services type parameter tracks which services are available.
363
+ */
364
+ type Context<Services = never> = {
365
+ readonly _tag: "Context";
366
+ readonly _services: ReadonlyMap<string, unknown>;
367
+ readonly _Services: Services;
368
+ };
369
+ /**
370
+ * Get a service from a context.
371
+ * Throws if the service is not found.
372
+ *
373
+ * @param service - The service class (tag)
374
+ * @returns The service implementation
375
+ * @throws Error if service not found
376
+ *
377
+ * @example
378
+ * ```ts
379
+ * const config = Context.get(ctx, Config)
380
+ * ```
381
+ */
382
+ declare function get<S>(ctx: Context<S>, service: ServiceClass<S>): S;
383
+ declare function get<S>(service: ServiceClass<S>): (ctx: Context<S>) => S;
384
+ /**
385
+ * Context namespace containing utilities for managing service contexts.
386
+ *
387
+ * A Context is an immutable map of services that can be provided to Fx computations.
388
+ * Services are identified by their unique keys.
389
+ *
390
+ * @example
391
+ * ```ts
392
+ * import { Context, Service } from "@repo/std"
393
+ *
394
+ * class Config extends Service<Config>()("Config") {
395
+ * readonly dbUrl!: string
396
+ * }
397
+ *
398
+ * class Logger extends Service<Logger>()("Logger") {
399
+ * readonly info!: (msg: string) => void
400
+ * }
401
+ *
402
+ * // Create a context with services
403
+ * const ctx = pipe(
404
+ * Context.empty(),
405
+ * Context.add(Config, { dbUrl: "postgres://..." }),
406
+ * Context.add(Logger, { info: console.log }),
407
+ * )
408
+ *
409
+ * // Or use make and merge
410
+ * const configCtx = Context.make(Config, { dbUrl: "postgres://..." })
411
+ * const loggerCtx = Context.make(Logger, { info: console.log })
412
+ * const fullCtx = Context.merge(configCtx, loggerCtx)
413
+ * ```
414
+ */
415
+ declare const Context: {
416
+ readonly empty: () => Context;
417
+ readonly make: <S>(service: ServiceClass<S>, impl: S) => Context<S>;
418
+ readonly add: <S>(service: ServiceClass<S>, impl: S) => <Existing>(ctx: Context<Existing>) => Context<Existing | S>;
419
+ readonly merge: <A, B>(a: Context<A>, b: Context<B>) => Context<A | B>;
420
+ readonly get: typeof get;
421
+ readonly unsafeGet: (ctx: Context<unknown>, key: string) => unknown;
422
+ readonly has: <S>(ctx: Context<unknown>, service: ServiceClass<S>) => boolean;
423
+ readonly keys: (ctx: Context<unknown>) => string[];
424
+ readonly size: (ctx: Context<unknown>) => number;
425
+ readonly isContext: (value: unknown) => value is Context<unknown>;
426
+ };
427
+ //#endregion
428
+ //#region src/fx/scope.d.ts
429
+ /**
430
+ * Scope manages resource lifecycles with finalizers.
431
+ * Finalizers run in LIFO (Last In, First Out) order when the scope closes.
432
+ *
433
+ * @example
434
+ * ```ts
435
+ * const DatabaseLive = Layer.scoped(Database)(
436
+ * Fx.gen(function* () {
437
+ * const scope = yield* Scope
438
+ *
439
+ * const connection = createConnection()
440
+ *
441
+ * // Register cleanup - runs when scope closes
442
+ * yield* scope.addFinalizer(() =>
443
+ * Fx.gen(function* () {
444
+ * connection.close()
445
+ * })
446
+ * )
447
+ *
448
+ * return { query: (sql) => connection.query(sql) }
449
+ * })
450
+ * )
451
+ * ```
452
+ */
453
+ type ScopeService = {
454
+ /**
455
+ * Add a finalizer to be run when the scope closes.
456
+ * Finalizers are run in LIFO order.
457
+ *
458
+ * @param finalizer - A function that returns an Fx to run on cleanup
459
+ * @returns An Fx that completes when the finalizer is registered
460
+ */
461
+ addFinalizer(finalizer: () => SyncFx<void, never> | AsyncFx<void, never>): SyncFx<void, never>;
462
+ /**
463
+ * Close the scope, running all finalizers in LIFO order.
464
+ *
465
+ * @param exit - The exit status of the computation
466
+ * @returns An Fx that completes when all finalizers have run
467
+ */
468
+ close(exit: Result$1<unknown, unknown>): SyncFx<void, never> | AsyncFx<void, never>;
469
+ /**
470
+ * Fork a child scope.
471
+ * The child scope will be closed when the parent scope closes.
472
+ *
473
+ * @returns A new child scope
474
+ */
475
+ fork(): ScopeService;
476
+ };
477
+ declare const ScopeTag_base: ServiceClass<ScopeService, "@std/Scope"> & (new () => ScopeService);
478
+ declare class ScopeTag extends ScopeTag_base {}
479
+ /**
480
+ * Type utility to exclude Scope from requirements.
481
+ * Used by Layer.scoped to auto-provide Scope.
482
+ */
483
+ type ExcludeScope<R> = Exclude<R, ScopeService>;
484
+ //#endregion
485
+ //#region src/fx/memo-map.d.ts
486
+ /**
487
+ * MemoMap caches built layers so each layer is only built once.
488
+ * Multiple dependents share the same service instance.
489
+ *
490
+ * This implements the "service singleton" pattern where a service
491
+ * is instantiated once and shared across all consumers.
492
+ *
493
+ * @example
494
+ * ```ts
495
+ * // Database is built once, shared by DocumentService and TeamService
496
+ * const AppLayer = Layer.merge(
497
+ * ConfigLive,
498
+ * LoggerLive,
499
+ * DatabaseLive, // Built once
500
+ * DocumentServiceLive, // Uses shared Database
501
+ * TeamServiceLive, // Uses same Database instance
502
+ * )
503
+ * ```
504
+ */
505
+ declare class MemoMap {
506
+ private cache;
507
+ /**
508
+ * Get a cached context or build the layer if not cached.
509
+ *
510
+ * @param layer - The layer to get or build
511
+ * @param scope - The scope for resource management
512
+ * @param deps - Context containing the layer's dependencies
513
+ * @returns An Fx producing the layer's context
514
+ */
515
+ getOrBuild<ROut, E, RIn>(layer: Layer$1<ROut, E, RIn>, scope: ScopeService, deps: Context<RIn>): Fx$1<Context<ROut>, E>;
516
+ /**
517
+ * Clear the cache.
518
+ * Useful for testing.
519
+ */
520
+ clear(): void;
521
+ /**
522
+ * Get the number of cached layers.
523
+ */
524
+ get size(): number;
525
+ }
526
+ //#endregion
527
+ //#region src/fx/layer.types.d.ts
528
+ /**
529
+ * Layer<ROut, E, RIn> describes how to build services:
530
+ * - ROut: Services this layer provides
531
+ * - E: Errors that can occur during construction
532
+ * - RIn: Services this layer requires to build
533
+ */
534
+ type Layer$1<ROut, E = never, RIn = never> = {
535
+ readonly _tag: "Layer";
536
+ /** Phantom type for output services */
537
+ readonly _ROut: ROut;
538
+ /** Phantom type for errors */
539
+ readonly _E: E;
540
+ /** Phantom type for input requirements */
541
+ readonly _RIn: RIn;
542
+ /**
543
+ * Build the layer given its dependencies.
544
+ * Returns an Fx that produces a Context with the provided services.
545
+ *
546
+ * @param memoMap - Cache for layer memoization
547
+ * @param scope - Scope for resource management
548
+ * @returns An Fx that produces the context
549
+ */
550
+ build(memoMap: MemoMap, scope: ScopeService): Fx$1<Context<ROut>, E, RIn>;
551
+ };
552
+ /**
553
+ * Extract the output services type from a Layer.
554
+ */
555
+ type LayerROut<T> = T extends Layer$1<infer ROut, unknown, unknown> ? ROut : never;
556
+ /**
557
+ * Extract the error type from a Layer.
558
+ */
559
+ type LayerError<T> = T extends Layer$1<unknown, infer E, unknown> ? E : never;
560
+ /**
561
+ * Extract the input requirements type from a Layer.
562
+ */
563
+ type LayerRIn<T> = T extends Layer$1<unknown, unknown, infer RIn> ? RIn : never;
564
+ /**
565
+ * Merge all ROut types from an array of layers into a union.
566
+ */
567
+ type MergeROut<L extends readonly Layer$1<unknown, unknown, unknown>[]> = L[number] extends Layer$1<infer ROut, unknown, unknown> ? ROut : never;
568
+ /**
569
+ * Merge all error types from an array of layers into a union.
570
+ */
571
+ type MergeError<L extends readonly Layer$1<unknown, unknown, unknown>[]> = L[number] extends Layer$1<unknown, infer E, unknown> ? E : never;
572
+ /**
573
+ * Get all requirements from an array of layers that are NOT provided by any layer in the array.
574
+ * This computes the "unprovided" or "external" dependencies.
575
+ */
576
+ type UnprovidedDeps<L extends readonly Layer$1<unknown, unknown, unknown>[]> = Exclude<MergeRIn<L>, MergeROut<L>>;
577
+ /**
578
+ * Merge all RIn types from an array of layers into a union.
579
+ */
580
+ type MergeRIn<L extends readonly Layer$1<unknown, unknown, unknown>[]> = L[number] extends Layer$1<unknown, unknown, infer RIn> ? RIn : never;
581
+ //#endregion
582
+ //#region src/fx/layer.d.ts
583
+ declare const Layer: {
584
+ readonly ok: <S>(service: ServiceClass<S>, impl: S) => Layer$1<S, never>;
585
+ readonly err: <E>(error: E) => Layer$1<never, E>;
586
+ readonly fx: <S>(service: ServiceClass<S>) => <E, R>(fx: Fx$1<S, E, R>) => Layer$1<S, E, R>;
587
+ readonly scoped: <S>(service: ServiceClass<S>) => <E, R>(fx: Fx$1<S, E, R | ScopeService>) => Layer$1<S, E, ExcludeScope<R>>;
588
+ readonly provide: <DepsROut, DepsE, DepsRIn>(deps: Layer$1<DepsROut, DepsE, DepsRIn>) => <ROut, E, RIn extends DepsROut>(layer: Layer$1<ROut, E, RIn>) => Layer$1<ROut | DepsROut, E | DepsE, DepsRIn>;
589
+ readonly merge: <L extends Layer$1<unknown, unknown, unknown>[]>(...layers: L) => Layer$1<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>>;
590
+ };
591
+ //#endregion
592
+ //#region src/fx/provide.d.ts
593
+ /**
594
+ * Provide a layer to an Fx computation, resolving all service requirements.
595
+ * Creates a new scope for resource management.
596
+ *
597
+ * @param layer - The layer providing services (must have no external requirements)
598
+ * @returns A function that takes an Fx and returns an Fx with dependencies resolved
599
+ *
600
+ * @example
601
+ * ```ts
602
+ * const result = pipe(
603
+ * updateDocumentWorkflow(userId, docId, data),
604
+ * provide(AppLayer)
605
+ * ).run()
606
+ * ```
607
+ */
608
+ declare const provide: <ROut, E2>(layer: Layer$1<ROut, E2>) => <A, E, R extends ROut>(fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>;
609
+ /**
610
+ * Provide a context directly to an Fx computation.
611
+ *
612
+ * @param ctx - The context containing services
613
+ * @returns A function that takes an Fx and returns an Fx with dependencies resolved
614
+ *
615
+ * @example
616
+ * ```ts
617
+ * const ctx = Context.make(Config, configImpl)
618
+ * const result = pipe(
619
+ * myWorkflow,
620
+ * provideContext(ctx)
621
+ * ).run()
622
+ * ```
623
+ */
624
+ declare const provideContext: <R>(ctx: Context<R>) => <A, E>(fx: Fx$1<A, E, R>) => Fx$1<A, E>;
625
+ /**
626
+ * Provide a single service to an Fx computation.
627
+ *
628
+ * @param service - The service class (tag)
629
+ * @param impl - The service implementation
630
+ * @returns A function that takes an Fx and returns an Fx with the service provided
631
+ *
632
+ * @example
633
+ * ```ts
634
+ * const result = pipe(
635
+ * myWorkflow,
636
+ * provideService(Config, configImpl),
637
+ * provideService(Logger, loggerImpl),
638
+ * ).run()
639
+ * ```
640
+ */
641
+ declare const provideService: <S>(service: ServiceClass<S>, impl: S) => <A, E, R>(fx: Fx$1<A, E, R | S>) => Fx$1<A, E, Exclude<R, S>>;
642
+ //#endregion
16
643
  //#region src/std.d.ts
17
644
  /**
18
645
  * Main Std namespace containing all utility functions and types.
@@ -94,9 +721,49 @@ declare const Std: {
94
721
  Brand: {
95
722
  readonly make: <B extends Branded<unknown, string>>(value: Unbrand<B>) => B;
96
723
  readonly unsafeMake: <B extends Branded<unknown, string>>(value: Unbrand<B>) => B;
97
- readonly is: <T, K extends string>(validator: Validator<T>) => ((value: T) => value is Branded<T, K>);
724
+ readonly is: <T, K$1 extends string>(validator: Validator<T>) => ((value: T) => value is Branded<T, K$1>);
98
725
  readonly refine: <B extends Branded<unknown, string>>(validator: Validator<Unbrand<B>>, errorMessage?: string | ((value: Unbrand<B>) => string)) => ((value: Unbrand<B>) => Result$1<B, BrandError<Unbrand<B>>>);
99
726
  };
727
+ Fx: {
728
+ readonly gen: {
729
+ <A, E, R>(generatorFn: () => FxGenerator<A, E, R>): SyncFx<A, E, R>;
730
+ <A, E, R>(generatorFn: () => AsyncFxGenerator<A, E, R>): AsyncFx<A, E, R>;
731
+ };
732
+ readonly fn: {
733
+ <A, E>(generatorFn: () => FxGenerator<A, E, never>): Result$1<A, E>;
734
+ <A, E>(generatorFn: () => AsyncFxGenerator<A, E, never>): Promise<Result$1<A, E>>;
735
+ <A, E, E2, R>(generatorFn: () => FxGenerator<A, E, R>, provider: (fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>): Result$1<A, E | E2>;
736
+ <A, E, E2, R>(generatorFn: () => AsyncFxGenerator<A, E, R>, provider: (fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>): Promise<Result$1<A, E | E2>>;
737
+ };
738
+ readonly ok: <T>(value: T) => Result$1<T, never>;
739
+ readonly err: <E>(error: E) => Result$1<never, E>;
740
+ };
741
+ Service: typeof Service;
742
+ Layer: {
743
+ readonly ok: <S>(service: ServiceClass<S>, impl: S) => Layer$1<S, never>;
744
+ readonly err: <E>(error: E) => Layer$1<never, E>;
745
+ readonly fx: <S>(service: ServiceClass<S>) => <E, R>(fx: Fx$1<S, E, R>) => Layer$1<S, E, R>;
746
+ readonly scoped: <S>(service: ServiceClass<S>) => <E, R>(fx: Fx$1<S, E, R | ScopeService>) => Layer$1<S, E, ExcludeScope<R>>;
747
+ readonly provide: <DepsROut, DepsE, DepsRIn>(deps: Layer$1<DepsROut, DepsE, DepsRIn>) => <ROut, E, RIn extends DepsROut>(layer: Layer$1<ROut, E, RIn>) => Layer$1<ROut | DepsROut, E | DepsE, DepsRIn>;
748
+ readonly merge: <L extends Layer$1<unknown, unknown, unknown>[]>(...layers: L) => Layer$1<MergeROut<L>, MergeError<L>, UnprovidedDeps<L>>;
749
+ };
750
+ Context: {
751
+ readonly empty: () => Context;
752
+ readonly make: <S>(service: ServiceClass<S>, impl: S) => Context<S>;
753
+ readonly add: <S>(service: ServiceClass<S>, impl: S) => <Existing>(ctx: Context<Existing>) => Context<Existing | S>;
754
+ readonly merge: <A, B>(a: Context<A>, b: Context<B>) => Context<A | B>;
755
+ readonly get: {
756
+ <S>(ctx: Context<S>, service: ServiceClass<S>): S;
757
+ <S>(service: ServiceClass<S>): (ctx: Context<S>) => S;
758
+ };
759
+ readonly unsafeGet: (ctx: Context<unknown>, key: string) => unknown;
760
+ readonly has: <S>(ctx: Context<unknown>, service: ServiceClass<S>) => boolean;
761
+ readonly keys: (ctx: Context<unknown>) => string[];
762
+ readonly size: (ctx: Context<unknown>) => number;
763
+ readonly isContext: (value: unknown) => value is Context<unknown>;
764
+ };
765
+ Scope: typeof ScopeTag;
766
+ provide: <ROut, E2>(layer: Layer$1<ROut, E2>) => <A, E, R extends ROut>(fx: Fx$1<A, E, R>) => Fx$1<A, E | E2, never>;
100
767
  ok: <T>(value: T) => Result$1<T, never>;
101
768
  err: <E>(error: E) => Result$1<never, E>;
102
769
  isOk: <T, E>(result: Result$1<T, E>) => result is Extract<Result$1<T, E>, {
@@ -131,5 +798,5 @@ declare const Std: {
131
798
  tuple: typeof tuple;
132
799
  };
133
800
  //#endregion
134
- export { type ADT, type ArrayValue, type AsyncComputation, type AsyncYieldable, Brand, type BrandError, type BrandKey, type Brand$1 as BrandType, type Branded, type Computation, Either, type Either$1 as EitherType, Err, type ErrorData, type ErrorTag, type Infer, type InferInput, type InferOutput, type None, Option, type Option$1 as OptionType, Predicate, type Predicate$1 as PredicateType, type RecordDef, type RecordObject, type Refinement, Result, type Result$1 as ResultType, Std, type StructValue, type SyncComputation, type TaggedConstructor, TaggedError, type TaggedErrorFactory, type TaggedErrorInstance, type TaggedError$1 as TaggedErrorType, type TaggedValue, type TupleValue, type Unbrand, type ValidationError, type Yieldable, array, data, ensure, ensureRefinement, flow, fn, gen, pipe, record, struct, tagged, tuple };
801
+ export { type ADT, type ArrayValue, type AsyncComputation, type AsyncFx, type AsyncYieldable, Brand, type BrandError, type BrandKey, type Brand$1 as BrandType, type Branded, type Computation, Context, type Context as ContextType, Either, type Either$1 as EitherType, Err, type ErrorData, type ErrorTag, Fx, type FxError, type FxRequirements, type FxSuccess, type Fx$1 as FxType, type Infer, type InferInput, type InferOutput, Layer, type LayerError, type LayerRIn, type LayerROut, type Layer$1 as LayerType, type None, Option, type Option$1 as OptionType, Predicate, type Predicate$1 as PredicateType, type RecordDef, type RecordObject, type Refinement, Result, type Result$1 as ResultType, ScopeTag as Scope, type ScopeService, Service, type ServiceClass, type ServiceOf, type ServiceRequest, Std, type StructValue, type SyncComputation, type SyncFx, type TaggedConstructor, TaggedError, type TaggedErrorFactory, type TaggedErrorInstance, type TaggedError$1 as TaggedErrorType, type TaggedValue, type TupleValue, type Unbrand, type ValidationError, type Yieldable, array, data, ensure, ensureRefinement, flow, fn, gen, pipe, provide, provideContext, provideService, record, serviceTag, struct, tagged, tuple };
135
802
  //# sourceMappingURL=index.d.mts.map