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