effect 3.9.2 → 3.10.1

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 (207) 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/channel/channelExecutor.js +160 -161
  42. package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
  43. package/dist/cjs/internal/core.js +4 -4
  44. package/dist/cjs/internal/core.js.map +1 -1
  45. package/dist/cjs/internal/fiberRuntime.js +14 -12
  46. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  47. package/dist/cjs/internal/logger.js +7 -6
  48. package/dist/cjs/internal/logger.js.map +1 -1
  49. package/dist/cjs/internal/redacted.js +4 -0
  50. package/dist/cjs/internal/redacted.js.map +1 -1
  51. package/dist/cjs/internal/schema/errors.js +116 -0
  52. package/dist/cjs/internal/schema/errors.js.map +1 -0
  53. package/dist/cjs/internal/schema/filters.js +41 -0
  54. package/dist/cjs/internal/schema/filters.js.map +1 -0
  55. package/dist/cjs/internal/schema/util.js +96 -0
  56. package/dist/cjs/internal/schema/util.js.map +1 -0
  57. package/dist/cjs/internal/stm/core.js +2 -3
  58. package/dist/cjs/internal/stm/core.js.map +1 -1
  59. package/dist/cjs/internal/stm/tPubSub.js.map +1 -1
  60. package/dist/cjs/internal/stm/tQueue.js +1 -2
  61. package/dist/cjs/internal/stm/tQueue.js.map +1 -1
  62. package/dist/cjs/internal/stm/tRef.js +6 -2
  63. package/dist/cjs/internal/stm/tRef.js.map +1 -1
  64. package/dist/cjs/internal/stm/tSubscriptionRef.js +178 -0
  65. package/dist/cjs/internal/stm/tSubscriptionRef.js.map +1 -0
  66. package/dist/cjs/internal/stream.js +36 -16
  67. package/dist/cjs/internal/stream.js.map +1 -1
  68. package/dist/cjs/internal/version.js +1 -1
  69. package/dist/cjs/internal/version.js.map +1 -1
  70. package/dist/dts/Arbitrary.d.ts +45 -0
  71. package/dist/dts/Arbitrary.d.ts.map +1 -0
  72. package/dist/dts/Effect.d.ts +298 -30
  73. package/dist/dts/Effect.d.ts.map +1 -1
  74. package/dist/dts/FastCheck.d.ts +9 -0
  75. package/dist/dts/FastCheck.d.ts.map +1 -0
  76. package/dist/dts/Inspectable.d.ts +28 -0
  77. package/dist/dts/Inspectable.d.ts.map +1 -1
  78. package/dist/dts/JSONSchema.d.ts +181 -0
  79. package/dist/dts/JSONSchema.d.ts.map +1 -0
  80. package/dist/dts/ParseResult.d.ts +551 -0
  81. package/dist/dts/ParseResult.d.ts.map +1 -0
  82. package/dist/dts/Predicate.d.ts.map +1 -1
  83. package/dist/dts/Pretty.d.ts +26 -0
  84. package/dist/dts/Pretty.d.ts.map +1 -0
  85. package/dist/dts/Schema.d.ts +4562 -0
  86. package/dist/dts/Schema.d.ts.map +1 -0
  87. package/dist/dts/SchemaAST.d.ts +1321 -0
  88. package/dist/dts/SchemaAST.d.ts.map +1 -0
  89. package/dist/dts/Stream.d.ts +67 -2
  90. package/dist/dts/Stream.d.ts.map +1 -1
  91. package/dist/dts/TPubSub.d.ts +8 -0
  92. package/dist/dts/TPubSub.d.ts.map +1 -1
  93. package/dist/dts/TQueue.d.ts +7 -7
  94. package/dist/dts/TQueue.d.ts.map +1 -1
  95. package/dist/dts/TRef.d.ts +2 -1
  96. package/dist/dts/TRef.d.ts.map +1 -1
  97. package/dist/dts/TSubscriptionRef.d.ts +251 -0
  98. package/dist/dts/TSubscriptionRef.d.ts.map +1 -0
  99. package/dist/dts/index.d.ts +32 -0
  100. package/dist/dts/index.d.ts.map +1 -1
  101. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  102. package/dist/dts/internal/schema/errors.d.ts +2 -0
  103. package/dist/dts/internal/schema/errors.d.ts.map +1 -0
  104. package/dist/dts/internal/schema/filters.d.ts +2 -0
  105. package/dist/dts/internal/schema/filters.d.ts.map +1 -0
  106. package/dist/dts/internal/schema/util.d.ts +2 -0
  107. package/dist/dts/internal/schema/util.d.ts.map +1 -0
  108. package/dist/dts/internal/stm/tRef.d.ts +3 -1
  109. package/dist/dts/internal/stm/tRef.d.ts.map +1 -1
  110. package/dist/dts/internal/stm/tSubscriptionRef.d.ts +2 -0
  111. package/dist/dts/internal/stm/tSubscriptionRef.d.ts.map +1 -0
  112. package/dist/dts/internal/stream.d.ts.map +1 -1
  113. package/dist/esm/Arbitrary.js +472 -0
  114. package/dist/esm/Arbitrary.js.map +1 -0
  115. package/dist/esm/Effect.js +256 -18
  116. package/dist/esm/Effect.js.map +1 -1
  117. package/dist/esm/FastCheck.js +9 -0
  118. package/dist/esm/FastCheck.js.map +1 -0
  119. package/dist/esm/Inspectable.js +39 -2
  120. package/dist/esm/Inspectable.js.map +1 -1
  121. package/dist/esm/JSONSchema.js +408 -0
  122. package/dist/esm/JSONSchema.js.map +1 -0
  123. package/dist/esm/ParseResult.js +1503 -0
  124. package/dist/esm/ParseResult.js.map +1 -0
  125. package/dist/esm/Predicate.js +2 -1
  126. package/dist/esm/Predicate.js.map +1 -1
  127. package/dist/esm/Pretty.js +173 -0
  128. package/dist/esm/Pretty.js.map +1 -0
  129. package/dist/esm/Schema.js +5328 -0
  130. package/dist/esm/Schema.js.map +1 -0
  131. package/dist/esm/SchemaAST.js +2300 -0
  132. package/dist/esm/SchemaAST.js.map +1 -0
  133. package/dist/esm/Stream.js +14 -0
  134. package/dist/esm/Stream.js.map +1 -1
  135. package/dist/esm/TPubSub.js +8 -0
  136. package/dist/esm/TPubSub.js.map +1 -1
  137. package/dist/esm/TQueue.js.map +1 -1
  138. package/dist/esm/TRef.js.map +1 -1
  139. package/dist/esm/TSubscriptionRef.js +87 -0
  140. package/dist/esm/TSubscriptionRef.js.map +1 -0
  141. package/dist/esm/index.js +32 -0
  142. package/dist/esm/index.js.map +1 -1
  143. package/dist/esm/internal/cause.js +3 -3
  144. package/dist/esm/internal/cause.js.map +1 -1
  145. package/dist/esm/internal/channel/channelExecutor.js +160 -161
  146. package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
  147. package/dist/esm/internal/core.js +4 -4
  148. package/dist/esm/internal/core.js.map +1 -1
  149. package/dist/esm/internal/fiberRuntime.js +14 -12
  150. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  151. package/dist/esm/internal/logger.js +7 -6
  152. package/dist/esm/internal/logger.js.map +1 -1
  153. package/dist/esm/internal/redacted.js +4 -0
  154. package/dist/esm/internal/redacted.js.map +1 -1
  155. package/dist/esm/internal/schema/errors.js +87 -0
  156. package/dist/esm/internal/schema/errors.js.map +1 -0
  157. package/dist/esm/internal/schema/filters.js +35 -0
  158. package/dist/esm/internal/schema/filters.js.map +1 -0
  159. package/dist/esm/internal/schema/util.js +78 -0
  160. package/dist/esm/internal/schema/util.js.map +1 -0
  161. package/dist/esm/internal/stm/core.js +1 -2
  162. package/dist/esm/internal/stm/core.js.map +1 -1
  163. package/dist/esm/internal/stm/tPubSub.js.map +1 -1
  164. package/dist/esm/internal/stm/tQueue.js +1 -2
  165. package/dist/esm/internal/stm/tQueue.js.map +1 -1
  166. package/dist/esm/internal/stm/tRef.js +5 -1
  167. package/dist/esm/internal/stm/tRef.js.map +1 -1
  168. package/dist/esm/internal/stm/tSubscriptionRef.js +166 -0
  169. package/dist/esm/internal/stm/tSubscriptionRef.js.map +1 -0
  170. package/dist/esm/internal/stream.js +33 -15
  171. package/dist/esm/internal/stream.js.map +1 -1
  172. package/dist/esm/internal/version.js +1 -1
  173. package/dist/esm/internal/version.js.map +1 -1
  174. package/package.json +68 -1
  175. package/src/Arbitrary.ts +563 -0
  176. package/src/Effect.ts +302 -31
  177. package/src/FastCheck.ts +9 -0
  178. package/src/Inspectable.ts +56 -2
  179. package/src/JSONSchema.ts +601 -0
  180. package/src/ParseResult.ts +2027 -0
  181. package/src/Predicate.ts +3 -1
  182. package/src/Pretty.ts +204 -0
  183. package/src/Schema.ts +10388 -0
  184. package/src/SchemaAST.ts +2827 -0
  185. package/src/Stream.ts +77 -9
  186. package/src/TPubSub.ts +9 -0
  187. package/src/TQueue.ts +7 -7
  188. package/src/TRef.ts +2 -1
  189. package/src/TSubscriptionRef.ts +284 -0
  190. package/src/index.ts +40 -0
  191. package/src/internal/cause.ts +3 -3
  192. package/src/internal/channel/channelExecutor.ts +213 -214
  193. package/src/internal/core-effect.ts +2 -2
  194. package/src/internal/core.ts +4 -4
  195. package/src/internal/fiberRuntime.ts +14 -12
  196. package/src/internal/logger.ts +7 -6
  197. package/src/internal/redacted.ts +4 -0
  198. package/src/internal/schema/errors.ts +189 -0
  199. package/src/internal/schema/filters.ts +86 -0
  200. package/src/internal/schema/util.ts +113 -0
  201. package/src/internal/stm/core.ts +1 -2
  202. package/src/internal/stm/tPubSub.ts +1 -0
  203. package/src/internal/stm/tQueue.ts +2 -2
  204. package/src/internal/stm/tRef.ts +7 -2
  205. package/src/internal/stm/tSubscriptionRef.ts +286 -0
  206. package/src/internal/stream.ts +97 -20
  207. package/src/internal/version.ts +1 -1
@@ -0,0 +1,2827 @@
1
+ /**
2
+ * @since 3.10.0
3
+ */
4
+
5
+ import * as Arr from "./Array.js"
6
+ import type { Effect } from "./Effect.js"
7
+ import type { Equivalence } from "./Equivalence.js"
8
+ import { dual, identity } from "./Function.js"
9
+ import { globalValue } from "./GlobalValue.js"
10
+ import * as errors_ from "./internal/schema/errors.js"
11
+ import * as util_ from "./internal/schema/util.js"
12
+ import * as Number from "./Number.js"
13
+ import * as Option from "./Option.js"
14
+ import * as Order from "./Order.js"
15
+ import type { ParseIssue } from "./ParseResult.js"
16
+ import * as Predicate from "./Predicate.js"
17
+ import * as regexp from "./RegExp.js"
18
+ import type { Concurrency } from "./Types.js"
19
+
20
+ /**
21
+ * @category model
22
+ * @since 3.10.0
23
+ */
24
+ export type AST =
25
+ | Declaration
26
+ | Literal
27
+ | UniqueSymbol
28
+ | UndefinedKeyword
29
+ | VoidKeyword
30
+ | NeverKeyword
31
+ | UnknownKeyword
32
+ | AnyKeyword
33
+ | StringKeyword
34
+ | NumberKeyword
35
+ | BooleanKeyword
36
+ | BigIntKeyword
37
+ | SymbolKeyword
38
+ | ObjectKeyword
39
+ | Enums
40
+ | TemplateLiteral
41
+ // possible transformations
42
+ | Refinement
43
+ | TupleType
44
+ | TypeLiteral
45
+ | Union
46
+ | Suspend
47
+ // transformations
48
+ | Transformation
49
+
50
+ // -------------------------------------------------------------------------------------
51
+ // annotations
52
+ // -------------------------------------------------------------------------------------
53
+
54
+ /**
55
+ * @category annotations
56
+ * @since 3.10.0
57
+ */
58
+ export type BrandAnnotation = Arr.NonEmptyReadonlyArray<string | symbol>
59
+
60
+ /**
61
+ * @category annotations
62
+ * @since 3.10.0
63
+ */
64
+ export const BrandAnnotationId: unique symbol = Symbol.for("effect/annotation/Brand")
65
+
66
+ /**
67
+ * @category annotations
68
+ * @since 3.10.0
69
+ */
70
+ export type SchemaIdAnnotation = string | symbol
71
+
72
+ /**
73
+ * @category annotations
74
+ * @since 3.10.0
75
+ */
76
+ export const SchemaIdAnnotationId: unique symbol = Symbol.for("effect/annotation/SchemaId")
77
+
78
+ /**
79
+ * @category annotations
80
+ * @since 3.10.0
81
+ */
82
+ export type MessageAnnotation = (issue: ParseIssue) => string | Effect<string> | {
83
+ readonly message: string | Effect<string>
84
+ readonly override: boolean
85
+ }
86
+
87
+ /**
88
+ * @category annotations
89
+ * @since 3.10.0
90
+ */
91
+ export const MessageAnnotationId: unique symbol = Symbol.for("effect/annotation/Message")
92
+
93
+ /**
94
+ * @category annotations
95
+ * @since 3.10.0
96
+ */
97
+ export type MissingMessageAnnotation = () => string | Effect<string>
98
+
99
+ /**
100
+ * @category annotations
101
+ * @since 3.10.0
102
+ */
103
+ export const MissingMessageAnnotationId: unique symbol = Symbol.for("effect/annotation/MissingMessage")
104
+
105
+ /**
106
+ * @category annotations
107
+ * @since 3.10.0
108
+ */
109
+ export type IdentifierAnnotation = string
110
+
111
+ /**
112
+ * @category annotations
113
+ * @since 3.10.0
114
+ */
115
+ export const IdentifierAnnotationId: unique symbol = Symbol.for("effect/annotation/Identifier")
116
+
117
+ /**
118
+ * @category annotations
119
+ * @since 3.10.0
120
+ */
121
+ export type TitleAnnotation = string
122
+
123
+ /**
124
+ * @category annotations
125
+ * @since 3.10.0
126
+ */
127
+ export const TitleAnnotationId: unique symbol = Symbol.for("effect/annotation/Title")
128
+
129
+ /**
130
+ * @category annotations
131
+ * @since 3.10.0
132
+ */
133
+ export type DescriptionAnnotation = string
134
+
135
+ /**
136
+ * @category annotations
137
+ * @since 3.10.0
138
+ */
139
+ export const DescriptionAnnotationId: unique symbol = Symbol.for("effect/annotation/Description")
140
+
141
+ /**
142
+ * @category annotations
143
+ * @since 3.10.0
144
+ */
145
+ export type ExamplesAnnotation<A> = Arr.NonEmptyReadonlyArray<A>
146
+
147
+ /**
148
+ * @category annotations
149
+ * @since 3.10.0
150
+ */
151
+ export const ExamplesAnnotationId: unique symbol = Symbol.for("effect/annotation/Examples")
152
+
153
+ /**
154
+ * @category annotations
155
+ * @since 3.10.0
156
+ */
157
+ export type DefaultAnnotation<A> = A
158
+
159
+ /**
160
+ * @category annotations
161
+ * @since 3.10.0
162
+ */
163
+ export const DefaultAnnotationId: unique symbol = Symbol.for("effect/annotation/Default")
164
+
165
+ /**
166
+ * @category annotations
167
+ * @since 3.10.0
168
+ */
169
+ export type JSONSchemaAnnotation = object
170
+
171
+ /**
172
+ * @category annotations
173
+ * @since 3.10.0
174
+ */
175
+ export const JSONSchemaAnnotationId: unique symbol = Symbol.for("effect/annotation/JSONSchema")
176
+
177
+ /**
178
+ * @category annotations
179
+ * @since 3.10.0
180
+ */
181
+ export const ArbitraryAnnotationId: unique symbol = Symbol.for("effect/annotation/Arbitrary")
182
+
183
+ /**
184
+ * @category annotations
185
+ * @since 3.10.0
186
+ */
187
+ export const PrettyAnnotationId: unique symbol = Symbol.for("effect/annotation/Pretty")
188
+
189
+ /**
190
+ * @category annotations
191
+ * @since 3.10.0
192
+ */
193
+ export type EquivalenceAnnotation<A, TypeParameters extends ReadonlyArray<any> = readonly []> = (
194
+ ...equivalences: { readonly [K in keyof TypeParameters]: Equivalence<TypeParameters[K]> }
195
+ ) => Equivalence<A>
196
+
197
+ /**
198
+ * @category annotations
199
+ * @since 3.10.0
200
+ */
201
+ export const EquivalenceAnnotationId: unique symbol = Symbol.for("effect/annotation/Equivalence")
202
+
203
+ /**
204
+ * @category annotations
205
+ * @since 3.10.0
206
+ */
207
+ export type DocumentationAnnotation = string
208
+
209
+ /**
210
+ * @category annotations
211
+ * @since 3.10.0
212
+ */
213
+ export const DocumentationAnnotationId: unique symbol = Symbol.for("effect/annotation/Documentation")
214
+
215
+ /**
216
+ * @category annotations
217
+ * @since 3.10.0
218
+ */
219
+ export type ConcurrencyAnnotation = Concurrency | undefined
220
+
221
+ /**
222
+ * @category annotations
223
+ * @since 3.10.0
224
+ */
225
+ export const ConcurrencyAnnotationId: unique symbol = Symbol.for("effect/annotation/Concurrency")
226
+
227
+ /**
228
+ * @category annotations
229
+ * @since 3.10.0
230
+ */
231
+ export type BatchingAnnotation = boolean | "inherit" | undefined
232
+
233
+ /**
234
+ * @category annotations
235
+ * @since 3.10.0
236
+ */
237
+ export const BatchingAnnotationId: unique symbol = Symbol.for("effect/annotation/Batching")
238
+
239
+ /**
240
+ * @category annotations
241
+ * @since 3.10.0
242
+ */
243
+ export type ParseIssueTitleAnnotation = (issue: ParseIssue) => string | undefined
244
+
245
+ /**
246
+ * @category annotations
247
+ * @since 3.10.0
248
+ */
249
+ export const ParseIssueTitleAnnotationId: unique symbol = Symbol.for("effect/annotation/ParseIssueTitle")
250
+
251
+ /**
252
+ * @category annotations
253
+ * @since 3.10.0
254
+ */
255
+ export const ParseOptionsAnnotationId: unique symbol = Symbol.for("effect/annotation/ParseOptions")
256
+
257
+ /**
258
+ * @category annotations
259
+ * @since 3.10.0
260
+ */
261
+ export type DecodingFallbackAnnotation<A> = (issue: ParseIssue) => Effect<A, ParseIssue>
262
+
263
+ /**
264
+ * @category annotations
265
+ * @since 3.10.0
266
+ */
267
+ export const DecodingFallbackAnnotationId: unique symbol = Symbol.for("effect/annotation/DecodingFallback")
268
+
269
+ /**
270
+ * @category annotations
271
+ * @since 3.10.0
272
+ */
273
+ export const SurrogateAnnotationId: unique symbol = Symbol.for("effect/annotation/Surrogate")
274
+
275
+ /**
276
+ * @category annotations
277
+ * @since 3.10.0
278
+ */
279
+ export type SurrogateAnnotation = AST
280
+
281
+ /** @internal */
282
+ export const StableFilterAnnotationId: unique symbol = Symbol.for("effect/annotation/StableFilter")
283
+
284
+ /**
285
+ * A stable filter consistently applies fixed validation rules, such as
286
+ * 'minItems', 'maxItems', and 'itemsCount', to ensure array length complies
287
+ * with set criteria regardless of the input data's content.
288
+ *
289
+ * @internal
290
+ */
291
+ export type StableFilterAnnotation = boolean
292
+
293
+ /**
294
+ * @category annotations
295
+ * @since 3.10.0
296
+ */
297
+ export interface Annotations {
298
+ readonly [_: string]: unknown
299
+ readonly [_: symbol]: unknown
300
+ }
301
+
302
+ /**
303
+ * @category annotations
304
+ * @since 3.10.0
305
+ */
306
+ export interface Annotated {
307
+ readonly annotations: Annotations
308
+ }
309
+
310
+ /**
311
+ * @category annotations
312
+ * @since 3.10.0
313
+ */
314
+ export const getAnnotation: {
315
+ /**
316
+ * @category annotations
317
+ * @since 3.10.0
318
+ */
319
+ <A>(key: symbol): (annotated: Annotated) => Option.Option<A>
320
+ /**
321
+ * @category annotations
322
+ * @since 3.10.0
323
+ */
324
+ <A>(annotated: Annotated, key: symbol): Option.Option<A>
325
+ } = dual(
326
+ 2,
327
+ <A>(annotated: Annotated, key: symbol): Option.Option<A> =>
328
+ Object.prototype.hasOwnProperty.call(annotated.annotations, key) ?
329
+ Option.some(annotated.annotations[key] as any) :
330
+ Option.none()
331
+ )
332
+
333
+ /**
334
+ * @category annotations
335
+ * @since 3.10.0
336
+ */
337
+ export const getBrandAnnotation = getAnnotation<BrandAnnotation>(BrandAnnotationId)
338
+
339
+ /**
340
+ * @category annotations
341
+ * @since 3.10.0
342
+ */
343
+ export const getMessageAnnotation = getAnnotation<MessageAnnotation>(MessageAnnotationId)
344
+
345
+ /**
346
+ * @category annotations
347
+ * @since 3.10.0
348
+ */
349
+ export const getMissingMessageAnnotation = getAnnotation<MissingMessageAnnotation>(MissingMessageAnnotationId)
350
+
351
+ /**
352
+ * @category annotations
353
+ * @since 3.10.0
354
+ */
355
+ export const getTitleAnnotation = getAnnotation<TitleAnnotation>(TitleAnnotationId)
356
+
357
+ /**
358
+ * @category annotations
359
+ * @since 3.10.0
360
+ */
361
+ export const getIdentifierAnnotation = getAnnotation<IdentifierAnnotation>(IdentifierAnnotationId)
362
+
363
+ /**
364
+ * @category annotations
365
+ * @since 3.10.0
366
+ */
367
+ export const getDescriptionAnnotation = getAnnotation<DescriptionAnnotation>(DescriptionAnnotationId)
368
+
369
+ /**
370
+ * @category annotations
371
+ * @since 3.10.0
372
+ */
373
+ export const getExamplesAnnotation = getAnnotation<ExamplesAnnotation<unknown>>(ExamplesAnnotationId)
374
+
375
+ /**
376
+ * @category annotations
377
+ * @since 3.10.0
378
+ */
379
+ export const getDefaultAnnotation = getAnnotation<DefaultAnnotation<unknown>>(DefaultAnnotationId)
380
+
381
+ /**
382
+ * @category annotations
383
+ * @since 3.10.0
384
+ */
385
+ export const getJSONSchemaAnnotation = getAnnotation<JSONSchemaAnnotation>(JSONSchemaAnnotationId)
386
+
387
+ /**
388
+ * @category annotations
389
+ * @since 3.10.0
390
+ */
391
+ export const getDocumentationAnnotation = getAnnotation<DocumentationAnnotation>(DocumentationAnnotationId)
392
+
393
+ /**
394
+ * @category annotations
395
+ * @since 3.10.0
396
+ */
397
+ export const getConcurrencyAnnotation = getAnnotation<ConcurrencyAnnotation>(ConcurrencyAnnotationId)
398
+
399
+ /**
400
+ * @category annotations
401
+ * @since 3.10.0
402
+ */
403
+ export const getBatchingAnnotation = getAnnotation<BatchingAnnotation>(BatchingAnnotationId)
404
+
405
+ /**
406
+ * @category annotations
407
+ * @since 3.10.0
408
+ */
409
+ export const getParseIssueTitleAnnotation = getAnnotation<ParseIssueTitleAnnotation>(ParseIssueTitleAnnotationId)
410
+
411
+ /**
412
+ * @category annotations
413
+ * @since 3.10.0
414
+ */
415
+ export const getParseOptionsAnnotation = getAnnotation<ParseOptions>(ParseOptionsAnnotationId)
416
+
417
+ /**
418
+ * @category annotations
419
+ * @since 3.10.0
420
+ */
421
+ export const getDecodingFallbackAnnotation = getAnnotation<DecodingFallbackAnnotation<unknown>>(
422
+ DecodingFallbackAnnotationId
423
+ )
424
+
425
+ /**
426
+ * @category annotations
427
+ * @since 3.10.0
428
+ */
429
+ export const getSurrogateAnnotation = getAnnotation<SurrogateAnnotation>(SurrogateAnnotationId)
430
+
431
+ const getStableFilterAnnotation = getAnnotation<StableFilterAnnotation>(StableFilterAnnotationId)
432
+
433
+ /** @internal */
434
+ export const hasStableFilter = (annotated: Annotated) =>
435
+ Option.exists(getStableFilterAnnotation(annotated), (b) => b === true)
436
+
437
+ /**
438
+ * @category annotations
439
+ * @since 3.10.0
440
+ */
441
+ export const JSONIdentifierAnnotationId: unique symbol = Symbol.for("effect/annotation/JSONIdentifier")
442
+
443
+ /**
444
+ * @category annotations
445
+ * @since 3.10.0
446
+ */
447
+ export const getJSONIdentifierAnnotation = getAnnotation<IdentifierAnnotation>(JSONIdentifierAnnotationId)
448
+
449
+ /**
450
+ * @category annotations
451
+ * @since 3.10.0
452
+ */
453
+ export const getJSONIdentifier = (annotated: Annotated) =>
454
+ Option.orElse(getJSONIdentifierAnnotation(annotated), () => getIdentifierAnnotation(annotated))
455
+
456
+ // -------------------------------------------------------------------------------------
457
+ // schema ids
458
+ // -------------------------------------------------------------------------------------
459
+
460
+ /**
461
+ * @category schema id
462
+ * @since 3.10.0
463
+ */
464
+ export const ParseJsonSchemaId: unique symbol = Symbol.for("effect/schema/ParseJson")
465
+
466
+ /**
467
+ * @category model
468
+ * @since 3.10.0
469
+ */
470
+ export class Declaration implements Annotated {
471
+ /**
472
+ * @since 3.10.0
473
+ */
474
+ readonly _tag = "Declaration"
475
+ constructor(
476
+ readonly typeParameters: ReadonlyArray<AST>,
477
+ readonly decodeUnknown: (
478
+ ...typeParameters: ReadonlyArray<AST>
479
+ ) => (input: unknown, options: ParseOptions, self: Declaration) => Effect<any, ParseIssue, any>,
480
+ readonly encodeUnknown: (
481
+ ...typeParameters: ReadonlyArray<AST>
482
+ ) => (input: unknown, options: ParseOptions, self: Declaration) => Effect<any, ParseIssue, any>,
483
+ readonly annotations: Annotations = {}
484
+ ) {}
485
+ /**
486
+ * @since 3.10.0
487
+ */
488
+ toString() {
489
+ return Option.getOrElse(getExpected(this), () => "<declaration schema>")
490
+ }
491
+ /**
492
+ * @since 3.10.0
493
+ */
494
+ toJSON(): object {
495
+ return {
496
+ _tag: this._tag,
497
+ typeParameters: this.typeParameters.map((ast) => ast.toJSON()),
498
+ annotations: toJSONAnnotations(this.annotations)
499
+ }
500
+ }
501
+ }
502
+
503
+ const createASTGuard = <T extends AST["_tag"]>(tag: T) => (ast: AST): ast is Extract<AST, { _tag: T }> =>
504
+ ast._tag === tag
505
+
506
+ /**
507
+ * @category guards
508
+ * @since 3.10.0
509
+ */
510
+ export const isDeclaration: (ast: AST) => ast is Declaration = createASTGuard("Declaration")
511
+
512
+ /**
513
+ * @category model
514
+ * @since 3.10.0
515
+ */
516
+ export type LiteralValue = string | number | boolean | null | bigint
517
+
518
+ /**
519
+ * @category model
520
+ * @since 3.10.0
521
+ */
522
+ export class Literal implements Annotated {
523
+ /**
524
+ * @since 3.10.0
525
+ */
526
+ readonly _tag = "Literal"
527
+ constructor(readonly literal: LiteralValue, readonly annotations: Annotations = {}) {}
528
+ /**
529
+ * @since 3.10.0
530
+ */
531
+ toString() {
532
+ return Option.getOrElse(getExpected(this), () => util_.formatUnknown(this.literal))
533
+ }
534
+ /**
535
+ * @since 3.10.0
536
+ */
537
+ toJSON(): object {
538
+ return {
539
+ _tag: this._tag,
540
+ literal: Predicate.isBigInt(this.literal) ? String(this.literal) : this.literal,
541
+ annotations: toJSONAnnotations(this.annotations)
542
+ }
543
+ }
544
+ }
545
+
546
+ /**
547
+ * @category guards
548
+ * @since 3.10.0
549
+ */
550
+ export const isLiteral: (ast: AST) => ast is Literal = createASTGuard("Literal")
551
+
552
+ const $null = new Literal(null)
553
+
554
+ export {
555
+ /**
556
+ * @category constructors
557
+ * @since 3.10.0
558
+ */
559
+ $null as null
560
+ }
561
+
562
+ /**
563
+ * @category model
564
+ * @since 3.10.0
565
+ */
566
+ export class UniqueSymbol implements Annotated {
567
+ /**
568
+ * @since 3.10.0
569
+ */
570
+ readonly _tag = "UniqueSymbol"
571
+ constructor(readonly symbol: symbol, readonly annotations: Annotations = {}) {}
572
+ /**
573
+ * @since 3.10.0
574
+ */
575
+ toString() {
576
+ return Option.getOrElse(getExpected(this), () => util_.formatUnknown(this.symbol))
577
+ }
578
+ /**
579
+ * @since 3.10.0
580
+ */
581
+ toJSON(): object {
582
+ return {
583
+ _tag: this._tag,
584
+ symbol: String(this.symbol),
585
+ annotations: toJSONAnnotations(this.annotations)
586
+ }
587
+ }
588
+ }
589
+
590
+ /**
591
+ * @category guards
592
+ * @since 3.10.0
593
+ */
594
+ export const isUniqueSymbol: (ast: AST) => ast is UniqueSymbol = createASTGuard("UniqueSymbol")
595
+
596
+ /**
597
+ * @category model
598
+ * @since 3.10.0
599
+ */
600
+ export class UndefinedKeyword implements Annotated {
601
+ /**
602
+ * @since 3.10.0
603
+ */
604
+ readonly _tag = "UndefinedKeyword"
605
+ constructor(readonly annotations: Annotations = {}) {}
606
+ /**
607
+ * @since 3.10.0
608
+ */
609
+ toString() {
610
+ return formatKeyword(this)
611
+ }
612
+ /**
613
+ * @since 3.10.0
614
+ */
615
+ toJSON(): object {
616
+ return {
617
+ _tag: this._tag,
618
+ annotations: toJSONAnnotations(this.annotations)
619
+ }
620
+ }
621
+ }
622
+
623
+ /**
624
+ * @category constructors
625
+ * @since 3.10.0
626
+ */
627
+ export const undefinedKeyword: UndefinedKeyword = new UndefinedKeyword({
628
+ [TitleAnnotationId]: "undefined"
629
+ })
630
+
631
+ /**
632
+ * @category guards
633
+ * @since 3.10.0
634
+ */
635
+ export const isUndefinedKeyword: (ast: AST) => ast is UndefinedKeyword = createASTGuard("UndefinedKeyword")
636
+
637
+ /**
638
+ * @category model
639
+ * @since 3.10.0
640
+ */
641
+ export class VoidKeyword implements Annotated {
642
+ /**
643
+ * @since 3.10.0
644
+ */
645
+ readonly _tag = "VoidKeyword"
646
+ constructor(readonly annotations: Annotations = {}) {}
647
+ /**
648
+ * @since 3.10.0
649
+ */
650
+ toString() {
651
+ return formatKeyword(this)
652
+ }
653
+ /**
654
+ * @since 3.10.0
655
+ */
656
+ toJSON(): object {
657
+ return {
658
+ _tag: this._tag,
659
+ annotations: toJSONAnnotations(this.annotations)
660
+ }
661
+ }
662
+ }
663
+
664
+ /**
665
+ * @category constructors
666
+ * @since 3.10.0
667
+ */
668
+ export const voidKeyword: VoidKeyword = new VoidKeyword({
669
+ [TitleAnnotationId]: "void"
670
+ })
671
+
672
+ /**
673
+ * @category guards
674
+ * @since 3.10.0
675
+ */
676
+ export const isVoidKeyword: (ast: AST) => ast is VoidKeyword = createASTGuard("VoidKeyword")
677
+
678
+ /**
679
+ * @category model
680
+ * @since 3.10.0
681
+ */
682
+ export class NeverKeyword implements Annotated {
683
+ /**
684
+ * @since 3.10.0
685
+ */
686
+ readonly _tag = "NeverKeyword"
687
+ constructor(readonly annotations: Annotations = {}) {}
688
+ /**
689
+ * @since 3.10.0
690
+ */
691
+ toString() {
692
+ return formatKeyword(this)
693
+ }
694
+ /**
695
+ * @since 3.10.0
696
+ */
697
+ toJSON(): object {
698
+ return {
699
+ _tag: this._tag,
700
+ annotations: toJSONAnnotations(this.annotations)
701
+ }
702
+ }
703
+ }
704
+
705
+ /**
706
+ * @category constructors
707
+ * @since 3.10.0
708
+ */
709
+ export const neverKeyword: NeverKeyword = new NeverKeyword({
710
+ [TitleAnnotationId]: "never"
711
+ })
712
+
713
+ /**
714
+ * @category guards
715
+ * @since 3.10.0
716
+ */
717
+ export const isNeverKeyword: (ast: AST) => ast is NeverKeyword = createASTGuard("NeverKeyword")
718
+
719
+ /**
720
+ * @category model
721
+ * @since 3.10.0
722
+ */
723
+ export class UnknownKeyword implements Annotated {
724
+ /**
725
+ * @since 3.10.0
726
+ */
727
+ readonly _tag = "UnknownKeyword"
728
+ constructor(readonly annotations: Annotations = {}) {}
729
+ /**
730
+ * @since 3.10.0
731
+ */
732
+ toString() {
733
+ return formatKeyword(this)
734
+ }
735
+ /**
736
+ * @since 3.10.0
737
+ */
738
+ toJSON(): object {
739
+ return {
740
+ _tag: this._tag,
741
+ annotations: toJSONAnnotations(this.annotations)
742
+ }
743
+ }
744
+ }
745
+
746
+ /**
747
+ * @category constructors
748
+ * @since 3.10.0
749
+ */
750
+ export const unknownKeyword: UnknownKeyword = new UnknownKeyword({
751
+ [TitleAnnotationId]: "unknown"
752
+ })
753
+
754
+ /**
755
+ * @category guards
756
+ * @since 3.10.0
757
+ */
758
+ export const isUnknownKeyword: (ast: AST) => ast is UnknownKeyword = createASTGuard("UnknownKeyword")
759
+
760
+ /**
761
+ * @category model
762
+ * @since 3.10.0
763
+ */
764
+ export class AnyKeyword implements Annotated {
765
+ /**
766
+ * @since 3.10.0
767
+ */
768
+ readonly _tag = "AnyKeyword"
769
+ constructor(readonly annotations: Annotations = {}) {}
770
+ /**
771
+ * @since 3.10.0
772
+ */
773
+ toString() {
774
+ return formatKeyword(this)
775
+ }
776
+ /**
777
+ * @since 3.10.0
778
+ */
779
+ toJSON(): object {
780
+ return {
781
+ _tag: this._tag,
782
+ annotations: toJSONAnnotations(this.annotations)
783
+ }
784
+ }
785
+ }
786
+
787
+ /**
788
+ * @category constructors
789
+ * @since 3.10.0
790
+ */
791
+ export const anyKeyword: AnyKeyword = new AnyKeyword({
792
+ [TitleAnnotationId]: "any"
793
+ })
794
+
795
+ /**
796
+ * @category guards
797
+ * @since 3.10.0
798
+ */
799
+ export const isAnyKeyword: (ast: AST) => ast is AnyKeyword = createASTGuard("AnyKeyword")
800
+
801
+ /**
802
+ * @category model
803
+ * @since 3.10.0
804
+ */
805
+ export class StringKeyword implements Annotated {
806
+ /**
807
+ * @since 3.10.0
808
+ */
809
+ readonly _tag = "StringKeyword"
810
+ constructor(readonly annotations: Annotations = {}) {}
811
+ /**
812
+ * @since 3.10.0
813
+ */
814
+ toString() {
815
+ return formatKeyword(this)
816
+ }
817
+ /**
818
+ * @since 3.10.0
819
+ */
820
+ toJSON(): object {
821
+ return {
822
+ _tag: this._tag,
823
+ annotations: toJSONAnnotations(this.annotations)
824
+ }
825
+ }
826
+ }
827
+
828
+ /**
829
+ * @category constructors
830
+ * @since 3.10.0
831
+ */
832
+ export const stringKeyword: StringKeyword = new StringKeyword({
833
+ [TitleAnnotationId]: "string",
834
+ [DescriptionAnnotationId]: "a string"
835
+ })
836
+
837
+ /**
838
+ * @category guards
839
+ * @since 3.10.0
840
+ */
841
+ export const isStringKeyword: (ast: AST) => ast is StringKeyword = createASTGuard("StringKeyword")
842
+
843
+ /**
844
+ * @category model
845
+ * @since 3.10.0
846
+ */
847
+ export class NumberKeyword implements Annotated {
848
+ /**
849
+ * @since 3.10.0
850
+ */
851
+ readonly _tag = "NumberKeyword"
852
+ constructor(readonly annotations: Annotations = {}) {}
853
+ /**
854
+ * @since 3.10.0
855
+ */
856
+ toString() {
857
+ return formatKeyword(this)
858
+ }
859
+ /**
860
+ * @since 3.10.0
861
+ */
862
+ toJSON(): object {
863
+ return {
864
+ _tag: this._tag,
865
+ annotations: toJSONAnnotations(this.annotations)
866
+ }
867
+ }
868
+ }
869
+
870
+ /**
871
+ * @category constructors
872
+ * @since 3.10.0
873
+ */
874
+ export const numberKeyword: NumberKeyword = new NumberKeyword({
875
+ [TitleAnnotationId]: "number",
876
+ [DescriptionAnnotationId]: "a number"
877
+ })
878
+
879
+ /**
880
+ * @category guards
881
+ * @since 3.10.0
882
+ */
883
+ export const isNumberKeyword: (ast: AST) => ast is NumberKeyword = createASTGuard("NumberKeyword")
884
+
885
+ /**
886
+ * @category model
887
+ * @since 3.10.0
888
+ */
889
+ export class BooleanKeyword implements Annotated {
890
+ /**
891
+ * @since 3.10.0
892
+ */
893
+ readonly _tag = "BooleanKeyword"
894
+ constructor(readonly annotations: Annotations = {}) {}
895
+ /**
896
+ * @since 3.10.0
897
+ */
898
+ toString() {
899
+ return formatKeyword(this)
900
+ }
901
+ /**
902
+ * @since 3.10.0
903
+ */
904
+ toJSON(): object {
905
+ return {
906
+ _tag: this._tag,
907
+ annotations: toJSONAnnotations(this.annotations)
908
+ }
909
+ }
910
+ }
911
+
912
+ /**
913
+ * @category constructors
914
+ * @since 3.10.0
915
+ */
916
+ export const booleanKeyword: BooleanKeyword = new BooleanKeyword({
917
+ [TitleAnnotationId]: "boolean",
918
+ [DescriptionAnnotationId]: "a boolean"
919
+ })
920
+
921
+ /**
922
+ * @category guards
923
+ * @since 3.10.0
924
+ */
925
+ export const isBooleanKeyword: (ast: AST) => ast is BooleanKeyword = createASTGuard("BooleanKeyword")
926
+
927
+ /**
928
+ * @category model
929
+ * @since 3.10.0
930
+ */
931
+ export class BigIntKeyword implements Annotated {
932
+ /**
933
+ * @since 3.10.0
934
+ */
935
+ readonly _tag = "BigIntKeyword"
936
+ constructor(readonly annotations: Annotations = {}) {}
937
+ /**
938
+ * @since 3.10.0
939
+ */
940
+ toString() {
941
+ return formatKeyword(this)
942
+ }
943
+ /**
944
+ * @since 3.10.0
945
+ */
946
+ toJSON(): object {
947
+ return {
948
+ _tag: this._tag,
949
+ annotations: toJSONAnnotations(this.annotations)
950
+ }
951
+ }
952
+ }
953
+
954
+ /**
955
+ * @category constructors
956
+ * @since 3.10.0
957
+ */
958
+ export const bigIntKeyword: BigIntKeyword = new BigIntKeyword({
959
+ [TitleAnnotationId]: "bigint",
960
+ [DescriptionAnnotationId]: "a bigint"
961
+ })
962
+
963
+ /**
964
+ * @category guards
965
+ * @since 3.10.0
966
+ */
967
+ export const isBigIntKeyword: (ast: AST) => ast is BigIntKeyword = createASTGuard("BigIntKeyword")
968
+
969
+ /**
970
+ * @category model
971
+ * @since 3.10.0
972
+ */
973
+ export class SymbolKeyword implements Annotated {
974
+ /**
975
+ * @since 3.10.0
976
+ */
977
+ readonly _tag = "SymbolKeyword"
978
+ constructor(readonly annotations: Annotations = {}) {}
979
+ /**
980
+ * @since 3.10.0
981
+ */
982
+ toString() {
983
+ return formatKeyword(this)
984
+ }
985
+ /**
986
+ * @since 3.10.0
987
+ */
988
+ toJSON(): object {
989
+ return {
990
+ _tag: this._tag,
991
+ annotations: toJSONAnnotations(this.annotations)
992
+ }
993
+ }
994
+ }
995
+
996
+ /**
997
+ * @category constructors
998
+ * @since 3.10.0
999
+ */
1000
+ export const symbolKeyword: SymbolKeyword = new SymbolKeyword({
1001
+ [TitleAnnotationId]: "symbol",
1002
+ [DescriptionAnnotationId]: "a symbol"
1003
+ })
1004
+
1005
+ /**
1006
+ * @category guards
1007
+ * @since 3.10.0
1008
+ */
1009
+ export const isSymbolKeyword: (ast: AST) => ast is SymbolKeyword = createASTGuard("SymbolKeyword")
1010
+
1011
+ /**
1012
+ * @category model
1013
+ * @since 3.10.0
1014
+ */
1015
+ export class ObjectKeyword implements Annotated {
1016
+ /**
1017
+ * @since 3.10.0
1018
+ */
1019
+ readonly _tag = "ObjectKeyword"
1020
+ constructor(readonly annotations: Annotations = {}) {}
1021
+ /**
1022
+ * @since 3.10.0
1023
+ */
1024
+ toString() {
1025
+ return formatKeyword(this)
1026
+ }
1027
+ /**
1028
+ * @since 3.10.0
1029
+ */
1030
+ toJSON(): object {
1031
+ return {
1032
+ _tag: this._tag,
1033
+ annotations: toJSONAnnotations(this.annotations)
1034
+ }
1035
+ }
1036
+ }
1037
+
1038
+ /**
1039
+ * @category constructors
1040
+ * @since 3.10.0
1041
+ */
1042
+ export const objectKeyword: ObjectKeyword = new ObjectKeyword({
1043
+ [TitleAnnotationId]: "object",
1044
+ [DescriptionAnnotationId]: "an object in the TypeScript meaning, i.e. the `object` type"
1045
+ })
1046
+
1047
+ /**
1048
+ * @category guards
1049
+ * @since 3.10.0
1050
+ */
1051
+ export const isObjectKeyword: (ast: AST) => ast is ObjectKeyword = createASTGuard("ObjectKeyword")
1052
+
1053
+ /**
1054
+ * @category model
1055
+ * @since 3.10.0
1056
+ */
1057
+ export class Enums implements Annotated {
1058
+ /**
1059
+ * @since 3.10.0
1060
+ */
1061
+ readonly _tag = "Enums"
1062
+ constructor(
1063
+ readonly enums: ReadonlyArray<readonly [string, string | number]>,
1064
+ readonly annotations: Annotations = {}
1065
+ ) {}
1066
+ /**
1067
+ * @since 3.10.0
1068
+ */
1069
+ toString() {
1070
+ return Option.getOrElse(
1071
+ getExpected(this),
1072
+ () => `<enum ${this.enums.length} value(s): ${this.enums.map((_, value) => JSON.stringify(value)).join(" | ")}>`
1073
+ )
1074
+ }
1075
+ /**
1076
+ * @since 3.10.0
1077
+ */
1078
+ toJSON(): object {
1079
+ return {
1080
+ _tag: this._tag,
1081
+ enums: this.enums,
1082
+ annotations: toJSONAnnotations(this.annotations)
1083
+ }
1084
+ }
1085
+ }
1086
+
1087
+ /**
1088
+ * @category guards
1089
+ * @since 3.10.0
1090
+ */
1091
+ export const isEnums: (ast: AST) => ast is Enums = createASTGuard("Enums")
1092
+
1093
+ /**
1094
+ * @category model
1095
+ * @since 3.10.0
1096
+ */
1097
+ export class TemplateLiteralSpan {
1098
+ constructor(readonly type: StringKeyword | NumberKeyword, readonly literal: string) {}
1099
+ /**
1100
+ * @since 3.10.0
1101
+ */
1102
+ toString() {
1103
+ const type = "${" + String(this.type) + "}"
1104
+ return type + this.literal
1105
+ }
1106
+ /**
1107
+ * @since 3.10.0
1108
+ */
1109
+ toJSON(): object {
1110
+ return {
1111
+ type: this.type.toJSON(),
1112
+ literal: this.literal
1113
+ }
1114
+ }
1115
+ }
1116
+
1117
+ /**
1118
+ * @category model
1119
+ * @since 3.10.0
1120
+ */
1121
+ export class TemplateLiteral implements Annotated {
1122
+ /**
1123
+ * @since 3.10.0
1124
+ */
1125
+ readonly _tag = "TemplateLiteral"
1126
+ constructor(
1127
+ readonly head: string,
1128
+ readonly spans: Arr.NonEmptyReadonlyArray<TemplateLiteralSpan>,
1129
+ readonly annotations: Annotations = {}
1130
+ ) {}
1131
+ /**
1132
+ * @since 3.10.0
1133
+ */
1134
+ toString() {
1135
+ return Option.getOrElse(getExpected(this), () => formatTemplateLiteral(this))
1136
+ }
1137
+ /**
1138
+ * @since 3.10.0
1139
+ */
1140
+ toJSON(): object {
1141
+ return {
1142
+ _tag: this._tag,
1143
+ head: this.head,
1144
+ spans: this.spans.map((span) => span.toJSON()),
1145
+ annotations: toJSONAnnotations(this.annotations)
1146
+ }
1147
+ }
1148
+ }
1149
+
1150
+ const formatTemplateLiteral = (ast: TemplateLiteral): string =>
1151
+ "`" + ast.head + ast.spans.map((span) => String(span)).join("") +
1152
+ "`"
1153
+
1154
+ /**
1155
+ * @category guards
1156
+ * @since 3.10.0
1157
+ */
1158
+ export const isTemplateLiteral: (ast: AST) => ast is TemplateLiteral = createASTGuard("TemplateLiteral")
1159
+
1160
+ /**
1161
+ * @category model
1162
+ * @since 3.10.0
1163
+ */
1164
+ export class Type implements Annotated {
1165
+ constructor(
1166
+ readonly type: AST,
1167
+ readonly annotations: Annotations = {}
1168
+ ) {}
1169
+ /**
1170
+ * @since 3.10.0
1171
+ */
1172
+ toJSON(): object {
1173
+ return {
1174
+ type: this.type.toJSON(),
1175
+ annotations: toJSONAnnotations(this.annotations)
1176
+ }
1177
+ }
1178
+ /**
1179
+ * @since 3.10.0
1180
+ */
1181
+ toString() {
1182
+ return String(this.type)
1183
+ }
1184
+ }
1185
+
1186
+ /**
1187
+ * @category model
1188
+ * @since 3.10.0
1189
+ */
1190
+ export class OptionalType extends Type {
1191
+ constructor(
1192
+ type: AST,
1193
+ readonly isOptional: boolean,
1194
+ annotations: Annotations = {}
1195
+ ) {
1196
+ super(type, annotations)
1197
+ }
1198
+ /**
1199
+ * @since 3.10.0
1200
+ */
1201
+ toJSON(): object {
1202
+ return {
1203
+ type: this.type.toJSON(),
1204
+ isOptional: this.isOptional,
1205
+ annotations: toJSONAnnotations(this.annotations)
1206
+ }
1207
+ }
1208
+ /**
1209
+ * @since 3.10.0
1210
+ */
1211
+ toString() {
1212
+ return String(this.type) + (this.isOptional ? "?" : "")
1213
+ }
1214
+ }
1215
+
1216
+ const getRestASTs = (rest: ReadonlyArray<Type>): ReadonlyArray<AST> => rest.map((annotatedAST) => annotatedAST.type)
1217
+
1218
+ /**
1219
+ * @category model
1220
+ * @since 3.10.0
1221
+ */
1222
+ export class TupleType implements Annotated {
1223
+ /**
1224
+ * @since 3.10.0
1225
+ */
1226
+ readonly _tag = "TupleType"
1227
+ constructor(
1228
+ readonly elements: ReadonlyArray<OptionalType>,
1229
+ readonly rest: ReadonlyArray<Type>,
1230
+ readonly isReadonly: boolean,
1231
+ readonly annotations: Annotations = {}
1232
+ ) {
1233
+ let hasOptionalElement = false
1234
+ let hasIllegalRequiredElement = false
1235
+ for (const e of elements) {
1236
+ if (e.isOptional) {
1237
+ hasOptionalElement = true
1238
+ } else if (hasOptionalElement) {
1239
+ hasIllegalRequiredElement = true
1240
+ break
1241
+ }
1242
+ }
1243
+ if (hasIllegalRequiredElement || (hasOptionalElement && rest.length > 1)) {
1244
+ throw new Error(errors_.getASTRequiredElementFollowinAnOptionalElementErrorMessage)
1245
+ }
1246
+ }
1247
+ /**
1248
+ * @since 3.10.0
1249
+ */
1250
+ toString() {
1251
+ return Option.getOrElse(getExpected(this), () => formatTuple(this))
1252
+ }
1253
+ /**
1254
+ * @since 3.10.0
1255
+ */
1256
+ toJSON(): object {
1257
+ return {
1258
+ _tag: this._tag,
1259
+ elements: this.elements.map((e) => e.toJSON()),
1260
+ rest: this.rest.map((ast) => ast.toJSON()),
1261
+ isReadonly: this.isReadonly,
1262
+ annotations: toJSONAnnotations(this.annotations)
1263
+ }
1264
+ }
1265
+ }
1266
+
1267
+ const formatTuple = (ast: TupleType): string => {
1268
+ const formattedElements = ast.elements.map(String)
1269
+ .join(", ")
1270
+ return Arr.matchLeft(ast.rest, {
1271
+ onEmpty: () => `readonly [${formattedElements}]`,
1272
+ onNonEmpty: (head, tail) => {
1273
+ const formattedHead = String(head)
1274
+ const wrappedHead = formattedHead.includes(" | ") ? `(${formattedHead})` : formattedHead
1275
+
1276
+ if (tail.length > 0) {
1277
+ const formattedTail = tail.map(String).join(", ")
1278
+ if (ast.elements.length > 0) {
1279
+ return `readonly [${formattedElements}, ...${wrappedHead}[], ${formattedTail}]`
1280
+ } else {
1281
+ return `readonly [...${wrappedHead}[], ${formattedTail}]`
1282
+ }
1283
+ } else {
1284
+ if (ast.elements.length > 0) {
1285
+ return `readonly [${formattedElements}, ...${wrappedHead}[]]`
1286
+ } else {
1287
+ return `ReadonlyArray<${formattedHead}>`
1288
+ }
1289
+ }
1290
+ }
1291
+ })
1292
+ }
1293
+
1294
+ /**
1295
+ * @category guards
1296
+ * @since 3.10.0
1297
+ */
1298
+ export const isTupleType: (ast: AST) => ast is TupleType = createASTGuard("TupleType")
1299
+
1300
+ /**
1301
+ * @category model
1302
+ * @since 3.10.0
1303
+ */
1304
+ export class PropertySignature extends OptionalType {
1305
+ constructor(
1306
+ readonly name: PropertyKey,
1307
+ type: AST,
1308
+ isOptional: boolean,
1309
+ readonly isReadonly: boolean,
1310
+ annotations?: Annotations
1311
+ ) {
1312
+ super(type, isOptional, annotations)
1313
+ }
1314
+ /**
1315
+ * @since 3.10.0
1316
+ */
1317
+ toString(): string {
1318
+ return (this.isReadonly ? "readonly " : "") + String(this.name) + (this.isOptional ? "?" : "") + ": " +
1319
+ this.type
1320
+ }
1321
+ /**
1322
+ * @since 3.10.0
1323
+ */
1324
+ toJSON(): object {
1325
+ return {
1326
+ name: String(this.name),
1327
+ type: this.type.toJSON(),
1328
+ isOptional: this.isOptional,
1329
+ isReadonly: this.isReadonly,
1330
+ annotations: toJSONAnnotations(this.annotations)
1331
+ }
1332
+ }
1333
+ }
1334
+
1335
+ /**
1336
+ * @since 3.10.0
1337
+ */
1338
+ export type Parameter = StringKeyword | SymbolKeyword | TemplateLiteral | Refinement<Parameter>
1339
+
1340
+ /**
1341
+ * @since 3.10.0
1342
+ */
1343
+ export const isParameter = (ast: AST): ast is Parameter => {
1344
+ switch (ast._tag) {
1345
+ case "StringKeyword":
1346
+ case "SymbolKeyword":
1347
+ case "TemplateLiteral":
1348
+ return true
1349
+ case "Refinement":
1350
+ return isParameter(ast.from)
1351
+ }
1352
+ return false
1353
+ }
1354
+
1355
+ /**
1356
+ * @category model
1357
+ * @since 3.10.0
1358
+ */
1359
+ export class IndexSignature {
1360
+ /**
1361
+ * @since 3.10.0
1362
+ */
1363
+ readonly parameter: Parameter
1364
+ constructor(
1365
+ parameter: AST,
1366
+ readonly type: AST,
1367
+ readonly isReadonly: boolean
1368
+ ) {
1369
+ if (isParameter(parameter)) {
1370
+ this.parameter = parameter
1371
+ } else {
1372
+ throw new Error(errors_.getASTIndexSignatureParameterErrorMessage)
1373
+ }
1374
+ }
1375
+ /**
1376
+ * @since 3.10.0
1377
+ */
1378
+ toString(): string {
1379
+ return (this.isReadonly ? "readonly " : "") + `[x: ${this.parameter}]: ${this.type}`
1380
+ }
1381
+ /**
1382
+ * @since 3.10.0
1383
+ */
1384
+ toJSON(): object {
1385
+ return {
1386
+ parameter: this.parameter.toJSON(),
1387
+ type: this.type.toJSON(),
1388
+ isReadonly: this.isReadonly
1389
+ }
1390
+ }
1391
+ }
1392
+
1393
+ /**
1394
+ * @category model
1395
+ * @since 3.10.0
1396
+ */
1397
+ export class TypeLiteral implements Annotated {
1398
+ /**
1399
+ * @since 3.10.0
1400
+ */
1401
+ readonly _tag = "TypeLiteral"
1402
+ /**
1403
+ * @since 3.10.0
1404
+ */
1405
+ readonly propertySignatures: ReadonlyArray<PropertySignature>
1406
+ /**
1407
+ * @since 3.10.0
1408
+ */
1409
+ readonly indexSignatures: ReadonlyArray<IndexSignature>
1410
+ constructor(
1411
+ propertySignatures: ReadonlyArray<PropertySignature>,
1412
+ indexSignatures: ReadonlyArray<IndexSignature>,
1413
+ readonly annotations: Annotations = {}
1414
+ ) {
1415
+ // check for duplicate property signatures
1416
+ const keys: Record<PropertyKey, null> = {}
1417
+ for (let i = 0; i < propertySignatures.length; i++) {
1418
+ const name = propertySignatures[i].name
1419
+ if (Object.prototype.hasOwnProperty.call(keys, name)) {
1420
+ throw new Error(errors_.getASTDuplicatePropertySignatureErrorMessage(name))
1421
+ }
1422
+ keys[name] = null
1423
+ }
1424
+ // check for duplicate index signatures
1425
+ const parameters = {
1426
+ string: false,
1427
+ symbol: false
1428
+ }
1429
+ for (let i = 0; i < indexSignatures.length; i++) {
1430
+ const parameter = getParameterBase(indexSignatures[i].parameter)
1431
+ if (isStringKeyword(parameter)) {
1432
+ if (parameters.string) {
1433
+ throw new Error(errors_.getASTDuplicateIndexSignatureErrorMessage("string"))
1434
+ }
1435
+ parameters.string = true
1436
+ } else if (isSymbolKeyword(parameter)) {
1437
+ if (parameters.symbol) {
1438
+ throw new Error(errors_.getASTDuplicateIndexSignatureErrorMessage("symbol"))
1439
+ }
1440
+ parameters.symbol = true
1441
+ }
1442
+ }
1443
+
1444
+ this.propertySignatures = propertySignatures
1445
+ this.indexSignatures = indexSignatures
1446
+ }
1447
+ /**
1448
+ * @since 3.10.0
1449
+ */
1450
+ toString() {
1451
+ return Option.getOrElse(getExpected(this), () => formatTypeLiteral(this))
1452
+ }
1453
+ /**
1454
+ * @since 3.10.0
1455
+ */
1456
+ toJSON(): object {
1457
+ return {
1458
+ _tag: this._tag,
1459
+ propertySignatures: this.propertySignatures.map((ps) => ps.toJSON()),
1460
+ indexSignatures: this.indexSignatures.map((ps) => ps.toJSON()),
1461
+ annotations: toJSONAnnotations(this.annotations)
1462
+ }
1463
+ }
1464
+ }
1465
+
1466
+ const formatIndexSignatures = (iss: ReadonlyArray<IndexSignature>): string => iss.map(String).join("; ")
1467
+
1468
+ const formatTypeLiteral = (ast: TypeLiteral): string => {
1469
+ if (ast.propertySignatures.length > 0) {
1470
+ const pss = ast.propertySignatures.map(String).join("; ")
1471
+ if (ast.indexSignatures.length > 0) {
1472
+ return `{ ${pss}; ${formatIndexSignatures(ast.indexSignatures)} }`
1473
+ } else {
1474
+ return `{ ${pss} }`
1475
+ }
1476
+ } else {
1477
+ if (ast.indexSignatures.length > 0) {
1478
+ return `{ ${formatIndexSignatures(ast.indexSignatures)} }`
1479
+ } else {
1480
+ return "{}"
1481
+ }
1482
+ }
1483
+ }
1484
+
1485
+ /**
1486
+ * @category guards
1487
+ * @since 3.10.0
1488
+ */
1489
+ export const isTypeLiteral: (ast: AST) => ast is TypeLiteral = createASTGuard("TypeLiteral")
1490
+
1491
+ /**
1492
+ * @since 3.10.0
1493
+ */
1494
+ export type Members<A> = readonly [A, A, ...Array<A>]
1495
+
1496
+ const sortCandidates = Arr.sort(
1497
+ Order.mapInput(Number.Order, (ast: AST) => {
1498
+ switch (ast._tag) {
1499
+ case "AnyKeyword":
1500
+ return 0
1501
+ case "UnknownKeyword":
1502
+ return 1
1503
+ case "ObjectKeyword":
1504
+ return 2
1505
+ case "StringKeyword":
1506
+ case "NumberKeyword":
1507
+ case "BooleanKeyword":
1508
+ case "BigIntKeyword":
1509
+ case "SymbolKeyword":
1510
+ return 3
1511
+ }
1512
+ return 4
1513
+ })
1514
+ )
1515
+
1516
+ const literalMap = {
1517
+ string: "StringKeyword",
1518
+ number: "NumberKeyword",
1519
+ boolean: "BooleanKeyword",
1520
+ bigint: "BigIntKeyword"
1521
+ } as const
1522
+
1523
+ /** @internal */
1524
+ export const flatten = (candidates: ReadonlyArray<AST>): Array<AST> =>
1525
+ Arr.flatMap(candidates, (ast) => isUnion(ast) ? flatten(ast.types) : [ast])
1526
+
1527
+ /** @internal */
1528
+ export const unify = (candidates: ReadonlyArray<AST>): Array<AST> => {
1529
+ const cs = sortCandidates(candidates)
1530
+ const out: Array<AST> = []
1531
+ const uniques: { [K in AST["_tag"] | "{}"]?: AST } = {}
1532
+ const literals: Array<LiteralValue | symbol> = []
1533
+ for (const ast of cs) {
1534
+ switch (ast._tag) {
1535
+ case "NeverKeyword":
1536
+ break
1537
+ case "AnyKeyword":
1538
+ return [anyKeyword]
1539
+ case "UnknownKeyword":
1540
+ return [unknownKeyword]
1541
+ // uniques
1542
+ case "ObjectKeyword":
1543
+ case "UndefinedKeyword":
1544
+ case "VoidKeyword":
1545
+ case "StringKeyword":
1546
+ case "NumberKeyword":
1547
+ case "BooleanKeyword":
1548
+ case "BigIntKeyword":
1549
+ case "SymbolKeyword": {
1550
+ if (!uniques[ast._tag]) {
1551
+ uniques[ast._tag] = ast
1552
+ out.push(ast)
1553
+ }
1554
+ break
1555
+ }
1556
+ case "Literal": {
1557
+ const type = typeof ast.literal
1558
+ switch (type) {
1559
+ case "string":
1560
+ case "number":
1561
+ case "bigint":
1562
+ case "boolean": {
1563
+ const _tag = literalMap[type]
1564
+ if (!uniques[_tag] && !literals.includes(ast.literal)) {
1565
+ literals.push(ast.literal)
1566
+ out.push(ast)
1567
+ }
1568
+ break
1569
+ }
1570
+ // null
1571
+ case "object": {
1572
+ if (!literals.includes(ast.literal)) {
1573
+ literals.push(ast.literal)
1574
+ out.push(ast)
1575
+ }
1576
+ break
1577
+ }
1578
+ }
1579
+ break
1580
+ }
1581
+ case "UniqueSymbol": {
1582
+ if (!uniques["SymbolKeyword"] && !literals.includes(ast.symbol)) {
1583
+ literals.push(ast.symbol)
1584
+ out.push(ast)
1585
+ }
1586
+ break
1587
+ }
1588
+ case "TupleType": {
1589
+ if (!uniques["ObjectKeyword"]) {
1590
+ out.push(ast)
1591
+ }
1592
+ break
1593
+ }
1594
+ case "TypeLiteral": {
1595
+ if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
1596
+ if (!uniques["{}"]) {
1597
+ uniques["{}"] = ast
1598
+ out.push(ast)
1599
+ }
1600
+ } else if (!uniques["ObjectKeyword"]) {
1601
+ out.push(ast)
1602
+ }
1603
+ break
1604
+ }
1605
+ default:
1606
+ out.push(ast)
1607
+ }
1608
+ }
1609
+ return out
1610
+ }
1611
+
1612
+ /**
1613
+ * @category model
1614
+ * @since 3.10.0
1615
+ */
1616
+ export class Union implements Annotated {
1617
+ static make = (types: ReadonlyArray<AST>, annotations?: Annotations): AST => {
1618
+ return isMembers(types) ? new Union(types, annotations) : types.length === 1 ? types[0] : neverKeyword
1619
+ }
1620
+ /** @internal */
1621
+ static unify = (candidates: ReadonlyArray<AST>, annotations?: Annotations): AST => {
1622
+ return Union.make(unify(flatten(candidates)), annotations)
1623
+ }
1624
+ /**
1625
+ * @since 3.10.0
1626
+ */
1627
+ readonly _tag = "Union"
1628
+ private constructor(readonly types: Members<AST>, readonly annotations: Annotations = {}) {}
1629
+ /**
1630
+ * @since 3.10.0
1631
+ */
1632
+ toString() {
1633
+ return Option.getOrElse(
1634
+ getExpected(this),
1635
+ () => this.types.map(String).join(" | ")
1636
+ )
1637
+ }
1638
+ /**
1639
+ * @since 3.10.0
1640
+ */
1641
+ toJSON(): object {
1642
+ return {
1643
+ _tag: this._tag,
1644
+ types: this.types.map((ast) => ast.toJSON()),
1645
+ annotations: toJSONAnnotations(this.annotations)
1646
+ }
1647
+ }
1648
+ }
1649
+
1650
+ /** @internal */
1651
+ export const mapMembers = <A, B>(members: Members<A>, f: (a: A) => B): Members<B> => members.map(f) as any
1652
+
1653
+ /** @internal */
1654
+ export const isMembers = <A>(as: ReadonlyArray<A>): as is Members<A> => as.length > 1
1655
+
1656
+ /**
1657
+ * @category guards
1658
+ * @since 3.10.0
1659
+ */
1660
+ export const isUnion: (ast: AST) => ast is Union = createASTGuard("Union")
1661
+
1662
+ const toJSONMemoMap = globalValue(
1663
+ Symbol.for("effect/Schema/AST/toJSONMemoMap"),
1664
+ () => new WeakMap<AST, object>()
1665
+ )
1666
+
1667
+ /**
1668
+ * @category model
1669
+ * @since 3.10.0
1670
+ */
1671
+ export class Suspend implements Annotated {
1672
+ /**
1673
+ * @since 3.10.0
1674
+ */
1675
+ readonly _tag = "Suspend"
1676
+ constructor(readonly f: () => AST, readonly annotations: Annotations = {}) {
1677
+ this.f = util_.memoizeThunk(f)
1678
+ }
1679
+ /**
1680
+ * @since 3.10.0
1681
+ */
1682
+ toString() {
1683
+ return getExpected(this).pipe(
1684
+ Option.orElse(() =>
1685
+ Option.flatMap(
1686
+ Option.liftThrowable(this.f)(),
1687
+ (ast) => getExpected(ast)
1688
+ )
1689
+ ),
1690
+ Option.getOrElse(() => "<suspended schema>")
1691
+ )
1692
+ }
1693
+ /**
1694
+ * @since 3.10.0
1695
+ */
1696
+ toJSON(): object {
1697
+ const ast = this.f()
1698
+ let out = toJSONMemoMap.get(ast)
1699
+ if (out) {
1700
+ return out
1701
+ }
1702
+ toJSONMemoMap.set(ast, { _tag: this._tag })
1703
+ out = {
1704
+ _tag: this._tag,
1705
+ ast: ast.toJSON(),
1706
+ annotations: toJSONAnnotations(this.annotations)
1707
+ }
1708
+ toJSONMemoMap.set(ast, out)
1709
+ return out
1710
+ }
1711
+ }
1712
+
1713
+ /**
1714
+ * @category guards
1715
+ * @since 3.10.0
1716
+ */
1717
+ export const isSuspend: (ast: AST) => ast is Suspend = createASTGuard("Suspend")
1718
+
1719
+ /**
1720
+ * @category model
1721
+ * @since 3.10.0
1722
+ */
1723
+ export class Refinement<From extends AST = AST> implements Annotated {
1724
+ /**
1725
+ * @since 3.10.0
1726
+ */
1727
+ readonly _tag = "Refinement"
1728
+ constructor(
1729
+ readonly from: From,
1730
+ readonly filter: (
1731
+ input: any,
1732
+ options: ParseOptions,
1733
+ self: Refinement
1734
+ ) => Option.Option<ParseIssue>,
1735
+ readonly annotations: Annotations = {}
1736
+ ) {}
1737
+ /**
1738
+ * @since 3.10.0
1739
+ */
1740
+ toString() {
1741
+ return Option.getOrElse(getExpected(this), () => `{ ${this.from} | filter }`)
1742
+ }
1743
+ /**
1744
+ * @since 3.10.0
1745
+ */
1746
+ toJSON(): object {
1747
+ return {
1748
+ _tag: this._tag,
1749
+ from: this.from.toJSON(),
1750
+ annotations: toJSONAnnotations(this.annotations)
1751
+ }
1752
+ }
1753
+ }
1754
+
1755
+ /**
1756
+ * @category guards
1757
+ * @since 3.10.0
1758
+ */
1759
+ export const isRefinement: (ast: AST) => ast is Refinement<AST> = createASTGuard("Refinement")
1760
+
1761
+ /**
1762
+ * @category model
1763
+ * @since 3.10.0
1764
+ */
1765
+ export interface ParseOptions {
1766
+ /**
1767
+ * The `errors` option allows you to receive all parsing errors when
1768
+ * attempting to parse a value using a schema. By default only the first error
1769
+ * is returned, but by setting the `errors` option to `"all"`, you can receive
1770
+ * all errors that occurred during the parsing process. This can be useful for
1771
+ * debugging or for providing more comprehensive error messages to the user.
1772
+ *
1773
+ * default: "first"
1774
+ *
1775
+ * @since 3.10.0
1776
+ */
1777
+ readonly errors?: "first" | "all" | undefined
1778
+ /**
1779
+ * When using a `Schema` to parse a value, by default any properties that are
1780
+ * not specified in the `Schema` will be stripped out from the output. This is
1781
+ * because the `Schema` is expecting a specific shape for the parsed value,
1782
+ * and any excess properties do not conform to that shape.
1783
+ *
1784
+ * However, you can use the `onExcessProperty` option (default value:
1785
+ * `"ignore"`) to trigger a parsing error. This can be particularly useful in
1786
+ * cases where you need to detect and handle potential errors or unexpected
1787
+ * values.
1788
+ *
1789
+ * If you want to allow excess properties to remain, you can use
1790
+ * `onExcessProperty` set to `"preserve"`.
1791
+ *
1792
+ * default: "ignore"
1793
+ *
1794
+ * @since 3.10.0
1795
+ */
1796
+ readonly onExcessProperty?: "ignore" | "error" | "preserve" | undefined
1797
+ /**
1798
+ * The `propertyOrder` option provides control over the order of object fields
1799
+ * in the output. This feature is particularly useful when the sequence of
1800
+ * keys is important for the consuming processes or when maintaining the input
1801
+ * order enhances readability and usability.
1802
+ *
1803
+ * By default, the `propertyOrder` option is set to `"none"`. This means that
1804
+ * the internal system decides the order of keys to optimize parsing speed.
1805
+ * The order of keys in this mode should not be considered stable, and it's
1806
+ * recommended not to rely on key ordering as it may change in future updates
1807
+ * without notice.
1808
+ *
1809
+ * Setting `propertyOrder` to `"original"` ensures that the keys are ordered
1810
+ * as they appear in the input during the decoding/encoding process.
1811
+ *
1812
+ * default: "none"
1813
+ *
1814
+ * @since 3.10.0
1815
+ */
1816
+ readonly propertyOrder?: "none" | "original" | undefined
1817
+ /**
1818
+ * Handles missing properties in data structures. By default, missing
1819
+ * properties are treated as if present with an `undefined` value. To treat
1820
+ * missing properties as errors, set the `exact` option to `true`. This
1821
+ * setting is already enabled by default for `is` and `asserts` functions,
1822
+ * treating absent properties strictly unless overridden.
1823
+ *
1824
+ * default: false
1825
+ *
1826
+ * @since 3.10.0
1827
+ */
1828
+ readonly exact?: boolean | undefined
1829
+ }
1830
+
1831
+ /**
1832
+ * @since 3.10.0
1833
+ */
1834
+ export const defaultParseOption: ParseOptions = {}
1835
+
1836
+ /**
1837
+ * @category model
1838
+ * @since 3.10.0
1839
+ */
1840
+ export class Transformation implements Annotated {
1841
+ /**
1842
+ * @since 3.10.0
1843
+ */
1844
+ readonly _tag = "Transformation"
1845
+ constructor(
1846
+ readonly from: AST,
1847
+ readonly to: AST,
1848
+ readonly transformation: TransformationKind,
1849
+ readonly annotations: Annotations = {}
1850
+ ) {}
1851
+ /**
1852
+ * @since 3.10.0
1853
+ */
1854
+ toString() {
1855
+ return Option.getOrElse(
1856
+ getExpected(this),
1857
+ () => `(${String(this.from)} <-> ${String(this.to)})`
1858
+ )
1859
+ }
1860
+ /**
1861
+ * @since 3.10.0
1862
+ */
1863
+ toJSON(): object {
1864
+ return {
1865
+ _tag: this._tag,
1866
+ from: this.from.toJSON(),
1867
+ to: this.to.toJSON(),
1868
+ annotations: toJSONAnnotations(this.annotations)
1869
+ }
1870
+ }
1871
+ }
1872
+
1873
+ /**
1874
+ * @category guards
1875
+ * @since 3.10.0
1876
+ */
1877
+ export const isTransformation: (ast: AST) => ast is Transformation = createASTGuard("Transformation")
1878
+
1879
+ /**
1880
+ * @category model
1881
+ * @since 3.10.0
1882
+ */
1883
+ export type TransformationKind =
1884
+ | FinalTransformation
1885
+ | ComposeTransformation
1886
+ | TypeLiteralTransformation
1887
+
1888
+ /**
1889
+ * @category model
1890
+ * @since 3.10.0
1891
+ */
1892
+ export class FinalTransformation {
1893
+ /**
1894
+ * @since 3.10.0
1895
+ */
1896
+ readonly _tag = "FinalTransformation"
1897
+ constructor(
1898
+ readonly decode: (
1899
+ fromA: any,
1900
+ options: ParseOptions,
1901
+ self: Transformation,
1902
+ fromI: any
1903
+ ) => Effect<any, ParseIssue, any>,
1904
+ readonly encode: (toI: any, options: ParseOptions, self: Transformation, toA: any) => Effect<any, ParseIssue, any>
1905
+ ) {}
1906
+ }
1907
+
1908
+ const createTransformationGuard =
1909
+ <T extends TransformationKind["_tag"]>(tag: T) =>
1910
+ (ast: TransformationKind): ast is Extract<TransformationKind, { _tag: T }> => ast._tag === tag
1911
+
1912
+ /**
1913
+ * @category guards
1914
+ * @since 3.10.0
1915
+ */
1916
+ export const isFinalTransformation: (ast: TransformationKind) => ast is FinalTransformation = createTransformationGuard(
1917
+ "FinalTransformation"
1918
+ )
1919
+
1920
+ /**
1921
+ * @category model
1922
+ * @since 3.10.0
1923
+ */
1924
+ export class ComposeTransformation {
1925
+ /**
1926
+ * @since 3.10.0
1927
+ */
1928
+ readonly _tag = "ComposeTransformation"
1929
+ }
1930
+
1931
+ /**
1932
+ * @category constructors
1933
+ * @since 3.10.0
1934
+ */
1935
+ export const composeTransformation: ComposeTransformation = new ComposeTransformation()
1936
+
1937
+ /**
1938
+ * @category guards
1939
+ * @since 3.10.0
1940
+ */
1941
+ export const isComposeTransformation: (ast: TransformationKind) => ast is ComposeTransformation =
1942
+ createTransformationGuard(
1943
+ "ComposeTransformation"
1944
+ )
1945
+
1946
+ /**
1947
+ * Represents a `PropertySignature -> PropertySignature` transformation
1948
+ *
1949
+ * The semantic of `decode` is:
1950
+ * - `none()` represents the absence of the key/value pair
1951
+ * - `some(value)` represents the presence of the key/value pair
1952
+ *
1953
+ * The semantic of `encode` is:
1954
+ * - `none()` you don't want to output the key/value pair
1955
+ * - `some(value)` you want to output the key/value pair
1956
+ *
1957
+ * @category model
1958
+ * @since 3.10.0
1959
+ */
1960
+ export class PropertySignatureTransformation {
1961
+ constructor(
1962
+ readonly from: PropertyKey,
1963
+ readonly to: PropertyKey,
1964
+ readonly decode: (o: Option.Option<any>) => Option.Option<any>,
1965
+ readonly encode: (o: Option.Option<any>) => Option.Option<any>
1966
+ ) {}
1967
+ }
1968
+
1969
+ const isRenamingPropertySignatureTransformation = (t: PropertySignatureTransformation) =>
1970
+ t.decode === identity && t.encode === identity
1971
+
1972
+ /**
1973
+ * @category model
1974
+ * @since 3.10.0
1975
+ */
1976
+ export class TypeLiteralTransformation {
1977
+ /**
1978
+ * @since 3.10.0
1979
+ */
1980
+ readonly _tag = "TypeLiteralTransformation"
1981
+ constructor(
1982
+ readonly propertySignatureTransformations: ReadonlyArray<
1983
+ PropertySignatureTransformation
1984
+ >
1985
+ ) {
1986
+ // check for duplicate property signature transformations
1987
+ const fromKeys: Record<PropertyKey, true> = {}
1988
+ const toKeys: Record<PropertyKey, true> = {}
1989
+ for (const pst of propertySignatureTransformations) {
1990
+ const from = pst.from
1991
+ if (fromKeys[from]) {
1992
+ throw new Error(errors_.getASTDuplicatePropertySignatureTransformationErrorMessage(from))
1993
+ }
1994
+ fromKeys[from] = true
1995
+ const to = pst.to
1996
+ if (toKeys[to]) {
1997
+ throw new Error(errors_.getASTDuplicatePropertySignatureTransformationErrorMessage(to))
1998
+ }
1999
+ toKeys[to] = true
2000
+ }
2001
+ }
2002
+ }
2003
+
2004
+ /**
2005
+ * @category guards
2006
+ * @since 3.10.0
2007
+ */
2008
+ export const isTypeLiteralTransformation: (ast: TransformationKind) => ast is TypeLiteralTransformation =
2009
+ createTransformationGuard("TypeLiteralTransformation")
2010
+
2011
+ // -------------------------------------------------------------------------------------
2012
+ // API
2013
+ // -------------------------------------------------------------------------------------
2014
+
2015
+ /**
2016
+ * Merges a set of new annotations with existing ones, potentially overwriting
2017
+ * any duplicates.
2018
+ *
2019
+ * @since 3.10.0
2020
+ */
2021
+ export const annotations = (ast: AST, annotations: Annotations): AST => {
2022
+ const d = Object.getOwnPropertyDescriptors(ast)
2023
+ d.annotations.value = { ...ast.annotations, ...annotations }
2024
+ return Object.create(Object.getPrototypeOf(ast), d)
2025
+ }
2026
+
2027
+ /**
2028
+ * Equivalent at runtime to the TypeScript type-level `keyof` operator.
2029
+ *
2030
+ * @since 3.10.0
2031
+ */
2032
+ export const keyof = (ast: AST): AST => Union.unify(_keyof(ast))
2033
+
2034
+ const STRING_KEYWORD_PATTERN = ".*"
2035
+ const NUMBER_KEYWORD_PATTERN = "[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?"
2036
+
2037
+ /**
2038
+ * @since 3.10.0
2039
+ */
2040
+ export const getTemplateLiteralRegExp = (ast: TemplateLiteral): RegExp => {
2041
+ let pattern = `^${regexp.escape(ast.head)}`
2042
+
2043
+ for (const span of ast.spans) {
2044
+ if (isStringKeyword(span.type)) {
2045
+ pattern += STRING_KEYWORD_PATTERN
2046
+ } else if (isNumberKeyword(span.type)) {
2047
+ pattern += NUMBER_KEYWORD_PATTERN
2048
+ }
2049
+ pattern += regexp.escape(span.literal)
2050
+ }
2051
+
2052
+ pattern += "$"
2053
+ return new RegExp(pattern)
2054
+ }
2055
+
2056
+ /**
2057
+ * @since 3.10.0
2058
+ */
2059
+ export const getTemplateLiteralCapturingRegExp = (ast: TemplateLiteral): RegExp => {
2060
+ let pattern = `^`
2061
+ if (ast.head !== "") {
2062
+ pattern += `(${regexp.escape(ast.head)})`
2063
+ }
2064
+
2065
+ for (const span of ast.spans) {
2066
+ if (isStringKeyword(span.type)) {
2067
+ pattern += `(${STRING_KEYWORD_PATTERN})`
2068
+ } else if (isNumberKeyword(span.type)) {
2069
+ pattern += `(${NUMBER_KEYWORD_PATTERN})`
2070
+ }
2071
+ if (span.literal !== "") {
2072
+ pattern += `(${regexp.escape(span.literal)})`
2073
+ }
2074
+ }
2075
+
2076
+ pattern += "$"
2077
+ return new RegExp(pattern)
2078
+ }
2079
+
2080
+ /**
2081
+ * @since 3.10.0
2082
+ */
2083
+ export const getPropertySignatures = (ast: AST): Array<PropertySignature> => {
2084
+ switch (ast._tag) {
2085
+ case "Declaration": {
2086
+ const annotation = getSurrogateAnnotation(ast)
2087
+ if (Option.isSome(annotation)) {
2088
+ return getPropertySignatures(annotation.value)
2089
+ }
2090
+ break
2091
+ }
2092
+ case "TypeLiteral":
2093
+ return ast.propertySignatures.slice()
2094
+ case "Suspend":
2095
+ return getPropertySignatures(ast.f())
2096
+ }
2097
+ return getPropertyKeys(ast).map((name) => getPropertyKeyIndexedAccess(ast, name))
2098
+ }
2099
+
2100
+ /** @internal */
2101
+ export const getNumberIndexedAccess = (ast: AST): AST => {
2102
+ switch (ast._tag) {
2103
+ case "TupleType": {
2104
+ let hasOptional = false
2105
+ let out: Array<AST> = []
2106
+ for (const e of ast.elements) {
2107
+ if (e.isOptional) {
2108
+ hasOptional = true
2109
+ }
2110
+ out.push(e.type)
2111
+ }
2112
+ if (hasOptional) {
2113
+ out.push(undefinedKeyword)
2114
+ }
2115
+ out = out.concat(getRestASTs(ast.rest))
2116
+ return Union.make(out)
2117
+ }
2118
+ case "Refinement":
2119
+ return getNumberIndexedAccess(ast.from)
2120
+ case "Union":
2121
+ return Union.make(ast.types.map(getNumberIndexedAccess))
2122
+ case "Suspend":
2123
+ return getNumberIndexedAccess(ast.f())
2124
+ }
2125
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2126
+ }
2127
+
2128
+ const getTypeLiteralPropertySignature = (ast: TypeLiteral, name: PropertyKey): PropertySignature | undefined => {
2129
+ // from property signatures...
2130
+ const ops = Arr.findFirst(ast.propertySignatures, (ps) => ps.name === name)
2131
+ if (Option.isSome(ops)) {
2132
+ return ops.value
2133
+ }
2134
+
2135
+ // from index signatures...
2136
+ if (Predicate.isString(name)) {
2137
+ let out: PropertySignature | undefined = undefined
2138
+ for (const is of ast.indexSignatures) {
2139
+ const parameterBase = getParameterBase(is.parameter)
2140
+ switch (parameterBase._tag) {
2141
+ case "TemplateLiteral": {
2142
+ const regex = getTemplateLiteralRegExp(parameterBase)
2143
+ if (regex.test(name)) {
2144
+ return new PropertySignature(name, is.type, false, true)
2145
+ }
2146
+ break
2147
+ }
2148
+ case "StringKeyword": {
2149
+ if (out === undefined) {
2150
+ out = new PropertySignature(name, is.type, false, true)
2151
+ }
2152
+ }
2153
+ }
2154
+ }
2155
+ if (out) {
2156
+ return out
2157
+ }
2158
+ } else if (Predicate.isSymbol(name)) {
2159
+ for (const is of ast.indexSignatures) {
2160
+ const parameterBase = getParameterBase(is.parameter)
2161
+ if (isSymbolKeyword(parameterBase)) {
2162
+ return new PropertySignature(name, is.type, false, true)
2163
+ }
2164
+ }
2165
+ }
2166
+ }
2167
+
2168
+ /** @internal */
2169
+ export const getPropertyKeyIndexedAccess = (ast: AST, name: PropertyKey): PropertySignature => {
2170
+ const annotation = getSurrogateAnnotation(ast)
2171
+ if (Option.isSome(annotation)) {
2172
+ return getPropertyKeyIndexedAccess(annotation.value, name)
2173
+ }
2174
+ switch (ast._tag) {
2175
+ case "TypeLiteral": {
2176
+ const ps = getTypeLiteralPropertySignature(ast, name)
2177
+ if (ps) {
2178
+ return ps
2179
+ }
2180
+ break
2181
+ }
2182
+ case "Union":
2183
+ return new PropertySignature(
2184
+ name,
2185
+ Union.make(ast.types.map((ast) => getPropertyKeyIndexedAccess(ast, name).type)),
2186
+ false,
2187
+ true
2188
+ )
2189
+ case "Suspend":
2190
+ return getPropertyKeyIndexedAccess(ast.f(), name)
2191
+ case "Refinement":
2192
+ return getPropertyKeyIndexedAccess(ast.from, name)
2193
+ }
2194
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2195
+ }
2196
+
2197
+ const getPropertyKeys = (ast: AST): Array<PropertyKey> => {
2198
+ const annotation = getSurrogateAnnotation(ast)
2199
+ if (Option.isSome(annotation)) {
2200
+ return getPropertyKeys(annotation.value)
2201
+ }
2202
+ switch (ast._tag) {
2203
+ case "TypeLiteral":
2204
+ return ast.propertySignatures.map((ps) => ps.name)
2205
+ case "Suspend":
2206
+ return getPropertyKeys(ast.f())
2207
+ case "Union":
2208
+ return ast.types.slice(1).reduce(
2209
+ (out: Array<PropertyKey>, ast) => Arr.intersection(out, getPropertyKeys(ast)),
2210
+ getPropertyKeys(ast.types[0])
2211
+ )
2212
+ case "Transformation":
2213
+ return getPropertyKeys(ast.to)
2214
+ }
2215
+ return []
2216
+ }
2217
+
2218
+ /** @internal */
2219
+ export const record = (key: AST, value: AST): {
2220
+ propertySignatures: Array<PropertySignature>
2221
+ indexSignatures: Array<IndexSignature>
2222
+ } => {
2223
+ const propertySignatures: Array<PropertySignature> = []
2224
+ const indexSignatures: Array<IndexSignature> = []
2225
+ const go = (key: AST): void => {
2226
+ switch (key._tag) {
2227
+ case "NeverKeyword":
2228
+ break
2229
+ case "StringKeyword":
2230
+ case "SymbolKeyword":
2231
+ case "TemplateLiteral":
2232
+ case "Refinement":
2233
+ indexSignatures.push(new IndexSignature(key, value, true))
2234
+ break
2235
+ case "Literal":
2236
+ if (Predicate.isString(key.literal) || Predicate.isNumber(key.literal)) {
2237
+ propertySignatures.push(new PropertySignature(key.literal, value, false, true))
2238
+ } else {
2239
+ throw new Error(errors_.getASTUnsupportedLiteral(key.literal))
2240
+ }
2241
+ break
2242
+ case "Enums": {
2243
+ for (const [_, name] of key.enums) {
2244
+ propertySignatures.push(new PropertySignature(name, value, false, true))
2245
+ }
2246
+ break
2247
+ }
2248
+ case "UniqueSymbol":
2249
+ propertySignatures.push(new PropertySignature(key.symbol, value, false, true))
2250
+ break
2251
+ case "Union":
2252
+ key.types.forEach(go)
2253
+ break
2254
+ default:
2255
+ throw new Error(errors_.getASTUnsupportedKeySchema(key))
2256
+ }
2257
+ }
2258
+ go(key)
2259
+ return { propertySignatures, indexSignatures }
2260
+ }
2261
+
2262
+ /**
2263
+ * Equivalent at runtime to the built-in TypeScript utility type `Pick`.
2264
+ *
2265
+ * @since 3.10.0
2266
+ */
2267
+ export const pick = (ast: AST, keys: ReadonlyArray<PropertyKey>): TypeLiteral | Transformation => {
2268
+ const annotation = getSurrogateAnnotation(ast)
2269
+ if (Option.isSome(annotation)) {
2270
+ return pick(annotation.value, keys)
2271
+ }
2272
+ switch (ast._tag) {
2273
+ case "TypeLiteral": {
2274
+ const pss: Array<PropertySignature> = []
2275
+ const names: Record<PropertyKey, null> = {}
2276
+ for (const ps of ast.propertySignatures) {
2277
+ names[ps.name] = null
2278
+ if (keys.includes(ps.name)) {
2279
+ pss.push(ps)
2280
+ }
2281
+ }
2282
+ for (const key of keys) {
2283
+ if (!(key in names)) {
2284
+ const ps = getTypeLiteralPropertySignature(ast, key)
2285
+ if (ps) {
2286
+ pss.push(ps)
2287
+ }
2288
+ }
2289
+ }
2290
+ return new TypeLiteral(pss, [])
2291
+ }
2292
+ case "Union":
2293
+ return new TypeLiteral(keys.map((name) => getPropertyKeyIndexedAccess(ast, name)), [])
2294
+ case "Suspend":
2295
+ return pick(ast.f(), keys)
2296
+ case "Refinement":
2297
+ return pick(ast.from, keys)
2298
+ case "Transformation": {
2299
+ switch (ast.transformation._tag) {
2300
+ case "ComposeTransformation":
2301
+ return new Transformation(
2302
+ pick(ast.from, keys),
2303
+ pick(ast.to, keys),
2304
+ composeTransformation
2305
+ )
2306
+ case "TypeLiteralTransformation": {
2307
+ const ts: Array<PropertySignatureTransformation> = []
2308
+ const fromKeys: Array<PropertyKey> = []
2309
+ for (const k of keys) {
2310
+ const t = ast.transformation.propertySignatureTransformations.find((t) => t.to === k)
2311
+ if (t) {
2312
+ ts.push(t)
2313
+ fromKeys.push(t.from)
2314
+ } else {
2315
+ fromKeys.push(k)
2316
+ }
2317
+ }
2318
+ return Arr.isNonEmptyReadonlyArray(ts) ?
2319
+ new Transformation(
2320
+ pick(ast.from, fromKeys),
2321
+ pick(ast.to, keys),
2322
+ new TypeLiteralTransformation(ts)
2323
+ ) :
2324
+ pick(ast.from, fromKeys)
2325
+ }
2326
+ }
2327
+ }
2328
+ }
2329
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2330
+ }
2331
+
2332
+ /**
2333
+ * Equivalent at runtime to the built-in TypeScript utility type `Omit`.
2334
+ *
2335
+ * @since 3.10.0
2336
+ */
2337
+ export const omit = (ast: AST, keys: ReadonlyArray<PropertyKey>): TypeLiteral | Transformation =>
2338
+ pick(ast, getPropertyKeys(ast).filter((name) => !keys.includes(name)))
2339
+
2340
+ /** @internal */
2341
+ export const orUndefined = (ast: AST): AST => Union.make([ast, undefinedKeyword])
2342
+
2343
+ /**
2344
+ * Equivalent at runtime to the built-in TypeScript utility type `Partial`.
2345
+ *
2346
+ * @since 3.10.0
2347
+ */
2348
+ export const partial = (ast: AST, options?: { readonly exact: true }): AST => {
2349
+ const exact = options?.exact === true
2350
+ switch (ast._tag) {
2351
+ case "TupleType":
2352
+ return new TupleType(
2353
+ ast.elements.map((e) => new OptionalType(exact ? e.type : orUndefined(e.type), true)),
2354
+ Arr.match(ast.rest, {
2355
+ onEmpty: () => ast.rest,
2356
+ onNonEmpty: (rest) => [new Type(Union.make([...getRestASTs(rest), undefinedKeyword]))]
2357
+ }),
2358
+ ast.isReadonly
2359
+ )
2360
+ case "TypeLiteral":
2361
+ return new TypeLiteral(
2362
+ ast.propertySignatures.map((ps) =>
2363
+ new PropertySignature(ps.name, exact ? ps.type : orUndefined(ps.type), true, ps.isReadonly, ps.annotations)
2364
+ ),
2365
+ ast.indexSignatures.map((is) => new IndexSignature(is.parameter, orUndefined(is.type), is.isReadonly))
2366
+ )
2367
+ case "Union":
2368
+ return Union.make(ast.types.map((member) => partial(member, options)))
2369
+ case "Suspend":
2370
+ return new Suspend(() => partial(ast.f(), options))
2371
+ case "Declaration":
2372
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2373
+ case "Refinement":
2374
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2375
+ case "Transformation": {
2376
+ if (
2377
+ isTypeLiteralTransformation(ast.transformation) &&
2378
+ ast.transformation.propertySignatureTransformations.every(isRenamingPropertySignatureTransformation)
2379
+ ) {
2380
+ return new Transformation(partial(ast.from, options), partial(ast.to, options), ast.transformation)
2381
+ }
2382
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2383
+ }
2384
+ }
2385
+ return ast
2386
+ }
2387
+
2388
+ /**
2389
+ * Equivalent at runtime to the built-in TypeScript utility type `Required`.
2390
+ *
2391
+ * @since 3.10.0
2392
+ */
2393
+ export const required = (ast: AST): AST => {
2394
+ switch (ast._tag) {
2395
+ case "TupleType":
2396
+ return new TupleType(
2397
+ ast.elements.map((e) => new OptionalType(e.type, false)),
2398
+ ast.rest,
2399
+ ast.isReadonly
2400
+ )
2401
+ case "TypeLiteral":
2402
+ return new TypeLiteral(
2403
+ ast.propertySignatures.map((f) => new PropertySignature(f.name, f.type, false, f.isReadonly, f.annotations)),
2404
+ ast.indexSignatures
2405
+ )
2406
+ case "Union":
2407
+ return Union.make(ast.types.map((member) => required(member)))
2408
+ case "Suspend":
2409
+ return new Suspend(() => required(ast.f()))
2410
+ case "Declaration":
2411
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2412
+ case "Refinement":
2413
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2414
+ case "Transformation": {
2415
+ if (
2416
+ isTypeLiteralTransformation(ast.transformation) &&
2417
+ ast.transformation.propertySignatureTransformations.every(isRenamingPropertySignatureTransformation)
2418
+ ) {
2419
+ return new Transformation(required(ast.from), required(ast.to), ast.transformation)
2420
+ }
2421
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2422
+ }
2423
+ }
2424
+ return ast
2425
+ }
2426
+
2427
+ /**
2428
+ * Creates a new AST with shallow mutability applied to its properties.
2429
+ *
2430
+ * @param ast - The original AST to make properties mutable (shallowly).
2431
+ *
2432
+ * @since 3.10.0
2433
+ */
2434
+ export const mutable = (ast: AST): AST => {
2435
+ switch (ast._tag) {
2436
+ case "TupleType":
2437
+ return ast.isReadonly === false ? ast : new TupleType(ast.elements, ast.rest, false, ast.annotations)
2438
+ case "TypeLiteral": {
2439
+ const propertySignatures = changeMap(
2440
+ ast.propertySignatures,
2441
+ (ps) =>
2442
+ ps.isReadonly === false ? ps : new PropertySignature(ps.name, ps.type, ps.isOptional, false, ps.annotations)
2443
+ )
2444
+ const indexSignatures = changeMap(
2445
+ ast.indexSignatures,
2446
+ (is) => is.isReadonly === false ? is : new IndexSignature(is.parameter, is.type, false)
2447
+ )
2448
+ return propertySignatures === ast.propertySignatures && indexSignatures === ast.indexSignatures ?
2449
+ ast :
2450
+ new TypeLiteral(propertySignatures, indexSignatures, ast.annotations)
2451
+ }
2452
+ case "Union": {
2453
+ const types = changeMap(ast.types, mutable)
2454
+ return types === ast.types ? ast : Union.make(types, ast.annotations)
2455
+ }
2456
+ case "Suspend":
2457
+ return new Suspend(() => mutable(ast.f()), ast.annotations)
2458
+ case "Refinement": {
2459
+ const from = mutable(ast.from)
2460
+ return from === ast.from ? ast : new Refinement(from, ast.filter, ast.annotations)
2461
+ }
2462
+ case "Transformation": {
2463
+ const from = mutable(ast.from)
2464
+ const to = mutable(ast.to)
2465
+ return from === ast.from && to === ast.to ?
2466
+ ast :
2467
+ new Transformation(from, to, ast.transformation, ast.annotations)
2468
+ }
2469
+ }
2470
+ return ast
2471
+ }
2472
+
2473
+ // -------------------------------------------------------------------------------------
2474
+ // compiler harness
2475
+ // -------------------------------------------------------------------------------------
2476
+
2477
+ /**
2478
+ * @since 3.10.0
2479
+ */
2480
+ export type Compiler<A> = (ast: AST, path: ReadonlyArray<PropertyKey>) => A
2481
+
2482
+ /**
2483
+ * @since 3.10.0
2484
+ */
2485
+ export type Match<A> = {
2486
+ [K in AST["_tag"]]: (ast: Extract<AST, { _tag: K }>, compile: Compiler<A>, path: ReadonlyArray<PropertyKey>) => A
2487
+ }
2488
+
2489
+ /**
2490
+ * @since 3.10.0
2491
+ */
2492
+ export const getCompiler = <A>(match: Match<A>): Compiler<A> => {
2493
+ const compile = (ast: AST, path: ReadonlyArray<PropertyKey>): A => match[ast._tag](ast as any, compile, path)
2494
+ return compile
2495
+ }
2496
+
2497
+ /**
2498
+ * @since 3.10.0
2499
+ */
2500
+ export const typeAST = (ast: AST): AST => {
2501
+ switch (ast._tag) {
2502
+ case "Declaration": {
2503
+ const typeParameters = changeMap(ast.typeParameters, typeAST)
2504
+ return typeParameters === ast.typeParameters ?
2505
+ ast :
2506
+ new Declaration(typeParameters, ast.decodeUnknown, ast.encodeUnknown, ast.annotations)
2507
+ }
2508
+ case "TupleType": {
2509
+ const elements = changeMap(ast.elements, (e) => {
2510
+ const type = typeAST(e.type)
2511
+ return type === e.type ? e : new OptionalType(type, e.isOptional)
2512
+ })
2513
+ const restASTs = getRestASTs(ast.rest)
2514
+ const rest = changeMap(restASTs, typeAST)
2515
+ return elements === ast.elements && rest === restASTs ?
2516
+ ast :
2517
+ new TupleType(elements, rest.map((type) => new Type(type)), ast.isReadonly, ast.annotations)
2518
+ }
2519
+ case "TypeLiteral": {
2520
+ const propertySignatures = changeMap(ast.propertySignatures, (p) => {
2521
+ const type = typeAST(p.type)
2522
+ return type === p.type ? p : new PropertySignature(p.name, type, p.isOptional, p.isReadonly)
2523
+ })
2524
+ const indexSignatures = changeMap(ast.indexSignatures, (is) => {
2525
+ const type = typeAST(is.type)
2526
+ return type === is.type ? is : new IndexSignature(is.parameter, type, is.isReadonly)
2527
+ })
2528
+ return propertySignatures === ast.propertySignatures && indexSignatures === ast.indexSignatures ?
2529
+ ast :
2530
+ new TypeLiteral(propertySignatures, indexSignatures, ast.annotations)
2531
+ }
2532
+ case "Union": {
2533
+ const types = changeMap(ast.types, typeAST)
2534
+ return types === ast.types ? ast : Union.make(types, ast.annotations)
2535
+ }
2536
+ case "Suspend":
2537
+ return new Suspend(() => typeAST(ast.f()), ast.annotations)
2538
+ case "Refinement": {
2539
+ const from = typeAST(ast.from)
2540
+ return from === ast.from ?
2541
+ ast :
2542
+ new Refinement(from, ast.filter, ast.annotations)
2543
+ }
2544
+ case "Transformation":
2545
+ return typeAST(ast.to)
2546
+ }
2547
+ return ast
2548
+ }
2549
+
2550
+ /** @internal */
2551
+ export const whiteListAnnotations =
2552
+ (annotationIds: ReadonlyArray<symbol>) => (annotated: Annotated): Annotations | undefined => {
2553
+ let out: { [_: symbol]: unknown } | undefined = undefined
2554
+ for (const id of annotationIds) {
2555
+ if (Object.prototype.hasOwnProperty.call(annotated.annotations, id)) {
2556
+ if (out === undefined) {
2557
+ out = {}
2558
+ }
2559
+ out[id] = annotated.annotations[id]
2560
+ }
2561
+ }
2562
+ return out
2563
+ }
2564
+
2565
+ /** @internal */
2566
+ export const blackListAnnotations =
2567
+ (annotationIds: ReadonlyArray<symbol>) => (annotated: Annotated): Annotations | undefined => {
2568
+ const out = { ...annotated.annotations }
2569
+ for (const id of annotationIds) {
2570
+ delete out[id]
2571
+ }
2572
+ return out
2573
+ }
2574
+
2575
+ // To generate a JSON Schema from a recursive schema, an `identifier` annotation
2576
+ // is required. So, when we calculate the encodedAST, we need to preserve the
2577
+ // annotation in the form of an internal custom annotation that acts as a
2578
+ // surrogate for the identifier, which the JSON Schema compiler can then read.
2579
+ const createJSONIdentifierAnnotation = (annotated: Annotated): Annotations | undefined =>
2580
+ Option.match(getJSONIdentifier(annotated), {
2581
+ onNone: () => undefined,
2582
+ onSome: (identifier) => ({ [JSONIdentifierAnnotationId]: identifier })
2583
+ })
2584
+
2585
+ function changeMap<A>(
2586
+ as: Arr.NonEmptyReadonlyArray<A>,
2587
+ f: (a: A) => A
2588
+ ): Arr.NonEmptyReadonlyArray<A>
2589
+ function changeMap<A>(as: ReadonlyArray<A>, f: (a: A) => A): ReadonlyArray<A>
2590
+ function changeMap<A>(as: ReadonlyArray<A>, f: (a: A) => A): ReadonlyArray<A> {
2591
+ let changed = false
2592
+ const out = Arr.allocate(as.length) as Array<A>
2593
+ for (let i = 0; i < as.length; i++) {
2594
+ const a = as[i]
2595
+ const fa = f(a)
2596
+ if (fa !== a) {
2597
+ changed = true
2598
+ }
2599
+ out[i] = fa
2600
+ }
2601
+ return changed ? out : as
2602
+ }
2603
+
2604
+ const encodedAST_ = (ast: AST, isBound: boolean): AST => {
2605
+ switch (ast._tag) {
2606
+ case "Declaration": {
2607
+ const typeParameters = changeMap(ast.typeParameters, (ast) => encodedAST_(ast, isBound))
2608
+ return typeParameters === ast.typeParameters ?
2609
+ ast :
2610
+ new Declaration(typeParameters, ast.decodeUnknown, ast.encodeUnknown, ast.annotations)
2611
+ }
2612
+ case "TupleType": {
2613
+ const elements = changeMap(ast.elements, (e) => {
2614
+ const type = encodedAST_(e.type, isBound)
2615
+ return type === e.type ? e : new OptionalType(type, e.isOptional)
2616
+ })
2617
+ const restASTs = getRestASTs(ast.rest)
2618
+ const rest = changeMap(restASTs, (ast) => encodedAST_(ast, isBound))
2619
+ return elements === ast.elements && rest === restASTs ?
2620
+ ast :
2621
+ new TupleType(
2622
+ elements,
2623
+ rest.map((ast) => new Type(ast)),
2624
+ ast.isReadonly,
2625
+ createJSONIdentifierAnnotation(ast)
2626
+ )
2627
+ }
2628
+ case "TypeLiteral": {
2629
+ const propertySignatures = changeMap(ast.propertySignatures, (ps) => {
2630
+ const type = encodedAST_(ps.type, isBound)
2631
+ return type === ps.type
2632
+ ? ps
2633
+ : new PropertySignature(ps.name, type, ps.isOptional, ps.isReadonly)
2634
+ })
2635
+ const indexSignatures = changeMap(ast.indexSignatures, (is) => {
2636
+ const type = encodedAST_(is.type, isBound)
2637
+ return type === is.type ? is : new IndexSignature(is.parameter, type, is.isReadonly)
2638
+ })
2639
+ return propertySignatures === ast.propertySignatures && indexSignatures === ast.indexSignatures ?
2640
+ ast :
2641
+ new TypeLiteral(propertySignatures, indexSignatures, createJSONIdentifierAnnotation(ast))
2642
+ }
2643
+ case "Union": {
2644
+ const types = changeMap(ast.types, (ast) => encodedAST_(ast, isBound))
2645
+ return types === ast.types ? ast : Union.make(types, createJSONIdentifierAnnotation(ast))
2646
+ }
2647
+ case "Suspend":
2648
+ return new Suspend(() => encodedAST_(ast.f(), isBound), createJSONIdentifierAnnotation(ast))
2649
+ case "Refinement": {
2650
+ const from = encodedAST_(ast.from, isBound)
2651
+ if (isBound) {
2652
+ if (from === ast.from) {
2653
+ return ast
2654
+ }
2655
+ if (!isTransformation(ast.from) && hasStableFilter(ast)) {
2656
+ return new Refinement(from, ast.filter)
2657
+ }
2658
+ }
2659
+ return from
2660
+ }
2661
+ case "Transformation":
2662
+ return encodedAST_(ast.from, isBound)
2663
+ }
2664
+ return ast
2665
+ }
2666
+
2667
+ /**
2668
+ * @since 3.10.0
2669
+ */
2670
+ export const encodedAST = (ast: AST): AST => encodedAST_(ast, false)
2671
+
2672
+ /**
2673
+ * @since 3.10.0
2674
+ */
2675
+ export const encodedBoundAST = (ast: AST): AST => encodedAST_(ast, true)
2676
+
2677
+ const toJSONAnnotations = (annotations: Annotations): object => {
2678
+ const out: Record<string, unknown> = {}
2679
+ for (const k of Object.getOwnPropertySymbols(annotations)) {
2680
+ out[String(k)] = annotations[k]
2681
+ }
2682
+ return out
2683
+ }
2684
+
2685
+ /** @internal */
2686
+ export const getParameterBase = (
2687
+ ast: Parameter
2688
+ ): StringKeyword | SymbolKeyword | TemplateLiteral => {
2689
+ switch (ast._tag) {
2690
+ case "StringKeyword":
2691
+ case "SymbolKeyword":
2692
+ case "TemplateLiteral":
2693
+ return ast
2694
+ case "Refinement":
2695
+ return getParameterBase(ast.from)
2696
+ }
2697
+ }
2698
+
2699
+ const equalsTemplateLiteralSpan = Arr.getEquivalence<TemplateLiteralSpan>((self, that) =>
2700
+ self.type._tag === that.type._tag && self.literal === that.literal
2701
+ )
2702
+
2703
+ const equalsEnums = Arr.getEquivalence<readonly [string, string | number]>((self, that) =>
2704
+ that[0] === self[0] && that[1] === self[1]
2705
+ )
2706
+
2707
+ const equals = (self: AST, that: AST) => {
2708
+ switch (self._tag) {
2709
+ case "Literal":
2710
+ return isLiteral(that) && that.literal === self.literal
2711
+ case "UniqueSymbol":
2712
+ return isUniqueSymbol(that) && that.symbol === self.symbol
2713
+ case "UndefinedKeyword":
2714
+ case "VoidKeyword":
2715
+ case "NeverKeyword":
2716
+ case "UnknownKeyword":
2717
+ case "AnyKeyword":
2718
+ case "StringKeyword":
2719
+ case "NumberKeyword":
2720
+ case "BooleanKeyword":
2721
+ case "BigIntKeyword":
2722
+ case "SymbolKeyword":
2723
+ case "ObjectKeyword":
2724
+ return that._tag === self._tag
2725
+ case "TemplateLiteral":
2726
+ return isTemplateLiteral(that) && that.head === self.head && equalsTemplateLiteralSpan(that.spans, self.spans)
2727
+ case "Enums":
2728
+ return isEnums(that) && equalsEnums(that.enums, self.enums)
2729
+ case "Refinement":
2730
+ case "TupleType":
2731
+ case "TypeLiteral":
2732
+ case "Union":
2733
+ case "Suspend":
2734
+ case "Transformation":
2735
+ case "Declaration":
2736
+ return self === that
2737
+ }
2738
+ }
2739
+
2740
+ const intersection = Arr.intersectionWith(equals)
2741
+
2742
+ const _keyof = (ast: AST): Array<AST> => {
2743
+ switch (ast._tag) {
2744
+ case "Declaration": {
2745
+ const annotation = getSurrogateAnnotation(ast)
2746
+ if (Option.isSome(annotation)) {
2747
+ return _keyof(annotation.value)
2748
+ }
2749
+ break
2750
+ }
2751
+ case "TypeLiteral":
2752
+ return ast.propertySignatures.map((p): AST =>
2753
+ Predicate.isSymbol(p.name) ? new UniqueSymbol(p.name) : new Literal(p.name)
2754
+ ).concat(ast.indexSignatures.map((is) => getParameterBase(is.parameter)))
2755
+ case "Suspend":
2756
+ return _keyof(ast.f())
2757
+ case "Union":
2758
+ return ast.types.slice(1).reduce(
2759
+ (out: Array<AST>, ast) => intersection(out, _keyof(ast)),
2760
+ _keyof(ast.types[0])
2761
+ )
2762
+ case "Transformation":
2763
+ return _keyof(ast.to)
2764
+ }
2765
+ throw new Error(errors_.getASTUnsupportedSchema(ast))
2766
+ }
2767
+
2768
+ /** @internal */
2769
+ export const compose = (ab: AST, cd: AST): AST => new Transformation(ab, cd, composeTransformation)
2770
+
2771
+ /** @internal */
2772
+ export const rename = (ast: AST, mapping: { readonly [K in PropertyKey]?: PropertyKey }): AST => {
2773
+ switch (ast._tag) {
2774
+ case "TypeLiteral": {
2775
+ const propertySignatureTransformations: Array<PropertySignatureTransformation> = []
2776
+ for (const key of util_.ownKeys(mapping)) {
2777
+ const name = mapping[key]
2778
+ if (name !== undefined) {
2779
+ propertySignatureTransformations.push(
2780
+ new PropertySignatureTransformation(
2781
+ key,
2782
+ name,
2783
+ identity,
2784
+ identity
2785
+ )
2786
+ )
2787
+ }
2788
+ }
2789
+ if (propertySignatureTransformations.length === 0) {
2790
+ return ast
2791
+ }
2792
+ return new Transformation(
2793
+ ast,
2794
+ new TypeLiteral(
2795
+ ast.propertySignatures.map((ps) => {
2796
+ const name = mapping[ps.name]
2797
+ return new PropertySignature(
2798
+ name === undefined ? ps.name : name,
2799
+ typeAST(ps.type),
2800
+ ps.isOptional,
2801
+ ps.isReadonly,
2802
+ ps.annotations
2803
+ )
2804
+ }),
2805
+ ast.indexSignatures
2806
+ ),
2807
+ new TypeLiteralTransformation(propertySignatureTransformations)
2808
+ )
2809
+ }
2810
+ case "Union":
2811
+ return Union.make(ast.types.map((ast) => rename(ast, mapping)))
2812
+ case "Suspend":
2813
+ return new Suspend(() => rename(ast.f(), mapping))
2814
+ case "Transformation":
2815
+ return compose(ast, rename(typeAST(ast), mapping))
2816
+ }
2817
+ throw new Error(errors_.getASTUnsupportedRenameSchema(ast))
2818
+ }
2819
+
2820
+ const formatKeyword = (ast: AST): string => Option.getOrElse(getExpected(ast), () => ast._tag)
2821
+
2822
+ const getExpected = (ast: Annotated): Option.Option<string> => {
2823
+ return getIdentifierAnnotation(ast).pipe(
2824
+ Option.orElse(() => getTitleAnnotation(ast)),
2825
+ Option.orElse(() => getDescriptionAnnotation(ast))
2826
+ )
2827
+ }