@amritk/generate-parsers 0.16.3 → 0.17.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/dist/generators/assert-supported-keywords.js +45 -72
- package/dist/generators/build-schema.js +56 -168
- package/dist/generators/generate-default-from-pattern.js +24 -31
- package/dist/generators/generate-discriminated-union-validation.js +27 -47
- package/dist/generators/generate-enum-check.js +27 -61
- package/dist/generators/generate-files.js +54 -83
- package/dist/generators/generate-non-discriminated-union-validation.js +24 -26
- package/dist/generators/generate-parser-function.d.ts +12 -0
- package/dist/generators/generate-parser-function.js +1132 -1711
- package/dist/generators/generate-schema-checks.js +216 -250
- package/dist/generators/generate-strict-assertion.js +311 -447
- package/dist/generators/generate-type-checks.js +287 -460
- package/dist/generators/generate-validation-expression.js +300 -439
- package/dist/generators/subschema-match.js +201 -266
- package/dist/helpers/apply-schema-extensions.js +18 -49
- package/dist/helpers/collect-helpers.js +58 -71
- package/dist/helpers/collect-imports.js +161 -237
- package/dist/helpers/find-discriminator.js +23 -29
- package/dist/helpers/get-default-value.js +76 -96
- package/dist/helpers/get-discriminator-value.js +16 -17
- package/dist/index.js +4 -1
- package/package.json +4 -4
|
@@ -1,86 +1,57 @@
|
|
|
1
|
-
import { generateTypeDefinition } from
|
|
2
|
-
import { collectHelpers
|
|
3
|
-
import { collectImports, collectImportTypeNames } from
|
|
4
|
-
import { generateParserFunction, generateShapeValidator } from
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* age: { type: "number" }
|
|
23
|
-
* },
|
|
24
|
-
* required: ["name"]
|
|
25
|
-
* };
|
|
26
|
-
*
|
|
27
|
-
* const result = generateFile(schema, "User");
|
|
28
|
-
* // result contains imports, type User, and parseUser function
|
|
29
|
-
*
|
|
30
|
-
* const typesOnly = generateFile(schema, "User", { typesOnly: true });
|
|
31
|
-
* // typesOnly contains only type-only imports and type User (no parser)
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export const generateFile = (schema, typeName, options) => {
|
|
35
|
-
const typesOnly = options?.typesOnly === true;
|
|
36
|
-
const selfRef = options?.selfRef;
|
|
37
|
-
const rootSchema = options?.rootSchema;
|
|
38
|
-
const helpersMode = options?.helpersMode ?? 'package';
|
|
39
|
-
const typeSuffix = options?.typeSuffix ?? '';
|
|
40
|
-
const importExt = options?.importExt ?? 'js';
|
|
41
|
-
const typeDefinition = generateTypeDefinition(schema, typeName, { readonly: options?.readonly ?? false, typeSuffix });
|
|
42
|
-
if (typesOnly) {
|
|
43
|
-
// In types-only mode, skip the parser function and use type-only imports
|
|
44
|
-
const imports = collectImports(schema, { typesOnly: true, selfRef, rootSchema, typeSuffix, importExt });
|
|
45
|
-
let result = '';
|
|
46
|
-
if (imports.length > 0) {
|
|
47
|
-
result += imports[0];
|
|
48
|
-
for (let i = 1; i < imports.length; i++) {
|
|
49
|
-
result += '\n' + imports[i];
|
|
50
|
-
}
|
|
51
|
-
result += '\n\n';
|
|
52
|
-
}
|
|
53
|
-
return { content: result + typeDefinition, usedHelpers: new Set() };
|
|
1
|
+
import { generateTypeDefinition } from "@amritk/helpers/generate-type-definition";
|
|
2
|
+
import { collectHelpers } from "../helpers/collect-helpers.js";
|
|
3
|
+
import { collectImports, collectImportTypeNames } from "../helpers/collect-imports.js";
|
|
4
|
+
import { generateParserFunction, generateShapeValidator } from "./generate-parser-function.js";
|
|
5
|
+
const generateFile = (schema, typeName, options) => {
|
|
6
|
+
const typesOnly = options?.typesOnly === true;
|
|
7
|
+
const selfRef = options?.selfRef;
|
|
8
|
+
const rootSchema = options?.rootSchema;
|
|
9
|
+
const helpersMode = options?.helpersMode ?? "package";
|
|
10
|
+
const typeSuffix = options?.typeSuffix ?? "";
|
|
11
|
+
const importExt = options?.importExt ?? "js";
|
|
12
|
+
const typeDefinition = generateTypeDefinition(schema, typeName, { readonly: options?.readonly ?? false, typeSuffix });
|
|
13
|
+
if (typesOnly) {
|
|
14
|
+
const imports2 = collectImports(schema, { typesOnly: true, selfRef, rootSchema, typeSuffix, importExt });
|
|
15
|
+
let result2 = "";
|
|
16
|
+
if (imports2.length > 0) {
|
|
17
|
+
result2 += imports2[0];
|
|
18
|
+
for (let i = 1; i < imports2.length; i++) {
|
|
19
|
+
result2 += "\n" + imports2[i];
|
|
20
|
+
}
|
|
21
|
+
result2 += "\n\n";
|
|
54
22
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
result += '\n\n';
|
|
23
|
+
return { content: result2 + typeDefinition, usedHelpers: /* @__PURE__ */ new Set() };
|
|
24
|
+
}
|
|
25
|
+
const stripUnknown = options?.stripUnknown ?? false;
|
|
26
|
+
const reservedNames = collectImportTypeNames(schema, { selfRef, rootSchema, typeSuffix });
|
|
27
|
+
const shapeValidator = generateShapeValidator(schema, typeName, true, typeSuffix, true, stripUnknown, reservedNames);
|
|
28
|
+
const parserFunction = generateParserFunction(schema, typeName, {
|
|
29
|
+
useRefImports: true,
|
|
30
|
+
typeSuffix,
|
|
31
|
+
reservedNames,
|
|
32
|
+
shapeValidatorSource: shapeValidator,
|
|
33
|
+
...options?.isRoot !== void 0 ? { isRoot: options.isRoot } : {},
|
|
34
|
+
...rootSchema !== void 0 ? { rootSchema } : {},
|
|
35
|
+
...options?.logWarnings !== void 0 ? { logWarnings: options.logWarnings } : {},
|
|
36
|
+
...options?.strict !== void 0 ? { strict: options.strict } : {},
|
|
37
|
+
...options?.stripUnknown !== void 0 ? { stripUnknown: options.stripUnknown } : {},
|
|
38
|
+
...options?.caseInsensitive !== void 0 ? { caseInsensitive: options.caseInsensitive } : {}
|
|
39
|
+
});
|
|
40
|
+
const combinedFunctions = `${shapeValidator}
|
|
41
|
+
|
|
42
|
+
${parserFunction}`;
|
|
43
|
+
const helpers = collectHelpers(combinedFunctions, helpersMode, options?.helpersImportPrefix, importExt);
|
|
44
|
+
const imports = [...collectImports(schema, { selfRef, rootSchema, typeSuffix, importExt }), ...helpers.imports];
|
|
45
|
+
let result = "";
|
|
46
|
+
if (imports.length > 0) {
|
|
47
|
+
result += imports[0];
|
|
48
|
+
for (let i = 1; i < imports.length; i++) {
|
|
49
|
+
result += "\n" + imports[i];
|
|
84
50
|
}
|
|
85
|
-
|
|
51
|
+
result += "\n\n";
|
|
52
|
+
}
|
|
53
|
+
return { content: result + typeDefinition + "\n\n" + combinedFunctions, usedHelpers: helpers.used };
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
generateFile
|
|
86
57
|
};
|
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
import { generateSchemaChecks } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
for (let i = 1; i < checks.length; i++) {
|
|
13
|
-
combinedChecks += ' && ' + checks[i];
|
|
14
|
-
}
|
|
15
|
-
cases.push('(' + combinedChecks + ')');
|
|
16
|
-
}
|
|
1
|
+
import { generateSchemaChecks } from "./generate-schema-checks.js";
|
|
2
|
+
const generateNonDiscriminatedUnionValidation = (accessor, schemas, defaultValue, isRequired) => {
|
|
3
|
+
const cases = [];
|
|
4
|
+
for (const schema of schemas) {
|
|
5
|
+
const checks = generateSchemaChecks(accessor, schema);
|
|
6
|
+
if (checks.length > 0) {
|
|
7
|
+
let combinedChecks = checks[0];
|
|
8
|
+
for (let i = 1; i < checks.length; i++) {
|
|
9
|
+
combinedChecks += " && " + checks[i];
|
|
10
|
+
}
|
|
11
|
+
cases.push("(" + combinedChecks + ")");
|
|
17
12
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
}
|
|
14
|
+
if (cases.length === 0) {
|
|
15
|
+
return isRequired ? `${accessor} ?? ${defaultValue}` : accessor;
|
|
16
|
+
}
|
|
17
|
+
let combinedCheck = cases[0];
|
|
18
|
+
for (let i = 1; i < cases.length; i++) {
|
|
19
|
+
combinedCheck += " || " + cases[i];
|
|
20
|
+
}
|
|
21
|
+
const finalDefault = isRequired ? defaultValue : "undefined";
|
|
22
|
+
return `(${combinedCheck}) ? ${accessor} : ${finalDefault}`;
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
generateNonDiscriminatedUnionValidation
|
|
28
26
|
};
|
|
@@ -67,6 +67,18 @@ type GenerateParserOptions = {
|
|
|
67
67
|
* exact `===` fast path and the hot path is unaffected.
|
|
68
68
|
*/
|
|
69
69
|
readonly caseInsensitive?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* The exact source of the `validate{TypeName}Shape` predicate emitted into
|
|
72
|
+
* the same file as this parser (generate-files produces it for the root
|
|
73
|
+
* type). When the parser can prove — by rendering the predicate it would
|
|
74
|
+
* need and comparing byte-for-byte — that this emitted predicate tests
|
|
75
|
+
* exactly its own fast-path guard, it emits `validate{TypeName}Shape(input)`
|
|
76
|
+
* instead of a second inline copy of the whole check chain, which roughly
|
|
77
|
+
* halves the emitted checks per object type. Any mismatch (composition
|
|
78
|
+
* keywords, conditional flattening, alias/union predicates, stubs) keeps
|
|
79
|
+
* the inline guard, so a wrong substitution is impossible by construction.
|
|
80
|
+
*/
|
|
81
|
+
readonly shapeValidatorSource?: string;
|
|
70
82
|
};
|
|
71
83
|
/**
|
|
72
84
|
* Generates a safe parser as an arrow function that never throws.
|