effect 3.11.4 → 3.11.6

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 (49) hide show
  1. package/dist/cjs/Arbitrary.js +354 -343
  2. package/dist/cjs/Arbitrary.js.map +1 -1
  3. package/dist/cjs/Effect.js.map +1 -1
  4. package/dist/cjs/JSONSchema.js +226 -134
  5. package/dist/cjs/JSONSchema.js.map +1 -1
  6. package/dist/cjs/Schema.js +67 -32
  7. package/dist/cjs/Schema.js.map +1 -1
  8. package/dist/cjs/SchemaAST.js +34 -9
  9. package/dist/cjs/SchemaAST.js.map +1 -1
  10. package/dist/cjs/internal/core.js +6 -7
  11. package/dist/cjs/internal/core.js.map +1 -1
  12. package/dist/cjs/internal/schema/filters.js +24 -18
  13. package/dist/cjs/internal/schema/filters.js.map +1 -1
  14. package/dist/cjs/internal/version.js +1 -1
  15. package/dist/dts/Arbitrary.d.ts +21 -1
  16. package/dist/dts/Arbitrary.d.ts.map +1 -1
  17. package/dist/dts/Effect.d.ts +50 -19
  18. package/dist/dts/Effect.d.ts.map +1 -1
  19. package/dist/dts/JSONSchema.d.ts +57 -1
  20. package/dist/dts/JSONSchema.d.ts.map +1 -1
  21. package/dist/dts/Schema.d.ts +47 -19
  22. package/dist/dts/Schema.d.ts.map +1 -1
  23. package/dist/dts/SchemaAST.d.ts +1 -1
  24. package/dist/dts/SchemaAST.d.ts.map +1 -1
  25. package/dist/dts/internal/core.d.ts +5 -0
  26. package/dist/dts/internal/core.d.ts.map +1 -1
  27. package/dist/esm/Arbitrary.js +348 -335
  28. package/dist/esm/Arbitrary.js.map +1 -1
  29. package/dist/esm/Effect.js.map +1 -1
  30. package/dist/esm/JSONSchema.js +224 -133
  31. package/dist/esm/JSONSchema.js.map +1 -1
  32. package/dist/esm/Schema.js +67 -32
  33. package/dist/esm/Schema.js.map +1 -1
  34. package/dist/esm/SchemaAST.js +31 -7
  35. package/dist/esm/SchemaAST.js.map +1 -1
  36. package/dist/esm/internal/core.js +7 -6
  37. package/dist/esm/internal/core.js.map +1 -1
  38. package/dist/esm/internal/schema/filters.js +23 -17
  39. package/dist/esm/internal/schema/filters.js.map +1 -1
  40. package/dist/esm/internal/version.js +1 -1
  41. package/package.json +1 -1
  42. package/src/Arbitrary.ts +406 -360
  43. package/src/Effect.ts +68 -20
  44. package/src/JSONSchema.ts +233 -134
  45. package/src/Schema.ts +176 -74
  46. package/src/SchemaAST.ts +31 -7
  47. package/src/internal/core.ts +9 -6
  48. package/src/internal/schema/filters.ts +32 -17
  49. package/src/internal/version.ts +1 -1
@@ -26,39 +26,134 @@ export const makeLazy = schema => go(schema.ast, {
26
26
  */
27
27
  export const make = schema => makeLazy(schema)(FastCheck);
28
28
  const getArbitraryAnnotation = /*#__PURE__*/AST.getAnnotation(AST.ArbitraryAnnotationId);
29
- const getRefinementFromArbitrary = (ast, ctx, path) => {
30
- const constraints = combineConstraints(ctx.constraints, getConstraints(ast));
31
- return go(ast.from, constraints ? {
32
- ...ctx,
33
- constraints
34
- } : ctx, path);
29
+ /**
30
+ * Represents an arbitrary with optional filters.
31
+ */
32
+ class Succeed {
33
+ lazyArbitrary;
34
+ filters;
35
+ _tag = "Succeed";
36
+ constructor(lazyArbitrary, filters = []) {
37
+ this.lazyArbitrary = lazyArbitrary;
38
+ this.filters = filters;
39
+ }
40
+ toLazyArbitrary() {
41
+ return fc => {
42
+ let out = this.lazyArbitrary(fc);
43
+ for (const f of this.filters) {
44
+ out = out.filter(f);
45
+ }
46
+ return out;
47
+ };
48
+ }
49
+ }
50
+ /**
51
+ * Represents a deferred arbitrary value generator with optional filters.
52
+ */
53
+ class Deferred {
54
+ config;
55
+ filters;
56
+ _tag = "Deferred";
57
+ constructor(config, filters = []) {
58
+ this.config = config;
59
+ this.filters = filters;
60
+ }
61
+ toLazyArbitrary(ctx, path) {
62
+ const config = this.config;
63
+ switch (config._tag) {
64
+ case "StringConstraints":
65
+ {
66
+ const pattern = config.pattern;
67
+ return pattern !== undefined ? fc => fc.stringMatching(new RegExp(pattern)) : fc => fc.string(config.constraints);
68
+ }
69
+ case "NumberConstraints":
70
+ {
71
+ return config.isInteger ? fc => fc.integer(config.constraints) : fc => fc.float(config.constraints);
72
+ }
73
+ case "BigIntConstraints":
74
+ return fc => fc.bigInt(config.constraints);
75
+ case "ArrayConstraints":
76
+ return goTupleType(config.ast, ctx, path, config.constraints);
77
+ }
78
+ }
79
+ }
80
+ /** @internal */
81
+ export const makeStringConstraints = options => {
82
+ const out = {
83
+ _tag: "StringConstraints",
84
+ constraints: {}
85
+ };
86
+ if (Predicate.isNumber(options.minLength)) {
87
+ out.constraints.minLength = options.minLength;
88
+ }
89
+ if (Predicate.isNumber(options.maxLength)) {
90
+ out.constraints.maxLength = options.maxLength;
91
+ }
92
+ if (Predicate.isString(options.pattern)) {
93
+ out.pattern = options.pattern;
94
+ }
95
+ return out;
35
96
  };
36
- const getSuspendedContext = (ctx, ast) => {
37
- if (ctx.depthIdentifier !== undefined) {
38
- return ctx;
97
+ /** @internal */
98
+ export const makeNumberConstraints = options => {
99
+ const out = {
100
+ _tag: "NumberConstraints",
101
+ constraints: {},
102
+ isInteger: options.isInteger ?? false
103
+ };
104
+ if (Predicate.isNumber(options.min)) {
105
+ out.constraints.min = Math.fround(options.min);
39
106
  }
40
- const depthIdentifier = AST.getIdentifierAnnotation(ast).pipe(Option.orElse(() => AST.getIdentifierAnnotation(ast.f())), Option.getOrElse(() => "SuspendDefaultDepthIdentifier"));
41
- return {
42
- ...ctx,
43
- depthIdentifier
107
+ if (Predicate.isBoolean(options.minExcluded)) {
108
+ out.constraints.minExcluded = options.minExcluded;
109
+ }
110
+ if (Predicate.isNumber(options.max)) {
111
+ out.constraints.max = Math.fround(options.max);
112
+ }
113
+ if (Predicate.isBoolean(options.maxExcluded)) {
114
+ out.constraints.maxExcluded = options.maxExcluded;
115
+ }
116
+ if (Predicate.isBoolean(options.noNaN)) {
117
+ out.constraints.noNaN = options.noNaN;
118
+ }
119
+ if (Predicate.isBoolean(options.noDefaultInfinity)) {
120
+ out.constraints.noDefaultInfinity = options.noDefaultInfinity;
121
+ }
122
+ return out;
123
+ };
124
+ /** @internal */
125
+ export const makeBigIntConstraints = options => {
126
+ const out = {
127
+ _tag: "BigIntConstraints",
128
+ constraints: {}
44
129
  };
130
+ if (Predicate.isBigInt(options.min)) {
131
+ out.constraints.min = options.min;
132
+ }
133
+ if (Predicate.isBigInt(options.max)) {
134
+ out.constraints.max = options.max;
135
+ }
136
+ return out;
45
137
  };
46
- const getSuspendedArray = (fc, depthIdentifier, maxDepth, item, constraints) => {
47
- let minLength = 1;
48
- let maxLength = 2;
49
- if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) {
50
- minLength = constraints.minLength;
51
- if (minLength > maxLength) {
52
- maxLength = minLength;
53
- }
138
+ /** @internal */
139
+ export const makeArrayConstraints = options => {
140
+ const out = {
141
+ _tag: "ArrayConstraints",
142
+ constraints: {}
143
+ };
144
+ if (Predicate.isNumber(options.minLength)) {
145
+ out.constraints.minLength = options.minLength;
54
146
  }
55
- return fc.oneof({
56
- maxDepth,
57
- depthIdentifier
58
- }, fc.constant([]), fc.array(item, {
59
- minLength,
60
- maxLength
61
- }));
147
+ if (Predicate.isNumber(options.maxLength)) {
148
+ out.constraints.maxLength = options.maxLength;
149
+ }
150
+ return out;
151
+ };
152
+ const makeArrayConfig = (options, ast) => {
153
+ return {
154
+ ast,
155
+ ...makeArrayConstraints(options)
156
+ };
62
157
  };
63
158
  const go = (ast, ctx, path) => {
64
159
  const hook = getArbitraryAnnotation(ast);
@@ -67,152 +162,117 @@ const go = (ast, ctx, path) => {
67
162
  case "Declaration":
68
163
  return hook.value(...ast.typeParameters.map(p => go(p, ctx, path)), ctx);
69
164
  case "Refinement":
70
- return hook.value(getRefinementFromArbitrary(ast, ctx, path), ctx);
165
+ {
166
+ const op = toOp(ast, ctx, path);
167
+ ctx = op._tag === "Deferred" ? {
168
+ ...ctx,
169
+ constraints: op.config
170
+ } : ctx;
171
+ const from = go(ast.from, ctx, path);
172
+ return new Succeed(hook.value(from, ctx), op.filters).toLazyArbitrary();
173
+ }
71
174
  default:
72
175
  return hook.value(ctx);
73
176
  }
74
177
  }
178
+ const op = toOp(ast, ctx, path);
179
+ switch (op._tag) {
180
+ case "Succeed":
181
+ return op.toLazyArbitrary();
182
+ case "Deferred":
183
+ return new Succeed(op.toLazyArbitrary(ctx, path), op.filters).toLazyArbitrary();
184
+ }
185
+ };
186
+ const constStringConstraints = /*#__PURE__*/makeStringConstraints({});
187
+ const constNumberConstraints = /*#__PURE__*/makeNumberConstraints({});
188
+ const constBigIntConstraints = /*#__PURE__*/makeBigIntConstraints({});
189
+ /** @internal */
190
+ export const toOp = (ast, ctx, path) => {
75
191
  switch (ast._tag) {
76
192
  case "Declaration":
77
- {
78
- throw new Error(errors_.getArbitraryMissingAnnotationErrorMessage(path, ast));
79
- }
193
+ throw new Error(errors_.getArbitraryMissingAnnotationErrorMessage(path, ast));
80
194
  case "Literal":
81
- return fc => fc.constant(ast.literal);
195
+ return new Succeed(fc => fc.constant(ast.literal));
82
196
  case "UniqueSymbol":
83
- return fc => fc.constant(ast.symbol);
197
+ return new Succeed(fc => fc.constant(ast.symbol));
84
198
  case "UndefinedKeyword":
85
- return fc => fc.constant(undefined);
199
+ return new Succeed(fc => fc.constant(undefined));
86
200
  case "NeverKeyword":
87
- return () => {
88
- throw new Error(errors_.getArbitraryUnsupportedErrorMessage(path, ast));
89
- };
201
+ throw new Error(errors_.getArbitraryMissingAnnotationErrorMessage(path, ast));
202
+ case "VoidKeyword":
90
203
  case "UnknownKeyword":
91
204
  case "AnyKeyword":
92
- case "VoidKeyword":
93
- return fc => fc.anything();
205
+ return new Succeed(fc => fc.anything());
94
206
  case "StringKeyword":
95
- return fc => {
96
- if (ctx.constraints) {
97
- switch (ctx.constraints._tag) {
98
- case "StringConstraints":
99
- return fc.string(ctx.constraints.constraints);
100
- }
101
- }
102
- return fc.string();
103
- };
207
+ return new Deferred(constStringConstraints);
104
208
  case "NumberKeyword":
105
- return fc => {
106
- if (ctx.constraints) {
107
- switch (ctx.constraints._tag) {
108
- case "NumberConstraints":
109
- return fc.float(ctx.constraints.constraints);
110
- case "IntegerConstraints":
111
- return fc.integer(ctx.constraints.constraints);
112
- }
113
- }
114
- return fc.float();
115
- };
209
+ return new Deferred(constNumberConstraints);
116
210
  case "BooleanKeyword":
117
- return fc => fc.boolean();
211
+ return new Succeed(fc => fc.boolean());
118
212
  case "BigIntKeyword":
119
- return fc => {
120
- if (ctx.constraints) {
121
- switch (ctx.constraints._tag) {
122
- case "BigIntConstraints":
123
- return fc.bigInt(ctx.constraints.constraints);
124
- }
125
- }
126
- return fc.bigInt();
127
- };
213
+ return new Deferred(constBigIntConstraints);
128
214
  case "SymbolKeyword":
129
- return fc => fc.string().map(s => Symbol.for(s));
215
+ return new Succeed(fc => fc.string().map(s => Symbol.for(s)));
130
216
  case "ObjectKeyword":
131
- return fc => fc.oneof(fc.object(), fc.array(fc.anything()));
132
- case "TemplateLiteral":
217
+ return new Succeed(fc => fc.oneof(fc.object(), fc.array(fc.anything())));
218
+ case "Enums":
133
219
  {
134
- return fc => {
135
- const string = fc.string({
136
- maxLength: 5
137
- });
138
- const number = fc.float({
139
- noDefaultInfinity: true
140
- }).filter(n => !Number.isNaN(n));
141
- const components = ast.head !== "" ? [fc.constant(ast.head)] : [];
142
- const addArb = ast => {
143
- switch (ast._tag) {
144
- case "StringKeyword":
145
- return components.push(string);
146
- case "NumberKeyword":
147
- return components.push(number);
148
- case "Literal":
149
- return components.push(fc.constant(String(ast.literal)));
150
- case "Union":
151
- return ast.types.forEach(addArb);
152
- }
153
- };
154
- ast.spans.forEach(span => {
155
- addArb(span.type);
156
- if (span.literal !== "") {
157
- components.push(fc.constant(span.literal));
158
- }
159
- });
160
- return fc.tuple(...components).map(spans => spans.join(""));
161
- };
220
+ if (ast.enums.length === 0) {
221
+ throw new Error(errors_.getArbitraryEmptyEnumErrorMessage(path));
222
+ }
223
+ return new Succeed(fc => fc.oneof(...ast.enums.map(([_, value]) => fc.constant(value))));
162
224
  }
163
- case "TupleType":
164
- {
165
- const elements = [];
166
- let hasOptionals = false;
167
- let i = 0;
168
- for (const element of ast.elements) {
169
- elements.push(go(element.type, ctx, path.concat(i++)));
170
- if (element.isOptional) {
171
- hasOptionals = true;
225
+ case "TemplateLiteral":
226
+ return new Succeed(fc => {
227
+ const string = fc.string({
228
+ maxLength: 5
229
+ });
230
+ const number = fc.float({
231
+ noDefaultInfinity: true
232
+ }).filter(n => !Number.isNaN(n));
233
+ const components = ast.head !== "" ? [fc.constant(ast.head)] : [];
234
+ const addArb = ast => {
235
+ switch (ast._tag) {
236
+ case "StringKeyword":
237
+ return components.push(string);
238
+ case "NumberKeyword":
239
+ return components.push(number);
240
+ case "Literal":
241
+ return components.push(fc.constant(String(ast.literal)));
242
+ case "Union":
243
+ return ast.types.forEach(addArb);
172
244
  }
173
- }
174
- const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, ctx, path));
175
- return fc => {
176
- // ---------------------------------------------
177
- // handle elements
178
- // ---------------------------------------------
179
- let output = fc.tuple(...elements.map(arb => arb(fc)));
180
- if (hasOptionals) {
181
- const indexes = fc.tuple(...ast.elements.map(element => element.isOptional ? fc.boolean() : fc.constant(true)));
182
- output = output.chain(tuple => indexes.map(booleans => {
183
- for (const [i, b] of booleans.reverse().entries()) {
184
- if (!b) {
185
- tuple.splice(booleans.length - i, 1);
186
- }
187
- }
188
- return tuple;
189
- }));
245
+ };
246
+ ast.spans.forEach(span => {
247
+ addArb(span.type);
248
+ if (span.literal !== "") {
249
+ components.push(fc.constant(span.literal));
190
250
  }
191
- // ---------------------------------------------
192
- // handle rest element
193
- // ---------------------------------------------
194
- if (Arr.isNonEmptyReadonlyArray(rest)) {
195
- const [head, ...tail] = rest;
196
- const item = head(fc);
197
- const constraints = ctx.constraints && ctx.constraints._tag === "ArrayConstraints" ? ctx.constraints.constraints : undefined;
198
- output = output.chain(as => {
199
- return (ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints) : fc.array(item, constraints)).map(rest => [...as, ...rest]);
200
- });
201
- // ---------------------------------------------
202
- // handle post rest elements
203
- // ---------------------------------------------
204
- for (let j = 0; j < tail.length; j++) {
205
- output = output.chain(as => tail[j](fc).map(a => [...as, a]));
251
+ });
252
+ return fc.tuple(...components).map(spans => spans.join(""));
253
+ });
254
+ case "Refinement":
255
+ {
256
+ const from = toOp(ast.from, ctx, path);
257
+ const filters = [...from.filters, a => Option.isNone(ast.filter(a, AST.defaultParseOption, ast))];
258
+ switch (from._tag) {
259
+ case "Succeed":
260
+ {
261
+ return new Succeed(from.lazyArbitrary, filters);
206
262
  }
207
- }
208
- return output;
209
- };
263
+ case "Deferred":
264
+ {
265
+ return new Deferred(merge(from.config, getConstraints(from.config._tag, ast)), filters);
266
+ }
267
+ }
210
268
  }
269
+ case "TupleType":
270
+ return new Deferred(makeArrayConfig({}, ast));
211
271
  case "TypeLiteral":
212
272
  {
213
273
  const propertySignaturesTypes = ast.propertySignatures.map(ps => go(ps.type, ctx, path.concat(ps.name)));
214
274
  const indexSignatures = ast.indexSignatures.map(is => [go(is.parameter, ctx, path), go(is.type, ctx, path)]);
215
- return fc => {
275
+ return new Succeed(fc => {
216
276
  const arbs = {};
217
277
  const requiredKeys = [];
218
278
  // ---------------------------------------------
@@ -245,238 +305,191 @@ const go = (ast, ctx, path) => {
245
305
  });
246
306
  }
247
307
  return output;
248
- };
308
+ });
249
309
  }
250
310
  case "Union":
251
311
  {
252
312
  const types = ast.types.map(member => go(member, ctx, path));
253
- return fc => fc.oneof(...types.map(arb => arb(fc)));
254
- }
255
- case "Enums":
256
- {
257
- if (ast.enums.length === 0) {
258
- throw new Error(errors_.getArbitraryEmptyEnumErrorMessage(path));
259
- }
260
- return fc => fc.oneof(...ast.enums.map(([_, value]) => fc.constant(value)));
261
- }
262
- case "Refinement":
263
- {
264
- const from = getRefinementFromArbitrary(ast, ctx, path);
265
- return fc => from(fc).filter(a => Option.isNone(ast.filter(a, AST.defaultParseOption, ast)));
313
+ return new Succeed(fc => fc.oneof(...types.map(arb => arb(fc))));
266
314
  }
267
315
  case "Suspend":
268
316
  {
269
317
  const get = util_.memoizeThunk(() => {
270
318
  return go(ast.f(), getSuspendedContext(ctx, ast), path);
271
319
  });
272
- return fc => fc.constant(null).chain(() => get()(fc));
320
+ return new Succeed(fc => fc.constant(null).chain(() => get()(fc)));
273
321
  }
274
322
  case "Transformation":
275
- return go(ast.to, ctx, path);
323
+ return new Succeed(go(ast.to, ctx, path));
276
324
  }
277
325
  };
278
- /** @internal */
279
- export class NumberConstraints {
280
- _tag = "NumberConstraints";
281
- constraints;
282
- constructor(options) {
283
- this.constraints = {};
284
- if (Predicate.isNumber(options.min)) {
285
- this.constraints.min = Math.fround(options.min);
286
- }
287
- if (Predicate.isNumber(options.max)) {
288
- this.constraints.max = Math.fround(options.max);
289
- }
290
- if (Predicate.isBoolean(options.noNaN)) {
291
- this.constraints.noNaN = options.noNaN;
292
- }
293
- if (Predicate.isBoolean(options.noDefaultInfinity)) {
294
- this.constraints.noDefaultInfinity = options.noDefaultInfinity;
326
+ const goTupleType = (ast, ctx, path, constraints) => {
327
+ const elements = [];
328
+ let hasOptionals = false;
329
+ let i = 0;
330
+ for (const element of ast.elements) {
331
+ elements.push(go(element.type, ctx, path.concat(i++)));
332
+ if (element.isOptional) {
333
+ hasOptionals = true;
295
334
  }
296
335
  }
297
- }
298
- /** @internal */
299
- export class StringConstraints {
300
- _tag = "StringConstraints";
301
- constraints;
302
- constructor(options) {
303
- this.constraints = {};
304
- if (Predicate.isNumber(options.minLength)) {
305
- this.constraints.minLength = options.minLength;
306
- }
307
- if (Predicate.isNumber(options.maxLength)) {
308
- this.constraints.maxLength = options.maxLength;
309
- }
310
- }
311
- }
312
- /** @internal */
313
- export class IntegerConstraints {
314
- _tag = "IntegerConstraints";
315
- constraints;
316
- constructor(options) {
317
- this.constraints = {};
318
- if (Predicate.isNumber(options.min)) {
319
- this.constraints.min = options.min;
320
- }
321
- if (Predicate.isNumber(options.max)) {
322
- this.constraints.max = options.max;
323
- }
324
- }
325
- }
326
- /** @internal */
327
- export class ArrayConstraints {
328
- _tag = "ArrayConstraints";
329
- constraints;
330
- constructor(options) {
331
- this.constraints = {};
332
- if (Predicate.isNumber(options.minLength)) {
333
- this.constraints.minLength = options.minLength;
334
- }
335
- if (Predicate.isNumber(options.maxLength)) {
336
- this.constraints.maxLength = options.maxLength;
337
- }
338
- }
339
- }
340
- /** @internal */
341
- export class BigIntConstraints {
342
- _tag = "BigIntConstraints";
343
- constraints;
344
- constructor(options) {
345
- this.constraints = {};
346
- if (Predicate.isBigInt(options.min)) {
347
- this.constraints.min = options.min;
336
+ const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, ctx, path));
337
+ return fc => {
338
+ // ---------------------------------------------
339
+ // handle elements
340
+ // ---------------------------------------------
341
+ let output = fc.tuple(...elements.map(arb => arb(fc)));
342
+ if (hasOptionals) {
343
+ const indexes = fc.tuple(...ast.elements.map(element => element.isOptional ? fc.boolean() : fc.constant(true)));
344
+ output = output.chain(tuple => indexes.map(booleans => {
345
+ for (const [i, b] of booleans.reverse().entries()) {
346
+ if (!b) {
347
+ tuple.splice(booleans.length - i, 1);
348
+ }
349
+ }
350
+ return tuple;
351
+ }));
348
352
  }
349
- if (Predicate.isBigInt(options.max)) {
350
- this.constraints.max = options.max;
353
+ // ---------------------------------------------
354
+ // handle rest element
355
+ // ---------------------------------------------
356
+ if (Arr.isNonEmptyReadonlyArray(rest)) {
357
+ const [head, ...tail] = rest;
358
+ const item = head(fc);
359
+ output = output.chain(as => {
360
+ return (ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints) : fc.array(item, constraints)).map(rest => [...as, ...rest]);
361
+ });
362
+ // ---------------------------------------------
363
+ // handle post rest elements
364
+ // ---------------------------------------------
365
+ for (let j = 0; j < tail.length; j++) {
366
+ output = output.chain(as => tail[j](fc).map(a => [...as, a]));
367
+ }
351
368
  }
352
- }
353
- }
354
- /** @internal */
355
- export const getConstraints = ast => {
369
+ return output;
370
+ };
371
+ };
372
+ const getConstraints = (_tag, ast) => {
356
373
  const TypeAnnotationId = ast.annotations[AST.SchemaIdAnnotationId];
357
- const jsonSchema = ast.annotations[AST.JSONSchemaAnnotationId];
358
- switch (TypeAnnotationId) {
359
- // int
360
- case filters_.IntSchemaId:
361
- return new IntegerConstraints({});
362
- // number
363
- case filters_.GreaterThanSchemaId:
364
- case filters_.GreaterThanOrEqualToSchemaId:
365
- case filters_.LessThanSchemaId:
366
- case filters_.LessThanOrEqualToSchemaId:
367
- case filters_.BetweenSchemaId:
368
- return new NumberConstraints({
369
- min: jsonSchema.exclusiveMinimum ?? jsonSchema.minimum,
370
- max: jsonSchema.exclusiveMaximum ?? jsonSchema.maximum
371
- });
372
- // bigint
373
- case filters_.GreaterThanBigintSchemaId:
374
- case filters_.GreaterThanOrEqualToBigIntSchemaId:
375
- case filters_.LessThanBigIntSchemaId:
376
- case filters_.LessThanOrEqualToBigIntSchemaId:
377
- case filters_.BetweenBigintSchemaId:
374
+ const jsonSchema = Option.getOrElse(AST.getJSONSchemaAnnotation(ast), () => ({}));
375
+ switch (_tag) {
376
+ case "StringConstraints":
377
+ return makeStringConstraints(jsonSchema);
378
+ case "NumberConstraints":
378
379
  {
379
- const constraints = ast.annotations[TypeAnnotationId];
380
- return new BigIntConstraints(constraints);
380
+ switch (TypeAnnotationId) {
381
+ case filters_.NonNaNSchemaId:
382
+ return makeNumberConstraints({
383
+ noNaN: true
384
+ });
385
+ default:
386
+ return makeNumberConstraints({
387
+ isInteger: "type" in jsonSchema && jsonSchema.type === "integer",
388
+ noNaN: "type" in jsonSchema && jsonSchema.type === "number" ? true : undefined,
389
+ noDefaultInfinity: "type" in jsonSchema && jsonSchema.type === "number" ? true : undefined,
390
+ min: jsonSchema.exclusiveMinimum ?? jsonSchema.minimum,
391
+ minExcluded: "exclusiveMinimum" in jsonSchema ? true : undefined,
392
+ max: jsonSchema.exclusiveMaximum ?? jsonSchema.maximum,
393
+ maxExcluded: "exclusiveMaximum" in jsonSchema ? true : undefined
394
+ });
395
+ }
381
396
  }
382
- // string
383
- case filters_.MinLengthSchemaId:
384
- case filters_.MaxLengthSchemaId:
385
- case filters_.LengthSchemaId:
386
- return new StringConstraints(jsonSchema);
387
- // array
388
- case filters_.MinItemsSchemaId:
389
- case filters_.MaxItemsSchemaId:
390
- case filters_.ItemsCountSchemaId:
391
- return new ArrayConstraints({
397
+ case "BigIntConstraints":
398
+ return makeBigIntConstraints(ast.annotations[TypeAnnotationId]);
399
+ case "ArrayConstraints":
400
+ return makeArrayConstraints({
392
401
  minLength: jsonSchema.minItems,
393
402
  maxLength: jsonSchema.maxItems
394
403
  });
395
404
  }
396
405
  };
397
- /** @internal */
398
- export const combineConstraints = (c1, c2) => {
399
- if (c1 === undefined) {
400
- return c2;
401
- }
402
- if (c2 === undefined) {
403
- return c1;
404
- }
405
- switch (c1._tag) {
406
- case "ArrayConstraints":
407
- {
408
- switch (c2._tag) {
409
- case "ArrayConstraints":
410
- return new ArrayConstraints({
406
+ function getMax(n1, n2) {
407
+ return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n2 : n1;
408
+ }
409
+ function getMin(n1, n2) {
410
+ return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n1 : n2;
411
+ }
412
+ const getOr = (a, b) => {
413
+ return a === undefined ? b : b === undefined ? a : a || b;
414
+ };
415
+ const merge = (c1, c2) => {
416
+ if (c2) {
417
+ switch (c1._tag) {
418
+ case "StringConstraints":
419
+ {
420
+ if (c2._tag === "StringConstraints") {
421
+ return makeStringConstraints({
411
422
  minLength: getMax(c1.constraints.minLength, c2.constraints.minLength),
412
- maxLength: getMin(c1.constraints.maxLength, c2.constraints.maxLength)
423
+ maxLength: getMin(c1.constraints.maxLength, c2.constraints.maxLength),
424
+ pattern: c1.pattern ?? c2.pattern
413
425
  });
426
+ }
427
+ break;
414
428
  }
415
- break;
416
- }
417
- case "NumberConstraints":
418
- {
419
- switch (c2._tag) {
420
- case "NumberConstraints":
421
- return new NumberConstraints({
429
+ case "NumberConstraints":
430
+ {
431
+ if (c2._tag === "NumberConstraints") {
432
+ return makeNumberConstraints({
433
+ isInteger: c1.isInteger || c2.isInteger,
422
434
  min: getMax(c1.constraints.min, c2.constraints.min),
435
+ minExcluded: getOr(c1.constraints.minExcluded, c2.constraints.minExcluded),
423
436
  max: getMin(c1.constraints.max, c2.constraints.max),
437
+ maxExcluded: getOr(c1.constraints.maxExcluded, c2.constraints.maxExcluded),
424
438
  noNaN: getOr(c1.constraints.noNaN, c2.constraints.noNaN),
425
439
  noDefaultInfinity: getOr(c1.constraints.noDefaultInfinity, c2.constraints.noDefaultInfinity)
426
440
  });
427
- case "IntegerConstraints":
428
- return new IntegerConstraints({
429
- min: getMax(c1.constraints.min, c2.constraints.min),
430
- max: getMin(c1.constraints.max, c2.constraints.max)
431
- });
441
+ }
442
+ break;
432
443
  }
433
- break;
434
- }
435
- case "BigIntConstraints":
436
- {
437
- switch (c2._tag) {
438
- case "BigIntConstraints":
439
- return new BigIntConstraints({
444
+ case "BigIntConstraints":
445
+ {
446
+ if (c2._tag === "BigIntConstraints") {
447
+ return makeBigIntConstraints({
440
448
  min: getMax(c1.constraints.min, c2.constraints.min),
441
449
  max: getMin(c1.constraints.max, c2.constraints.max)
442
450
  });
451
+ }
452
+ break;
443
453
  }
444
- break;
445
- }
446
- case "StringConstraints":
447
- {
448
- switch (c2._tag) {
449
- case "StringConstraints":
450
- return new StringConstraints({
454
+ case "ArrayConstraints":
455
+ {
456
+ if (c2._tag === "ArrayConstraints") {
457
+ return makeArrayConfig({
451
458
  minLength: getMax(c1.constraints.minLength, c2.constraints.minLength),
452
459
  maxLength: getMin(c1.constraints.maxLength, c2.constraints.maxLength)
453
- });
454
- }
455
- break;
456
- }
457
- case "IntegerConstraints":
458
- {
459
- switch (c2._tag) {
460
- case "NumberConstraints":
461
- case "IntegerConstraints":
462
- {
463
- return new IntegerConstraints({
464
- min: getMax(c1.constraints.min, c2.constraints.min),
465
- max: getMin(c1.constraints.max, c2.constraints.max)
466
- });
467
- }
460
+ }, c1.ast);
461
+ }
462
+ break;
468
463
  }
469
- break;
470
- }
464
+ }
471
465
  }
466
+ return c1;
472
467
  };
473
- const getOr = (a, b) => {
474
- return a === undefined ? b : b === undefined ? a : a || b;
468
+ const getSuspendedArray = (fc, depthIdentifier, maxDepth, item, constraints) => {
469
+ let minLength = 1;
470
+ let maxLength = 2;
471
+ if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) {
472
+ minLength = constraints.minLength;
473
+ if (minLength > maxLength) {
474
+ maxLength = minLength;
475
+ }
476
+ }
477
+ return fc.oneof({
478
+ maxDepth,
479
+ depthIdentifier
480
+ }, fc.constant([]), fc.array(item, {
481
+ minLength,
482
+ maxLength
483
+ }));
484
+ };
485
+ const getSuspendedContext = (ctx, ast) => {
486
+ if (ctx.depthIdentifier !== undefined) {
487
+ return ctx;
488
+ }
489
+ const depthIdentifier = AST.getIdentifierAnnotation(ast).pipe(Option.orElse(() => AST.getIdentifierAnnotation(ast.f())), Option.getOrElse(() => "SuspendDefaultDepthIdentifier"));
490
+ return {
491
+ ...ctx,
492
+ depthIdentifier
493
+ };
475
494
  };
476
- function getMax(n1, n2) {
477
- return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n2 : n1;
478
- }
479
- function getMin(n1, n2) {
480
- return n1 === undefined ? n2 : n2 === undefined ? n1 : n1 <= n2 ? n1 : n2;
481
- }
482
495
  //# sourceMappingURL=Arbitrary.js.map