effect 4.0.0-beta.93 → 4.0.0-beta.94

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/Config.d.ts +1 -1
  2. package/dist/Config.d.ts.map +1 -1
  3. package/dist/Config.js.map +1 -1
  4. package/dist/Effect.d.ts +130 -0
  5. package/dist/Effect.d.ts.map +1 -1
  6. package/dist/Effect.js +43 -0
  7. package/dist/Effect.js.map +1 -1
  8. package/dist/FileSystem.d.ts +7 -0
  9. package/dist/FileSystem.d.ts.map +1 -1
  10. package/dist/FileSystem.js +3 -0
  11. package/dist/FileSystem.js.map +1 -1
  12. package/dist/Layer.d.ts +1 -1
  13. package/dist/Layer.d.ts.map +1 -1
  14. package/dist/Layer.js +6 -3
  15. package/dist/Layer.js.map +1 -1
  16. package/dist/LayerMap.js +1 -1
  17. package/dist/LayerMap.js.map +1 -1
  18. package/dist/LayerRef.d.ts +252 -0
  19. package/dist/LayerRef.d.ts.map +1 -0
  20. package/dist/LayerRef.js +171 -0
  21. package/dist/LayerRef.js.map +1 -0
  22. package/dist/Schema.d.ts +74 -30
  23. package/dist/Schema.d.ts.map +1 -1
  24. package/dist/Schema.js.map +1 -1
  25. package/dist/SchemaParser.d.ts +1 -1
  26. package/dist/SchemaParser.d.ts.map +1 -1
  27. package/dist/SchemaParser.js.map +1 -1
  28. package/dist/internal/effect.js +2 -0
  29. package/dist/internal/effect.js.map +1 -1
  30. package/dist/testing/TestSchema.d.ts +2 -2
  31. package/dist/testing/TestSchema.d.ts.map +1 -1
  32. package/dist/testing/TestSchema.js.map +1 -1
  33. package/dist/unstable/ai/Chat.d.ts +1 -1
  34. package/dist/unstable/ai/Chat.d.ts.map +1 -1
  35. package/dist/unstable/ai/LanguageModel.d.ts +2 -2
  36. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  37. package/dist/unstable/cli/Argument.d.ts +2 -2
  38. package/dist/unstable/cli/Argument.d.ts.map +1 -1
  39. package/dist/unstable/cli/Argument.js.map +1 -1
  40. package/dist/unstable/cli/Flag.d.ts +2 -2
  41. package/dist/unstable/cli/Flag.d.ts.map +1 -1
  42. package/dist/unstable/cli/Flag.js.map +1 -1
  43. package/dist/unstable/cli/Param.d.ts +2 -2
  44. package/dist/unstable/cli/Param.d.ts.map +1 -1
  45. package/dist/unstable/cli/Param.js.map +1 -1
  46. package/dist/unstable/cli/Primitive.js.map +1 -1
  47. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  48. package/dist/unstable/cluster/ClusterWorkflowEngine.js +1 -0
  49. package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
  50. package/dist/unstable/cluster/Entity.d.ts.map +1 -1
  51. package/dist/unstable/cluster/Entity.js +5 -3
  52. package/dist/unstable/cluster/Entity.js.map +1 -1
  53. package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
  54. package/dist/unstable/cluster/Sharding.js +3 -1
  55. package/dist/unstable/cluster/Sharding.js.map +1 -1
  56. package/dist/unstable/cluster/internal/entityManager.js +3 -2
  57. package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
  58. package/dist/unstable/cluster/internal/resourceMap.js +39 -14
  59. package/dist/unstable/cluster/internal/resourceMap.js.map +1 -1
  60. package/dist/unstable/encoding/Sse.d.ts +2 -2
  61. package/dist/unstable/encoding/Sse.d.ts.map +1 -1
  62. package/dist/unstable/http/HttpClientResponse.d.ts +1 -1
  63. package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
  64. package/dist/unstable/http/HttpClientResponse.js.map +1 -1
  65. package/dist/unstable/http/HttpIncomingMessage.d.ts +2 -2
  66. package/dist/unstable/http/HttpIncomingMessage.d.ts.map +1 -1
  67. package/dist/unstable/http/HttpIncomingMessage.js.map +1 -1
  68. package/dist/unstable/http/HttpRouter.d.ts +4 -4
  69. package/dist/unstable/http/HttpRouter.d.ts.map +1 -1
  70. package/dist/unstable/http/HttpRouter.js.map +1 -1
  71. package/dist/unstable/http/HttpServerRequest.d.ts +8 -8
  72. package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
  73. package/dist/unstable/http/HttpServerRequest.js.map +1 -1
  74. package/dist/unstable/http/HttpServerResponse.d.ts +1 -1
  75. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  76. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  77. package/dist/unstable/http/Multipart.d.ts +2 -2
  78. package/dist/unstable/http/Multipart.d.ts.map +1 -1
  79. package/dist/unstable/http/Multipart.js.map +1 -1
  80. package/dist/unstable/httpapi/HttpApi.d.ts.map +1 -1
  81. package/dist/unstable/httpapi/HttpApi.js +2 -4
  82. package/dist/unstable/httpapi/HttpApi.js.map +1 -1
  83. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  84. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +7 -7
  85. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  86. package/dist/unstable/httpapi/HttpApiSchema.d.ts +1 -1
  87. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  88. package/dist/unstable/reactivity/Atom.d.ts +4 -4
  89. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  90. package/dist/unstable/reactivity/Atom.js.map +1 -1
  91. package/package.json +1 -1
  92. package/src/Config.ts +1 -1
  93. package/src/Effect.ts +131 -0
  94. package/src/FileSystem.ts +13 -0
  95. package/src/Layer.ts +6 -6
  96. package/src/LayerMap.ts +1 -1
  97. package/src/LayerRef.ts +379 -0
  98. package/src/Schema.ts +80 -33
  99. package/src/SchemaParser.ts +2 -2
  100. package/src/internal/effect.ts +19 -0
  101. package/src/testing/TestSchema.ts +2 -2
  102. package/src/unstable/ai/Chat.ts +1 -1
  103. package/src/unstable/ai/LanguageModel.ts +3 -3
  104. package/src/unstable/cli/Argument.ts +14 -7
  105. package/src/unstable/cli/Flag.ts +6 -3
  106. package/src/unstable/cli/Param.ts +6 -3
  107. package/src/unstable/cli/Primitive.ts +2 -2
  108. package/src/unstable/cluster/ClusterWorkflowEngine.ts +1 -0
  109. package/src/unstable/cluster/Entity.ts +13 -14
  110. package/src/unstable/cluster/Sharding.ts +134 -131
  111. package/src/unstable/cluster/internal/entityManager.ts +11 -9
  112. package/src/unstable/cluster/internal/resourceMap.ts +59 -25
  113. package/src/unstable/encoding/Sse.ts +3 -3
  114. package/src/unstable/http/HttpClientResponse.ts +2 -3
  115. package/src/unstable/http/HttpIncomingMessage.ts +4 -5
  116. package/src/unstable/http/HttpRouter.ts +8 -10
  117. package/src/unstable/http/HttpServerRequest.ts +20 -19
  118. package/src/unstable/http/HttpServerResponse.ts +2 -2
  119. package/src/unstable/http/Multipart.ts +3 -3
  120. package/src/unstable/httpapi/HttpApi.ts +2 -4
  121. package/src/unstable/httpapi/HttpApiClient.ts +2 -2
  122. package/src/unstable/httpapi/HttpApiEndpoint.ts +7 -7
  123. package/src/unstable/httpapi/HttpApiSchema.ts +1 -1
  124. package/src/unstable/reactivity/Atom.ts +10 -7
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Creates refreshable references to a single layer-built service context.
3
+ *
4
+ * A `LayerRef<I, E>` builds one `Layer` into a cached `Context<I>`, exposes it
5
+ * back as a layer or scoped effect, and supports invalidation so later users can
6
+ * acquire a fresh context.
7
+ *
8
+ * @since 4.0.0
9
+ */
10
+ import * as Context from "./Context.ts"
11
+ import type * as Duration from "./Duration.ts"
12
+ import * as Effect from "./Effect.ts"
13
+ import { identity } from "./Function.ts"
14
+ import { getStackTraceLimit, setStackTraceLimit } from "./internal/stackTraceLimit.ts"
15
+ import * as Layer from "./Layer.ts"
16
+ import * as RcRef from "./RcRef.ts"
17
+ import type * as Schedule from "./Schedule.ts"
18
+ import * as Scope from "./Scope.ts"
19
+ import type { Mutable } from "./Types.ts"
20
+
21
+ const TypeId = "~effect/LayerRef"
22
+
23
+ /**
24
+ * A refreshable reference to a single layer-built service context.
25
+ *
26
+ * **When to use**
27
+ *
28
+ * Use when you want to share one scoped layer resource across many users while
29
+ * retaining the ability to invalidate it and rebuild it later.
30
+ *
31
+ * **Details**
32
+ *
33
+ * A `LayerRef` is the unkeyed counterpart to a layer cache: it lazily builds the
34
+ * layer on first use, reuses the resulting context while it is borrowed or kept
35
+ * idle, and can invalidate the cached context so the next use rebuilds it.
36
+ *
37
+ * @see {@link make} for constructing a `LayerRef` from a layer
38
+ * @see {@link Service} for defining a `LayerRef` as a service class
39
+ *
40
+ * @category models
41
+ * @since 4.0.0
42
+ */
43
+ export interface LayerRef<in out I, in out E = never> {
44
+ readonly [TypeId]: typeof TypeId
45
+
46
+ /**
47
+ * The underlying reference-counted cache that stores the built context.
48
+ */
49
+ readonly rcRef: RcRef.RcRef<Context.Context<I>, E>
50
+
51
+ /**
52
+ * Layer that provides the currently cached context, acquiring it if needed.
53
+ */
54
+ readonly get: Layer.Layer<I, E>
55
+
56
+ /**
57
+ * Scoped effect that retrieves the currently cached context, acquiring it if needed.
58
+ */
59
+ readonly contextEffect: Effect.Effect<Context.Context<I>, E, Scope.Scope>
60
+
61
+ /**
62
+ * Invalidates the cached context so the next use rebuilds the layer.
63
+ */
64
+ readonly invalidate: Effect.Effect<void>
65
+
66
+ /**
67
+ * Invalidates the cached context so the next use rebuilds the layer, and
68
+ * reacquires it.
69
+ */
70
+ readonly refresh: Effect.Effect<void, E>
71
+ }
72
+
73
+ /**
74
+ * Creates a `LayerRef` from a `Layer`.
75
+ *
76
+ * **When to use**
77
+ *
78
+ * Use when you have one layer-built resource that should be shared, optionally
79
+ * kept alive while idle, and refreshed on demand.
80
+ *
81
+ * **Details**
82
+ *
83
+ * The layer is built lazily on first use unless `preload` is `true`.
84
+ * `idleTimeToLive` keeps the context cached after it stops being used, and
85
+ * `invalidationSchedule` can periodically invalidate it. When `preload` is
86
+ * `true`, scheduled invalidation also reacquires the context.
87
+ *
88
+ * **Gotchas**
89
+ *
90
+ * Invalidation does not revoke contexts already borrowed by active scopes; those
91
+ * contexts remain usable until their scopes close.
92
+ *
93
+ * **Example** (Sharing one layer-built service)
94
+ *
95
+ * ```ts
96
+ * import { Context, Effect, Layer } from "effect"
97
+ * import { make } from "effect/LayerRef"
98
+ *
99
+ * class Database extends Context.Service<Database, {
100
+ * readonly query: Effect.Effect<string>
101
+ * }>()("Database") {}
102
+ *
103
+ * const databaseLayer = Layer.succeed(Database, {
104
+ * query: Effect.succeed("result")
105
+ * })
106
+ *
107
+ * const query = Effect.gen(function*() {
108
+ * const database = yield* Database
109
+ * return yield* database.query
110
+ * })
111
+ *
112
+ * const program = Effect.scoped(
113
+ * Effect.gen(function*() {
114
+ * const ref = yield* make(databaseLayer, {
115
+ * idleTimeToLive: "5 seconds"
116
+ * })
117
+ *
118
+ * const result = yield* Effect.provide(query, ref.get)
119
+ *
120
+ * yield* ref.invalidate
121
+ *
122
+ * return result
123
+ * })
124
+ * )
125
+ * ```
126
+ *
127
+ * @see {@link Service} for defining a reusable service class around a `LayerRef`
128
+ *
129
+ * @category constructors
130
+ * @since 4.0.0
131
+ */
132
+ export const make = Effect.fnUntraced(
133
+ function*<I, E, R, X, const Preload extends boolean = never, SE = never, SR = never>(
134
+ layer: Layer.Layer<I, E, R>,
135
+ options?: {
136
+ /**
137
+ * Duration to keep the resource alive after it is no longer used.
138
+ */
139
+ readonly idleTimeToLive?: Duration.Input | undefined
140
+ /**
141
+ * Whether to acquire the resource during creation.
142
+ */
143
+ readonly preload?: Preload | undefined
144
+ /**
145
+ * Schedule used to invalidate the cached resource. When `preload` is
146
+ * `true`, each scheduled invalidation also reacquires the resource.
147
+ */
148
+ readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined
149
+ } | undefined
150
+ ): Effect.fn.Return<
151
+ LayerRef<I, E>,
152
+ [Preload] extends [true] ? E : never,
153
+ Scope.Scope | R | SR
154
+ > {
155
+ const context = yield* Effect.context<never>()
156
+ const memoMap = Layer.CurrentMemoMap.forkOrCreate(context)
157
+
158
+ const rcRef = yield* RcRef.make({
159
+ acquire: Effect.contextWith((_: Context.Context<Scope.Scope>) =>
160
+ Layer.buildWithMemoMap(layer, memoMap, Context.get(_, Scope.Scope))
161
+ ),
162
+ idleTimeToLive: options?.idleTimeToLive
163
+ })
164
+
165
+ const refresh = RcRef.invalidate(rcRef).pipe(
166
+ Effect.andThen(Effect.scoped(RcRef.get(rcRef))),
167
+ Effect.asVoid
168
+ )
169
+
170
+ if (options?.preload) {
171
+ yield* refresh as Effect.Effect<void>
172
+ }
173
+
174
+ if (options?.invalidationSchedule) {
175
+ const onRefresh = options.preload ? refresh : RcRef.invalidate(rcRef)
176
+ yield* onRefresh.pipe(
177
+ Effect.ignoreCause,
178
+ Effect.schedule(options.invalidationSchedule),
179
+ Effect.forkScoped
180
+ )
181
+ }
182
+
183
+ return identity<LayerRef<I, any>>({
184
+ [TypeId]: TypeId,
185
+ rcRef,
186
+ get: Layer.effectContext(RcRef.get(rcRef)),
187
+ contextEffect: RcRef.get(rcRef),
188
+ invalidate: RcRef.invalidate(rcRef),
189
+ refresh
190
+ })
191
+ }
192
+ )
193
+
194
+ /**
195
+ * Service class shape produced by `LayerRef.Service`.
196
+ *
197
+ * **When to use**
198
+ *
199
+ * Use as the public type for classes returned by `LayerRef.Service` when an API
200
+ * needs to accept, return, or alias the generated service class and its static
201
+ * helpers.
202
+ *
203
+ * **Details**
204
+ *
205
+ * It combines a `Context.Service` tag for the `LayerRef` with default layers and
206
+ * helper accessors for retrieving, using, and invalidating the cached resource.
207
+ *
208
+ * @see {@link Service} for creating concrete `LayerRef` service classes
209
+ *
210
+ * @category services
211
+ * @since 4.0.0
212
+ */
213
+ export interface TagClass<
214
+ in out Self,
215
+ in out Id extends string,
216
+ in out I,
217
+ in out E,
218
+ in out R,
219
+ in out LE,
220
+ in out Deps extends Layer.Layer<any, any, any>
221
+ > extends Context.ServiceClass<Self, Id, LayerRef<I, E>> {
222
+ /**
223
+ * Default layer for the `LayerRef` service, with dependencies applied.
224
+ */
225
+ readonly layer: Layer.Layer<
226
+ Self,
227
+ (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _E : never) | LE,
228
+ | Exclude<R, (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _A : never)>
229
+ | (Deps extends Layer.Layer<infer _A, infer _E, infer _R> ? _R : never)
230
+ >
231
+
232
+ /**
233
+ * Default layer for the `LayerRef` service without provided dependencies.
234
+ */
235
+ readonly layerNoDeps: Layer.Layer<Self, LE, R>
236
+
237
+ /**
238
+ * Layer that provides the currently cached context, requiring this service.
239
+ */
240
+ readonly get: Layer.Layer<I, E, Self>
241
+
242
+ /**
243
+ * Scoped effect that retrieves the currently cached context through this service.
244
+ */
245
+ readonly contextEffect: Effect.Effect<Context.Context<I>, E, Scope.Scope | Self>
246
+
247
+ /**
248
+ * Invalidates the cached context through this service.
249
+ */
250
+ readonly invalidate: Effect.Effect<void, never, Self>
251
+
252
+ /**
253
+ * Invalidates the cached context through this service, and reacquires it.
254
+ */
255
+ readonly refresh: Effect.Effect<void, E, Self>
256
+ }
257
+
258
+ /**
259
+ * Creates a service class for a `LayerRef`.
260
+ *
261
+ * **When to use**
262
+ *
263
+ * Use when you want to name a shared layer reference as an application service
264
+ * and expose static helpers for providing, retrieving, and invalidating it.
265
+ *
266
+ * **Details**
267
+ *
268
+ * The returned class is a `Context.Service` whose value is a `LayerRef`. It also
269
+ * includes `.layer`, `.layerNoDeps`, `.get`, `.contextEffect`, and `.invalidate`
270
+ * helpers so callers do not need to access the `LayerRef` value directly.
271
+ *
272
+ * **Example** (Defining a refreshable service)
273
+ *
274
+ * ```ts
275
+ * import { Context, Effect, Layer } from "effect"
276
+ * import { Service } from "effect/LayerRef"
277
+ *
278
+ * class Database extends Context.Service<Database, {
279
+ * readonly query: Effect.Effect<string>
280
+ * }>()("Database") {}
281
+ *
282
+ * const databaseLayer = Layer.succeed(Database, {
283
+ * query: Effect.succeed("result")
284
+ * })
285
+ *
286
+ * class DatabaseRef extends Service<DatabaseRef>()("DatabaseRef", {
287
+ * layer: databaseLayer,
288
+ * preload: true
289
+ * }) {}
290
+ *
291
+ * const program = Effect.gen(function*() {
292
+ * const database = yield* Database
293
+ * return yield* database.query
294
+ * }).pipe(
295
+ * Effect.provide(DatabaseRef.get),
296
+ * Effect.provide(DatabaseRef.layer)
297
+ * )
298
+ * ```
299
+ *
300
+ * @see {@link make} for creating a `LayerRef` value without defining a service class
301
+ *
302
+ * @category services
303
+ * @since 4.0.0
304
+ */
305
+ export const Service = <Self>() =>
306
+ <
307
+ const Id extends string,
308
+ I,
309
+ E,
310
+ R,
311
+ X,
312
+ const Deps extends ReadonlyArray<Layer.Layer<any, any, any>> = [],
313
+ const Preload extends boolean = never,
314
+ SE = never,
315
+ SR = never
316
+ >(
317
+ id: Id,
318
+ options: {
319
+ /**
320
+ * Layer used to build the cached context.
321
+ */
322
+ readonly layer: Layer.Layer<I, E, R>
323
+ /**
324
+ * Layers used to satisfy dependencies of the `LayerRef` service layer.
325
+ */
326
+ readonly dependencies?: Deps | undefined
327
+ /**
328
+ * Duration to keep the resource alive after it is no longer used.
329
+ */
330
+ readonly idleTimeToLive?: Duration.Input | undefined
331
+ /**
332
+ * Whether to acquire the resource during creation.
333
+ */
334
+ readonly preload?: Preload | undefined
335
+ /**
336
+ * Schedule used to invalidate the cached resource. When `preload` is
337
+ * `true`, each scheduled invalidation also reacquires the resource.
338
+ */
339
+ readonly invalidationSchedule?: Schedule.Schedule<X, unknown, SE, SR> | undefined
340
+ }
341
+ ): TagClass<
342
+ Self,
343
+ Id,
344
+ I,
345
+ E,
346
+ R | SR,
347
+ [Preload] extends [true] ? E : never,
348
+ Deps[number]
349
+ > => {
350
+ const Err = globalThis.Error as any
351
+ const limit = getStackTraceLimit()
352
+ setStackTraceLimit(2)
353
+ const creationError = new Err()
354
+ setStackTraceLimit(limit)
355
+
356
+ function TagClass() {}
357
+ const TagClass_ = TagClass as any as Mutable<TagClass<Self, Id, any, any, any, any, any>>
358
+ Object.setPrototypeOf(TagClass, Object.getPrototypeOf(Context.Service<Self, any>(id)))
359
+ TagClass.key = id
360
+ Object.defineProperty(TagClass, "stack", {
361
+ get() {
362
+ return creationError.stack
363
+ }
364
+ })
365
+
366
+ TagClass_.layerNoDeps = Layer.effect(TagClass_)(
367
+ make(options.layer, options)
368
+ )
369
+ TagClass_.layer = options.dependencies && options.dependencies.length > 0 ?
370
+ Layer.provide(TagClass_.layerNoDeps, options.dependencies as any) :
371
+ TagClass_.layerNoDeps
372
+
373
+ TagClass_.get = Layer.unwrap(TagClass_.useSync((ref) => ref.get))
374
+ TagClass_.contextEffect = TagClass_.use((ref) => ref.contextEffect)
375
+ TagClass_.invalidate = TagClass_.use((ref) => ref.invalidate)
376
+ TagClass_.refresh = TagClass_.use((ref) => ref.refresh)
377
+
378
+ return TagClass as any
379
+ }
package/src/Schema.ts CHANGED
@@ -888,31 +888,6 @@ export declare namespace Codec {
888
888
  export type EncodingServices<S> = S extends { readonly "EncodingServices": infer R } ? R : never
889
889
  }
890
890
 
891
- /**
892
- * A schema that additionally supports optic (lens/prism) operations.
893
- *
894
- * **Details**
895
- *
896
- * `Optic<T, Iso>` extends {@link Schema}`<T>` with an `Iso` type that
897
- * describes the isomorphic counterpart used by the optic layer. Crucially,
898
- * decoding and encoding require *no* Effect services (`DecodingServices` and
899
- * `EncodingServices` are both `never`), which means the optic can operate
900
- * purely without an Effect runtime.
901
- *
902
- * Most primitive schemas (e.g. `Schema.String`, `Schema.Number`) implement
903
- * `Optic` automatically. You normally interact with this interface through
904
- * {@link Optic_} utilities rather than constructing it directly.
905
- *
906
- * @category models
907
- * @since 4.0.0
908
- */
909
- export interface Optic<out T, out Iso> extends Schema<T> {
910
- readonly "Iso": Iso
911
- readonly "DecodingServices": never
912
- readonly "EncodingServices": never
913
- readonly "Rebuild": Optic<T, Iso>
914
- }
915
-
916
891
  /**
917
892
  * A schema that tracks the decoded type `T`, the encoded type `E`, and the
918
893
  * Effect services required during decoding (`RD`) and encoding (`RE`).
@@ -924,8 +899,8 @@ export interface Optic<out T, out Iso> extends Schema<T> {
924
899
  * Most concrete schemas produced by this module implement `Codec`.
925
900
  *
926
901
  * For APIs that only need one direction, prefer the narrower views:
927
- * - {@link ConstraintDecoder}`<T, RD>` — decode-only
928
- * - {@link ConstraintEncoder}`<E, RE>` — encode-only
902
+ * - {@link Decoder}`<T, RD>` — decode-only
903
+ * - {@link Encoder}`<E, RE>` — encode-only
929
904
  * - {@link Schema}`<T>` — type-only (no encoded representation)
930
905
  *
931
906
  * **Example** (Accepting a codec that decodes to `number` from `string`)
@@ -953,6 +928,52 @@ export interface Codec<out T, out E = T, out RD = never, out RE = never> extends
953
928
  readonly "Rebuild": Codec<T, E, RD, RE>
954
929
  }
955
930
 
931
+ /**
932
+ * A schema that tracks the decoded type `T` and the Effect services required
933
+ * during decoding (`RD`).
934
+ *
935
+ * **When to use**
936
+ *
937
+ * Use when you need to preserve a schema's decoded type and decoding service
938
+ * requirements, but do not need to constrain its encoded representation or
939
+ * encoding services.
940
+ *
941
+ * @see {@link Codec} for preserving both decoded and encoded type information.
942
+ * @see {@link Encoder} for the encode-only view.
943
+ *
944
+ * @category models
945
+ * @since 4.0.0
946
+ */
947
+ export interface Decoder<out T, out RD = never> extends Schema<T> {
948
+ readonly "Encoded": unknown
949
+ readonly "DecodingServices": RD
950
+ readonly "EncodingServices": unknown
951
+ readonly "Rebuild": Decoder<T, RD>
952
+ }
953
+
954
+ /**
955
+ * A schema that tracks the encoded type `E` and the Effect services required
956
+ * during encoding (`RE`).
957
+ *
958
+ * **When to use**
959
+ *
960
+ * Use when you need to preserve a schema's encoded type and encoding service
961
+ * requirements, but do not need to constrain its decoded representation or
962
+ * decoding services.
963
+ *
964
+ * @see {@link Codec} for preserving both decoded and encoded type information.
965
+ * @see {@link Decoder} for the decode-only view.
966
+ *
967
+ * @category models
968
+ * @since 4.0.0
969
+ */
970
+ export interface Encoder<out E, out RE = never> extends Schema<unknown> {
971
+ readonly "Encoded": E
972
+ readonly "DecodingServices": unknown
973
+ readonly "EncodingServices": RE
974
+ readonly "Rebuild": Encoder<E, RE>
975
+ }
976
+
956
977
  /**
957
978
  * Returns a codec widened to the full {@link Codec} interface, prompting
958
979
  * TypeScript to infer all four type parameters (`T`, `E`, `RD`, `RE`).
@@ -982,6 +1003,31 @@ export function revealCodec<T, E, RD, RE>(codec: Codec<T, E, RD, RE>) {
982
1003
  return codec
983
1004
  }
984
1005
 
1006
+ /**
1007
+ * A schema that additionally supports optic (lens/prism) operations.
1008
+ *
1009
+ * **Details**
1010
+ *
1011
+ * `Optic<T, Iso>` extends {@link Schema}`<T>` with an `Iso` type that
1012
+ * describes the isomorphic counterpart used by the optic layer. Crucially,
1013
+ * decoding and encoding require *no* Effect services (`DecodingServices` and
1014
+ * `EncodingServices` are both `never`), which means the optic can operate
1015
+ * purely without an Effect runtime.
1016
+ *
1017
+ * Most primitive schemas (e.g. `Schema.String`, `Schema.Number`) implement
1018
+ * `Optic` automatically. You normally interact with this interface through
1019
+ * {@link Optic_} utilities rather than constructing it directly.
1020
+ *
1021
+ * @category models
1022
+ * @since 4.0.0
1023
+ */
1024
+ export interface Optic<out T, out Iso> extends Schema<T> {
1025
+ readonly "Iso": Iso
1026
+ readonly "DecodingServices": never
1027
+ readonly "EncodingServices": never
1028
+ readonly "Rebuild": Optic<T, Iso>
1029
+ }
1030
+
985
1031
  export {
986
1032
  /**
987
1033
  * Error thrown (or returned as the error channel value) when schema decoding
@@ -2757,7 +2803,7 @@ export declare namespace TemplateLiteralParser {
2757
2803
  */
2758
2804
  export type Type<Parts> = Parts extends readonly [infer Head, ...infer Tail] ? readonly [
2759
2805
  Head extends TemplateLiteral.LiteralPart ? Head :
2760
- Head extends Codec<infer T, unknown, unknown, unknown> ? T
2806
+ Head extends ConstraintDecoder<infer T, unknown> ? T
2761
2807
  : never,
2762
2808
  ...Type<Tail>
2763
2809
  ]
@@ -12612,7 +12658,8 @@ function getClassSchemaFactory<S extends Constraint>(
12612
12658
  {
12613
12659
  identifier,
12614
12660
  [SchemaAST.ClassTypeId]: ([from]: readonly [SchemaAST.AST]) => new SchemaAST.Link(from, transformation),
12615
- toCodec: ([from]: readonly [Codec<S["Encoded"]>]) => new SchemaAST.Link(from.ast, transformation),
12661
+ toCodec: ([from]: readonly [ConstraintCodec<S["Encoded"], S["Encoded"]>]) =>
12662
+ new SchemaAST.Link(from.ast, transformation),
12616
12663
  toArbitrary: ([from]: readonly [Annotations.ToArbitrary.TypeParameter<S["Type"]>]) => () => ({
12617
12664
  arbitrary: from.arbitrary.map((args: S["Type"]) => new self(args)),
12618
12665
  terminal: from.terminal?.map((args: S["Type"]) => new self(args))
@@ -14002,8 +14049,8 @@ type XmlEncoderOptions = {
14002
14049
  * @category Canonical Codecs
14003
14050
  * @since 4.0.0
14004
14051
  */
14005
- export function toEncoderXml<T, E, RD, RE>(
14006
- codec: Codec<T, E, RD, RE>,
14052
+ export function toEncoderXml<T, RE>(
14053
+ codec: ConstraintCodec<T, unknown, unknown, RE>,
14007
14054
  options?: XmlEncoderOptions
14008
14055
  ) {
14009
14056
  const rootName = InternalAnnotations.resolveIdentifier(codec.ast) ?? InternalAnnotations.resolveTitle(codec.ast)
@@ -14338,7 +14385,7 @@ export interface overrideToCodecIso<S extends Constraint, Iso> extends
14338
14385
  * @since 4.0.0
14339
14386
  */
14340
14387
  export function overrideToCodecIso<S extends Constraint, Iso>(
14341
- to: Codec<Iso>,
14388
+ to: ConstraintCodec<Iso>,
14342
14389
  transformation: {
14343
14390
  readonly decode: SchemaGetter.Getter<S["Type"], Iso>
14344
14391
  readonly encode: SchemaGetter.Getter<Iso, S["Type"]>
@@ -14366,7 +14413,7 @@ export function overrideToCodecIso<S extends Constraint, Iso>(
14366
14413
  * @category converting
14367
14414
  * @since 4.0.0
14368
14415
  */
14369
- export function toDifferJsonPatch<T, E>(schema: Codec<T, E>): Differ<T, JsonPatch.JsonPatch> {
14416
+ export function toDifferJsonPatch<T>(schema: ConstraintCodec<T, unknown>): Differ<T, JsonPatch.JsonPatch> {
14370
14417
  const serializer = toCodecJson(schema)
14371
14418
  const get = SchemaParser.encodeSync(serializer)
14372
14419
  const set = SchemaParser.decodeSync(serializer)
@@ -170,8 +170,8 @@ export function make<S extends Schema.Constraint>(schema: S) {
170
170
  * @category Asserting
171
171
  * @since 3.10.0
172
172
  */
173
- export function is<T>(schema: Schema.Schema<T>): <I>(input: I) => input is I & T {
174
- return _is<T>(schema.ast)
173
+ export function is<S extends Schema.Constraint>(schema: S): <I>(input: I) => input is I & S["Type"] {
174
+ return _is<S["Type"]>(schema.ast)
175
175
  }
176
176
 
177
177
  /** @internal */
@@ -2081,6 +2081,25 @@ export const contextWith = <R, A, E, R2>(
2081
2081
  f: (context: Context.Context<R>) => Effect.Effect<A, E, R2>
2082
2082
  ): Effect.Effect<A, E, R | R2> => withFiber((fiber) => f(fiber.context as Context.Context<R>))
2083
2083
 
2084
+ /** @internal */
2085
+ export const setContext: {
2086
+ <R>(
2087
+ context: Context.Context<R>
2088
+ ): <A, E>(
2089
+ self: Effect.Effect<A, E, R>
2090
+ ) => Effect.Effect<A, E>
2091
+ <A, E, R>(
2092
+ self: Effect.Effect<A, E, R>,
2093
+ context: Context.Context<R>
2094
+ ): Effect.Effect<A, E>
2095
+ } = dual(
2096
+ 2,
2097
+ <A, E, R>(
2098
+ self: Effect.Effect<A, E, R>,
2099
+ context: Context.Context<R>
2100
+ ): Effect.Effect<A, E> => updateContext(self, constant(context))
2101
+ )
2102
+
2084
2103
  /** @internal */
2085
2104
  export const provideContext: {
2086
2105
  <XR>(
@@ -167,7 +167,7 @@ export class Asserts<S extends Schema.Constraint> {
167
167
  *
168
168
  * @see {@link arbitrary} for checking that generated values satisfy the schema
169
169
  */
170
- verifyLosslessTransformation<S extends Schema.Codec<unknown, unknown>>(this: Asserts<S>, options?: {
170
+ verifyLosslessTransformation<S extends Schema.ConstraintCodec<unknown, unknown>>(this: Asserts<S>, options?: {
171
171
  readonly params?: FastCheck.Parameters<[S["Type"]]>
172
172
  }) {
173
173
  const decodeUnknownEffect = SchemaParser.decodeUnknownEffect(this.schema)
@@ -272,7 +272,7 @@ export class Asserts<S extends Schema.Constraint> {
272
272
  *
273
273
  * @see {@link verifyLosslessTransformation} for property-based round-trip checks
274
274
  */
275
- arbitrary<S extends Schema.Codec<unknown, unknown, never, unknown>>(this: Asserts<S>) {
275
+ arbitrary<S extends Schema.ConstraintCodec<unknown, unknown>>(this: Asserts<S>) {
276
276
  const schema = this.schema
277
277
  return {
278
278
  verifyGeneration(options?: {
@@ -336,7 +336,7 @@ export interface Service {
336
336
  */
337
337
  readonly generateObject: <
338
338
  ObjectEncoded extends Record<string, any>,
339
- ObjectSchema extends Schema.Codec<unknown, ObjectEncoded, unknown, unknown>,
339
+ ObjectSchema extends Schema.Encoder<ObjectEncoded, unknown>,
340
340
  Options extends NoExcessProperties<LanguageModel.GenerateObjectOptions<any, ObjectSchema>, Options>
341
341
  >(
342
342
  options: Options & LanguageModel.GenerateObjectOptions<LanguageModel.ExtractTools<Options>, ObjectSchema>
@@ -124,7 +124,7 @@ export interface Service {
124
124
  */
125
125
  readonly generateObject: <
126
126
  ObjectEncoded extends Record<string, any>,
127
- StructuredOutputSchema extends Schema.Codec<unknown, ObjectEncoded, unknown, unknown>,
127
+ StructuredOutputSchema extends Schema.Encoder<ObjectEncoded, unknown>,
128
128
  Options extends NoExcessProperties<
129
129
  GenerateObjectOptions<any, StructuredOutputSchema>,
130
130
  Options
@@ -835,7 +835,7 @@ export const make: (params: {
835
835
 
836
836
  const generateObject = <
837
837
  ObjectEncoded extends Record<string, any>,
838
- StructuredOutputSchema extends Schema.Codec<unknown, ObjectEncoded, unknown, unknown>,
838
+ StructuredOutputSchema extends Schema.Encoder<ObjectEncoded, unknown>,
839
839
  Options extends NoExcessProperties<
840
840
  GenerateObjectOptions<any, StructuredOutputSchema>,
841
841
  Options
@@ -1691,7 +1691,7 @@ export const generateText: {
1691
1691
  */
1692
1692
  export const generateObject = <
1693
1693
  ObjectEncoded extends Record<string, any>,
1694
- StructuredOutputSchema extends Schema.Codec<unknown, ObjectEncoded, unknown, unknown>,
1694
+ StructuredOutputSchema extends Schema.Encoder<ObjectEncoded, unknown>,
1695
1695
  Options extends NoExcessProperties<
1696
1696
  GenerateObjectOptions<any, StructuredOutputSchema>,
1697
1697
  Options
@@ -401,8 +401,8 @@ export const withDefault: {
401
401
  * @since 4.0.0
402
402
  */
403
403
  <A, const B>(
404
- self: Argument<A>,
405
- defaultValue: B | Effect.Effect<B, CliError.CliError, Environment>
404
+ self: Argument<A>,
405
+ defaultValue: B | Effect.Effect<B, CliError.CliError, Environment>
406
406
  ): Argument<A | B>
407
407
  } = Param.withDefault
408
408
 
@@ -729,8 +729,8 @@ export const mapEffect: {
729
729
  * @since 4.0.0
730
730
  */
731
731
  <A, B>(
732
- self: Argument<A>,
733
- f: (a: A) => Effect.Effect<B, CliError.CliError, Environment>
732
+ self: Argument<A>,
733
+ f: (a: A) => Effect.Effect<B, CliError.CliError, Environment>
734
734
  ): Argument<B>
735
735
  } = dual(2, <A, B>(
736
736
  self: Argument<A>,
@@ -982,7 +982,7 @@ export const withSchema: {
982
982
  * @category combinators
983
983
  * @since 4.0.0
984
984
  */
985
- <A, B>(schema: Schema.Codec<B, A, Environment, Environment>): (self: Argument<A>) => Argument<B>
985
+ <A, B>(schema: Schema.ConstraintCodec<B, A, Environment, unknown>): (self: Argument<A>) => Argument<B>
986
986
  /**
987
987
  * Validates parsed values against a Schema.
988
988
  *
@@ -1000,8 +1000,15 @@ export const withSchema: {
1000
1000
  * @category combinators
1001
1001
  * @since 4.0.0
1002
1002
  */
1003
- <A, B>(self: Argument<A>, schema: Schema.Codec<B, A, Environment, Environment>): Argument<B>
1004
- } = dual(2, <A, B>(self: Argument<A>, schema: Schema.Codec<B, A>) => Param.withSchema(self, schema))
1003
+ <A, B>(
1004
+ self: Argument<A>,
1005
+ schema: Schema.ConstraintCodec<B, A, Environment, unknown>
1006
+ ): Argument<B>
1007
+ } = dual(
1008
+ 2,
1009
+ <A, B>(self: Argument<A>, schema: Schema.ConstraintCodec<B, A, Environment, unknown>): Argument<B> =>
1010
+ Param.withSchema(self, schema)
1011
+ )
1005
1012
 
1006
1013
  /**
1007
1014
  * Creates a positional choice argument with custom value mapping.