@amritk/generate-examples 0.5.1 → 0.5.3
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/LICENSE +21 -0
- package/dist/generators/build-schema.js +23 -50
- package/dist/generators/collect-example-imports.js +64 -94
- package/dist/generators/derive-example.js +507 -680
- package/dist/generators/find-schema-cycles.js +91 -115
- package/dist/generators/generate-arbitrary.js +316 -471
- package/dist/generators/generate-files.js +28 -45
- package/dist/generators/schema-validation.js +55 -78
- package/dist/index.js +10 -3
- package/package.json +4 -4
|
@@ -1,46 +1,29 @@
|
|
|
1
|
-
import { generateTypeDefinition } from
|
|
2
|
-
import { collectExampleImports } from
|
|
3
|
-
import { generateExampleConst } from
|
|
4
|
-
import { generateArbitrary, VALIDATE_IMPORT_NAME, VALIDATE_IMPORT_STATEMENT } from
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
typeSuffix,
|
|
30
|
-
});
|
|
31
|
-
const typeDefinition = generateTypeDefinition(schema, typeName, { typeSuffix });
|
|
32
|
-
const arbitrary = generateArbitrary(schema, typeName, typeSuffix, options?.lazyRefFilenames, options?.rootSchema);
|
|
33
|
-
const example = generateExampleConst(schema, typeName, options?.rootSchema);
|
|
34
|
-
let result = `import * as fc from 'fast-check'\n`;
|
|
35
|
-
// The arbitrary embeds a runtime validator only for schemas whose keywords no
|
|
36
|
-
// `fc.*` combinator captures; import it just for those files.
|
|
37
|
-
if (arbitrary.includes(`${VALIDATE_IMPORT_NAME}(`)) {
|
|
38
|
-
result += VALIDATE_IMPORT_STATEMENT + '\n';
|
|
39
|
-
}
|
|
40
|
-
for (const imp of refImports) {
|
|
41
|
-
result += imp + '\n';
|
|
42
|
-
}
|
|
43
|
-
result += '\n';
|
|
44
|
-
result += typeDefinition + '\n\n' + arbitrary + '\n\n' + example + '\n';
|
|
45
|
-
return result;
|
|
1
|
+
import { generateTypeDefinition } from "@amritk/helpers/generate-type-definition";
|
|
2
|
+
import { collectExampleImports } from "./collect-example-imports.js";
|
|
3
|
+
import { generateExampleConst } from "./derive-example.js";
|
|
4
|
+
import { generateArbitrary, VALIDATE_IMPORT_NAME, VALIDATE_IMPORT_STATEMENT } from "./generate-arbitrary.js";
|
|
5
|
+
const generateExampleFile = (schema, typeName, options) => {
|
|
6
|
+
const typeSuffix = options?.typeSuffix ?? "";
|
|
7
|
+
const refImports = collectExampleImports(schema, {
|
|
8
|
+
selfRef: options?.selfRef,
|
|
9
|
+
rootSchema: options?.rootSchema,
|
|
10
|
+
typeSuffix
|
|
11
|
+
});
|
|
12
|
+
const typeDefinition = generateTypeDefinition(schema, typeName, { typeSuffix });
|
|
13
|
+
const arbitrary = generateArbitrary(schema, typeName, typeSuffix, options?.lazyRefFilenames, options?.rootSchema);
|
|
14
|
+
const example = generateExampleConst(schema, typeName, options?.rootSchema);
|
|
15
|
+
let result = `import * as fc from 'fast-check'
|
|
16
|
+
`;
|
|
17
|
+
if (arbitrary.includes(`${VALIDATE_IMPORT_NAME}(`)) {
|
|
18
|
+
result += VALIDATE_IMPORT_STATEMENT + "\n";
|
|
19
|
+
}
|
|
20
|
+
for (const imp of refImports) {
|
|
21
|
+
result += imp + "\n";
|
|
22
|
+
}
|
|
23
|
+
result += "\n";
|
|
24
|
+
result += typeDefinition + "\n\n" + arbitrary + "\n\n" + example + "\n";
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
generateExampleFile
|
|
46
29
|
};
|
|
@@ -1,83 +1,60 @@
|
|
|
1
|
-
import { isSchemaObject } from
|
|
2
|
-
import { validateGuard } from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'dependentRequired',
|
|
18
|
-
'dependentSchemas',
|
|
19
|
-
'dependencies',
|
|
20
|
-
'minProperties',
|
|
21
|
-
'maxProperties',
|
|
22
|
-
'contains',
|
|
1
|
+
import { isSchemaObject } from "@amritk/helpers/schema-guards";
|
|
2
|
+
import { validateGuard } from "@amritk/runtime-validators";
|
|
3
|
+
const FILTER_KEYWORDS = /* @__PURE__ */ new Set([
|
|
4
|
+
"if",
|
|
5
|
+
"then",
|
|
6
|
+
"else",
|
|
7
|
+
"not",
|
|
8
|
+
"oneOf",
|
|
9
|
+
"patternProperties",
|
|
10
|
+
"propertyNames",
|
|
11
|
+
"dependentRequired",
|
|
12
|
+
"dependentSchemas",
|
|
13
|
+
"dependencies",
|
|
14
|
+
"minProperties",
|
|
15
|
+
"maxProperties",
|
|
16
|
+
"contains"
|
|
23
17
|
]);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (node === null || typeof node !== 'object')
|
|
42
|
-
return false;
|
|
43
|
-
const obj = node;
|
|
44
|
-
for (const key of Object.keys(obj)) {
|
|
45
|
-
if (FILTER_KEYWORDS.has(key))
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
49
|
-
if (SKIP_RECURSE.has(key))
|
|
50
|
-
continue;
|
|
51
|
-
if (walk(value))
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
};
|
|
56
|
-
return walk(schema);
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Returns `schema` augmented with the root document's `$defs`/`definitions` so its
|
|
60
|
-
* local `$ref`s (`#/$defs/…`) resolve when it is validated in isolation. The
|
|
61
|
-
* schema's own definitions win on collision.
|
|
62
|
-
*/
|
|
63
|
-
export const withResolvableDefs = (schema, rootSchema) => {
|
|
64
|
-
const base = isSchemaObject(schema) ? { ...schema } : { const: schema };
|
|
65
|
-
if (!rootSchema)
|
|
66
|
-
return base;
|
|
67
|
-
for (const key of ['$defs', 'definitions']) {
|
|
68
|
-
const rootDefs = rootSchema[key];
|
|
69
|
-
if (rootDefs && typeof rootDefs === 'object') {
|
|
70
|
-
base[key] = { ...rootDefs, ...(base[key] ?? {}) };
|
|
71
|
-
}
|
|
18
|
+
const SKIP_RECURSE = /* @__PURE__ */ new Set(["enum", "const", "examples", "default", "$ref", "required", "$defs", "definitions"]);
|
|
19
|
+
const needsValidationFilter = (schema) => {
|
|
20
|
+
const walk = (node) => {
|
|
21
|
+
if (Array.isArray(node))
|
|
22
|
+
return node.some(walk);
|
|
23
|
+
if (node === null || typeof node !== "object")
|
|
24
|
+
return false;
|
|
25
|
+
const obj = node;
|
|
26
|
+
for (const key of Object.keys(obj)) {
|
|
27
|
+
if (FILTER_KEYWORDS.has(key))
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
31
|
+
if (SKIP_RECURSE.has(key))
|
|
32
|
+
continue;
|
|
33
|
+
if (walk(value))
|
|
34
|
+
return true;
|
|
72
35
|
}
|
|
36
|
+
return false;
|
|
37
|
+
};
|
|
38
|
+
return walk(schema);
|
|
39
|
+
};
|
|
40
|
+
const withResolvableDefs = (schema, rootSchema) => {
|
|
41
|
+
const base = isSchemaObject(schema) ? { ...schema } : { const: schema };
|
|
42
|
+
if (!rootSchema)
|
|
73
43
|
return base;
|
|
44
|
+
for (const key of ["$defs", "definitions"]) {
|
|
45
|
+
const rootDefs = rootSchema[key];
|
|
46
|
+
if (rootDefs && typeof rootDefs === "object") {
|
|
47
|
+
base[key] = { ...rootDefs, ...base[key] ?? {} };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return base;
|
|
51
|
+
};
|
|
52
|
+
const makeInstanceCheck = (schema, rootSchema) => {
|
|
53
|
+
const guard = validateGuard(withResolvableDefs(schema, rootSchema));
|
|
54
|
+
return (value) => guard(value) === true;
|
|
74
55
|
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*/
|
|
80
|
-
export const makeInstanceCheck = (schema, rootSchema) => {
|
|
81
|
-
const guard = validateGuard(withResolvableDefs(schema, rootSchema));
|
|
82
|
-
return (value) => guard(value) === true;
|
|
56
|
+
export {
|
|
57
|
+
makeInstanceCheck,
|
|
58
|
+
needsValidationFilter,
|
|
59
|
+
withResolvableDefs
|
|
83
60
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { buildExampleSchema } from "./generators/build-schema.js";
|
|
2
|
+
import { deriveExample, generateExampleConst, serializeValue } from "./generators/derive-example.js";
|
|
3
|
+
import { generateArbitrary } from "./generators/generate-arbitrary.js";
|
|
4
|
+
export {
|
|
5
|
+
buildExampleSchema,
|
|
6
|
+
deriveExample,
|
|
7
|
+
generateArbitrary,
|
|
8
|
+
generateExampleConst,
|
|
9
|
+
serializeValue
|
|
10
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amritk/generate-examples",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Generate fast-check arbitraries and example values from JSON Schemas.",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"build": "tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f",
|
|
35
|
+
"build": "tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs",
|
|
36
36
|
"types:check": "tsgo -p . --noEmit",
|
|
37
37
|
"test": "NODE_ENV=production vitest run --root ../.. generate-examples"
|
|
38
38
|
},
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"json-schema-typed": "^8.0.1",
|
|
50
|
-
"@amritk/helpers": "0.13.
|
|
51
|
-
"@amritk/runtime-validators": "0.7.
|
|
50
|
+
"@amritk/helpers": "0.13.3",
|
|
51
|
+
"@amritk/runtime-validators": "0.7.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"ajv": "^8.17.1"
|