effect 3.9.2 → 3.10.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.
Files changed (202) hide show
  1. package/Arbitrary/package.json +6 -0
  2. package/FastCheck/package.json +6 -0
  3. package/JSONSchema/package.json +6 -0
  4. package/ParseResult/package.json +6 -0
  5. package/Pretty/package.json +6 -0
  6. package/Schema/package.json +6 -0
  7. package/SchemaAST/package.json +6 -0
  8. package/TSubscriptionRef/package.json +6 -0
  9. package/dist/cjs/Arbitrary.js +490 -0
  10. package/dist/cjs/Arbitrary.js.map +1 -0
  11. package/dist/cjs/Effect.js +247 -16
  12. package/dist/cjs/Effect.js.map +1 -1
  13. package/dist/cjs/FastCheck.js +17 -0
  14. package/dist/cjs/FastCheck.js.map +1 -0
  15. package/dist/cjs/Inspectable.js +43 -3
  16. package/dist/cjs/Inspectable.js.map +1 -1
  17. package/dist/cjs/JSONSchema.js +418 -0
  18. package/dist/cjs/JSONSchema.js.map +1 -0
  19. package/dist/cjs/ParseResult.js +1539 -0
  20. package/dist/cjs/ParseResult.js.map +1 -0
  21. package/dist/cjs/Predicate.js +3 -1
  22. package/dist/cjs/Predicate.js.map +1 -1
  23. package/dist/cjs/Pretty.js +183 -0
  24. package/dist/cjs/Pretty.js.map +1 -0
  25. package/dist/cjs/Schema.js +5529 -0
  26. package/dist/cjs/Schema.js.map +1 -0
  27. package/dist/cjs/SchemaAST.js +2365 -0
  28. package/dist/cjs/SchemaAST.js.map +1 -0
  29. package/dist/cjs/Stream.js +17 -3
  30. package/dist/cjs/Stream.js.map +1 -1
  31. package/dist/cjs/TPubSub.js +9 -1
  32. package/dist/cjs/TPubSub.js.map +1 -1
  33. package/dist/cjs/TQueue.js.map +1 -1
  34. package/dist/cjs/TRef.js.map +1 -1
  35. package/dist/cjs/TSubscriptionRef.js +96 -0
  36. package/dist/cjs/TSubscriptionRef.js.map +1 -0
  37. package/dist/cjs/index.js +18 -2
  38. package/dist/cjs/index.js.map +1 -1
  39. package/dist/cjs/internal/cause.js +2 -2
  40. package/dist/cjs/internal/cause.js.map +1 -1
  41. package/dist/cjs/internal/core.js +4 -4
  42. package/dist/cjs/internal/core.js.map +1 -1
  43. package/dist/cjs/internal/fiberRuntime.js +14 -12
  44. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  45. package/dist/cjs/internal/logger.js +7 -6
  46. package/dist/cjs/internal/logger.js.map +1 -1
  47. package/dist/cjs/internal/redacted.js +4 -0
  48. package/dist/cjs/internal/redacted.js.map +1 -1
  49. package/dist/cjs/internal/schema/errors.js +116 -0
  50. package/dist/cjs/internal/schema/errors.js.map +1 -0
  51. package/dist/cjs/internal/schema/filters.js +41 -0
  52. package/dist/cjs/internal/schema/filters.js.map +1 -0
  53. package/dist/cjs/internal/schema/util.js +96 -0
  54. package/dist/cjs/internal/schema/util.js.map +1 -0
  55. package/dist/cjs/internal/stm/core.js +2 -3
  56. package/dist/cjs/internal/stm/core.js.map +1 -1
  57. package/dist/cjs/internal/stm/tPubSub.js.map +1 -1
  58. package/dist/cjs/internal/stm/tQueue.js +1 -2
  59. package/dist/cjs/internal/stm/tQueue.js.map +1 -1
  60. package/dist/cjs/internal/stm/tRef.js +6 -2
  61. package/dist/cjs/internal/stm/tRef.js.map +1 -1
  62. package/dist/cjs/internal/stm/tSubscriptionRef.js +178 -0
  63. package/dist/cjs/internal/stm/tSubscriptionRef.js.map +1 -0
  64. package/dist/cjs/internal/stream.js +36 -16
  65. package/dist/cjs/internal/stream.js.map +1 -1
  66. package/dist/cjs/internal/version.js +1 -1
  67. package/dist/cjs/internal/version.js.map +1 -1
  68. package/dist/dts/Arbitrary.d.ts +45 -0
  69. package/dist/dts/Arbitrary.d.ts.map +1 -0
  70. package/dist/dts/Effect.d.ts +298 -30
  71. package/dist/dts/Effect.d.ts.map +1 -1
  72. package/dist/dts/FastCheck.d.ts +9 -0
  73. package/dist/dts/FastCheck.d.ts.map +1 -0
  74. package/dist/dts/Inspectable.d.ts +28 -0
  75. package/dist/dts/Inspectable.d.ts.map +1 -1
  76. package/dist/dts/JSONSchema.d.ts +181 -0
  77. package/dist/dts/JSONSchema.d.ts.map +1 -0
  78. package/dist/dts/ParseResult.d.ts +551 -0
  79. package/dist/dts/ParseResult.d.ts.map +1 -0
  80. package/dist/dts/Predicate.d.ts.map +1 -1
  81. package/dist/dts/Pretty.d.ts +26 -0
  82. package/dist/dts/Pretty.d.ts.map +1 -0
  83. package/dist/dts/Schema.d.ts +4562 -0
  84. package/dist/dts/Schema.d.ts.map +1 -0
  85. package/dist/dts/SchemaAST.d.ts +1321 -0
  86. package/dist/dts/SchemaAST.d.ts.map +1 -0
  87. package/dist/dts/Stream.d.ts +67 -2
  88. package/dist/dts/Stream.d.ts.map +1 -1
  89. package/dist/dts/TPubSub.d.ts +8 -0
  90. package/dist/dts/TPubSub.d.ts.map +1 -1
  91. package/dist/dts/TQueue.d.ts +7 -7
  92. package/dist/dts/TQueue.d.ts.map +1 -1
  93. package/dist/dts/TRef.d.ts +2 -1
  94. package/dist/dts/TRef.d.ts.map +1 -1
  95. package/dist/dts/TSubscriptionRef.d.ts +251 -0
  96. package/dist/dts/TSubscriptionRef.d.ts.map +1 -0
  97. package/dist/dts/index.d.ts +32 -0
  98. package/dist/dts/index.d.ts.map +1 -1
  99. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  100. package/dist/dts/internal/schema/errors.d.ts +2 -0
  101. package/dist/dts/internal/schema/errors.d.ts.map +1 -0
  102. package/dist/dts/internal/schema/filters.d.ts +2 -0
  103. package/dist/dts/internal/schema/filters.d.ts.map +1 -0
  104. package/dist/dts/internal/schema/util.d.ts +2 -0
  105. package/dist/dts/internal/schema/util.d.ts.map +1 -0
  106. package/dist/dts/internal/stm/tRef.d.ts +3 -1
  107. package/dist/dts/internal/stm/tRef.d.ts.map +1 -1
  108. package/dist/dts/internal/stm/tSubscriptionRef.d.ts +2 -0
  109. package/dist/dts/internal/stm/tSubscriptionRef.d.ts.map +1 -0
  110. package/dist/dts/internal/stream.d.ts.map +1 -1
  111. package/dist/esm/Arbitrary.js +472 -0
  112. package/dist/esm/Arbitrary.js.map +1 -0
  113. package/dist/esm/Effect.js +256 -18
  114. package/dist/esm/Effect.js.map +1 -1
  115. package/dist/esm/FastCheck.js +9 -0
  116. package/dist/esm/FastCheck.js.map +1 -0
  117. package/dist/esm/Inspectable.js +39 -2
  118. package/dist/esm/Inspectable.js.map +1 -1
  119. package/dist/esm/JSONSchema.js +408 -0
  120. package/dist/esm/JSONSchema.js.map +1 -0
  121. package/dist/esm/ParseResult.js +1503 -0
  122. package/dist/esm/ParseResult.js.map +1 -0
  123. package/dist/esm/Predicate.js +2 -1
  124. package/dist/esm/Predicate.js.map +1 -1
  125. package/dist/esm/Pretty.js +173 -0
  126. package/dist/esm/Pretty.js.map +1 -0
  127. package/dist/esm/Schema.js +5328 -0
  128. package/dist/esm/Schema.js.map +1 -0
  129. package/dist/esm/SchemaAST.js +2300 -0
  130. package/dist/esm/SchemaAST.js.map +1 -0
  131. package/dist/esm/Stream.js +14 -0
  132. package/dist/esm/Stream.js.map +1 -1
  133. package/dist/esm/TPubSub.js +8 -0
  134. package/dist/esm/TPubSub.js.map +1 -1
  135. package/dist/esm/TQueue.js.map +1 -1
  136. package/dist/esm/TRef.js.map +1 -1
  137. package/dist/esm/TSubscriptionRef.js +87 -0
  138. package/dist/esm/TSubscriptionRef.js.map +1 -0
  139. package/dist/esm/index.js +32 -0
  140. package/dist/esm/index.js.map +1 -1
  141. package/dist/esm/internal/cause.js +3 -3
  142. package/dist/esm/internal/cause.js.map +1 -1
  143. package/dist/esm/internal/core.js +4 -4
  144. package/dist/esm/internal/core.js.map +1 -1
  145. package/dist/esm/internal/fiberRuntime.js +14 -12
  146. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  147. package/dist/esm/internal/logger.js +7 -6
  148. package/dist/esm/internal/logger.js.map +1 -1
  149. package/dist/esm/internal/redacted.js +4 -0
  150. package/dist/esm/internal/redacted.js.map +1 -1
  151. package/dist/esm/internal/schema/errors.js +87 -0
  152. package/dist/esm/internal/schema/errors.js.map +1 -0
  153. package/dist/esm/internal/schema/filters.js +35 -0
  154. package/dist/esm/internal/schema/filters.js.map +1 -0
  155. package/dist/esm/internal/schema/util.js +78 -0
  156. package/dist/esm/internal/schema/util.js.map +1 -0
  157. package/dist/esm/internal/stm/core.js +1 -2
  158. package/dist/esm/internal/stm/core.js.map +1 -1
  159. package/dist/esm/internal/stm/tPubSub.js.map +1 -1
  160. package/dist/esm/internal/stm/tQueue.js +1 -2
  161. package/dist/esm/internal/stm/tQueue.js.map +1 -1
  162. package/dist/esm/internal/stm/tRef.js +5 -1
  163. package/dist/esm/internal/stm/tRef.js.map +1 -1
  164. package/dist/esm/internal/stm/tSubscriptionRef.js +166 -0
  165. package/dist/esm/internal/stm/tSubscriptionRef.js.map +1 -0
  166. package/dist/esm/internal/stream.js +33 -15
  167. package/dist/esm/internal/stream.js.map +1 -1
  168. package/dist/esm/internal/version.js +1 -1
  169. package/dist/esm/internal/version.js.map +1 -1
  170. package/package.json +68 -1
  171. package/src/Arbitrary.ts +563 -0
  172. package/src/Effect.ts +302 -31
  173. package/src/FastCheck.ts +9 -0
  174. package/src/Inspectable.ts +56 -2
  175. package/src/JSONSchema.ts +601 -0
  176. package/src/ParseResult.ts +2027 -0
  177. package/src/Predicate.ts +3 -1
  178. package/src/Pretty.ts +204 -0
  179. package/src/Schema.ts +10388 -0
  180. package/src/SchemaAST.ts +2827 -0
  181. package/src/Stream.ts +77 -9
  182. package/src/TPubSub.ts +9 -0
  183. package/src/TQueue.ts +7 -7
  184. package/src/TRef.ts +2 -1
  185. package/src/TSubscriptionRef.ts +284 -0
  186. package/src/index.ts +40 -0
  187. package/src/internal/cause.ts +3 -3
  188. package/src/internal/core-effect.ts +2 -2
  189. package/src/internal/core.ts +4 -4
  190. package/src/internal/fiberRuntime.ts +14 -12
  191. package/src/internal/logger.ts +7 -6
  192. package/src/internal/redacted.ts +4 -0
  193. package/src/internal/schema/errors.ts +189 -0
  194. package/src/internal/schema/filters.ts +86 -0
  195. package/src/internal/schema/util.ts +113 -0
  196. package/src/internal/stm/core.ts +1 -2
  197. package/src/internal/stm/tPubSub.ts +1 -0
  198. package/src/internal/stm/tQueue.ts +2 -2
  199. package/src/internal/stm/tRef.ts +7 -2
  200. package/src/internal/stm/tSubscriptionRef.ts +286 -0
  201. package/src/internal/stream.ts +97 -20
  202. package/src/internal/version.ts +1 -1
@@ -0,0 +1,2027 @@
1
+ /**
2
+ * @since 3.10.0
3
+ */
4
+
5
+ import * as array_ from "./Array.js"
6
+ import type * as cause_ from "./Cause.js"
7
+ import { TaggedError } from "./Data.js"
8
+ import * as Effect from "./Effect.js"
9
+ import * as Either from "./Either.js"
10
+ import type { LazyArg } from "./Function.js"
11
+ import { dual } from "./Function.js"
12
+ import { globalValue } from "./GlobalValue.js"
13
+ import * as Inspectable from "./Inspectable.js"
14
+ import * as util_ from "./internal/schema/util.js"
15
+ import * as Option from "./Option.js"
16
+ import * as Predicate from "./Predicate.js"
17
+ import type * as Schema from "./Schema.js"
18
+ import * as AST from "./SchemaAST.js"
19
+ import type { Concurrency } from "./Types.js"
20
+
21
+ /**
22
+ * `ParseIssue` is a type that represents the different types of errors that can occur when decoding/encoding a value.
23
+ *
24
+ * @category model
25
+ * @since 3.10.0
26
+ */
27
+ export type ParseIssue =
28
+ // leaf
29
+ | Type
30
+ | Missing
31
+ | Unexpected
32
+ | Forbidden
33
+ // composite
34
+ | Pointer
35
+ | Refinement
36
+ | Transformation
37
+ | Composite
38
+
39
+ /**
40
+ * @category model
41
+ * @since 3.10.0
42
+ */
43
+ export type SingleOrNonEmpty<A> = A | array_.NonEmptyReadonlyArray<A>
44
+
45
+ /**
46
+ * @category model
47
+ * @since 3.10.0
48
+ */
49
+ export type Path = SingleOrNonEmpty<PropertyKey>
50
+
51
+ /**
52
+ * @category model
53
+ * @since 3.10.0
54
+ */
55
+ export class Pointer {
56
+ /**
57
+ * @since 3.10.0
58
+ */
59
+ readonly _tag = "Pointer"
60
+ constructor(
61
+ readonly path: Path,
62
+ readonly actual: unknown,
63
+ readonly issue: ParseIssue
64
+ ) {}
65
+ }
66
+
67
+ /**
68
+ * Error that occurs when an unexpected key or index is present.
69
+ *
70
+ * @category model
71
+ * @since 3.10.0
72
+ */
73
+ export class Unexpected {
74
+ /**
75
+ * @since 3.10.0
76
+ */
77
+ readonly _tag = "Unexpected"
78
+ constructor(
79
+ readonly actual: unknown,
80
+ /**
81
+ * @since 3.10.0
82
+ */
83
+ readonly message?: string
84
+ ) {}
85
+ }
86
+
87
+ /**
88
+ * Error that occurs when a required key or index is missing.
89
+ *
90
+ * @category model
91
+ * @since 3.10.0
92
+ */
93
+ export class Missing {
94
+ /**
95
+ * @since 3.10.0
96
+ */
97
+ readonly _tag = "Missing"
98
+ /**
99
+ * @since 3.10.0
100
+ */
101
+ readonly actual = undefined
102
+ constructor(
103
+ /**
104
+ * @since 3.10.0
105
+ */
106
+ readonly ast: AST.Type,
107
+ /**
108
+ * @since 3.10.0
109
+ */
110
+ readonly message?: string
111
+ ) {}
112
+ }
113
+
114
+ /**
115
+ * Error that contains multiple issues.
116
+ *
117
+ * @category model
118
+ * @since 3.10.0
119
+ */
120
+ export class Composite {
121
+ /**
122
+ * @since 3.10.0
123
+ */
124
+ readonly _tag = "Composite"
125
+ constructor(
126
+ readonly ast: AST.AST,
127
+ readonly actual: unknown,
128
+ readonly issues: SingleOrNonEmpty<ParseIssue>,
129
+ readonly output?: unknown
130
+ ) {}
131
+ }
132
+
133
+ /**
134
+ * Error that occurs when a refinement has an error.
135
+ *
136
+ * @category model
137
+ * @since 3.10.0
138
+ */
139
+ export class Refinement {
140
+ /**
141
+ * @since 3.10.0
142
+ */
143
+ readonly _tag = "Refinement"
144
+ constructor(
145
+ readonly ast: AST.Refinement,
146
+ readonly actual: unknown,
147
+ readonly kind: "From" | "Predicate",
148
+ readonly issue: ParseIssue
149
+ ) {}
150
+ }
151
+
152
+ /**
153
+ * Error that occurs when a transformation has an error.
154
+ *
155
+ * @category model
156
+ * @since 3.10.0
157
+ */
158
+ export class Transformation {
159
+ /**
160
+ * @since 3.10.0
161
+ */
162
+ readonly _tag = "Transformation"
163
+ constructor(
164
+ readonly ast: AST.Transformation,
165
+ readonly actual: unknown,
166
+ readonly kind: "Encoded" | "Transformation" | "Type",
167
+ readonly issue: ParseIssue
168
+ ) {}
169
+ }
170
+
171
+ /**
172
+ * The `Type` variant of the `ParseIssue` type represents an error that occurs when the `actual` value is not of the expected type.
173
+ * The `ast` field specifies the expected type, and the `actual` field contains the value that caused the error.
174
+ *
175
+ * @category model
176
+ * @since 3.10.0
177
+ */
178
+ export class Type {
179
+ /**
180
+ * @since 3.10.0
181
+ */
182
+ readonly _tag = "Type"
183
+ constructor(
184
+ readonly ast: AST.AST,
185
+ readonly actual: unknown,
186
+ readonly message?: string
187
+ ) {}
188
+ }
189
+
190
+ /**
191
+ * The `Forbidden` variant of the `ParseIssue` type represents a forbidden operation, such as when encountering an Effect that is not allowed to execute (e.g., using `runSync`).
192
+ *
193
+ * @category model
194
+ * @since 3.10.0
195
+ */
196
+ export class Forbidden {
197
+ /**
198
+ * @since 3.10.0
199
+ */
200
+ readonly _tag = "Forbidden"
201
+ constructor(
202
+ readonly ast: AST.AST,
203
+ readonly actual: unknown,
204
+ readonly message?: string
205
+ ) {}
206
+ }
207
+
208
+ /**
209
+ * @category type id
210
+ * @since 3.10.0
211
+ */
212
+ export const ParseErrorTypeId: unique symbol = Symbol.for("effect/Schema/ParseErrorTypeId")
213
+
214
+ /**
215
+ * @category type id
216
+ * @since 3.10.0
217
+ */
218
+ export type ParseErrorTypeId = typeof ParseErrorTypeId
219
+
220
+ /**
221
+ * @since 3.10.0
222
+ */
223
+ export const isParseError = (u: unknown): u is ParseError => Predicate.hasProperty(u, ParseErrorTypeId)
224
+
225
+ /**
226
+ * @since 3.10.0
227
+ */
228
+ export class ParseError extends TaggedError("ParseError")<{ readonly issue: ParseIssue }> {
229
+ /**
230
+ * @since 3.10.0
231
+ */
232
+ readonly [ParseErrorTypeId] = ParseErrorTypeId
233
+
234
+ get message() {
235
+ return this.toString()
236
+ }
237
+ /**
238
+ * @since 3.10.0
239
+ */
240
+ toString() {
241
+ return TreeFormatter.formatIssueSync(this.issue)
242
+ }
243
+ /**
244
+ * @since 3.10.0
245
+ */
246
+ toJSON() {
247
+ return {
248
+ _id: "ParseError",
249
+ message: this.toString()
250
+ }
251
+ }
252
+ /**
253
+ * @since 3.10.0
254
+ */
255
+ [Inspectable.NodeInspectSymbol]() {
256
+ return this.toJSON()
257
+ }
258
+ }
259
+
260
+ /**
261
+ * @category constructors
262
+ * @since 3.10.0
263
+ */
264
+ export const parseError = (issue: ParseIssue): ParseError => new ParseError({ issue })
265
+
266
+ /**
267
+ * @category constructors
268
+ * @since 3.10.0
269
+ */
270
+ export const succeed: <A>(a: A) => Either.Either<A, ParseIssue> = Either.right
271
+
272
+ /**
273
+ * @category constructors
274
+ * @since 3.10.0
275
+ */
276
+ export const fail: (issue: ParseIssue) => Either.Either<never, ParseIssue> = Either.left
277
+
278
+ const _try: <A>(options: {
279
+ try: LazyArg<A>
280
+ catch: (e: unknown) => ParseIssue
281
+ }) => Either.Either<A, ParseIssue> = Either.try
282
+
283
+ export {
284
+ /**
285
+ * @category constructors
286
+ * @since 3.10.0
287
+ */
288
+ _try as try
289
+ }
290
+
291
+ /**
292
+ * @category constructors
293
+ * @since 3.10.0
294
+ */
295
+ export const fromOption: {
296
+ /**
297
+ * @category constructors
298
+ * @since 3.10.0
299
+ */
300
+ (onNone: () => ParseIssue): <A>(self: Option.Option<A>) => Either.Either<A, ParseIssue>
301
+ /**
302
+ * @category constructors
303
+ * @since 3.10.0
304
+ */
305
+ <A>(self: Option.Option<A>, onNone: () => ParseIssue): Either.Either<A, ParseIssue>
306
+ } = Either.fromOption
307
+
308
+ /**
309
+ * @category optimisation
310
+ * @since 3.10.0
311
+ */
312
+ export const flatMap: {
313
+ /**
314
+ * @category optimisation
315
+ * @since 3.10.0
316
+ */
317
+ <A, B, E1, R1>(
318
+ f: (a: A) => Effect.Effect<B, E1, R1>
319
+ ): <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<B, E1 | E, R1 | R>
320
+ /**
321
+ * @category optimisation
322
+ * @since 3.10.0
323
+ */
324
+ <A, E, R, B, E1, R1>(
325
+ self: Effect.Effect<A, E, R>,
326
+ f: (a: A) => Effect.Effect<B, E1, R1>
327
+ ): Effect.Effect<B, E | E1, R | R1>
328
+ } = dual(2, <A, E, R, B, E1, R1>(
329
+ self: Effect.Effect<A, E, R>,
330
+ f: (a: A) => Effect.Effect<B, E1, R1>
331
+ ): Effect.Effect<B, E | E1, R | R1> => {
332
+ const s: any = self
333
+ if (s["_tag"] === "Left") {
334
+ return s
335
+ }
336
+ if (s["_tag"] === "Right") {
337
+ return f(s.right)
338
+ }
339
+ return Effect.flatMap(self, f)
340
+ })
341
+
342
+ /**
343
+ * @category optimisation
344
+ * @since 3.10.0
345
+ */
346
+ export const map: {
347
+ /**
348
+ * @category optimisation
349
+ * @since 3.10.0
350
+ */
351
+ <A, B>(f: (a: A) => B): <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<B, E, R>
352
+ /**
353
+ * @category optimisation
354
+ * @since 3.10.0
355
+ */
356
+ <A, E, R, B>(self: Effect.Effect<A, E, R>, f: (a: A) => B): Effect.Effect<B, E, R>
357
+ } = dual(2, <A, E, R, B>(self: Effect.Effect<A, E, R>, f: (a: A) => B): Effect.Effect<B, E, R> => {
358
+ const s: any = self
359
+ if (s["_tag"] === "Left") {
360
+ return s
361
+ }
362
+ if (s["_tag"] === "Right") {
363
+ return Either.right(f(s.right))
364
+ }
365
+ return Effect.map(self, f)
366
+ })
367
+
368
+ /**
369
+ * @category optimisation
370
+ * @since 3.10.0
371
+ */
372
+ export const mapError: {
373
+ /**
374
+ * @category optimisation
375
+ * @since 3.10.0
376
+ */
377
+ <E, E2>(f: (e: E) => E2): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E2, R>
378
+ /**
379
+ * @category optimisation
380
+ * @since 3.10.0
381
+ */
382
+ <A, E, R, E2>(self: Effect.Effect<A, E, R>, f: (e: E) => E2): Effect.Effect<A, E2, R>
383
+ } = dual(2, <A, E, R, E2>(self: Effect.Effect<A, E, R>, f: (e: E) => E2): Effect.Effect<A, E2, R> => {
384
+ const s: any = self
385
+ if (s["_tag"] === "Left") {
386
+ return Either.left(f(s.left))
387
+ }
388
+ if (s["_tag"] === "Right") {
389
+ return s
390
+ }
391
+ return Effect.mapError(self, f)
392
+ })
393
+
394
+ /**
395
+ * @category optimisation
396
+ * @since 3.10.0
397
+ */
398
+ export const eitherOrUndefined = <A, E, R>(
399
+ self: Effect.Effect<A, E, R>
400
+ ): Either.Either<A, E> | undefined => {
401
+ const s: any = self
402
+ if (s["_tag"] === "Left" || s["_tag"] === "Right") {
403
+ return s
404
+ }
405
+ }
406
+
407
+ /**
408
+ * @category optimisation
409
+ * @since 3.10.0
410
+ */
411
+ export const mapBoth: {
412
+ /**
413
+ * @category optimisation
414
+ * @since 3.10.0
415
+ */
416
+ <E, E2, A, A2>(
417
+ options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 }
418
+ ): <R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2, E2, R>
419
+ /**
420
+ * @category optimisation
421
+ * @since 3.10.0
422
+ */
423
+ <A, E, R, E2, A2>(
424
+ self: Effect.Effect<A, E, R>,
425
+ options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 }
426
+ ): Effect.Effect<A2, E2, R>
427
+ } = dual(2, <A, E, R, E2, A2>(
428
+ self: Effect.Effect<A, E, R>,
429
+ options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 }
430
+ ): Effect.Effect<A2, E2, R> => {
431
+ const s: any = self
432
+ if (s["_tag"] === "Left") {
433
+ return Either.left(options.onFailure(s.left))
434
+ }
435
+ if (s["_tag"] === "Right") {
436
+ return Either.right(options.onSuccess(s.right))
437
+ }
438
+ return Effect.mapBoth(self, options)
439
+ })
440
+
441
+ /**
442
+ * @category optimisation
443
+ * @since 3.10.0
444
+ */
445
+ export const orElse: {
446
+ /**
447
+ * @category optimisation
448
+ * @since 3.10.0
449
+ */
450
+ <E, A2, E2, R2>(
451
+ f: (e: E) => Effect.Effect<A2, E2, R2>
452
+ ): <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2 | A, E2, R2 | R>
453
+ /**
454
+ * @category optimisation
455
+ * @since 3.10.0
456
+ */
457
+ <A, E, R, A2, E2, R2>(
458
+ self: Effect.Effect<A, E, R>,
459
+ f: (e: E) => Effect.Effect<A2, E2, R2>
460
+ ): Effect.Effect<A2 | A, E2, R2 | R>
461
+ } = dual(2, <A, E, R, A2, E2, R2>(
462
+ self: Effect.Effect<A, E, R>,
463
+ f: (e: E) => Effect.Effect<A2, E2, R2>
464
+ ): Effect.Effect<A2 | A, E2, R2 | R> => {
465
+ const s: any = self
466
+ if (s["_tag"] === "Left") {
467
+ return f(s.left)
468
+ }
469
+ if (s["_tag"] === "Right") {
470
+ return s
471
+ }
472
+ return Effect.catchAll(self, f)
473
+ })
474
+
475
+ /**
476
+ * @since 3.10.0
477
+ */
478
+ export type DecodeUnknown<Out, R> = (u: unknown, options?: AST.ParseOptions) => Effect.Effect<Out, ParseIssue, R>
479
+
480
+ /**
481
+ * @since 3.10.0
482
+ */
483
+ export type DeclarationDecodeUnknown<Out, R> = (
484
+ u: unknown,
485
+ options: AST.ParseOptions,
486
+ ast: AST.Declaration
487
+ ) => Effect.Effect<Out, ParseIssue, R>
488
+
489
+ /** @internal */
490
+ export const mergeInternalOptions = (
491
+ options: InternalOptions | undefined,
492
+ overrideOptions: InternalOptions | number | undefined
493
+ ): InternalOptions | undefined => {
494
+ if (overrideOptions === undefined || Predicate.isNumber(overrideOptions)) {
495
+ return options
496
+ }
497
+ if (options === undefined) {
498
+ return overrideOptions
499
+ }
500
+ return { ...options, ...overrideOptions }
501
+ }
502
+
503
+ const getEither = (ast: AST.AST, isDecoding: boolean, options?: AST.ParseOptions) => {
504
+ const parser = goMemo(ast, isDecoding)
505
+ return (u: unknown, overrideOptions?: AST.ParseOptions): Either.Either<any, ParseIssue> =>
506
+ parser(u, mergeInternalOptions(options, overrideOptions)) as any
507
+ }
508
+
509
+ const getSync = (ast: AST.AST, isDecoding: boolean, options?: AST.ParseOptions) => {
510
+ const parser = getEither(ast, isDecoding, options)
511
+ return (input: unknown, overrideOptions?: AST.ParseOptions) =>
512
+ Either.getOrThrowWith(parser(input, overrideOptions), parseError)
513
+ }
514
+
515
+ const getOption = (ast: AST.AST, isDecoding: boolean, options?: AST.ParseOptions) => {
516
+ const parser = getEither(ast, isDecoding, options)
517
+ return (input: unknown, overrideOptions?: AST.ParseOptions): Option.Option<any> =>
518
+ Option.getRight(parser(input, overrideOptions))
519
+ }
520
+
521
+ const getEffect = <R>(ast: AST.AST, isDecoding: boolean, options?: AST.ParseOptions) => {
522
+ const parser = goMemo(ast, isDecoding)
523
+ return (input: unknown, overrideOptions?: AST.ParseOptions): Effect.Effect<any, ParseIssue, R> =>
524
+ parser(input, { ...mergeInternalOptions(options, overrideOptions), isEffectAllowed: true })
525
+ }
526
+
527
+ /**
528
+ * @throws `ParseError`
529
+ * @category decoding
530
+ * @since 3.10.0
531
+ */
532
+ export const decodeUnknownSync = <A, I>(
533
+ schema: Schema.Schema<A, I, never>,
534
+ options?: AST.ParseOptions
535
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => A => getSync(schema.ast, true, options)
536
+
537
+ /**
538
+ * @category decoding
539
+ * @since 3.10.0
540
+ */
541
+ export const decodeUnknownOption = <A, I>(
542
+ schema: Schema.Schema<A, I, never>,
543
+ options?: AST.ParseOptions
544
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Option.Option<A> => getOption(schema.ast, true, options)
545
+
546
+ /**
547
+ * @category decoding
548
+ * @since 3.10.0
549
+ */
550
+ export const decodeUnknownEither = <A, I>(
551
+ schema: Schema.Schema<A, I, never>,
552
+ options?: AST.ParseOptions
553
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Either.Either<A, ParseIssue> =>
554
+ getEither(schema.ast, true, options)
555
+
556
+ /**
557
+ * @category decoding
558
+ * @since 3.10.0
559
+ */
560
+ export const decodeUnknownPromise = <A, I>(
561
+ schema: Schema.Schema<A, I, never>,
562
+ options?: AST.ParseOptions
563
+ ) => {
564
+ const parser = decodeUnknown(schema, options)
565
+ return (u: unknown, overrideOptions?: AST.ParseOptions): Promise<A> => Effect.runPromise(parser(u, overrideOptions))
566
+ }
567
+
568
+ /**
569
+ * @category decoding
570
+ * @since 3.10.0
571
+ */
572
+ export const decodeUnknown = <A, I, R>(
573
+ schema: Schema.Schema<A, I, R>,
574
+ options?: AST.ParseOptions
575
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Effect.Effect<A, ParseIssue, R> =>
576
+ getEffect(schema.ast, true, options)
577
+
578
+ /**
579
+ * @throws `ParseError`
580
+ * @category encoding
581
+ * @since 3.10.0
582
+ */
583
+ export const encodeUnknownSync = <A, I>(
584
+ schema: Schema.Schema<A, I, never>,
585
+ options?: AST.ParseOptions
586
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => I => getSync(schema.ast, false, options)
587
+
588
+ /**
589
+ * @category encoding
590
+ * @since 3.10.0
591
+ */
592
+ export const encodeUnknownOption = <A, I>(
593
+ schema: Schema.Schema<A, I, never>,
594
+ options?: AST.ParseOptions
595
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Option.Option<I> => getOption(schema.ast, false, options)
596
+
597
+ /**
598
+ * @category encoding
599
+ * @since 3.10.0
600
+ */
601
+ export const encodeUnknownEither = <A, I>(
602
+ schema: Schema.Schema<A, I, never>,
603
+ options?: AST.ParseOptions
604
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Either.Either<I, ParseIssue> =>
605
+ getEither(schema.ast, false, options)
606
+
607
+ /**
608
+ * @category encoding
609
+ * @since 3.10.0
610
+ */
611
+ export const encodeUnknownPromise = <A, I>(
612
+ schema: Schema.Schema<A, I, never>,
613
+ options?: AST.ParseOptions
614
+ ) => {
615
+ const parser = encodeUnknown(schema, options)
616
+ return (u: unknown, overrideOptions?: AST.ParseOptions): Promise<I> => Effect.runPromise(parser(u, overrideOptions))
617
+ }
618
+
619
+ /**
620
+ * @category encoding
621
+ * @since 3.10.0
622
+ */
623
+ export const encodeUnknown = <A, I, R>(
624
+ schema: Schema.Schema<A, I, R>,
625
+ options?: AST.ParseOptions
626
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Effect.Effect<I, ParseIssue, R> =>
627
+ getEffect(schema.ast, false, options)
628
+
629
+ /**
630
+ * @category decoding
631
+ * @since 3.10.0
632
+ */
633
+ export const decodeSync: <A, I>(
634
+ schema: Schema.Schema<A, I, never>,
635
+ options?: AST.ParseOptions
636
+ ) => (i: I, overrideOptions?: AST.ParseOptions) => A = decodeUnknownSync
637
+
638
+ /**
639
+ * @category decoding
640
+ * @since 3.10.0
641
+ */
642
+ export const decodeOption: <A, I>(
643
+ schema: Schema.Schema<A, I, never>,
644
+ options?: AST.ParseOptions
645
+ ) => (i: I, overrideOptions?: AST.ParseOptions) => Option.Option<A> = decodeUnknownOption
646
+
647
+ /**
648
+ * @category decoding
649
+ * @since 3.10.0
650
+ */
651
+ export const decodeEither: <A, I>(
652
+ schema: Schema.Schema<A, I, never>,
653
+ options?: AST.ParseOptions
654
+ ) => (i: I, overrideOptions?: AST.ParseOptions) => Either.Either<A, ParseIssue> = decodeUnknownEither
655
+
656
+ /**
657
+ * @category decoding
658
+ * @since 3.10.0
659
+ */
660
+ export const decodePromise: <A, I>(
661
+ schema: Schema.Schema<A, I, never>,
662
+ options?: AST.ParseOptions
663
+ ) => (i: I, overrideOptions?: AST.ParseOptions) => Promise<A> = decodeUnknownPromise
664
+
665
+ /**
666
+ * @category decoding
667
+ * @since 3.10.0
668
+ */
669
+ export const decode: <A, I, R>(
670
+ schema: Schema.Schema<A, I, R>,
671
+ options?: AST.ParseOptions
672
+ ) => (i: I, overrideOptions?: AST.ParseOptions) => Effect.Effect<A, ParseIssue, R> = decodeUnknown
673
+
674
+ /**
675
+ * @throws `ParseError`
676
+ * @category validation
677
+ * @since 3.10.0
678
+ */
679
+ export const validateSync = <A, I, R>(
680
+ schema: Schema.Schema<A, I, R>,
681
+ options?: AST.ParseOptions
682
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => A => getSync(AST.typeAST(schema.ast), true, options)
683
+
684
+ /**
685
+ * @category validation
686
+ * @since 3.10.0
687
+ */
688
+ export const validateOption = <A, I, R>(
689
+ schema: Schema.Schema<A, I, R>,
690
+ options?: AST.ParseOptions
691
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Option.Option<A> =>
692
+ getOption(AST.typeAST(schema.ast), true, options)
693
+
694
+ /**
695
+ * @category validation
696
+ * @since 3.10.0
697
+ */
698
+ export const validateEither = <A, I, R>(
699
+ schema: Schema.Schema<A, I, R>,
700
+ options?: AST.ParseOptions
701
+ ): (u: unknown, overrideOptions?: AST.ParseOptions) => Either.Either<A, ParseIssue> =>
702
+ getEither(AST.typeAST(schema.ast), true, options)
703
+
704
+ /**
705
+ * @category validation
706
+ * @since 3.10.0
707
+ */
708
+ export const validatePromise = <A, I>(
709
+ schema: Schema.Schema<A, I, never>,
710
+ options?: AST.ParseOptions
711
+ ) => {
712
+ const parser = validate(schema, options)
713
+ return (u: unknown, overrideOptions?: AST.ParseOptions): Promise<A> => Effect.runPromise(parser(u, overrideOptions))
714
+ }
715
+
716
+ /**
717
+ * @category validation
718
+ * @since 3.10.0
719
+ */
720
+ export const validate = <A, I, R>(
721
+ schema: Schema.Schema<A, I, R>,
722
+ options?: AST.ParseOptions
723
+ ): (a: unknown, overrideOptions?: AST.ParseOptions) => Effect.Effect<A, ParseIssue, R> =>
724
+ getEffect(AST.typeAST(schema.ast), true, options)
725
+
726
+ /**
727
+ * By default the option `exact` is set to `true`.
728
+ *
729
+ * @category validation
730
+ * @since 3.10.0
731
+ */
732
+ export const is = <A, I, R>(schema: Schema.Schema<A, I, R>, options?: AST.ParseOptions) => {
733
+ const parser = goMemo(AST.typeAST(schema.ast), true)
734
+ return (u: unknown, overrideOptions?: AST.ParseOptions | number): u is A =>
735
+ Either.isRight(parser(u, { exact: true, ...mergeInternalOptions(options, overrideOptions) }) as any)
736
+ }
737
+
738
+ /**
739
+ * By default the option `exact` is set to `true`.
740
+ *
741
+ * @throws `ParseError`
742
+ * @category validation
743
+ * @since 3.10.0
744
+ */
745
+ export const asserts = <A, I, R>(schema: Schema.Schema<A, I, R>, options?: AST.ParseOptions) => {
746
+ const parser = goMemo(AST.typeAST(schema.ast), true)
747
+ return (u: unknown, overrideOptions?: AST.ParseOptions): asserts u is A => {
748
+ const result: Either.Either<any, ParseIssue> = parser(u, {
749
+ exact: true,
750
+ ...mergeInternalOptions(options, overrideOptions)
751
+ }) as any
752
+ if (Either.isLeft(result)) {
753
+ throw parseError(result.left)
754
+ }
755
+ }
756
+ }
757
+
758
+ /**
759
+ * @category encoding
760
+ * @since 3.10.0
761
+ */
762
+ export const encodeSync: <A, I>(
763
+ schema: Schema.Schema<A, I, never>,
764
+ options?: AST.ParseOptions
765
+ ) => (a: A, overrideOptions?: AST.ParseOptions) => I = encodeUnknownSync
766
+
767
+ /**
768
+ * @category encoding
769
+ * @since 3.10.0
770
+ */
771
+ export const encodeOption: <A, I>(
772
+ schema: Schema.Schema<A, I, never>,
773
+ options?: AST.ParseOptions
774
+ ) => (input: A, overrideOptions?: AST.ParseOptions) => Option.Option<I> = encodeUnknownOption
775
+
776
+ /**
777
+ * @category encoding
778
+ * @since 3.10.0
779
+ */
780
+ export const encodeEither: <A, I>(
781
+ schema: Schema.Schema<A, I, never>,
782
+ options?: AST.ParseOptions
783
+ ) => (a: A, overrideOptions?: AST.ParseOptions) => Either.Either<I, ParseIssue> = encodeUnknownEither
784
+
785
+ /**
786
+ * @category encoding
787
+ * @since 3.10.0
788
+ */
789
+ export const encodePromise: <A, I>(
790
+ schema: Schema.Schema<A, I, never>,
791
+ options?: AST.ParseOptions
792
+ ) => (a: A, overrideOptions?: AST.ParseOptions) => Promise<I> = encodeUnknownPromise
793
+
794
+ /**
795
+ * @category encoding
796
+ * @since 3.10.0
797
+ */
798
+ export const encode: <A, I, R>(
799
+ schema: Schema.Schema<A, I, R>,
800
+ options?: AST.ParseOptions
801
+ ) => (a: A, overrideOptions?: AST.ParseOptions) => Effect.Effect<I, ParseIssue, R> = encodeUnknown
802
+
803
+ interface InternalOptions extends AST.ParseOptions {
804
+ readonly isEffectAllowed?: boolean
805
+ }
806
+
807
+ interface Parser {
808
+ (i: any, options?: InternalOptions): Effect.Effect<any, ParseIssue, any>
809
+ }
810
+
811
+ const decodeMemoMap = globalValue(
812
+ Symbol.for("effect/Schema/Parser/decodeMemoMap"),
813
+ () => new WeakMap<AST.AST, Parser>()
814
+ )
815
+ const encodeMemoMap = globalValue(
816
+ Symbol.for("effect/Schema/Parser/encodeMemoMap"),
817
+ () => new WeakMap<AST.AST, Parser>()
818
+ )
819
+
820
+ const goMemo = (ast: AST.AST, isDecoding: boolean): Parser => {
821
+ const memoMap = isDecoding ? decodeMemoMap : encodeMemoMap
822
+ const memo = memoMap.get(ast)
823
+ if (memo) {
824
+ return memo
825
+ }
826
+ const raw = go(ast, isDecoding)
827
+ const parseOptionsAnnotation = AST.getParseOptionsAnnotation(ast)
828
+ const parserWithOptions: Parser = Option.isSome(parseOptionsAnnotation)
829
+ ? (i, options) => raw(i, mergeInternalOptions(options, parseOptionsAnnotation.value))
830
+ : raw
831
+ const decodingFallbackAnnotation = AST.getDecodingFallbackAnnotation(ast)
832
+ const parser: Parser = isDecoding && Option.isSome(decodingFallbackAnnotation)
833
+ ? (i, options) =>
834
+ handleForbidden(orElse(parserWithOptions(i, options), decodingFallbackAnnotation.value), ast, i, options)
835
+ : parserWithOptions
836
+ memoMap.set(ast, parser)
837
+ return parser
838
+ }
839
+
840
+ const getConcurrency = (ast: AST.AST): Concurrency | undefined =>
841
+ Option.getOrUndefined(AST.getConcurrencyAnnotation(ast))
842
+
843
+ const getBatching = (ast: AST.AST): boolean | "inherit" | undefined =>
844
+ Option.getOrUndefined(AST.getBatchingAnnotation(ast))
845
+
846
+ const go = (ast: AST.AST, isDecoding: boolean): Parser => {
847
+ switch (ast._tag) {
848
+ case "Refinement": {
849
+ if (isDecoding) {
850
+ const from = goMemo(ast.from, true)
851
+ return (i, options) => {
852
+ options = options ?? AST.defaultParseOption
853
+ const allErrors = options?.errors === "all"
854
+ const result = flatMap(
855
+ orElse(from(i, options), (ef) => {
856
+ const issue = new Refinement(ast, i, "From", ef)
857
+ if (allErrors && AST.hasStableFilter(ast)) {
858
+ return Option.match(
859
+ ast.filter(i, options, ast),
860
+ {
861
+ onNone: () => Either.left<ParseIssue>(issue),
862
+ onSome: (ep) => Either.left(new Composite(ast, i, [issue, new Refinement(ast, i, "Predicate", ep)]))
863
+ }
864
+ )
865
+ }
866
+ return Either.left(issue)
867
+ }),
868
+ (a) =>
869
+ Option.match(
870
+ ast.filter(a, options, ast),
871
+ {
872
+ onNone: () => Either.right(a),
873
+ onSome: (ep) => Either.left(new Refinement(ast, i, "Predicate", ep))
874
+ }
875
+ )
876
+ )
877
+ return handleForbidden(result, ast, i, options)
878
+ }
879
+ } else {
880
+ const from = goMemo(AST.typeAST(ast), true)
881
+ const to = goMemo(dropRightRefinement(ast.from), false)
882
+ return (i, options) => handleForbidden(flatMap(from(i, options), (a) => to(a, options)), ast, i, options)
883
+ }
884
+ }
885
+ case "Transformation": {
886
+ const transform = getFinalTransformation(ast.transformation, isDecoding)
887
+ const from = isDecoding ? goMemo(ast.from, true) : goMemo(ast.to, false)
888
+ const to = isDecoding ? goMemo(ast.to, true) : goMemo(ast.from, false)
889
+ return (i, options) =>
890
+ handleForbidden(
891
+ flatMap(
892
+ mapError(
893
+ from(i, options),
894
+ (e) => new Transformation(ast, i, isDecoding ? "Encoded" : "Type", e)
895
+ ),
896
+ (a) =>
897
+ flatMap(
898
+ mapError(
899
+ transform(a, options ?? AST.defaultParseOption, ast, i),
900
+ (e) => new Transformation(ast, i, "Transformation", e)
901
+ ),
902
+ (i2) =>
903
+ mapError(
904
+ to(i2, options),
905
+ (e) => new Transformation(ast, i, isDecoding ? "Type" : "Encoded", e)
906
+ )
907
+ )
908
+ ),
909
+ ast,
910
+ i,
911
+ options
912
+ )
913
+ }
914
+ case "Declaration": {
915
+ const parse = isDecoding
916
+ ? ast.decodeUnknown(...ast.typeParameters)
917
+ : ast.encodeUnknown(...ast.typeParameters)
918
+ return (i, options) => handleForbidden(parse(i, options ?? AST.defaultParseOption, ast), ast, i, options)
919
+ }
920
+ case "Literal":
921
+ return fromRefinement(ast, (u): u is typeof ast.literal => u === ast.literal)
922
+ case "UniqueSymbol":
923
+ return fromRefinement(ast, (u): u is typeof ast.symbol => u === ast.symbol)
924
+ case "UndefinedKeyword":
925
+ return fromRefinement(ast, Predicate.isUndefined)
926
+ case "NeverKeyword":
927
+ return fromRefinement(ast, Predicate.isNever)
928
+ case "UnknownKeyword":
929
+ case "AnyKeyword":
930
+ case "VoidKeyword":
931
+ return Either.right
932
+ case "StringKeyword":
933
+ return fromRefinement(ast, Predicate.isString)
934
+ case "NumberKeyword":
935
+ return fromRefinement(ast, Predicate.isNumber)
936
+ case "BooleanKeyword":
937
+ return fromRefinement(ast, Predicate.isBoolean)
938
+ case "BigIntKeyword":
939
+ return fromRefinement(ast, Predicate.isBigInt)
940
+ case "SymbolKeyword":
941
+ return fromRefinement(ast, Predicate.isSymbol)
942
+ case "ObjectKeyword":
943
+ return fromRefinement(ast, Predicate.isObject)
944
+ case "Enums":
945
+ return fromRefinement(ast, (u): u is any => ast.enums.some(([_, value]) => value === u))
946
+ case "TemplateLiteral": {
947
+ const regex = AST.getTemplateLiteralRegExp(ast)
948
+ return fromRefinement(ast, (u): u is any => Predicate.isString(u) && regex.test(u))
949
+ }
950
+ case "TupleType": {
951
+ const elements = ast.elements.map((e) => goMemo(e.type, isDecoding))
952
+ const rest = ast.rest.map((annotatedAST) => goMemo(annotatedAST.type, isDecoding))
953
+ let requiredTypes: Array<AST.Type> = ast.elements.filter((e) => !e.isOptional)
954
+ if (ast.rest.length > 0) {
955
+ requiredTypes = requiredTypes.concat(ast.rest.slice(1))
956
+ }
957
+ const requiredLen = requiredTypes.length
958
+ const expectedIndexes = ast.elements.length > 0 ? ast.elements.map((_, i) => i).join(" | ") : "never"
959
+ const concurrency = getConcurrency(ast)
960
+ const batching = getBatching(ast)
961
+ return (input: unknown, options) => {
962
+ if (!array_.isArray(input)) {
963
+ return Either.left(new Type(ast, input))
964
+ }
965
+ const allErrors = options?.errors === "all"
966
+ const es: Array<[number, ParseIssue]> = []
967
+ let stepKey = 0
968
+ const output: Array<[number, any]> = []
969
+ // ---------------------------------------------
970
+ // handle missing indexes
971
+ // ---------------------------------------------
972
+ const len = input.length
973
+ for (let i = len; i <= requiredLen - 1; i++) {
974
+ const e = new Pointer(i, input, new Missing(requiredTypes[i - len]))
975
+ if (allErrors) {
976
+ es.push([stepKey++, e])
977
+ continue
978
+ } else {
979
+ return Either.left(new Composite(ast, input, e, output))
980
+ }
981
+ }
982
+
983
+ // ---------------------------------------------
984
+ // handle excess indexes
985
+ // ---------------------------------------------
986
+ if (ast.rest.length === 0) {
987
+ for (let i = ast.elements.length; i <= len - 1; i++) {
988
+ const e = new Pointer(i, input, new Unexpected(input[i], `is unexpected, expected: ${expectedIndexes}`))
989
+ if (allErrors) {
990
+ es.push([stepKey++, e])
991
+ continue
992
+ } else {
993
+ return Either.left(new Composite(ast, input, e, output))
994
+ }
995
+ }
996
+ }
997
+
998
+ let i = 0
999
+ type State = {
1000
+ es: typeof es
1001
+ output: typeof output
1002
+ }
1003
+ let queue:
1004
+ | Array<(_: State) => Effect.Effect<void, ParseIssue, any>>
1005
+ | undefined = undefined
1006
+
1007
+ // ---------------------------------------------
1008
+ // handle elements
1009
+ // ---------------------------------------------
1010
+ for (; i < elements.length; i++) {
1011
+ if (len < i + 1) {
1012
+ if (ast.elements[i].isOptional) {
1013
+ // the input element is missing
1014
+ continue
1015
+ }
1016
+ } else {
1017
+ const parser = elements[i]
1018
+ const te = parser(input[i], options)
1019
+ const eu = eitherOrUndefined(te)
1020
+ if (eu) {
1021
+ if (Either.isLeft(eu)) {
1022
+ // the input element is present but is not valid
1023
+ const e = new Pointer(i, input, eu.left)
1024
+ if (allErrors) {
1025
+ es.push([stepKey++, e])
1026
+ continue
1027
+ } else {
1028
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1029
+ }
1030
+ }
1031
+ output.push([stepKey++, eu.right])
1032
+ } else {
1033
+ const nk = stepKey++
1034
+ const index = i
1035
+ if (!queue) {
1036
+ queue = []
1037
+ }
1038
+ queue.push(({ es, output }: State) =>
1039
+ Effect.flatMap(Effect.either(te), (t) => {
1040
+ if (Either.isLeft(t)) {
1041
+ // the input element is present but is not valid
1042
+ const e = new Pointer(index, input, t.left)
1043
+ if (allErrors) {
1044
+ es.push([nk, e])
1045
+ return Effect.void
1046
+ } else {
1047
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1048
+ }
1049
+ }
1050
+ output.push([nk, t.right])
1051
+ return Effect.void
1052
+ })
1053
+ )
1054
+ }
1055
+ }
1056
+ }
1057
+ // ---------------------------------------------
1058
+ // handle rest element
1059
+ // ---------------------------------------------
1060
+ if (array_.isNonEmptyReadonlyArray(rest)) {
1061
+ const [head, ...tail] = rest
1062
+ for (; i < len - tail.length; i++) {
1063
+ const te = head(input[i], options)
1064
+ const eu = eitherOrUndefined(te)
1065
+ if (eu) {
1066
+ if (Either.isLeft(eu)) {
1067
+ const e = new Pointer(i, input, eu.left)
1068
+ if (allErrors) {
1069
+ es.push([stepKey++, e])
1070
+ continue
1071
+ } else {
1072
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1073
+ }
1074
+ } else {
1075
+ output.push([stepKey++, eu.right])
1076
+ }
1077
+ } else {
1078
+ const nk = stepKey++
1079
+ const index = i
1080
+ if (!queue) {
1081
+ queue = []
1082
+ }
1083
+ queue.push(
1084
+ ({ es, output }: State) =>
1085
+ Effect.flatMap(Effect.either(te), (t) => {
1086
+ if (Either.isLeft(t)) {
1087
+ const e = new Pointer(index, input, t.left)
1088
+ if (allErrors) {
1089
+ es.push([nk, e])
1090
+ return Effect.void
1091
+ } else {
1092
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1093
+ }
1094
+ } else {
1095
+ output.push([nk, t.right])
1096
+ return Effect.void
1097
+ }
1098
+ })
1099
+ )
1100
+ }
1101
+ }
1102
+ // ---------------------------------------------
1103
+ // handle post rest elements
1104
+ // ---------------------------------------------
1105
+ for (let j = 0; j < tail.length; j++) {
1106
+ i += j
1107
+ if (len < i + 1) {
1108
+ continue
1109
+ } else {
1110
+ const te = tail[j](input[i], options)
1111
+ const eu = eitherOrUndefined(te)
1112
+ if (eu) {
1113
+ if (Either.isLeft(eu)) {
1114
+ // the input element is present but is not valid
1115
+ const e = new Pointer(i, input, eu.left)
1116
+ if (allErrors) {
1117
+ es.push([stepKey++, e])
1118
+ continue
1119
+ } else {
1120
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1121
+ }
1122
+ }
1123
+ output.push([stepKey++, eu.right])
1124
+ } else {
1125
+ const nk = stepKey++
1126
+ const index = i
1127
+ if (!queue) {
1128
+ queue = []
1129
+ }
1130
+ queue.push(
1131
+ ({ es, output }: State) =>
1132
+ Effect.flatMap(Effect.either(te), (t) => {
1133
+ if (Either.isLeft(t)) {
1134
+ // the input element is present but is not valid
1135
+ const e = new Pointer(index, input, t.left)
1136
+ if (allErrors) {
1137
+ es.push([nk, e])
1138
+ return Effect.void
1139
+ } else {
1140
+ return Either.left(new Composite(ast, input, e, sortByIndex(output)))
1141
+ }
1142
+ }
1143
+ output.push([nk, t.right])
1144
+ return Effect.void
1145
+ })
1146
+ )
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+ // ---------------------------------------------
1153
+ // compute result
1154
+ // ---------------------------------------------
1155
+ const computeResult = ({ es, output }: State) =>
1156
+ array_.isNonEmptyArray(es) ?
1157
+ Either.left(new Composite(ast, input, sortByIndex(es), sortByIndex(output))) :
1158
+ Either.right(sortByIndex(output))
1159
+ if (queue && queue.length > 0) {
1160
+ const cqueue = queue
1161
+ return Effect.suspend(() => {
1162
+ const state: State = {
1163
+ es: array_.copy(es),
1164
+ output: array_.copy(output)
1165
+ }
1166
+ return Effect.flatMap(
1167
+ Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
1168
+ () => computeResult(state)
1169
+ )
1170
+ })
1171
+ }
1172
+ return computeResult({ output, es })
1173
+ }
1174
+ }
1175
+ case "TypeLiteral": {
1176
+ if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
1177
+ return fromRefinement(ast, Predicate.isNotNullable)
1178
+ }
1179
+
1180
+ const propertySignatures: Array<readonly [Parser, AST.PropertySignature]> = []
1181
+ const expectedKeysMap: Record<PropertyKey, null> = {}
1182
+ const expectedKeys: Array<PropertyKey> = []
1183
+ for (const ps of ast.propertySignatures) {
1184
+ propertySignatures.push([goMemo(ps.type, isDecoding), ps])
1185
+ expectedKeysMap[ps.name] = null
1186
+ expectedKeys.push(ps.name)
1187
+ }
1188
+
1189
+ const indexSignatures = ast.indexSignatures.map((is) =>
1190
+ [
1191
+ goMemo(is.parameter, isDecoding),
1192
+ goMemo(is.type, isDecoding),
1193
+ is.parameter
1194
+ ] as const
1195
+ )
1196
+ const expectedAST = AST.Union.make(
1197
+ ast.indexSignatures.map((is): AST.AST => is.parameter).concat(
1198
+ expectedKeys.map((key) => Predicate.isSymbol(key) ? new AST.UniqueSymbol(key) : new AST.Literal(key))
1199
+ )
1200
+ )
1201
+ const expected = goMemo(expectedAST, isDecoding)
1202
+ const concurrency = getConcurrency(ast)
1203
+ const batching = getBatching(ast)
1204
+ return (input: unknown, options) => {
1205
+ if (!Predicate.isRecord(input)) {
1206
+ return Either.left(new Type(ast, input))
1207
+ }
1208
+ const allErrors = options?.errors === "all"
1209
+ const es: Array<[number, ParseIssue]> = []
1210
+ let stepKey = 0
1211
+
1212
+ // ---------------------------------------------
1213
+ // handle excess properties
1214
+ // ---------------------------------------------
1215
+ const onExcessPropertyError = options?.onExcessProperty === "error"
1216
+ const onExcessPropertyPreserve = options?.onExcessProperty === "preserve"
1217
+ const output: Record<PropertyKey, unknown> = {}
1218
+ let inputKeys: Array<PropertyKey> | undefined
1219
+ if (onExcessPropertyError || onExcessPropertyPreserve) {
1220
+ inputKeys = util_.ownKeys(input)
1221
+ for (const key of inputKeys) {
1222
+ const eu = eitherOrUndefined(expected(key, options))!
1223
+ if (Either.isLeft(eu)) {
1224
+ // key is unexpected
1225
+ if (onExcessPropertyError) {
1226
+ const e = new Pointer(
1227
+ key,
1228
+ input,
1229
+ new Unexpected(input[key], `is unexpected, expected: ${String(expectedAST)}`)
1230
+ )
1231
+ if (allErrors) {
1232
+ es.push([stepKey++, e])
1233
+ continue
1234
+ } else {
1235
+ return Either.left(new Composite(ast, input, e, output))
1236
+ }
1237
+ } else {
1238
+ // preserve key
1239
+ output[key] = input[key]
1240
+ }
1241
+ }
1242
+ }
1243
+ }
1244
+
1245
+ // ---------------------------------------------
1246
+ // handle property signatures
1247
+ // ---------------------------------------------
1248
+ type State = {
1249
+ es: typeof es
1250
+ output: typeof output
1251
+ }
1252
+ let queue:
1253
+ | Array<(state: State) => Effect.Effect<void, ParseIssue, any>>
1254
+ | undefined = undefined
1255
+
1256
+ const isExact = options?.exact === true
1257
+ for (let i = 0; i < propertySignatures.length; i++) {
1258
+ const ps = propertySignatures[i][1]
1259
+ const name = ps.name
1260
+ const hasKey = Object.prototype.hasOwnProperty.call(input, name)
1261
+ if (!hasKey) {
1262
+ if (ps.isOptional) {
1263
+ continue
1264
+ } else if (isExact) {
1265
+ const e = new Pointer(name, input, new Missing(ps))
1266
+ if (allErrors) {
1267
+ es.push([stepKey++, e])
1268
+ continue
1269
+ } else {
1270
+ return Either.left(new Composite(ast, input, e, output))
1271
+ }
1272
+ }
1273
+ }
1274
+ const parser = propertySignatures[i][0]
1275
+ const te = parser(input[name], options)
1276
+ const eu = eitherOrUndefined(te)
1277
+ if (eu) {
1278
+ if (Either.isLeft(eu)) {
1279
+ const e = new Pointer(name, input, hasKey ? eu.left : new Missing(ps))
1280
+ if (allErrors) {
1281
+ es.push([stepKey++, e])
1282
+ continue
1283
+ } else {
1284
+ return Either.left(new Composite(ast, input, e, output))
1285
+ }
1286
+ }
1287
+ output[name] = eu.right
1288
+ } else {
1289
+ const nk = stepKey++
1290
+ const index = name
1291
+ if (!queue) {
1292
+ queue = []
1293
+ }
1294
+ queue.push(
1295
+ ({ es, output }: State) =>
1296
+ Effect.flatMap(Effect.either(te), (t) => {
1297
+ if (Either.isLeft(t)) {
1298
+ const e = new Pointer(index, input, hasKey ? t.left : new Missing(ps))
1299
+ if (allErrors) {
1300
+ es.push([nk, e])
1301
+ return Effect.void
1302
+ } else {
1303
+ return Either.left(new Composite(ast, input, e, output))
1304
+ }
1305
+ }
1306
+ output[index] = t.right
1307
+ return Effect.void
1308
+ })
1309
+ )
1310
+ }
1311
+ }
1312
+
1313
+ // ---------------------------------------------
1314
+ // handle index signatures
1315
+ // ---------------------------------------------
1316
+ for (let i = 0; i < indexSignatures.length; i++) {
1317
+ const indexSignature = indexSignatures[i]
1318
+ const parameter = indexSignature[0]
1319
+ const type = indexSignature[1]
1320
+ const keys = util_.getKeysForIndexSignature(input, indexSignature[2])
1321
+ for (const key of keys) {
1322
+ // ---------------------------------------------
1323
+ // handle keys
1324
+ // ---------------------------------------------
1325
+ const keu = eitherOrUndefined(parameter(key, options))
1326
+ if (keu && Either.isRight(keu)) {
1327
+ // ---------------------------------------------
1328
+ // handle values
1329
+ // ---------------------------------------------
1330
+ const vpr = type(input[key], options)
1331
+ const veu = eitherOrUndefined(vpr)
1332
+ if (veu) {
1333
+ if (Either.isLeft(veu)) {
1334
+ const e = new Pointer(key, input, veu.left)
1335
+ if (allErrors) {
1336
+ es.push([stepKey++, e])
1337
+ continue
1338
+ } else {
1339
+ return Either.left(new Composite(ast, input, e, output))
1340
+ }
1341
+ } else {
1342
+ if (!Object.prototype.hasOwnProperty.call(expectedKeysMap, key)) {
1343
+ output[key] = veu.right
1344
+ }
1345
+ }
1346
+ } else {
1347
+ const nk = stepKey++
1348
+ const index = key
1349
+ if (!queue) {
1350
+ queue = []
1351
+ }
1352
+ queue.push(
1353
+ ({ es, output }: State) =>
1354
+ Effect.flatMap(
1355
+ Effect.either(vpr),
1356
+ (tv) => {
1357
+ if (Either.isLeft(tv)) {
1358
+ const e = new Pointer(index, input, tv.left)
1359
+ if (allErrors) {
1360
+ es.push([nk, e])
1361
+ return Effect.void
1362
+ } else {
1363
+ return Either.left(new Composite(ast, input, e, output))
1364
+ }
1365
+ } else {
1366
+ if (!Object.prototype.hasOwnProperty.call(expectedKeysMap, key)) {
1367
+ output[key] = tv.right
1368
+ }
1369
+ return Effect.void
1370
+ }
1371
+ }
1372
+ )
1373
+ )
1374
+ }
1375
+ }
1376
+ }
1377
+ }
1378
+ // ---------------------------------------------
1379
+ // compute result
1380
+ // ---------------------------------------------
1381
+ const computeResult = ({ es, output }: State) => {
1382
+ if (array_.isNonEmptyArray(es)) {
1383
+ return Either.left(new Composite(ast, input, sortByIndex(es), output))
1384
+ }
1385
+ if (options?.propertyOrder === "original") {
1386
+ // preserve input keys order
1387
+ const keys = inputKeys || util_.ownKeys(input)
1388
+ for (const name of expectedKeys) {
1389
+ if (keys.indexOf(name) === -1) {
1390
+ keys.push(name)
1391
+ }
1392
+ }
1393
+ const out: any = {}
1394
+ for (const key of keys) {
1395
+ if (Object.prototype.hasOwnProperty.call(output, key)) {
1396
+ out[key] = output[key]
1397
+ }
1398
+ }
1399
+ return Either.right(out)
1400
+ }
1401
+ return Either.right(output)
1402
+ }
1403
+ if (queue && queue.length > 0) {
1404
+ const cqueue = queue
1405
+ return Effect.suspend(() => {
1406
+ const state: State = {
1407
+ es: array_.copy(es),
1408
+ output: Object.assign({}, output)
1409
+ }
1410
+ return Effect.flatMap(
1411
+ Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
1412
+ () => computeResult(state)
1413
+ )
1414
+ })
1415
+ }
1416
+ return computeResult({ es, output })
1417
+ }
1418
+ }
1419
+ case "Union": {
1420
+ const searchTree = getSearchTree(ast.types, isDecoding)
1421
+ const ownKeys = util_.ownKeys(searchTree.keys)
1422
+ const len = ownKeys.length
1423
+ const map = new Map<any, Parser>()
1424
+ for (let i = 0; i < ast.types.length; i++) {
1425
+ map.set(ast.types[i], goMemo(ast.types[i], isDecoding))
1426
+ }
1427
+ const concurrency = getConcurrency(ast) ?? 1
1428
+ const batching = getBatching(ast)
1429
+ return (input, options) => {
1430
+ const es: Array<[number, ParseIssue]> = []
1431
+ let stepKey = 0
1432
+ let candidates: Array<AST.AST> = []
1433
+ if (len > 0) {
1434
+ if (Predicate.isRecordOrArray(input)) {
1435
+ for (let i = 0; i < len; i++) {
1436
+ const name = ownKeys[i]
1437
+ const buckets = searchTree.keys[name].buckets
1438
+ // for each property that should contain a literal, check if the input contains that property
1439
+ if (Object.prototype.hasOwnProperty.call(input, name)) {
1440
+ const literal = String(input[name])
1441
+ // check that the value obtained from the input for the property corresponds to an existing bucket
1442
+ if (Object.prototype.hasOwnProperty.call(buckets, literal)) {
1443
+ // retrive the minimal set of candidates for decoding
1444
+ candidates = candidates.concat(buckets[literal])
1445
+ } else {
1446
+ const literals = AST.Union.make(searchTree.keys[name].literals)
1447
+ es.push([
1448
+ stepKey++,
1449
+ new Composite(
1450
+ new AST.TypeLiteral([
1451
+ new AST.PropertySignature(name, literals, false, true)
1452
+ ], []),
1453
+ input,
1454
+ new Pointer(name, input, new Type(literals, input[name]))
1455
+ )
1456
+ ])
1457
+ }
1458
+ } else {
1459
+ const literals = AST.Union.make(searchTree.keys[name].literals)
1460
+ const fakeps = new AST.PropertySignature(name, literals, false, true)
1461
+ es.push([
1462
+ stepKey++,
1463
+ new Composite(
1464
+ new AST.TypeLiteral([fakeps], []),
1465
+ input,
1466
+ new Pointer(name, input, new Missing(fakeps))
1467
+ )
1468
+ ])
1469
+ }
1470
+ }
1471
+ } else {
1472
+ es.push([stepKey++, new Type(ast, input)])
1473
+ }
1474
+ }
1475
+ if (searchTree.otherwise.length > 0) {
1476
+ candidates = candidates.concat(searchTree.otherwise)
1477
+ }
1478
+
1479
+ let queue:
1480
+ | Array<(state: State) => Effect.Effect<unknown, ParseIssue, any>>
1481
+ | undefined = undefined
1482
+
1483
+ type State = {
1484
+ finalResult?: any
1485
+ es: typeof es
1486
+ }
1487
+
1488
+ for (let i = 0; i < candidates.length; i++) {
1489
+ const candidate = candidates[i]
1490
+ const pr = map.get(candidate)!(input, options)
1491
+ // the members of a union are ordered based on which one should be decoded first,
1492
+ // therefore if one member has added a task, all subsequent members must
1493
+ // also add a task to the queue even if they are synchronous
1494
+ const eu = !queue || queue.length === 0 ? eitherOrUndefined(pr) : undefined
1495
+ if (eu) {
1496
+ if (Either.isRight(eu)) {
1497
+ return eu
1498
+ } else {
1499
+ es.push([stepKey++, eu.left])
1500
+ }
1501
+ } else {
1502
+ const nk = stepKey++
1503
+ if (!queue) {
1504
+ queue = []
1505
+ }
1506
+ queue.push(
1507
+ (state) =>
1508
+ Effect.suspend(() => {
1509
+ if ("finalResult" in state) {
1510
+ return Effect.void
1511
+ } else {
1512
+ return Effect.flatMap(Effect.either(pr), (t) => {
1513
+ if (Either.isRight(t)) {
1514
+ state.finalResult = t
1515
+ } else {
1516
+ state.es.push([nk, t.left])
1517
+ }
1518
+ return Effect.void
1519
+ })
1520
+ }
1521
+ })
1522
+ )
1523
+ }
1524
+ }
1525
+
1526
+ // ---------------------------------------------
1527
+ // compute result
1528
+ // ---------------------------------------------
1529
+ const computeResult = (es: State["es"]) =>
1530
+ array_.isNonEmptyArray(es) ?
1531
+ es.length === 1 && es[0][1]._tag === "Type" ?
1532
+ Either.left(es[0][1]) :
1533
+ Either.left(new Composite(ast, input, sortByIndex(es))) :
1534
+ // this should never happen
1535
+ Either.left(new Type(ast, input))
1536
+
1537
+ if (queue && queue.length > 0) {
1538
+ const cqueue = queue
1539
+ return Effect.suspend(() => {
1540
+ const state: State = { es: array_.copy(es) }
1541
+ return Effect.flatMap(
1542
+ Effect.forEach(cqueue, (f) => f(state), { concurrency, batching, discard: true }),
1543
+ () => {
1544
+ if ("finalResult" in state) {
1545
+ return state.finalResult
1546
+ }
1547
+ return computeResult(state.es)
1548
+ }
1549
+ )
1550
+ })
1551
+ }
1552
+ return computeResult(es)
1553
+ }
1554
+ }
1555
+ case "Suspend": {
1556
+ const get = util_.memoizeThunk(() => goMemo(AST.annotations(ast.f(), ast.annotations), isDecoding))
1557
+ return (a, options) => get()(a, options)
1558
+ }
1559
+ }
1560
+ }
1561
+
1562
+ const fromRefinement = <A>(ast: AST.AST, refinement: (u: unknown) => u is A): Parser => (u) =>
1563
+ refinement(u) ? Either.right(u) : Either.left(new Type(ast, u))
1564
+
1565
+ /** @internal */
1566
+ export const getLiterals = (
1567
+ ast: AST.AST,
1568
+ isDecoding: boolean
1569
+ ): ReadonlyArray<[PropertyKey, AST.Literal]> => {
1570
+ switch (ast._tag) {
1571
+ case "Declaration": {
1572
+ const annotation = AST.getSurrogateAnnotation(ast)
1573
+ if (Option.isSome(annotation)) {
1574
+ return getLiterals(annotation.value, isDecoding)
1575
+ }
1576
+ break
1577
+ }
1578
+ case "TypeLiteral": {
1579
+ const out: Array<[PropertyKey, AST.Literal]> = []
1580
+ for (let i = 0; i < ast.propertySignatures.length; i++) {
1581
+ const propertySignature = ast.propertySignatures[i]
1582
+ const type = isDecoding ? AST.encodedAST(propertySignature.type) : AST.typeAST(propertySignature.type)
1583
+ if (AST.isLiteral(type) && !propertySignature.isOptional) {
1584
+ out.push([propertySignature.name, type])
1585
+ }
1586
+ }
1587
+ return out
1588
+ }
1589
+ case "TupleType": {
1590
+ const out: Array<[PropertyKey, AST.Literal]> = []
1591
+ for (let i = 0; i < ast.elements.length; i++) {
1592
+ const element = ast.elements[i]
1593
+ const type = isDecoding ? AST.encodedAST(element.type) : AST.typeAST(element.type)
1594
+ if (AST.isLiteral(type) && !element.isOptional) {
1595
+ out.push([i, type])
1596
+ }
1597
+ }
1598
+ return out
1599
+ }
1600
+ case "Refinement":
1601
+ return getLiterals(ast.from, isDecoding)
1602
+ case "Suspend":
1603
+ return getLiterals(ast.f(), isDecoding)
1604
+ case "Transformation":
1605
+ return getLiterals(isDecoding ? ast.from : ast.to, isDecoding)
1606
+ }
1607
+ return []
1608
+ }
1609
+
1610
+ /**
1611
+ * The purpose of the algorithm is to narrow down the pool of possible candidates for decoding as much as possible.
1612
+ *
1613
+ * This function separates the schemas into two groups, `keys` and `otherwise`:
1614
+ *
1615
+ * - `keys`: the schema has at least one property with a literal value
1616
+ * - `otherwise`: the schema has no properties with a literal value
1617
+ *
1618
+ * If a schema has at least one property with a literal value, so it ends up in `keys`, first a namespace is created for
1619
+ * the name of the property containing the literal, and then within this namespace a "bucket" is created for the literal
1620
+ * value in which to store all the schemas that have the same property and literal value.
1621
+ *
1622
+ * @internal
1623
+ */
1624
+ export const getSearchTree = (
1625
+ members: ReadonlyArray<AST.AST>,
1626
+ isDecoding: boolean
1627
+ ): {
1628
+ keys: {
1629
+ readonly [key: PropertyKey]: {
1630
+ buckets: { [literal: string]: ReadonlyArray<AST.AST> }
1631
+ literals: ReadonlyArray<AST.Literal> // this is for error messages
1632
+ }
1633
+ }
1634
+ otherwise: ReadonlyArray<AST.AST>
1635
+ } => {
1636
+ const keys: {
1637
+ [key: PropertyKey]: {
1638
+ buckets: { [literal: string]: Array<AST.AST> }
1639
+ literals: Array<AST.Literal>
1640
+ }
1641
+ } = {}
1642
+ const otherwise: Array<AST.AST> = []
1643
+ for (let i = 0; i < members.length; i++) {
1644
+ const member = members[i]
1645
+ const tags = getLiterals(member, isDecoding)
1646
+ if (tags.length > 0) {
1647
+ for (let j = 0; j < tags.length; j++) {
1648
+ const [key, literal] = tags[j]
1649
+ const hash = String(literal.literal)
1650
+ keys[key] = keys[key] || { buckets: {}, literals: [] }
1651
+ const buckets = keys[key].buckets
1652
+ if (Object.prototype.hasOwnProperty.call(buckets, hash)) {
1653
+ if (j < tags.length - 1) {
1654
+ continue
1655
+ }
1656
+ buckets[hash].push(member)
1657
+ keys[key].literals.push(literal)
1658
+ } else {
1659
+ buckets[hash] = [member]
1660
+ keys[key].literals.push(literal)
1661
+ break
1662
+ }
1663
+ }
1664
+ } else {
1665
+ otherwise.push(member)
1666
+ }
1667
+ }
1668
+ return { keys, otherwise }
1669
+ }
1670
+
1671
+ const dropRightRefinement = (ast: AST.AST): AST.AST => AST.isRefinement(ast) ? dropRightRefinement(ast.from) : ast
1672
+
1673
+ const handleForbidden = <A, R>(
1674
+ effect: Effect.Effect<A, ParseIssue, R>,
1675
+ ast: AST.AST,
1676
+ actual: unknown,
1677
+ options: InternalOptions | undefined
1678
+ ): Effect.Effect<A, ParseIssue, R> => {
1679
+ const eu = eitherOrUndefined(effect)
1680
+ if (eu) {
1681
+ return eu
1682
+ }
1683
+ if (options?.isEffectAllowed === true) {
1684
+ return effect
1685
+ }
1686
+ try {
1687
+ return Effect.runSync(Effect.either(effect as Effect.Effect<A, ParseIssue>))
1688
+ } catch (e) {
1689
+ return Either.left(
1690
+ new Forbidden(
1691
+ ast,
1692
+ actual,
1693
+ "cannot be be resolved synchronously, this is caused by using runSync on an effect that performs async work"
1694
+ )
1695
+ )
1696
+ }
1697
+ }
1698
+
1699
+ const compare = ([a]: [number, ...Array<unknown>], [b]: [number, ...Array<unknown>]) => a > b ? 1 : a < b ? -1 : 0
1700
+
1701
+ function sortByIndex<T>(
1702
+ es: array_.NonEmptyArray<[number, T]>
1703
+ ): array_.NonEmptyArray<T>
1704
+ function sortByIndex<T>(es: Array<[number, T]>): Array<T>
1705
+ function sortByIndex(es: Array<[number, any]>) {
1706
+ return es.sort(compare).map((t) => t[1])
1707
+ }
1708
+
1709
+ // -------------------------------------------------------------------------------------
1710
+ // transformations interpreter
1711
+ // -------------------------------------------------------------------------------------
1712
+
1713
+ /** @internal */
1714
+ export const getFinalTransformation = (
1715
+ transformation: AST.TransformationKind,
1716
+ isDecoding: boolean
1717
+ ): (
1718
+ fromA: any,
1719
+ options: AST.ParseOptions,
1720
+ self: AST.Transformation,
1721
+ fromI: any
1722
+ ) => Effect.Effect<any, ParseIssue, any> => {
1723
+ switch (transformation._tag) {
1724
+ case "FinalTransformation":
1725
+ return isDecoding ? transformation.decode : transformation.encode
1726
+ case "ComposeTransformation":
1727
+ return Either.right
1728
+ case "TypeLiteralTransformation":
1729
+ return (input) => {
1730
+ let out: Effect.Effect<any, ParseIssue, any> = Either.right(input)
1731
+
1732
+ // ---------------------------------------------
1733
+ // handle property signature transformations
1734
+ // ---------------------------------------------
1735
+ for (const pst of transformation.propertySignatureTransformations) {
1736
+ const [from, to] = isDecoding ?
1737
+ [pst.from, pst.to] :
1738
+ [pst.to, pst.from]
1739
+ const transformation = isDecoding ? pst.decode : pst.encode
1740
+ const f = (input: any) => {
1741
+ const o = transformation(
1742
+ Object.prototype.hasOwnProperty.call(input, from) ?
1743
+ Option.some(input[from]) :
1744
+ Option.none()
1745
+ )
1746
+ delete input[from]
1747
+ if (Option.isSome(o)) {
1748
+ input[to] = o.value
1749
+ }
1750
+ return input
1751
+ }
1752
+ out = map(out, f)
1753
+ }
1754
+ return out
1755
+ }
1756
+ }
1757
+ }
1758
+
1759
+ // ----------------
1760
+ // Formatters
1761
+ // ----------------
1762
+
1763
+ interface Forest<A> extends ReadonlyArray<Tree<A>> {}
1764
+
1765
+ interface Tree<A> {
1766
+ readonly value: A
1767
+ readonly forest: Forest<A>
1768
+ }
1769
+
1770
+ const makeTree = <A>(value: A, forest: Forest<A> = []): Tree<A> => ({
1771
+ value,
1772
+ forest
1773
+ })
1774
+
1775
+ /**
1776
+ * @category formatting
1777
+ * @since 3.10.0
1778
+ */
1779
+ export interface ParseResultFormatter<A> {
1780
+ readonly formatIssue: (issue: ParseIssue) => Effect.Effect<A>
1781
+ readonly formatIssueSync: (issue: ParseIssue) => A
1782
+ readonly formatError: (error: ParseError) => Effect.Effect<A>
1783
+ readonly formatErrorSync: (error: ParseError) => A
1784
+ }
1785
+
1786
+ /**
1787
+ * @category formatting
1788
+ * @since 3.10.0
1789
+ */
1790
+ export const TreeFormatter: ParseResultFormatter<string> = {
1791
+ formatIssue: (issue) => Effect.map(formatTree(issue), drawTree),
1792
+ formatIssueSync: (issue) => Effect.runSync(TreeFormatter.formatIssue(issue)),
1793
+ formatError: (error) => TreeFormatter.formatIssue(error.issue),
1794
+ formatErrorSync: (error) => TreeFormatter.formatIssueSync(error.issue)
1795
+ }
1796
+
1797
+ const drawTree = (tree: Tree<string>): string => tree.value + draw("\n", tree.forest)
1798
+
1799
+ const draw = (indentation: string, forest: Forest<string>): string => {
1800
+ let r = ""
1801
+ const len = forest.length
1802
+ let tree: Tree<string>
1803
+ for (let i = 0; i < len; i++) {
1804
+ tree = forest[i]
1805
+ const isLast = i === len - 1
1806
+ r += indentation + (isLast ? "└" : "├") + "─ " + tree.value
1807
+ r += draw(indentation + (len > 1 && !isLast ? "│ " : " "), tree.forest)
1808
+ }
1809
+ return r
1810
+ }
1811
+
1812
+ const formatTransformationKind = (kind: Transformation["kind"]): string => {
1813
+ switch (kind) {
1814
+ case "Encoded":
1815
+ return "Encoded side transformation failure"
1816
+ case "Transformation":
1817
+ return "Transformation process failure"
1818
+ case "Type":
1819
+ return "Type side transformation failure"
1820
+ }
1821
+ }
1822
+
1823
+ const formatRefinementKind = (kind: Refinement["kind"]): string => {
1824
+ switch (kind) {
1825
+ case "From":
1826
+ return "From side refinement failure"
1827
+ case "Predicate":
1828
+ return "Predicate refinement failure"
1829
+ }
1830
+ }
1831
+
1832
+ const getAnnotated = (issue: ParseIssue): Option.Option<AST.Annotated> =>
1833
+ "ast" in issue ? Option.some(issue.ast) : Option.none()
1834
+
1835
+ interface CurrentMessage {
1836
+ readonly message: string
1837
+ readonly override: boolean
1838
+ }
1839
+
1840
+ const getCurrentMessage = (
1841
+ issue: ParseIssue
1842
+ ): Effect.Effect<CurrentMessage, cause_.NoSuchElementException> =>
1843
+ getAnnotated(issue).pipe(
1844
+ Option.flatMap(AST.getMessageAnnotation),
1845
+ Effect.flatMap((annotation) => {
1846
+ const out = annotation(issue)
1847
+ return Predicate.isString(out)
1848
+ ? Effect.succeed({ message: out, override: false })
1849
+ : Effect.isEffect(out)
1850
+ ? Effect.map(out, (message) => ({ message, override: false }))
1851
+ : Predicate.isString(out.message)
1852
+ ? Effect.succeed({ message: out.message, override: out.override })
1853
+ : Effect.map(out.message, (message) => ({ message, override: out.override }))
1854
+ })
1855
+ )
1856
+
1857
+ const createParseIssueGuard =
1858
+ <T extends ParseIssue["_tag"]>(tag: T) => (issue: ParseIssue): issue is Extract<ParseIssue, { _tag: T }> =>
1859
+ issue._tag === tag
1860
+
1861
+ /**
1862
+ * Returns `true` if the value is a `Composite`.
1863
+ *
1864
+ * @category guards
1865
+ * @since 3.10.0
1866
+ */
1867
+ export const isComposite = createParseIssueGuard("Composite")
1868
+
1869
+ const isRefinement = createParseIssueGuard("Refinement")
1870
+ const isTransformation = createParseIssueGuard("Transformation")
1871
+
1872
+ const getMessage: (
1873
+ issue: ParseIssue
1874
+ ) => Effect.Effect<string, cause_.NoSuchElementException> = (issue: ParseIssue) =>
1875
+ getCurrentMessage(issue).pipe(
1876
+ Effect.flatMap((currentMessage) => {
1877
+ const useInnerMessage = !currentMessage.override && (
1878
+ isComposite(issue) ||
1879
+ (isRefinement(issue) && issue.kind === "From") ||
1880
+ (isTransformation(issue) && issue.kind !== "Transformation")
1881
+ )
1882
+ return useInnerMessage
1883
+ ? isTransformation(issue) || isRefinement(issue) ? getMessage(issue.issue) : Option.none()
1884
+ : Effect.succeed(currentMessage.message)
1885
+ })
1886
+ )
1887
+
1888
+ const getParseIssueTitleAnnotation = (issue: ParseIssue): Option.Option<string> =>
1889
+ getAnnotated(issue).pipe(
1890
+ Option.flatMap(AST.getParseIssueTitleAnnotation),
1891
+ Option.filterMap(
1892
+ (annotation) => Option.fromNullable(annotation(issue))
1893
+ )
1894
+ )
1895
+
1896
+ const formatTypeMessage = (e: Type): Effect.Effect<string> =>
1897
+ getMessage(e).pipe(
1898
+ Effect.orElse(() => getParseIssueTitleAnnotation(e)),
1899
+ Effect.catchAll(() =>
1900
+ Effect.succeed(e.message ?? `Expected ${String(e.ast)}, actual ${util_.formatUnknown(e.actual)}`)
1901
+ )
1902
+ )
1903
+
1904
+ const getParseIssueTitle = (
1905
+ issue: Forbidden | Transformation | Refinement | Composite
1906
+ ): string => Option.getOrElse(getParseIssueTitleAnnotation(issue), () => String(issue.ast))
1907
+
1908
+ const formatForbiddenMessage = (e: Forbidden): string => e.message ?? "is forbidden"
1909
+
1910
+ const formatUnexpectedMessage = (e: Unexpected): string => e.message ?? "is unexpected"
1911
+
1912
+ const formatMissingMessage = (e: Missing): Effect.Effect<string> =>
1913
+ AST.getMissingMessageAnnotation(e.ast).pipe(
1914
+ Effect.flatMap((annotation) => {
1915
+ const out = annotation()
1916
+ return Predicate.isString(out) ? Effect.succeed(out) : out
1917
+ }),
1918
+ Effect.catchAll(() => Effect.succeed(e.message ?? "is missing"))
1919
+ )
1920
+
1921
+ const getTree = (issue: ParseIssue, onFailure: () => Effect.Effect<Tree<string>>) =>
1922
+ Effect.matchEffect(getMessage(issue), {
1923
+ onFailure,
1924
+ onSuccess: (message) => Effect.succeed(makeTree(message))
1925
+ })
1926
+
1927
+ const formatTree = (
1928
+ e: ParseIssue | Pointer
1929
+ ): Effect.Effect<Tree<string>> => {
1930
+ switch (e._tag) {
1931
+ case "Type":
1932
+ return Effect.map(formatTypeMessage(e), makeTree)
1933
+ case "Forbidden":
1934
+ return Effect.succeed(makeTree(getParseIssueTitle(e), [makeTree(formatForbiddenMessage(e))]))
1935
+ case "Unexpected":
1936
+ return Effect.succeed(makeTree(formatUnexpectedMessage(e)))
1937
+ case "Missing":
1938
+ return Effect.map(formatMissingMessage(e), makeTree)
1939
+ case "Transformation":
1940
+ return getTree(e, () =>
1941
+ Effect.map(
1942
+ formatTree(e.issue),
1943
+ (tree) => makeTree(getParseIssueTitle(e), [makeTree(formatTransformationKind(e.kind), [tree])])
1944
+ ))
1945
+ case "Refinement":
1946
+ return getTree(
1947
+ e,
1948
+ () =>
1949
+ Effect.map(
1950
+ formatTree(e.issue),
1951
+ (tree) => makeTree(getParseIssueTitle(e), [makeTree(formatRefinementKind(e.kind), [tree])])
1952
+ )
1953
+ )
1954
+ case "Pointer":
1955
+ return Effect.map(formatTree(e.issue), (tree) => makeTree(util_.formatPath(e.path), [tree]))
1956
+ case "Composite": {
1957
+ const parseIssueTitle = getParseIssueTitle(e)
1958
+ return getTree(
1959
+ e,
1960
+ () =>
1961
+ util_.isNonEmpty(e.issues)
1962
+ ? Effect.map(Effect.forEach(e.issues, formatTree), (forest) => makeTree(parseIssueTitle, forest))
1963
+ : Effect.map(formatTree(e.issues), (tree) => makeTree(parseIssueTitle, [tree]))
1964
+ )
1965
+ }
1966
+ }
1967
+ }
1968
+
1969
+ /**
1970
+ * @category model
1971
+ * @since 3.10.0
1972
+ */
1973
+ export interface ArrayFormatterIssue {
1974
+ readonly _tag: ParseIssue["_tag"]
1975
+ readonly path: ReadonlyArray<PropertyKey>
1976
+ readonly message: string
1977
+ }
1978
+
1979
+ /**
1980
+ * @category formatting
1981
+ * @since 3.10.0
1982
+ */
1983
+ export const ArrayFormatter: ParseResultFormatter<Array<ArrayFormatterIssue>> = {
1984
+ formatIssue: (issue) => formatArray(issue),
1985
+ formatIssueSync: (issue) => Effect.runSync(ArrayFormatter.formatIssue(issue)),
1986
+ formatError: (error) => ArrayFormatter.formatIssue(error.issue),
1987
+ formatErrorSync: (error) => ArrayFormatter.formatIssueSync(error.issue)
1988
+ }
1989
+
1990
+ const succeedArrayFormatterIssue = (issue: ArrayFormatterIssue) => Effect.succeed([issue])
1991
+
1992
+ const getArray = (
1993
+ issue: ParseIssue,
1994
+ path: ReadonlyArray<PropertyKey>,
1995
+ onFailure: () => Effect.Effect<Array<ArrayFormatterIssue>>
1996
+ ) =>
1997
+ Effect.matchEffect(getMessage(issue), {
1998
+ onFailure,
1999
+ onSuccess: (message) => succeedArrayFormatterIssue({ _tag: issue._tag, path, message })
2000
+ })
2001
+
2002
+ const formatArray = (
2003
+ e: ParseIssue | Pointer,
2004
+ path: ReadonlyArray<PropertyKey> = []
2005
+ ): Effect.Effect<Array<ArrayFormatterIssue>> => {
2006
+ const _tag = e._tag
2007
+ switch (_tag) {
2008
+ case "Type":
2009
+ return Effect.map(formatTypeMessage(e), (message) => [{ _tag, path, message }])
2010
+ case "Forbidden":
2011
+ return succeedArrayFormatterIssue({ _tag, path, message: formatForbiddenMessage(e) })
2012
+ case "Unexpected":
2013
+ return succeedArrayFormatterIssue({ _tag, path, message: formatUnexpectedMessage(e) })
2014
+ case "Missing":
2015
+ return Effect.map(formatMissingMessage(e), (message) => [{ _tag, path, message }])
2016
+ case "Pointer":
2017
+ return formatArray(e.issue, path.concat(e.path))
2018
+ case "Composite":
2019
+ return getArray(e, path, () =>
2020
+ util_.isNonEmpty(e.issues)
2021
+ ? Effect.map(Effect.forEach(e.issues, (issue) => formatArray(issue, path)), array_.flatten)
2022
+ : formatArray(e.issues, path))
2023
+ case "Refinement":
2024
+ case "Transformation":
2025
+ return getArray(e, path, () => formatArray(e.issue, path))
2026
+ }
2027
+ }