@amritk/generate-examples 0.6.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI.md +19 -0
- package/README.md +56 -1
- package/dist/generators/assert-generator-depth.d.ts +28 -0
- package/dist/generators/assert-generator-depth.js +10 -0
- package/dist/generators/closed-value-set.d.ts +14 -0
- package/dist/generators/closed-value-set.js +20 -0
- package/dist/generators/collect-example-imports.js +9 -3
- package/dist/generators/derive-example.js +154 -89
- package/dist/generators/generate-arbitrary.js +187 -96
- package/dist/generators/generate-files.js +3 -2
- package/dist/generators/is-object-like.d.ts +47 -0
- package/dist/generators/is-object-like.js +23 -0
- package/dist/generators/satisfies-scalar-constraints.d.ts +17 -0
- package/dist/generators/satisfies-scalar-constraints.js +34 -0
- package/dist/generators/schema-validation.d.ts +12 -0
- package/dist/generators/schema-validation.js +70 -9
- package/package.json +3 -3
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { getMjstInstanceOf, getMjstPrimitive } from "@amritk/helpers/mjst-extension";
|
|
2
|
+
import { readKey } from "@amritk/helpers/read-key";
|
|
2
3
|
import { resolveRef } from "@amritk/helpers/resolve-ref";
|
|
3
4
|
import { hasAdditionalProperties, hasAllOf, hasAnyOf, hasConst, hasDefault, hasDependentRequired, hasDependentSchemas, hasEnum, hasExamples, hasExclusiveMaximum, hasExclusiveMinimum, hasFormat, hasItems, hasMaxItems, hasMaximum, hasMaxLength, hasMaxProperties, hasMinItems, hasMinimum, hasMinLength, hasMinProperties, hasMultipleOf, hasOneOf, hasPattern, hasPatternProperties, hasProperties, hasPropertyNames, hasRef, hasRequired, hasType, hasUniqueItems, isSchemaObject } from "@amritk/helpers/schema-guards";
|
|
5
|
+
import { assertGeneratorDepth } from "./assert-generator-depth.js";
|
|
6
|
+
import { closedValueSet } from "./closed-value-set.js";
|
|
7
|
+
import { declaresOwnShape, isObjectLike, typesConflict } from "./is-object-like.js";
|
|
8
|
+
import { satisfiesScalarConstraints } from "./satisfies-scalar-constraints.js";
|
|
4
9
|
import { makeInstanceCheck, needsValidationFilter } from "./schema-validation.js";
|
|
5
10
|
const lowerFirst = (name) => name.charAt(0).toLowerCase() + name.slice(1);
|
|
6
11
|
const exampleName = (typeName) => `${lowerFirst(typeName)}Example`;
|
|
@@ -67,6 +72,13 @@ const topLevelAlternatives = (s) => {
|
|
|
67
72
|
parts.push(cur);
|
|
68
73
|
return parts;
|
|
69
74
|
};
|
|
75
|
+
const matchesPattern = (pattern, value) => {
|
|
76
|
+
try {
|
|
77
|
+
return new RegExp(pattern).test(value);
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
70
82
|
const sampleFromPattern = (pattern, minLength) => {
|
|
71
83
|
let body = pattern;
|
|
72
84
|
if (body.startsWith("^"))
|
|
@@ -178,16 +190,17 @@ const FORMAT_EXAMPLES = {
|
|
|
178
190
|
// The `regex` format asks for a string that *compiles* as a regular expression.
|
|
179
191
|
regex: "^example$"
|
|
180
192
|
};
|
|
193
|
+
const MAX_DERIVED_SIZE = 1e4;
|
|
181
194
|
const exampleString = (schema) => {
|
|
182
195
|
if (hasFormat(schema)) {
|
|
183
|
-
const formatted = FORMAT_EXAMPLES
|
|
196
|
+
const formatted = readKey(FORMAT_EXAMPLES, schema.format);
|
|
184
197
|
if (formatted !== void 0)
|
|
185
198
|
return formatted;
|
|
186
199
|
}
|
|
187
|
-
const minLength = hasMinLength(schema) ? schema.minLength : 0;
|
|
200
|
+
const minLength = Math.min(hasMinLength(schema) ? schema.minLength : 0, MAX_DERIVED_SIZE);
|
|
188
201
|
if (hasPattern(schema)) {
|
|
189
202
|
const sampled = sampleFromPattern(schema.pattern, minLength);
|
|
190
|
-
if (sampled !== void 0 && sampled.length >= minLength &&
|
|
203
|
+
if (sampled !== void 0 && sampled.length >= minLength && matchesPattern(schema.pattern, sampled)) {
|
|
191
204
|
if (!(hasMaxLength(schema) && sampled.length > schema.maxLength))
|
|
192
205
|
return sampled;
|
|
193
206
|
}
|
|
@@ -204,7 +217,9 @@ const newContext = (rootSchema) => ({
|
|
|
204
217
|
rootSchema,
|
|
205
218
|
values: /* @__PURE__ */ new Map(),
|
|
206
219
|
active: /* @__PURE__ */ new Set(),
|
|
207
|
-
cycleBroken: false
|
|
220
|
+
cycleBroken: false,
|
|
221
|
+
needsAssertion: false,
|
|
222
|
+
depth: 0
|
|
208
223
|
});
|
|
209
224
|
const contextFor = (rootSchema) => {
|
|
210
225
|
if (rootSchema === void 0)
|
|
@@ -216,52 +231,76 @@ const contextFor = (rootSchema) => {
|
|
|
216
231
|
contexts.set(rootSchema, created);
|
|
217
232
|
return created;
|
|
218
233
|
};
|
|
219
|
-
const deriveExample = (schema, rootSchema) =>
|
|
234
|
+
const deriveExample = (schema, rootSchema) => deriveReported(schema, rootSchema).value;
|
|
235
|
+
const deriveReported = (schema, rootSchema) => {
|
|
220
236
|
const ctx = contextFor(rootSchema);
|
|
221
237
|
ctx.active.clear();
|
|
222
238
|
ctx.cycleBroken = false;
|
|
223
|
-
|
|
239
|
+
ctx.needsAssertion = false;
|
|
240
|
+
ctx.depth = 0;
|
|
241
|
+
const value = derive(schema, ctx);
|
|
242
|
+
return { value, needsAssertion: ctx.needsAssertion, cycleBroken: ctx.cycleBroken };
|
|
224
243
|
};
|
|
225
244
|
const derive = (schema, ctx) => {
|
|
245
|
+
assertGeneratorDepth(ctx.depth, "deriveExample");
|
|
226
246
|
if (!isSchemaObject(schema))
|
|
227
247
|
return null;
|
|
228
|
-
|
|
229
|
-
|
|
248
|
+
ctx.depth++;
|
|
249
|
+
try {
|
|
250
|
+
const base = deriveBase(schema, ctx);
|
|
251
|
+
return needsValidationFilter(schema) ? refineExample(schema, base, ctx) : base;
|
|
252
|
+
} finally {
|
|
253
|
+
ctx.depth--;
|
|
254
|
+
}
|
|
230
255
|
};
|
|
231
256
|
const deriveRef = (ref, ctx) => {
|
|
232
257
|
if (ctx.active.has(ref)) {
|
|
233
258
|
ctx.cycleBroken = true;
|
|
234
259
|
return null;
|
|
235
260
|
}
|
|
236
|
-
|
|
237
|
-
|
|
261
|
+
const memoized = ctx.values.get(ref);
|
|
262
|
+
if (memoized !== void 0) {
|
|
263
|
+
if (memoized.needsAssertion)
|
|
264
|
+
ctx.needsAssertion = true;
|
|
265
|
+
return memoized.value;
|
|
266
|
+
}
|
|
238
267
|
if (!ctx.rootSchema)
|
|
239
268
|
return null;
|
|
240
269
|
const resolved = resolveRef(ref, ctx.rootSchema);
|
|
241
270
|
if (!resolved)
|
|
242
271
|
return null;
|
|
243
272
|
const outerBroken = ctx.cycleBroken;
|
|
273
|
+
const outerUndeclared = ctx.needsAssertion;
|
|
244
274
|
ctx.cycleBroken = false;
|
|
275
|
+
ctx.needsAssertion = false;
|
|
245
276
|
ctx.active.add(ref);
|
|
246
277
|
try {
|
|
247
278
|
const value = derive(resolved, ctx);
|
|
248
279
|
if (!ctx.cycleBroken)
|
|
249
|
-
ctx.values.set(ref, value);
|
|
280
|
+
ctx.values.set(ref, { value, needsAssertion: ctx.needsAssertion });
|
|
250
281
|
ctx.cycleBroken = outerBroken || ctx.cycleBroken;
|
|
282
|
+
ctx.needsAssertion = outerUndeclared || ctx.needsAssertion;
|
|
251
283
|
return value;
|
|
252
284
|
} finally {
|
|
253
285
|
ctx.active.delete(ref);
|
|
254
286
|
}
|
|
255
287
|
};
|
|
288
|
+
const authoredHint = (schema) => {
|
|
289
|
+
if (hasExamples(schema) && Array.isArray(schema.examples) && schema.examples.length > 0) {
|
|
290
|
+
return { value: schema.examples[0] };
|
|
291
|
+
}
|
|
292
|
+
if (hasDefault(schema))
|
|
293
|
+
return { value: schema.default };
|
|
294
|
+
return void 0;
|
|
295
|
+
};
|
|
256
296
|
const deriveBase = (schema, ctx) => {
|
|
257
297
|
if (!isSchemaObject(schema))
|
|
258
298
|
return null;
|
|
259
299
|
if (hasConst(schema))
|
|
260
300
|
return schema.const;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return schema.default;
|
|
301
|
+
const hint = authoredHint(schema);
|
|
302
|
+
if (hint !== void 0 && makeInstanceCheck(schema, ctx.rootSchema)(hint.value))
|
|
303
|
+
return hint.value;
|
|
265
304
|
if (hasEnum(schema) && schema.enum.length > 0) {
|
|
266
305
|
const fitting = schema.enum.find((value) => satisfiesScalarConstraints(schema, value));
|
|
267
306
|
return fitting !== void 0 ? fitting : schema.enum[0];
|
|
@@ -276,10 +315,16 @@ const deriveBase = (schema, ctx) => {
|
|
|
276
315
|
return 0n;
|
|
277
316
|
if (hasAllOf(schema))
|
|
278
317
|
return derive(mergeAllOf(schema), ctx);
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
318
|
+
const branches = hasOneOf(schema) ? schema.oneOf : hasAnyOf(schema) ? schema.anyOf : void 0;
|
|
319
|
+
if (branches !== void 0 && branches.length > 0) {
|
|
320
|
+
const rest = withoutCombinators(schema);
|
|
321
|
+
if (!declaresOwnShape(rest))
|
|
322
|
+
return derive(branches[0], ctx);
|
|
323
|
+
const chosen = branches.find((branch) => !typesConflict(rest, branch)) ?? branches[0];
|
|
324
|
+
return derive({ allOf: [rest, chosen] }, ctx);
|
|
325
|
+
}
|
|
326
|
+
if (isObjectLike(schema))
|
|
327
|
+
return deriveObject(schema, ctx);
|
|
283
328
|
if (hasType(schema))
|
|
284
329
|
return deriveForType(schema.type, schema, ctx);
|
|
285
330
|
if (Array.isArray(schema.type) && schema.type.length > 0) {
|
|
@@ -287,6 +332,12 @@ const deriveBase = (schema, ctx) => {
|
|
|
287
332
|
}
|
|
288
333
|
return null;
|
|
289
334
|
};
|
|
335
|
+
const withoutCombinators = (schema) => {
|
|
336
|
+
const rest = { ...schema };
|
|
337
|
+
delete rest["oneOf"];
|
|
338
|
+
delete rest["anyOf"];
|
|
339
|
+
return rest;
|
|
340
|
+
};
|
|
290
341
|
const REFINED_APPLICATORS = ["if", "then", "else", "not", "oneOf"];
|
|
291
342
|
const structuralOnly = (schema) => {
|
|
292
343
|
const clone = { ...schema };
|
|
@@ -336,26 +387,6 @@ const refineExample = (schema, base, ctx) => {
|
|
|
336
387
|
return candidate;
|
|
337
388
|
return base;
|
|
338
389
|
};
|
|
339
|
-
const satisfiesScalarConstraints = (schema, value) => {
|
|
340
|
-
if (typeof value === "string") {
|
|
341
|
-
if (hasMinLength(schema) && value.length < schema.minLength)
|
|
342
|
-
return false;
|
|
343
|
-
if (hasMaxLength(schema) && value.length > schema.maxLength)
|
|
344
|
-
return false;
|
|
345
|
-
} else if (typeof value === "number") {
|
|
346
|
-
if (hasMinimum(schema) && value < schema.minimum)
|
|
347
|
-
return false;
|
|
348
|
-
if (hasMaximum(schema) && value > schema.maximum)
|
|
349
|
-
return false;
|
|
350
|
-
if (hasExclusiveMinimum(schema) && value <= schema.exclusiveMinimum)
|
|
351
|
-
return false;
|
|
352
|
-
if (hasExclusiveMaximum(schema) && value >= schema.exclusiveMaximum)
|
|
353
|
-
return false;
|
|
354
|
-
if (hasMultipleOf(schema) && schema.multipleOf > 0 && value % schema.multipleOf !== 0)
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
return true;
|
|
358
|
-
};
|
|
359
390
|
const deriveForType = (type, schema, ctx) => {
|
|
360
391
|
switch (type) {
|
|
361
392
|
case "string":
|
|
@@ -396,6 +427,15 @@ const deriveObject = (schema, ctx) => {
|
|
|
396
427
|
const additionalClosed = hasAdditionalProperties(schema) && schema.additionalProperties === false;
|
|
397
428
|
const extrasAllowed = !additionalClosed || patternEntries.length > 0;
|
|
398
429
|
const nameCheck = hasPropertyNames(schema) ? makeInstanceCheck(schema.propertyNames, ctx.rootSchema) : void 0;
|
|
430
|
+
const declaredKeys = new Set(hasProperties(schema) ? Object.keys(schema.properties) : []);
|
|
431
|
+
const hasIndexSignature = additionalSchema !== void 0 || hasPatternProperties(schema) && Object.keys(schema.patternProperties).length > 0;
|
|
432
|
+
const noteKey = (key) => {
|
|
433
|
+
if (!hasIndexSignature && !declaredKeys.has(key))
|
|
434
|
+
ctx.needsAssertion = true;
|
|
435
|
+
};
|
|
436
|
+
const raw = schema;
|
|
437
|
+
if (Object.hasOwn(raw, "if") && Object.hasOwn(raw, "then"))
|
|
438
|
+
ctx.needsAssertion = true;
|
|
399
439
|
const valueSchemaFor = (key) => {
|
|
400
440
|
const matches = patternEntries.filter(([re]) => re.test(key)).map(([, sub]) => sub);
|
|
401
441
|
if (matches.length === 1)
|
|
@@ -408,6 +448,7 @@ const deriveObject = (schema, ctx) => {
|
|
|
408
448
|
const sub = valueSchemaFor(key);
|
|
409
449
|
if (sub === void 0 && additionalClosed)
|
|
410
450
|
return;
|
|
451
|
+
noteKey(key);
|
|
411
452
|
setProperty(out, key, sub !== void 0 ? derive(sub, ctx) : null);
|
|
412
453
|
};
|
|
413
454
|
if (hasProperties(schema)) {
|
|
@@ -416,9 +457,10 @@ const deriveObject = (schema, ctx) => {
|
|
|
416
457
|
}
|
|
417
458
|
}
|
|
418
459
|
if (hasRequired(schema)) {
|
|
419
|
-
for (const key of schema.required)
|
|
420
|
-
if (!Object.hasOwn(out, key))
|
|
460
|
+
for (const key of schema.required) {
|
|
461
|
+
if (typeof key === "string" && !Object.hasOwn(out, key))
|
|
421
462
|
addKey(key);
|
|
463
|
+
}
|
|
422
464
|
}
|
|
423
465
|
if (hasDependentRequired(schema)) {
|
|
424
466
|
for (const [trigger, deps] of Object.entries(schema.dependentRequired)) {
|
|
@@ -432,63 +474,78 @@ const deriveObject = (schema, ctx) => {
|
|
|
432
474
|
if (hasDependentSchemas(schema)) {
|
|
433
475
|
for (const [trigger, sub] of Object.entries(schema.dependentSchemas)) {
|
|
434
476
|
if (Object.hasOwn(out, trigger) && isSchemaObject(sub))
|
|
435
|
-
applyDependentSchema(out, sub, ctx);
|
|
477
|
+
applyDependentSchema(out, sub, ctx, noteKey);
|
|
436
478
|
}
|
|
437
479
|
}
|
|
438
480
|
if (hasMinProperties(schema) && extrasAllowed) {
|
|
481
|
+
const target = Math.min(schema.minProperties, MAX_DERIVED_SIZE);
|
|
482
|
+
let count = Object.keys(out).length;
|
|
439
483
|
let n = 0;
|
|
440
|
-
let
|
|
441
|
-
while (
|
|
484
|
+
let attempts = 0;
|
|
485
|
+
while (count < target && attempts++ < target + 50) {
|
|
442
486
|
const key = synthKey(n++, patternEntries, schema, nameCheck);
|
|
443
|
-
if (key === void 0
|
|
487
|
+
if (key === void 0)
|
|
488
|
+
break;
|
|
489
|
+
if (Object.hasOwn(out, key))
|
|
444
490
|
continue;
|
|
445
491
|
addKey(key);
|
|
492
|
+
if (Object.hasOwn(out, key))
|
|
493
|
+
count++;
|
|
446
494
|
}
|
|
447
495
|
}
|
|
448
496
|
if (hasMaxProperties(schema))
|
|
449
497
|
enforceMaxProperties(out, schema, schema.maxProperties);
|
|
450
498
|
return out;
|
|
451
499
|
};
|
|
452
|
-
const applyDependentSchema = (out, sub, ctx) => {
|
|
500
|
+
const applyDependentSchema = (out, sub, ctx, noteKey) => {
|
|
501
|
+
const add = (key, propSchema) => {
|
|
502
|
+
noteKey(key);
|
|
503
|
+
setProperty(out, key, propSchema !== void 0 ? derive(propSchema, ctx) : null);
|
|
504
|
+
};
|
|
453
505
|
if (hasProperties(sub)) {
|
|
454
506
|
for (const [key, propSchema] of Object.entries(sub.properties)) {
|
|
455
507
|
if (!Object.hasOwn(out, key))
|
|
456
|
-
|
|
508
|
+
add(key, propSchema);
|
|
457
509
|
}
|
|
458
510
|
}
|
|
459
511
|
if (hasRequired(sub)) {
|
|
460
512
|
const propSchemas = hasProperties(sub) ? sub.properties : {};
|
|
461
513
|
for (const key of sub.required) {
|
|
462
|
-
if (Object.hasOwn(out, key))
|
|
514
|
+
if (typeof key !== "string" || Object.hasOwn(out, key))
|
|
463
515
|
continue;
|
|
464
|
-
|
|
465
|
-
setProperty(out, key, propSchema !== void 0 ? derive(propSchema, ctx) : null);
|
|
516
|
+
add(key, propSchemas[key]);
|
|
466
517
|
}
|
|
467
518
|
}
|
|
468
519
|
};
|
|
520
|
+
const MAX_SYNTH_KEY_LENGTH = 64;
|
|
469
521
|
const synthKey = (i, patternEntries, schema, nameCheck) => {
|
|
470
|
-
const
|
|
522
|
+
const variants = (seed) => i === 0 ? [seed] : [`${seed}${i}`, seed.repeat(i + 1)].filter((key) => key.length <= MAX_SYNTH_KEY_LENGTH);
|
|
471
523
|
const seeds = [];
|
|
472
524
|
for (const [re] of patternEntries) {
|
|
473
525
|
const sampled = sampleFromPattern(re.source, 0);
|
|
474
|
-
if (sampled !== void 0 && sampled.length > 0)
|
|
475
|
-
seeds.push(
|
|
526
|
+
if (sampled !== void 0 && sampled.length > 0) {
|
|
527
|
+
seeds.push({ seed: sampled, matches: (key) => re.test(key) });
|
|
528
|
+
}
|
|
476
529
|
}
|
|
477
530
|
const propertyNames = isSchemaObject(schema) && hasPropertyNames(schema) ? schema.propertyNames : void 0;
|
|
478
531
|
if (propertyNames !== void 0 && isSchemaObject(propertyNames) && hasPattern(propertyNames)) {
|
|
479
532
|
const sampled = sampleFromPattern(propertyNames.pattern, 0);
|
|
480
533
|
if (sampled !== void 0 && sampled.length > 0)
|
|
481
|
-
seeds.push(
|
|
534
|
+
seeds.push({ seed: sampled, matches: () => true });
|
|
482
535
|
}
|
|
483
|
-
seeds.push(
|
|
484
|
-
for (const seed of seeds) {
|
|
485
|
-
|
|
486
|
-
|
|
536
|
+
seeds.push({ seed: "extra", matches: () => true });
|
|
537
|
+
for (const { seed, matches } of seeds) {
|
|
538
|
+
for (const key of variants(seed)) {
|
|
539
|
+
if (matches(key) && (!nameCheck || nameCheck(key)))
|
|
540
|
+
return key;
|
|
541
|
+
}
|
|
487
542
|
}
|
|
488
543
|
return void 0;
|
|
489
544
|
};
|
|
490
545
|
const enforceMaxProperties = (out, schema, max) => {
|
|
491
|
-
|
|
546
|
+
const keys = Object.keys(out);
|
|
547
|
+
let count = keys.length;
|
|
548
|
+
if (count <= max)
|
|
492
549
|
return;
|
|
493
550
|
const protectedKeys = new Set(hasRequired(schema) ? schema.required : []);
|
|
494
551
|
if (hasDependentRequired(schema)) {
|
|
@@ -498,11 +555,13 @@ const enforceMaxProperties = (out, schema, max) => {
|
|
|
498
555
|
protectedKeys.add(dep);
|
|
499
556
|
}
|
|
500
557
|
}
|
|
501
|
-
for (const key of
|
|
502
|
-
if (
|
|
558
|
+
for (const key of keys) {
|
|
559
|
+
if (count <= max)
|
|
503
560
|
break;
|
|
504
|
-
if (
|
|
505
|
-
|
|
561
|
+
if (protectedKeys.has(key))
|
|
562
|
+
continue;
|
|
563
|
+
delete out[key];
|
|
564
|
+
count--;
|
|
506
565
|
}
|
|
507
566
|
};
|
|
508
567
|
const deriveNumber = (schema, isInteger) => {
|
|
@@ -516,7 +575,7 @@ const deriveNumber = (schema, isInteger) => {
|
|
|
516
575
|
let value = Number.isFinite(lo) ? lo : Number.isFinite(hi) ? Math.min(0, hi) : 0;
|
|
517
576
|
if (isInteger)
|
|
518
577
|
value = Math.ceil(value);
|
|
519
|
-
if (hasMultipleOf(schema) && schema.multipleOf > 0) {
|
|
578
|
+
if (hasMultipleOf(schema) && Number.isFinite(schema.multipleOf) && schema.multipleOf > 0) {
|
|
520
579
|
const m = schema.multipleOf;
|
|
521
580
|
value = Math.ceil(value / m - 1e-9) * m;
|
|
522
581
|
if (value > hi && Number.isFinite(hi))
|
|
@@ -551,35 +610,27 @@ const deriveArray = (schema, ctx) => {
|
|
|
551
610
|
const unique = hasUniqueItems(schema) && schema.uniqueItems === true;
|
|
552
611
|
const elem = rest ?? contains;
|
|
553
612
|
const choices = unique && contains === void 0 ? closedValueSet(elem) : void 0;
|
|
554
|
-
const wanted = Math.min(Math.max(min, minContains, max === 0 ? 0 : 1), max);
|
|
613
|
+
const wanted = Math.min(Math.max(min, minContains, max === 0 ? 0 : 1), max, MAX_DERIVED_SIZE);
|
|
555
614
|
const count = choices !== void 0 ? Math.min(wanted, choices.length) : wanted;
|
|
615
|
+
const itemsCheck = rest !== void 0 && contains !== void 0 ? makeInstanceCheck(rest, ctx.rootSchema) : void 0;
|
|
556
616
|
const result = [];
|
|
557
617
|
for (let i = 0; i < count; i++) {
|
|
558
618
|
if (choices !== void 0) {
|
|
559
619
|
result.push(choices[i]);
|
|
560
620
|
continue;
|
|
561
621
|
}
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
|
|
622
|
+
const useContains = contains !== void 0 && i < minContains;
|
|
623
|
+
const itemSchema = useContains ? contains : elem;
|
|
624
|
+
let chosen = itemSchema;
|
|
625
|
+
let base = itemSchema !== void 0 ? derive(itemSchema, ctx) : null;
|
|
626
|
+
if (useContains && itemsCheck !== void 0 && !itemsCheck(base)) {
|
|
627
|
+
chosen = rest;
|
|
628
|
+
base = rest !== void 0 ? derive(rest, ctx) : null;
|
|
629
|
+
}
|
|
630
|
+
result.push(unique ? distinctify(base, i, chosen) : base);
|
|
565
631
|
}
|
|
566
632
|
return result;
|
|
567
633
|
};
|
|
568
|
-
const closedValueSet = (schema) => {
|
|
569
|
-
if (schema === void 0 || !isSchemaObject(schema))
|
|
570
|
-
return void 0;
|
|
571
|
-
if (hasConst(schema))
|
|
572
|
-
return [schema.const];
|
|
573
|
-
if (hasEnum(schema)) {
|
|
574
|
-
const fitting = schema.enum.filter((value) => satisfiesScalarConstraints(schema, value));
|
|
575
|
-
return fitting.length > 0 ? fitting : [...schema.enum];
|
|
576
|
-
}
|
|
577
|
-
if (hasType(schema) && schema.type === "boolean")
|
|
578
|
-
return [true, false];
|
|
579
|
-
if (hasType(schema) && schema.type === "null")
|
|
580
|
-
return [null];
|
|
581
|
-
return void 0;
|
|
582
|
-
};
|
|
583
634
|
const distinctify = (base, i, itemSchema) => {
|
|
584
635
|
if (i === 0)
|
|
585
636
|
return base;
|
|
@@ -605,10 +656,20 @@ const TIGHTEST = /* @__PURE__ */ new Map([
|
|
|
605
656
|
["maxItems", "min"],
|
|
606
657
|
["maxProperties", "min"]
|
|
607
658
|
]);
|
|
659
|
+
const flattenBranches = (nodes, depth = 0) => {
|
|
660
|
+
assertGeneratorDepth(depth, "mergeAllOf");
|
|
661
|
+
return nodes.flatMap((node) => {
|
|
662
|
+
if (!isSchemaObject(node) || !hasAllOf(node))
|
|
663
|
+
return [node];
|
|
664
|
+
const own = { ...node };
|
|
665
|
+
delete own["allOf"];
|
|
666
|
+
return [...flattenBranches(node.allOf, depth + 1), own];
|
|
667
|
+
});
|
|
668
|
+
};
|
|
608
669
|
const mergeAllOf = (schema) => {
|
|
609
|
-
const branches = hasAllOf(schema) ? schema.allOf : [];
|
|
610
|
-
const merged =
|
|
611
|
-
const properties =
|
|
670
|
+
const branches = hasAllOf(schema) ? flattenBranches(schema.allOf) : [];
|
|
671
|
+
const merged = /* @__PURE__ */ Object.create(null);
|
|
672
|
+
const properties = /* @__PURE__ */ Object.create(null);
|
|
612
673
|
const required = /* @__PURE__ */ new Set();
|
|
613
674
|
for (const branch of [...branches, schema]) {
|
|
614
675
|
if (!isSchemaObject(branch))
|
|
@@ -636,7 +697,7 @@ const mergeAllOf = (schema) => {
|
|
|
636
697
|
}
|
|
637
698
|
}
|
|
638
699
|
}
|
|
639
|
-
const mergedProps =
|
|
700
|
+
const mergedProps = /* @__PURE__ */ Object.create(null);
|
|
640
701
|
for (const [prop, schemas] of Object.entries(properties)) {
|
|
641
702
|
mergedProps[prop] = schemas.length === 1 ? schemas[0] : { allOf: schemas };
|
|
642
703
|
}
|
|
@@ -671,9 +732,13 @@ const warnInvalidExample = (schema, typeName, value, rootSchema) => {
|
|
|
671
732
|
console.warn(`Warning: the derived example for ${typeName} does not validate against its own schema \u2014 ${quoted}. It is emitted anyway so the file still compiles, but treat it as a placeholder: either the schema has no instance, or it uses a constraint the deriver cannot satisfy structurally (see the README's "Known limits"). ${arbitraryName(typeName)} is unaffected.`);
|
|
672
733
|
};
|
|
673
734
|
const generateExampleConst = (schema, typeName, rootSchema) => {
|
|
674
|
-
const value =
|
|
735
|
+
const { value, needsAssertion, cycleBroken } = deriveReported(schema, rootSchema);
|
|
675
736
|
warnInvalidExample(schema, typeName, value, rootSchema);
|
|
676
|
-
|
|
737
|
+
const literal = serializeValue(value);
|
|
738
|
+
const admitsNothing = schema === false;
|
|
739
|
+
const assertion = cycleBroken || admitsNothing ? ` as unknown as ${typeName}` : needsAssertion ? ` as ${typeName}` : "";
|
|
740
|
+
const expression = `${literal}${assertion}`;
|
|
741
|
+
return `export const ${exampleName(typeName)}: ${typeName} = ${expression}`;
|
|
677
742
|
};
|
|
678
743
|
export {
|
|
679
744
|
deriveExample,
|