effect 4.0.0-beta.82 → 4.0.0-beta.84

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 (199) hide show
  1. package/dist/Array.d.ts +64 -64
  2. package/dist/Array.js +26 -26
  3. package/dist/Cache.d.ts +1 -1
  4. package/dist/Cache.js +1 -1
  5. package/dist/Cause.d.ts +68 -68
  6. package/dist/Cause.js +47 -47
  7. package/dist/Channel.d.ts +5 -5
  8. package/dist/Channel.js +3 -3
  9. package/dist/Clock.d.ts +1 -1
  10. package/dist/Clock.js +1 -1
  11. package/dist/Combiner.d.ts +9 -9
  12. package/dist/Combiner.js +8 -8
  13. package/dist/Config.d.ts +15 -94
  14. package/dist/Config.d.ts.map +1 -1
  15. package/dist/Config.js +22 -70
  16. package/dist/Config.js.map +1 -1
  17. package/dist/ConfigProvider.d.ts +58 -74
  18. package/dist/ConfigProvider.d.ts.map +1 -1
  19. package/dist/ConfigProvider.js +66 -41
  20. package/dist/ConfigProvider.js.map +1 -1
  21. package/dist/Console.d.ts +1 -1
  22. package/dist/Console.js +1 -1
  23. package/dist/Data.d.ts +15 -15
  24. package/dist/Data.js +3 -3
  25. package/dist/DateTime.d.ts +6 -6
  26. package/dist/DateTime.js +2 -2
  27. package/dist/Duration.d.ts +3 -3
  28. package/dist/Duration.js +3 -3
  29. package/dist/Effect.d.ts +84 -45
  30. package/dist/Effect.d.ts.map +1 -1
  31. package/dist/Effect.js +72 -33
  32. package/dist/Effect.js.map +1 -1
  33. package/dist/Equal.d.ts +7 -7
  34. package/dist/Equal.js +5 -5
  35. package/dist/Equivalence.d.ts +17 -17
  36. package/dist/Equivalence.js +13 -13
  37. package/dist/Exit.d.ts +3 -3
  38. package/dist/Exit.js +3 -3
  39. package/dist/Formatter.d.ts +5 -5
  40. package/dist/Formatter.js +4 -4
  41. package/dist/Function.d.ts +10 -10
  42. package/dist/Function.js +3 -3
  43. package/dist/HashMap.d.ts +3 -3
  44. package/dist/HashMap.js +1 -1
  45. package/dist/Iterable.d.ts +6 -6
  46. package/dist/Iterable.js +2 -2
  47. package/dist/JsonPatch.d.ts +2 -2
  48. package/dist/Layer.d.ts +1 -1
  49. package/dist/Layer.js +1 -1
  50. package/dist/Logger.d.ts +1 -1
  51. package/dist/Logger.js +1 -1
  52. package/dist/Match.d.ts +8 -8
  53. package/dist/Match.js +8 -8
  54. package/dist/Metric.d.ts +3 -3
  55. package/dist/Metric.js +3 -3
  56. package/dist/Optic.d.ts +30 -30
  57. package/dist/Optic.js +12 -12
  58. package/dist/Option.d.ts +7 -7
  59. package/dist/Option.js +7 -7
  60. package/dist/Order.d.ts +23 -23
  61. package/dist/Order.js +20 -20
  62. package/dist/Pool.d.ts +1 -1
  63. package/dist/Pool.js +1 -1
  64. package/dist/Predicate.d.ts +88 -88
  65. package/dist/Predicate.js +47 -47
  66. package/dist/PubSub.d.ts +3 -3
  67. package/dist/PubSub.js +3 -3
  68. package/dist/Reducer.d.ts +1 -1
  69. package/dist/Reducer.js +1 -1
  70. package/dist/Result.d.ts +18 -18
  71. package/dist/Result.js +8 -8
  72. package/dist/Runtime.d.ts +1 -1
  73. package/dist/Runtime.js +1 -1
  74. package/dist/Schema.d.ts +265 -120
  75. package/dist/Schema.d.ts.map +1 -1
  76. package/dist/Schema.js +285 -116
  77. package/dist/Schema.js.map +1 -1
  78. package/dist/SchemaAST.d.ts +1 -1
  79. package/dist/SchemaAST.d.ts.map +1 -1
  80. package/dist/SchemaAST.js +13 -9
  81. package/dist/SchemaAST.js.map +1 -1
  82. package/dist/SchemaGetter.d.ts +48 -48
  83. package/dist/SchemaGetter.js +44 -44
  84. package/dist/SchemaIssue.d.ts +3 -3
  85. package/dist/SchemaIssue.js +3 -3
  86. package/dist/SchemaParser.d.ts +122 -22
  87. package/dist/SchemaParser.d.ts.map +1 -1
  88. package/dist/SchemaParser.js +186 -50
  89. package/dist/SchemaParser.js.map +1 -1
  90. package/dist/SchemaRepresentation.d.ts +1 -1
  91. package/dist/SchemaRepresentation.d.ts.map +1 -1
  92. package/dist/SchemaRepresentation.js +96 -2
  93. package/dist/SchemaRepresentation.js.map +1 -1
  94. package/dist/SchemaTransformation.d.ts +20 -20
  95. package/dist/SchemaTransformation.js +18 -18
  96. package/dist/Stream.d.ts +3 -3
  97. package/dist/Stream.js +2 -2
  98. package/dist/Stream.js.map +1 -1
  99. package/dist/String.d.ts +1 -1
  100. package/dist/String.js +1 -1
  101. package/dist/Struct.d.ts +1 -1
  102. package/dist/Struct.js +1 -1
  103. package/dist/Types.d.ts +13 -13
  104. package/dist/internal/effect.js +23 -10
  105. package/dist/internal/effect.js.map +1 -1
  106. package/dist/internal/schema/cause.d.ts +2 -0
  107. package/dist/internal/schema/cause.d.ts.map +1 -0
  108. package/dist/internal/schema/cause.js +24 -0
  109. package/dist/internal/schema/cause.js.map +1 -0
  110. package/dist/internal/schema/schema.d.ts +8 -4
  111. package/dist/internal/schema/schema.d.ts.map +1 -1
  112. package/dist/internal/schema/schema.js +21 -8
  113. package/dist/internal/schema/schema.js.map +1 -1
  114. package/dist/testing/TestSchema.d.ts +3 -3
  115. package/dist/testing/TestSchema.js +1 -1
  116. package/dist/unstable/ai/AiError.d.ts +1 -1
  117. package/dist/unstable/ai/AiError.js +1 -1
  118. package/dist/unstable/ai/Chat.d.ts +1 -1
  119. package/dist/unstable/ai/Chat.js +1 -1
  120. package/dist/unstable/cli/Prompt.js +2 -2
  121. package/dist/unstable/cli/Prompt.js.map +1 -1
  122. package/dist/unstable/httpapi/HttpApiScalar.d.ts +2 -2
  123. package/dist/unstable/httpapi/HttpApiSchema.d.ts +39 -0
  124. package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
  125. package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
  126. package/dist/unstable/rpc/Rpc.d.ts +1 -1
  127. package/dist/unstable/rpc/Rpc.js +1 -1
  128. package/dist/unstable/rpc/RpcGroup.d.ts.map +1 -1
  129. package/dist/unstable/rpc/RpcGroup.js +3 -4
  130. package/dist/unstable/rpc/RpcGroup.js.map +1 -1
  131. package/dist/unstable/sql/SqlResolver.d.ts.map +1 -1
  132. package/dist/unstable/sql/SqlResolver.js +15 -2
  133. package/dist/unstable/sql/SqlResolver.js.map +1 -1
  134. package/dist/unstable/workflow/Activity.d.ts +1 -0
  135. package/dist/unstable/workflow/Activity.d.ts.map +1 -1
  136. package/dist/unstable/workflow/Activity.js +1 -0
  137. package/dist/unstable/workflow/Activity.js.map +1 -1
  138. package/dist/unstable/workflow/WorkflowEngine.js +1 -1
  139. package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
  140. package/package.json +1 -1
  141. package/src/Array.ts +65 -65
  142. package/src/Cache.ts +1 -1
  143. package/src/Cause.ts +68 -68
  144. package/src/Channel.ts +5 -5
  145. package/src/Clock.ts +1 -1
  146. package/src/Combiner.ts +9 -9
  147. package/src/Config.ts +40 -108
  148. package/src/ConfigProvider.ts +139 -100
  149. package/src/Console.ts +1 -1
  150. package/src/Data.ts +15 -15
  151. package/src/DateTime.ts +6 -6
  152. package/src/Duration.ts +3 -3
  153. package/src/Effect.ts +89 -45
  154. package/src/Equal.ts +7 -7
  155. package/src/Equivalence.ts +17 -17
  156. package/src/Exit.ts +3 -3
  157. package/src/Formatter.ts +5 -5
  158. package/src/Function.ts +10 -10
  159. package/src/HashMap.ts +3 -3
  160. package/src/Iterable.ts +6 -6
  161. package/src/JsonPatch.ts +2 -2
  162. package/src/Layer.ts +1 -1
  163. package/src/Logger.ts +1 -1
  164. package/src/Match.ts +8 -8
  165. package/src/Metric.ts +3 -3
  166. package/src/Optic.ts +30 -30
  167. package/src/Option.ts +7 -7
  168. package/src/Order.ts +23 -23
  169. package/src/Pool.ts +1 -1
  170. package/src/Predicate.ts +88 -88
  171. package/src/PubSub.ts +3 -3
  172. package/src/Reducer.ts +1 -1
  173. package/src/Result.ts +20 -20
  174. package/src/Runtime.ts +1 -1
  175. package/src/Schema.ts +314 -131
  176. package/src/SchemaAST.ts +20 -11
  177. package/src/SchemaGetter.ts +48 -48
  178. package/src/SchemaIssue.ts +3 -3
  179. package/src/SchemaParser.ts +197 -58
  180. package/src/SchemaRepresentation.ts +73 -3
  181. package/src/SchemaTransformation.ts +20 -20
  182. package/src/Stream.ts +4 -4
  183. package/src/String.ts +1 -1
  184. package/src/Struct.ts +1 -1
  185. package/src/Types.ts +13 -13
  186. package/src/internal/effect.ts +29 -10
  187. package/src/internal/schema/cause.ts +26 -0
  188. package/src/internal/schema/schema.ts +36 -10
  189. package/src/testing/TestSchema.ts +3 -3
  190. package/src/unstable/ai/AiError.ts +1 -1
  191. package/src/unstable/ai/Chat.ts +1 -1
  192. package/src/unstable/cli/Prompt.ts +1 -1
  193. package/src/unstable/httpapi/HttpApiScalar.ts +2 -2
  194. package/src/unstable/httpapi/HttpApiSchema.ts +18 -6
  195. package/src/unstable/rpc/Rpc.ts +1 -1
  196. package/src/unstable/rpc/RpcGroup.ts +3 -4
  197. package/src/unstable/sql/SqlResolver.ts +15 -2
  198. package/src/unstable/workflow/Activity.ts +2 -0
  199. package/src/unstable/workflow/WorkflowEngine.ts +1 -1
@@ -14,7 +14,8 @@ import * as Arr from "./Array.ts"
14
14
  import * as Cause from "./Cause.ts"
15
15
  import * as Effect from "./Effect.ts"
16
16
  import * as Exit from "./Exit.ts"
17
- import { identity, memoize } from "./Function.ts"
17
+ import { memoize } from "./Function.ts"
18
+ import * as InternalSchemaCause from "./internal/schema/cause.ts"
18
19
  import * as Option from "./Option.ts"
19
20
  import * as Predicate from "./Predicate.ts"
20
21
  import * as Result from "./Result.ts"
@@ -81,20 +82,31 @@ export function makeEffect<S extends Schema.Top>(schema: S) {
81
82
 
82
83
  /**
83
84
  * Creates a synchronous maker that returns `Option.some` with the constructed
84
- * value on success, or `Option.none` when construction fails.
85
+ * value on success, or `Option.none` when construction fails with schema issues.
85
86
  *
86
87
  * **When to use**
87
88
  *
88
89
  * Use when you need to validate schema constructor input and only care whether
89
90
  * construction succeeds, without exposing `SchemaIssue.Issue` details.
90
91
  *
92
+ * **Gotchas**
93
+ *
94
+ * Only causes made entirely of schema issues are converted to `Option.none`.
95
+ * Causes that contain defects, interruptions, or asynchronous work at this
96
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`.
97
+ *
91
98
  * @category constructors
92
99
  * @since 4.0.0
93
100
  */
94
101
  export function makeOption<S extends Schema.Top>(schema: S) {
95
102
  const parser = makeEffect(schema)
96
103
  return (input: S["~type.make.in"], options?: Schema.MakeOptions): Option.Option<S["Type"]> => {
97
- return Exit.getSuccess(Effect.runSyncExit(parser(input, options) as any))
104
+ const exit = Effect.runSyncExit(parser(input, options))
105
+ if (Exit.isSuccess(exit)) {
106
+ return Option.some(exit.value)
107
+ }
108
+ InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Option adapter can only return none for schema issues")
109
+ return Option.none()
98
110
  }
99
111
  }
100
112
 
@@ -111,18 +123,27 @@ export function makeOption<S extends Schema.Top>(schema: S) {
111
123
  * The returned function constructs a value from constructor input and throws an
112
124
  * `Error` with the `SchemaIssue.Issue` in its `cause` when construction fails.
113
125
  *
126
+ * **Gotchas**
127
+ *
128
+ * Causes that contain defects, interruptions, or asynchronous work at this
129
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
130
+ * instead of being converted to a schema validation error.
131
+ *
114
132
  * @category constructors
115
133
  * @since 4.0.0
116
134
  */
117
135
  export function make<S extends Schema.Top>(schema: S) {
118
136
  const parser = makeEffect(schema)
119
137
  return (input: S["~type.make.in"], options?: Schema.MakeOptions): S["Type"] => {
120
- return Effect.runSync(
121
- Effect.mapErrorEager(
122
- parser(input, options),
123
- (issue) => new Error(issue.toString(), { cause: issue })
124
- )
138
+ const exit = Effect.runSyncExit(parser(input, options))
139
+ if (Exit.isSuccess(exit)) {
140
+ return exit.value
141
+ }
142
+ const issue = InternalSchemaCause.getSchemaIssueOrThrow(
143
+ exit.cause,
144
+ "Constructor adapter can only throw schema issues"
125
145
  )
146
+ throw new Error(issue.toString(), { cause: issue })
126
147
  }
127
148
  }
128
149
 
@@ -137,8 +158,14 @@ export function make<S extends Schema.Top>(schema: S) {
137
158
  *
138
159
  * **Details**
139
160
  *
140
- * The guard returns `true` on successful validation and `false` on failure, without
141
- * exposing issue details.
161
+ * The guard returns `true` on successful validation and `false` when validation
162
+ * fails only with schema issues, without exposing issue details.
163
+ *
164
+ * **Gotchas**
165
+ *
166
+ * Only causes made entirely of schema issues are converted to `false`. Causes
167
+ * that contain defects, interruptions, or asynchronous work at this synchronous
168
+ * boundary throw an `Error` whose cause is the underlying `Cause`.
142
169
  *
143
170
  * @category Asserting
144
171
  * @since 3.10.0
@@ -151,7 +178,12 @@ export function is<T>(schema: Schema.Schema<T>): <I>(input: I) => input is I & T
151
178
  export function _is<T>(ast: SchemaAST.AST) {
152
179
  const parser = asExit(run<T, never>(SchemaAST.toType(ast)))
153
180
  return <I>(input: I): input is I & T => {
154
- return Exit.isSuccess(parser(input, SchemaAST.defaultParseOptions))
181
+ const exit = parser(input, SchemaAST.defaultParseOptions)
182
+ if (Exit.isSuccess(exit)) {
183
+ return true
184
+ }
185
+ InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Type guard adapter can only return false for schema issues")
186
+ return false
155
187
  }
156
188
  }
157
189
 
@@ -159,10 +191,11 @@ export function _is<T>(ast: SchemaAST.AST) {
159
191
  export function _issue<T>(ast: SchemaAST.AST) {
160
192
  const parser = run<T, never>(ast)
161
193
  return (input: unknown, options: SchemaAST.ParseOptions): SchemaIssue.Issue | undefined => {
162
- return Effect.runSync(Effect.matchEager(parser(input, options), {
163
- onSuccess: () => undefined,
164
- onFailure: identity
165
- }))
194
+ const exit = Effect.runSyncExit(parser(input, options))
195
+ if (Exit.isSuccess(exit)) {
196
+ return undefined
197
+ }
198
+ return InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Issue adapter can only return schema issues")
166
199
  }
167
200
  }
168
201
 
@@ -171,13 +204,20 @@ export function _issue<T>(ast: SchemaAST.AST) {
171
204
  *
172
205
  * **When to use**
173
206
  *
174
- * Use to assert that an input satisfies the decoded side of a schema, throwing
175
- * an `Error` whose cause is `SchemaIssue.Issue` when validation fails.
207
+ * Use to assert that an input satisfies the decoded side of a schema when schema
208
+ * validation failures should throw an `Error` whose cause is `SchemaIssue.Issue`.
176
209
  *
177
210
  * **Details**
178
211
  *
179
- * The assertion returns normally when validation succeeds and throws when the
180
- * input does not satisfy the schema.
212
+ * The assertion returns normally when validation succeeds. When the input does
213
+ * not satisfy the schema with a schema-only failure, it throws an `Error` with
214
+ * the `SchemaIssue.Issue` in its `cause`.
215
+ *
216
+ * **Gotchas**
217
+ *
218
+ * Causes that contain defects, interruptions, or asynchronous work at this
219
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
220
+ * instead of being converted to a schema validation error.
181
221
  *
182
222
  * @category Asserting
183
223
  * @since 4.0.0
@@ -186,11 +226,11 @@ export function asserts<S extends Schema.Top, I>(schema: S, input: I): asserts i
186
226
  const parser = asExit(run<S["Type"], never>(SchemaAST.toType(schema.ast)))
187
227
  const exit = parser(input, SchemaAST.defaultParseOptions)
188
228
  if (Exit.isFailure(exit)) {
189
- const issue = Cause.findError(exit.cause)
190
- if (Result.isFailure(issue)) {
191
- throw Cause.squash(issue.failure)
192
- }
193
- throw new Error(issue.success.toString(), { cause: issue.success })
229
+ const issue = InternalSchemaCause.getSchemaIssueOrThrow(
230
+ exit.cause,
231
+ "Assertion adapter can only throw schema issues"
232
+ )
233
+ throw new Error(issue.toString(), { cause: issue })
194
234
  }
195
235
  }
196
236
 
@@ -264,12 +304,17 @@ export const decodeEffect: <S extends Schema.Top>(
264
304
  * **When to use**
265
305
  *
266
306
  * Use when you need to decode untyped input with a service-free schema and
267
- * return a JavaScript `Promise` that rejects with `SchemaIssue.Issue`.
307
+ * return a JavaScript `Promise`.
268
308
  *
269
309
  * **Details**
270
310
  *
271
311
  * The returned function resolves with the decoded `Type` on success and rejects
272
- * with a `SchemaIssue.Issue` on decoding failure.
312
+ * with an `Error` whose cause is a `SchemaIssue.Issue` on decoding failure.
313
+ *
314
+ * **Gotchas**
315
+ *
316
+ * Causes that contain defects, interruptions, or other non-schema reasons reject
317
+ * with an `Error` whose cause is the underlying `Cause`.
273
318
  *
274
319
  * @see {@link decodePromise} for input already typed as the schema's `Encoded` type
275
320
  * @see {@link decodeUnknownEffect} for schemas that require decoding services or when failures should remain in `Effect`
@@ -291,12 +336,17 @@ export function decodeUnknownPromise<S extends Schema.Decoder<unknown>>(
291
336
  * **When to use**
292
337
  *
293
338
  * Use when you already have input typed as the schema's `Encoded` type and need
294
- * decoding to return a JavaScript `Promise` that rejects with `SchemaIssue.Issue`.
339
+ * decoding to return a JavaScript `Promise`.
295
340
  *
296
341
  * **Details**
297
342
  *
298
343
  * The returned function resolves with the decoded `Type` on success and rejects
299
- * with a `SchemaIssue.Issue` on decoding failure.
344
+ * with an `Error` whose cause is a `SchemaIssue.Issue` on decoding failure.
345
+ *
346
+ * **Gotchas**
347
+ *
348
+ * Causes that contain defects, interruptions, or other non-schema reasons reject
349
+ * with an `Error` whose cause is the underlying `Cause`.
300
350
  *
301
351
  * @see {@link decodeUnknownPromise} for untyped input returning a JavaScript `Promise`
302
352
  * @see {@link decodeEffect} for preserving decoding services and failures in `Effect`
@@ -329,7 +379,8 @@ export function decodePromise<S extends Schema.Decoder<unknown>>(
329
379
  * **Gotchas**
330
380
  *
331
381
  * Because this adapter runs synchronously, async decoding work can produce an
332
- * `Exit.Failure` with a defect cause.
382
+ * `Exit.Failure` with a defect cause. When the cause contains both schema
383
+ * issues and non-schema reasons, all reasons remain in the returned `Cause`.
333
384
  *
334
385
  * @see {@link decodeExit} for input already typed as the schema's `Encoded` type
335
386
  * @see {@link decodeUnknownEffect} for preserving decoding services and failures in `Effect`
@@ -360,6 +411,12 @@ export function decodeUnknownExit<S extends Schema.Decoder<unknown>>(
360
411
  * The returned function produces `Exit.Success` with the decoded `Type` or
361
412
  * `Exit.Failure` with a `SchemaIssue.Issue`.
362
413
  *
414
+ * **Gotchas**
415
+ *
416
+ * Because this adapter runs synchronously, async decoding work can produce an
417
+ * `Exit.Failure` with a defect cause. When the cause contains both schema
418
+ * issues and non-schema reasons, all reasons remain in the returned `Cause`.
419
+ *
363
420
  * @see {@link decodeUnknownExit} for untyped input with the same `Exit` result shape
364
421
  * @see {@link decodeEffect} for preserving decoding services and failures in `Effect`
365
422
  *
@@ -402,8 +459,9 @@ export const decodeOption: <S extends Schema.Decoder<unknown>>(
402
459
  *
403
460
  * **Gotchas**
404
461
  *
405
- * This adapter runs synchronously. Schema issues become `Result.fail`, but async
406
- * decoding or defects can still throw.
462
+ * This adapter runs synchronously. Causes made entirely of schema issues become
463
+ * `Result.fail`, but causes that contain defects, interruptions, or asynchronous
464
+ * work at this synchronous boundary throw instead.
407
465
  *
408
466
  * @see {@link decodeResult} for input already typed as the schema's `Encoded` type
409
467
  * @see {@link decodeUnknownEffect} for effectful or service-requiring decoding
@@ -434,8 +492,9 @@ export function decodeUnknownResult<S extends Schema.Decoder<unknown>>(
434
492
  *
435
493
  * **Gotchas**
436
494
  *
437
- * This synchronous adapter returns `Result.fail` for schema issues, but async
438
- * decoding or other non-schema failures can still throw.
495
+ * This synchronous adapter returns `Result.fail` for causes made entirely of
496
+ * schema issues, but causes that contain defects, interruptions, or other
497
+ * non-schema reasons throw instead.
439
498
  *
440
499
  * @see {@link decodeUnknownResult} for untyped input with the same `Result` shape
441
500
  * @see {@link decodeEffect} for effectful or service-requiring decoding
@@ -462,6 +521,12 @@ export const decodeResult: <S extends Schema.Decoder<unknown>>(
462
521
  * The returned function returns the decoded `Type` on success and throws an
463
522
  * `Error` with the `SchemaIssue.Issue` in its `cause` on decoding failure.
464
523
  *
524
+ * **Gotchas**
525
+ *
526
+ * Causes that contain defects, interruptions, or asynchronous work at this
527
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
528
+ * instead of being converted to a schema validation error.
529
+ *
465
530
  * @see {@link decodeSync} for input already typed as the schema's `Encoded` type
466
531
  * @see {@link decodeUnknownEffect} for preserving decoding failures in `Effect`
467
532
  * @see {@link decodeUnknownResult} for returning schema issues as data
@@ -490,6 +555,12 @@ export function decodeUnknownSync<S extends Schema.Decoder<unknown>>(
490
555
  * The returned function returns the decoded `Type` on success and throws an
491
556
  * `Error` with the `SchemaIssue.Issue` in its `cause` on decoding failure.
492
557
  *
558
+ * **Gotchas**
559
+ *
560
+ * Causes that contain defects, interruptions, or asynchronous work at this
561
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
562
+ * instead of being converted to a schema validation error.
563
+ *
493
564
  * @see {@link decodeUnknownSync} for untrusted or dynamically typed input
494
565
  * @see {@link decodeResult} for returning schema issues as data
495
566
  * @see {@link decodeEffect} for preserving decoding failures in `Effect`
@@ -571,13 +642,17 @@ export const encodeEffect: <S extends Schema.Top>(
571
642
  * **When to use**
572
643
  *
573
644
  * Use when you need to encode untrusted or dynamically typed values with a
574
- * service-free schema and return a JavaScript `Promise` that rejects with
575
- * `SchemaIssue.Issue`.
645
+ * service-free schema and return a JavaScript `Promise`.
576
646
  *
577
647
  * **Details**
578
648
  *
579
649
  * The returned function resolves with the schema's `Encoded` value on success and
580
- * rejects with a `SchemaIssue.Issue` on encoding failure.
650
+ * rejects with an `Error` whose cause is a `SchemaIssue.Issue` on encoding failure.
651
+ *
652
+ * **Gotchas**
653
+ *
654
+ * Causes that contain defects, interruptions, or other non-schema reasons reject
655
+ * with an `Error` whose cause is the underlying `Cause`.
581
656
  *
582
657
  * @see {@link encodePromise} for input already typed as the schema's decoded `Type`
583
658
  * @see {@link encodeUnknownEffect} for schemas that require encoding services or when failures should remain in `Effect`
@@ -598,13 +673,17 @@ export const encodeUnknownPromise = <S extends Schema.Encoder<unknown>>(
598
673
  * **When to use**
599
674
  *
600
675
  * Use when you already have values typed as the schema's decoded `Type` and
601
- * need encoding to return a JavaScript `Promise` that rejects with
602
- * `SchemaIssue.Issue`.
676
+ * need encoding to return a JavaScript `Promise`.
603
677
  *
604
678
  * **Details**
605
679
  *
606
680
  * The returned function resolves with the schema's `Encoded` value on success and
607
- * rejects with a `SchemaIssue.Issue` on encoding failure.
681
+ * rejects with an `Error` whose cause is a `SchemaIssue.Issue` on encoding failure.
682
+ *
683
+ * **Gotchas**
684
+ *
685
+ * Causes that contain defects, interruptions, or other non-schema reasons reject
686
+ * with an `Error` whose cause is the underlying `Cause`.
608
687
  *
609
688
  * @see {@link encodeUnknownPromise} for encoding untyped input
610
689
  * @see {@link encodeEffect} for effectful encoding or schemas with encoding service requirements
@@ -631,6 +710,12 @@ export const encodePromise: <S extends Schema.Encoder<unknown>>(
631
710
  * The returned function produces `Exit.Success` with the schema's `Encoded` value
632
711
  * or `Exit.Failure` with a `SchemaIssue.Issue`.
633
712
  *
713
+ * **Gotchas**
714
+ *
715
+ * Because this adapter runs synchronously, async encoding work can produce an
716
+ * `Exit.Failure` with a defect cause. When the cause contains both schema
717
+ * issues and non-schema reasons, all reasons remain in the returned `Cause`.
718
+ *
634
719
  * @see {@link encodeExit} for input already typed as the schema's decoded `Type`
635
720
  * @see {@link encodeUnknownEffect} for effectful encoding that preserves service requirements
636
721
  *
@@ -658,6 +743,12 @@ export function encodeUnknownExit<S extends Schema.Encoder<unknown>>(
658
743
  * The returned function produces `Exit.Success` with the schema's `Encoded` value
659
744
  * or `Exit.Failure` with a `SchemaIssue.Issue`.
660
745
  *
746
+ * **Gotchas**
747
+ *
748
+ * Because this adapter runs synchronously, async encoding work can produce an
749
+ * `Exit.Failure` with a defect cause. When the cause contains both schema
750
+ * issues and non-schema reasons, all reasons remain in the returned `Cause`.
751
+ *
661
752
  * @see {@link encodeUnknownExit} for unknown input with the same `Exit` result shape
662
753
  * @see {@link encodeEffect} for effectful encoding that preserves service requirements
663
754
  *
@@ -700,6 +791,12 @@ export const encodeOption: <S extends Schema.Encoder<unknown>>(
700
791
  * value on success or `Result.fail` with a `SchemaIssue.Issue` on encoding
701
792
  * failure.
702
793
  *
794
+ * **Gotchas**
795
+ *
796
+ * This adapter runs synchronously. Causes made entirely of schema issues become
797
+ * `Result.fail`, but causes that contain defects, interruptions, or asynchronous
798
+ * work at this synchronous boundary throw instead.
799
+ *
703
800
  * @see {@link encodeResult} for input already typed as the schema's decoded `Type`
704
801
  * @see {@link encodeUnknownEffect} for effectful encoding, including schemas with encoding service requirements
705
802
  *
@@ -728,6 +825,12 @@ export function encodeUnknownResult<S extends Schema.Encoder<unknown>>(
728
825
  * value on success or `Result.fail` with a `SchemaIssue.Issue` on encoding
729
826
  * failure.
730
827
  *
828
+ * **Gotchas**
829
+ *
830
+ * This synchronous adapter returns `Result.fail` for causes made entirely of
831
+ * schema issues, but causes that contain defects, interruptions, or other
832
+ * non-schema reasons throw instead.
833
+ *
731
834
  * @see {@link encodeUnknownResult} for the same `Result` shape when the input is not already typed
732
835
  *
733
836
  * @category encoding
@@ -752,6 +855,12 @@ export const encodeResult: <S extends Schema.Encoder<unknown>>(
752
855
  * The returned function returns the schema's `Encoded` value on success and throws
753
856
  * an `Error` with the `SchemaIssue.Issue` in its `cause` on encoding failure.
754
857
  *
858
+ * **Gotchas**
859
+ *
860
+ * Causes that contain defects, interruptions, or asynchronous work at this
861
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
862
+ * instead of being converted to a schema validation error.
863
+ *
755
864
  * @see {@link encodeSync} for input already typed as the schema's decoded `Type`
756
865
  * @see {@link encodeUnknownEffect} for effectful encoding that preserves service requirements
757
866
  *
@@ -779,6 +888,12 @@ export function encodeUnknownSync<S extends Schema.Encoder<unknown>>(
779
888
  * The returned function returns the schema's `Encoded` value on success and throws
780
889
  * an `Error` with the `SchemaIssue.Issue` in its `cause` on encoding failure.
781
890
  *
891
+ * **Gotchas**
892
+ *
893
+ * Causes that contain defects, interruptions, or asynchronous work at this
894
+ * synchronous boundary throw an `Error` whose cause is the underlying `Cause`,
895
+ * instead of being converted to a schema validation error.
896
+ *
782
897
  * @see {@link encodeUnknownSync} for unknown input with the same throwing boundary
783
898
  * @see {@link encodeResult} for returning schema issues as data
784
899
  * @see {@link encodeEffect} for effectful encoding that preserves service requirements
@@ -811,7 +926,17 @@ export function run<T, R>(ast: SchemaAST.AST) {
811
926
  function asPromise<T, E>(
812
927
  parser: (input: E, options?: SchemaAST.ParseOptions) => Effect.Effect<T, SchemaIssue.Issue>
813
928
  ): (input: E, options?: SchemaAST.ParseOptions) => Promise<T> {
814
- return (input: E, options?: SchemaAST.ParseOptions) => Effect.runPromise(parser(input, options))
929
+ return (input: E, options?: SchemaAST.ParseOptions) =>
930
+ Effect.runPromiseExit(parser(input, options)).then((exit) => {
931
+ if (Exit.isSuccess(exit)) {
932
+ return exit.value
933
+ }
934
+ const issue = InternalSchemaCause.getSchemaIssueOrThrow(
935
+ exit.cause,
936
+ "Promise adapter can only reject schema issues"
937
+ )
938
+ throw new Error(issue.toString(), { cause: issue })
939
+ })
815
940
  }
816
941
 
817
942
  function asExit<T, E, R>(
@@ -825,7 +950,14 @@ export function asOption<T, E, R>(
825
950
  parser: (input: E, options?: SchemaAST.ParseOptions) => Effect.Effect<T, SchemaIssue.Issue, R>
826
951
  ): (input: E, options?: SchemaAST.ParseOptions) => Option.Option<T> {
827
952
  const parserExit = asExit(parser)
828
- return (input: E, options?: SchemaAST.ParseOptions) => Exit.getSuccess(parserExit(input, options))
953
+ return (input: E, options?: SchemaAST.ParseOptions) => {
954
+ const exit = parserExit(input, options)
955
+ if (Exit.isSuccess(exit)) {
956
+ return Option.some(exit.value)
957
+ }
958
+ InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Option adapter can only return none for schema issues")
959
+ return Option.none()
960
+ }
829
961
  }
830
962
 
831
963
  function asResult<T, E, R>(
@@ -837,24 +969,31 @@ function asResult<T, E, R>(
837
969
  if (Exit.isSuccess(exit)) {
838
970
  return Result.succeed(exit.value)
839
971
  }
840
- const error = Cause.findError(exit.cause)
841
- if (Result.isFailure(error)) {
842
- throw Cause.squash(error.failure)
843
- }
844
- return Result.fail(error.success)
972
+ return Result.fail(
973
+ InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Result adapter can only return schema issues")
974
+ )
845
975
  }
846
976
  }
847
977
 
848
- function asSync<T, E, R>(
849
- parser: (input: E, options?: SchemaAST.ParseOptions) => Effect.Effect<T, SchemaIssue.Issue, R>
978
+ function asSync<T, E>(
979
+ parser: (input: E, options?: SchemaAST.ParseOptions) => Effect.Effect<T, SchemaIssue.Issue>
850
980
  ): (input: E, options?: SchemaAST.ParseOptions) => T {
851
- return (input: E, options?: SchemaAST.ParseOptions) =>
852
- Effect.runSync(
853
- Effect.mapErrorEager(
854
- parser(input, options),
855
- (issue) => new Error(issue.toString(), { cause: issue })
856
- ) as any
857
- )
981
+ const parserExit = asExit(parser)
982
+ return (input: E, options?: SchemaAST.ParseOptions) => {
983
+ const exit = parserExit(input, options)
984
+ if (Exit.isSuccess(exit)) {
985
+ return exit.value
986
+ }
987
+ const issue = InternalSchemaCause.getSchemaIssueOrThrow(exit.cause, "Sync adapter can only throw schema issues")
988
+ throw new Error(issue.toString(), { cause: issue })
989
+ }
990
+ }
991
+
992
+ function mapSchemaIssueEffect<A, R>(
993
+ self: Effect.Effect<A, SchemaIssue.Issue, R>,
994
+ f: (issue: SchemaIssue.Issue) => SchemaIssue.Issue
995
+ ): Effect.Effect<A, SchemaIssue.Issue, R> {
996
+ return Effect.catchCause(self, (cause) => Effect.failCauseSync(() => Cause.map(cause, f)))
858
997
  }
859
998
 
860
999
  /** @internal */
@@ -904,7 +1043,7 @@ const recur = memoize(
904
1043
  srou = link.transformation.decode(srou, options)
905
1044
  }
906
1045
  }
907
- srou = Effect.mapErrorEager(srou!, (issue) => new SchemaIssue.Encoding(ast, ou, issue))
1046
+ srou = mapSchemaIssueEffect(srou!, (issue) => new SchemaIssue.Encoding(ast, ou, issue))
908
1047
  }
909
1048
 
910
1049
  parser ??= ast.getParser(recur)
@@ -928,7 +1067,7 @@ const recur = memoize(
928
1067
  if (ast.checks && !options?.disableChecks) {
929
1068
  const checks = ast.checks
930
1069
  if (options?.errors === "all" && isStructural && Option.isSome(ou)) {
931
- sroa = Effect.catchEager(sroa, (issue) => {
1070
+ sroa = mapSchemaIssueEffect(sroa, (issue) => {
932
1071
  const issues: Array<SchemaIssue.Issue> = []
933
1072
  SchemaAST.collectIssues(
934
1073
  checks.filter((check) => check.annotations?.[SchemaAST.STRUCTURAL_ANNOTATION_KEY]),
@@ -942,7 +1081,7 @@ const recur = memoize(
942
1081
  ? new SchemaIssue.Composite(ast, issue.actual, [...issue.issues, ...issues])
943
1082
  : new SchemaIssue.Composite(ast, ou, [issue, ...issues])
944
1083
  : issue
945
- return Effect.fail(out)
1084
+ return out
946
1085
  })
947
1086
  }
948
1087
  sroa = Effect.flatMapEager(sroa, (oa) => {
@@ -22,7 +22,7 @@ import * as Option from "./Option.ts"
22
22
  import * as Predicate from "./Predicate.ts"
23
23
  import * as Rec from "./Record.ts"
24
24
  import * as Schema from "./Schema.ts"
25
- import type * as SchemaAST from "./SchemaAST.ts"
25
+ import * as SchemaAST from "./SchemaAST.ts"
26
26
  import * as SchemaGetter from "./SchemaGetter.ts"
27
27
 
28
28
  // -----------------------------------------------------------------------------
@@ -3091,11 +3091,11 @@ export function fromJsonSchemaMultiDocument(document: JsonSchema.MultiDocument<"
3091
3091
 
3092
3092
  Object.entries(document.definitions).forEach(([identifier, definition]) => {
3093
3093
  visited = new Set<string>([identifier])
3094
- references[identifier] = recur(definition)
3094
+ references[identifier] = unknownToJson(recur(definition))
3095
3095
  })
3096
3096
 
3097
3097
  visited = new Set<string>()
3098
- const representations = Arr.map(document.schemas, recur)
3098
+ const representations = Arr.map(document.schemas, (schema) => unknownToJson(recur(schema)))
3099
3099
  return {
3100
3100
  representations,
3101
3101
  references
@@ -3529,6 +3529,60 @@ export function fromJsonSchemaMultiDocument(document: JsonSchema.MultiDocument<"
3529
3529
  }
3530
3530
  return out
3531
3531
  }
3532
+
3533
+ function unknownToJson(representation: Representation): Representation {
3534
+ switch (representation._tag) {
3535
+ case "Unknown":
3536
+ return representation.annotations === undefined ?
3537
+ json :
3538
+ {
3539
+ ...json,
3540
+ annotations: {
3541
+ ...json.annotations,
3542
+ ...representation.annotations
3543
+ }
3544
+ }
3545
+ case "Suspend": {
3546
+ const thunk = unknownToJson(representation.thunk)
3547
+ return thunk === representation.thunk ? representation : { ...representation, thunk }
3548
+ }
3549
+ case "String": {
3550
+ if (representation.contentSchema === undefined) return representation
3551
+ const contentSchema = unknownToJson(representation.contentSchema)
3552
+ return contentSchema === representation.contentSchema ? representation : { ...representation, contentSchema }
3553
+ }
3554
+ case "Arrays": {
3555
+ const elements = SchemaAST.mapOrSame(representation.elements, (element) => {
3556
+ const type = unknownToJson(element.type)
3557
+ return type === element.type ? element : { ...element, type }
3558
+ })
3559
+ const rest = SchemaAST.mapOrSame(representation.rest, unknownToJson)
3560
+ return elements === representation.elements && rest === representation.rest ?
3561
+ representation :
3562
+ { ...representation, elements, rest }
3563
+ }
3564
+ case "Objects": {
3565
+ const propertySignatures = SchemaAST.mapOrSame(representation.propertySignatures, (propertySignature) => {
3566
+ const type = unknownToJson(propertySignature.type)
3567
+ return type === propertySignature.type ? propertySignature : { ...propertySignature, type }
3568
+ })
3569
+ const indexSignatures = SchemaAST.mapOrSame(representation.indexSignatures, (indexSignature) => {
3570
+ const type = unknownToJson(indexSignature.type)
3571
+ return type === indexSignature.type ? indexSignature : { ...indexSignature, type }
3572
+ })
3573
+ return propertySignatures === representation.propertySignatures &&
3574
+ indexSignatures === representation.indexSignatures ?
3575
+ representation :
3576
+ { ...representation, propertySignatures, indexSignatures }
3577
+ }
3578
+ case "Union": {
3579
+ const types = SchemaAST.mapOrSame(representation.types, unknownToJson)
3580
+ return types === representation.types ? representation : { ...representation, types }
3581
+ }
3582
+ default:
3583
+ return representation
3584
+ }
3585
+ }
3532
3586
  }
3533
3587
 
3534
3588
  function asChecks<M>(
@@ -3654,6 +3708,22 @@ function collectArraysChecks(js: JsonSchema.JsonSchema): Array<Check<ArraysMeta>
3654
3708
  }
3655
3709
 
3656
3710
  const unknown: Unknown = { _tag: "Unknown" }
3711
+ const json: Declaration = {
3712
+ _tag: "Declaration",
3713
+ annotations: {
3714
+ expected: "JSON value",
3715
+ generation: {
3716
+ Type: "Schema.Json",
3717
+ runtime: "Schema.Json"
3718
+ },
3719
+ typeConstructor: {
3720
+ _tag: "effect/Json"
3721
+ }
3722
+ },
3723
+ checks: [],
3724
+ encodedSchema: unknown,
3725
+ typeParameters: []
3726
+ }
3657
3727
  const never: Never = { _tag: "Never" }
3658
3728
  const null_: Null = { _tag: "Null" }
3659
3729
  const string: String = { _tag: "String", checks: [] }