@amritk/generate-parsers 0.5.0 → 0.6.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/build-schema.d.ts +4 -1
- package/dist/generators/generate-files.d.ts +5 -0
- package/dist/generators/generate-parser-function.d.ts +6 -1
- package/dist/helpers/collect-imports.d.ts +6 -0
- package/dist/index.js +82 -76
- package/package.json +2 -2
- package/src/generators/build-schema.test.ts +17 -17
- package/src/generators/build-schema.ts +7 -1
- package/src/generators/generate-files.test.ts +65 -52
- package/src/generators/generate-files.ts +11 -4
- package/src/generators/generate-parser-function.test.ts +254 -258
- package/src/generators/generate-parser-function.ts +87 -58
- package/src/helpers/collect-imports.test.ts +44 -84
- package/src/helpers/collect-imports.ts +8 -1
|
@@ -40,6 +40,9 @@ export type GeneratedFile = {
|
|
|
40
40
|
* directory while the helper sources are emitted once at the output root.
|
|
41
41
|
* @param readonly - When true, every property, array, and record in the generated type
|
|
42
42
|
* definitions is emitted as `readonly`.
|
|
43
|
+
* @param typeSuffix - Suffix appended to every type/parser name derived from a `$ref`
|
|
44
|
+
* (e.g. `'Object'` → `ContactObject`). Defaults to `''` (no suffix). The root type name
|
|
45
|
+
* is used verbatim and is not affected by this suffix.
|
|
43
46
|
* @returns An array of generated TypeScript files
|
|
44
47
|
*
|
|
45
48
|
* @example
|
|
@@ -72,4 +75,4 @@ export type GeneratedFile = {
|
|
|
72
75
|
* });
|
|
73
76
|
* ```
|
|
74
77
|
*/
|
|
75
|
-
export declare const buildSchema: (rootSchema: JSONSchema, rootTypeName: string, extensions?: SchemaExtensions, typesOnly?: boolean, logWarnings?: boolean, strict?: boolean, helpersMode?: HelpersMode, helpersImportPrefix?: string, readonly?: boolean) => Promise<GeneratedFile[]>;
|
|
78
|
+
export declare const buildSchema: (rootSchema: JSONSchema, rootTypeName: string, extensions?: SchemaExtensions, typesOnly?: boolean, logWarnings?: boolean, strict?: boolean, helpersMode?: HelpersMode, helpersImportPrefix?: string, readonly?: boolean, typeSuffix?: string) => Promise<GeneratedFile[]>;
|
|
@@ -49,6 +49,11 @@ type GenerateFileOptions = {
|
|
|
49
49
|
* definitions is emitted as `readonly`.
|
|
50
50
|
*/
|
|
51
51
|
readonly readonly?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Suffix appended to every type/parser name derived from a `$ref`.
|
|
54
|
+
* Defaults to `''` (no suffix). Set to e.g. `'Object'` to emit `ContactObject`.
|
|
55
|
+
*/
|
|
56
|
+
readonly typeSuffix?: string;
|
|
52
57
|
};
|
|
53
58
|
/** Result of generating a single parser file. */
|
|
54
59
|
export type GeneratedFileContent = {
|
|
@@ -20,6 +20,11 @@ type GenerateParserOptions = {
|
|
|
20
20
|
* with a path-aware Error. Unknown extra keys are still allowed.
|
|
21
21
|
*/
|
|
22
22
|
readonly strict?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Suffix appended to every type/parser name derived from a `$ref`. Must match
|
|
25
|
+
* the suffix used when generating the referenced files. Defaults to `''`.
|
|
26
|
+
*/
|
|
27
|
+
readonly typeSuffix?: string;
|
|
23
28
|
};
|
|
24
29
|
/**
|
|
25
30
|
* Generates a safe parser as an arrow function that never throws.
|
|
@@ -49,5 +54,5 @@ export declare const shapeValidatorFunctionName: (typeName: string) => string;
|
|
|
49
54
|
* in additionalProperties). The stub is safe: parents calling it will fall
|
|
50
55
|
* through to the slow path, matching the pre-deep-fast-path behavior.
|
|
51
56
|
*/
|
|
52
|
-
export declare const generateShapeValidator: (schema: JSONSchema, typeName: string, useRefImports: boolean) => string;
|
|
57
|
+
export declare const generateShapeValidator: (schema: JSONSchema, typeName: string, useRefImports: boolean, suffix?: string) => string;
|
|
53
58
|
export {};
|
|
@@ -20,6 +20,12 @@ type CollectImportsOptions = {
|
|
|
20
20
|
* imports for external schemas that were never generated as files.
|
|
21
21
|
*/
|
|
22
22
|
readonly rootSchema?: Record<string, unknown> | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Suffix appended to every type name derived from a `$ref`. Must match the
|
|
25
|
+
* suffix used when generating the referenced files so imports resolve.
|
|
26
|
+
* Defaults to `''` (no suffix).
|
|
27
|
+
*/
|
|
28
|
+
readonly typeSuffix?: string;
|
|
23
29
|
};
|
|
24
30
|
/**
|
|
25
31
|
* Collects all import statements needed for a schema by finding $ref references
|
package/dist/index.js
CHANGED
|
@@ -137,15 +137,15 @@ var refToFilename2 = (ref) => {
|
|
|
137
137
|
}
|
|
138
138
|
return filename;
|
|
139
139
|
};
|
|
140
|
-
var kebabToPascal = (kebab) => {
|
|
140
|
+
var kebabToPascal = (kebab, suffix) => {
|
|
141
141
|
const words = kebab.split("-");
|
|
142
142
|
let pascalCase = "";
|
|
143
143
|
for (const word of words) {
|
|
144
144
|
pascalCase += word.charAt(0).toUpperCase() + word.slice(1);
|
|
145
145
|
}
|
|
146
|
-
return pascalCase +
|
|
146
|
+
return pascalCase + suffix;
|
|
147
147
|
};
|
|
148
|
-
var refToName = (ref) => kebabToPascal(refToFilename2(ref));
|
|
148
|
+
var refToName = (ref, suffix = "") => kebabToPascal(refToFilename2(ref), suffix);
|
|
149
149
|
|
|
150
150
|
// ../helpers/dist/resolve-dynamic-refs.js
|
|
151
151
|
var resolveDynamicRefs = (schema, dynamicRefMap) => {
|
|
@@ -439,15 +439,15 @@ var refToFilename4 = (ref) => {
|
|
|
439
439
|
}
|
|
440
440
|
return filename;
|
|
441
441
|
};
|
|
442
|
-
var kebabToPascal2 = (kebab) => {
|
|
442
|
+
var kebabToPascal2 = (kebab, suffix) => {
|
|
443
443
|
const words = kebab.split("-");
|
|
444
444
|
let pascalCase = "";
|
|
445
445
|
for (const word of words) {
|
|
446
446
|
pascalCase += word.charAt(0).toUpperCase() + word.slice(1);
|
|
447
447
|
}
|
|
448
|
-
return pascalCase +
|
|
448
|
+
return pascalCase + suffix;
|
|
449
449
|
};
|
|
450
|
-
var refToName2 = (ref) => kebabToPascal2(refToFilename4(ref));
|
|
450
|
+
var refToName2 = (ref, suffix = "") => kebabToPascal2(refToFilename4(ref), suffix);
|
|
451
451
|
var JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
452
452
|
var safeKey = (key) => {
|
|
453
453
|
if (JS_IDENTIFIER.test(key)) {
|
|
@@ -565,13 +565,13 @@ var getUnbrandedType = (schema, options = {}) => {
|
|
|
565
565
|
if (!schema.$ref.startsWith("#")) {
|
|
566
566
|
return "unknown";
|
|
567
567
|
}
|
|
568
|
-
return refToName2(schema.$ref);
|
|
568
|
+
return refToName2(schema.$ref, options.typeSuffix);
|
|
569
569
|
}
|
|
570
570
|
if (schema.$dynamicRef) {
|
|
571
571
|
if (schema.$dynamicRef === "#meta") {
|
|
572
|
-
return
|
|
572
|
+
return `Schema${options.typeSuffix ?? ""}`;
|
|
573
573
|
}
|
|
574
|
-
return refToName2(schema.$dynamicRef);
|
|
574
|
+
return refToName2(schema.$dynamicRef, options.typeSuffix);
|
|
575
575
|
}
|
|
576
576
|
if (schema.const !== undefined) {
|
|
577
577
|
return JSON.stringify(schema.const);
|
|
@@ -618,7 +618,7 @@ var getUnbrandedType = (schema, options = {}) => {
|
|
|
618
618
|
if (conditionalResult) {
|
|
619
619
|
const baseType = getTypeScriptType(conditionalResult.schema, options);
|
|
620
620
|
if (conditionalResult.thenRef) {
|
|
621
|
-
return `(${baseType}) & ${refToName2(conditionalResult.thenRef)}`;
|
|
621
|
+
return `(${baseType}) & ${refToName2(conditionalResult.thenRef, options.typeSuffix)}`;
|
|
622
622
|
}
|
|
623
623
|
return baseType;
|
|
624
624
|
}
|
|
@@ -811,12 +811,12 @@ var generateTypeDefinition = (schema, typeName, options = {}) => {
|
|
|
811
811
|
if (isSchemaObject2(schema) && Array.isArray(schema.allOf)) {
|
|
812
812
|
for (const entry of schema.allOf) {
|
|
813
813
|
if (isSchemaObject2(entry) && entry.$ref) {
|
|
814
|
-
allOfIntersections.push(refToName2(entry.$ref));
|
|
814
|
+
allOfIntersections.push(refToName2(entry.$ref, options.typeSuffix));
|
|
815
815
|
}
|
|
816
816
|
}
|
|
817
817
|
}
|
|
818
818
|
if (isSchemaObject2(schema) && typeof schema.$ref === "string" && schema.$ref.startsWith("#")) {
|
|
819
|
-
allOfIntersections.push(refToName2(schema.$ref));
|
|
819
|
+
allOfIntersections.push(refToName2(schema.$ref, options.typeSuffix));
|
|
820
820
|
}
|
|
821
821
|
let result = "";
|
|
822
822
|
if (jsDocTitle && jsDocDescription) {
|
|
@@ -826,7 +826,7 @@ var generateTypeDefinition = (schema, typeName, options = {}) => {
|
|
|
826
826
|
` + properties + `
|
|
827
827
|
}`;
|
|
828
828
|
if (conditionalThenRef) {
|
|
829
|
-
typeBody += " & " + refToName2(conditionalThenRef);
|
|
829
|
+
typeBody += " & " + refToName2(conditionalThenRef, options.typeSuffix);
|
|
830
830
|
}
|
|
831
831
|
for (const intersectionType of allOfIntersections) {
|
|
832
832
|
typeBody += " & " + intersectionType;
|
|
@@ -967,6 +967,7 @@ var collectImports = (schema, options) => {
|
|
|
967
967
|
const typesOnly = options?.typesOnly === true;
|
|
968
968
|
const selfFilename = options?.selfRef ? refToFilename(options.selfRef) : undefined;
|
|
969
969
|
const rootSchema = options?.rootSchema;
|
|
970
|
+
const typeSuffix = options?.typeSuffix;
|
|
970
971
|
const refs = new Set;
|
|
971
972
|
const collectRefsFromValue = (value) => {
|
|
972
973
|
if (typeof value !== "object" || value === null) {
|
|
@@ -1094,7 +1095,7 @@ var collectImports = (schema, options) => {
|
|
|
1094
1095
|
if (!resolveRef(ref, rootSchema))
|
|
1095
1096
|
continue;
|
|
1096
1097
|
}
|
|
1097
|
-
const typeName = refToName(ref);
|
|
1098
|
+
const typeName = refToName(ref, typeSuffix);
|
|
1098
1099
|
const filename = refToFilename(ref);
|
|
1099
1100
|
if (selfFilename !== undefined && filename === selfFilename) {
|
|
1100
1101
|
continue;
|
|
@@ -1786,33 +1787,33 @@ var isPropertyRequired = (key, schema) => {
|
|
|
1786
1787
|
}
|
|
1787
1788
|
return schema.required.includes(key);
|
|
1788
1789
|
};
|
|
1789
|
-
var generateRequiredRefCall = (key, ref) => {
|
|
1790
|
+
var generateRequiredRefCall = (key, ref, suffix) => {
|
|
1790
1791
|
const acc = safeAccessor("input", key);
|
|
1791
|
-
const parserName = generateParserName(refToName(ref));
|
|
1792
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1792
1793
|
return `${parserName}(${acc})`;
|
|
1793
1794
|
};
|
|
1794
|
-
var generateOptionalRefCall = (key, ref) => {
|
|
1795
|
+
var generateOptionalRefCall = (key, ref, suffix) => {
|
|
1795
1796
|
const acc = safeAccessor("input", key);
|
|
1796
|
-
const parserName = generateParserName(refToName(ref));
|
|
1797
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1797
1798
|
return `...(${acc} && { ${safeKey2(key)}: ${parserName}(${acc}) })`;
|
|
1798
1799
|
};
|
|
1799
|
-
var generateRequiredArrayRefCall = (key, ref) => {
|
|
1800
|
-
const parserName = generateParserName(refToName(ref));
|
|
1800
|
+
var generateRequiredArrayRefCall = (key, ref, suffix) => {
|
|
1801
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1801
1802
|
return `validateArray(${safeAccessor("input", key)}, ${parserName})`;
|
|
1802
1803
|
};
|
|
1803
|
-
var generateOptionalArrayRefCall = (key, ref) => {
|
|
1804
|
-
const parserName = generateParserName(refToName(ref));
|
|
1804
|
+
var generateOptionalArrayRefCall = (key, ref, suffix) => {
|
|
1805
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1805
1806
|
const acc = safeAccessor("input", key);
|
|
1806
1807
|
return `...(${acc} && { ${safeKey2(key)}: validateArray(${acc}, ${parserName}) })`;
|
|
1807
1808
|
};
|
|
1808
|
-
var generateRequiredRecordRefCall = (key, ref) => {
|
|
1809
|
+
var generateRequiredRecordRefCall = (key, ref, suffix) => {
|
|
1809
1810
|
const acc = safeAccessor("input", key);
|
|
1810
|
-
const parserName = generateParserName(refToName(ref));
|
|
1811
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1811
1812
|
return `validateRecord(${acc}, ${parserName})`;
|
|
1812
1813
|
};
|
|
1813
|
-
var generateOptionalRecordRefCall = (key, ref) => {
|
|
1814
|
+
var generateOptionalRecordRefCall = (key, ref, suffix) => {
|
|
1814
1815
|
const acc = safeAccessor("input", key);
|
|
1815
|
-
const parserName = generateParserName(refToName(ref));
|
|
1816
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1816
1817
|
return `...(${acc} && { ${safeKey2(key)}: validateRecord(${acc}, ${parserName}) })`;
|
|
1817
1818
|
};
|
|
1818
1819
|
var generateOptionalInlineProperty = (key, valueExpression) => {
|
|
@@ -1857,20 +1858,20 @@ var shouldUseRecordRefImport = (propSchema, useRefImports) => {
|
|
|
1857
1858
|
const additionalProps = propSchema.additionalProperties;
|
|
1858
1859
|
return isSchemaObject3(additionalProps) && hasRef(additionalProps);
|
|
1859
1860
|
};
|
|
1860
|
-
var generatePropertyValue = (key, propSchema, isRequired, useRefImports) => {
|
|
1861
|
+
var generatePropertyValue = (key, propSchema, isRequired, useRefImports, suffix) => {
|
|
1861
1862
|
if (shouldUseRefImport(propSchema, useRefImports)) {
|
|
1862
1863
|
const ref = propSchema.$ref;
|
|
1863
|
-
return isRequired ? generateRequiredRefCall(key, ref) : generateOptionalRefCall(key, ref);
|
|
1864
|
+
return isRequired ? generateRequiredRefCall(key, ref, suffix) : generateOptionalRefCall(key, ref, suffix);
|
|
1864
1865
|
}
|
|
1865
1866
|
if (shouldUseArrayRefImport(propSchema, useRefImports)) {
|
|
1866
1867
|
const items = propSchema.items;
|
|
1867
1868
|
const ref = items.$ref;
|
|
1868
|
-
return isRequired ? generateRequiredArrayRefCall(key, ref) : generateOptionalArrayRefCall(key, ref);
|
|
1869
|
+
return isRequired ? generateRequiredArrayRefCall(key, ref, suffix) : generateOptionalArrayRefCall(key, ref, suffix);
|
|
1869
1870
|
}
|
|
1870
1871
|
if (shouldUseRecordRefImport(propSchema, useRefImports)) {
|
|
1871
1872
|
const additionalProps = propSchema.additionalProperties;
|
|
1872
1873
|
const ref = additionalProps.$ref;
|
|
1873
|
-
return isRequired ? generateRequiredRecordRefCall(key, ref) : generateOptionalRecordRefCall(key, ref);
|
|
1874
|
+
return isRequired ? generateRequiredRecordRefCall(key, ref, suffix) : generateOptionalRecordRefCall(key, ref, suffix);
|
|
1874
1875
|
}
|
|
1875
1876
|
if (!isSchemaObject3(propSchema)) {
|
|
1876
1877
|
return isRequired ? "undefined" : generateOptionalInlineProperty(key, "undefined");
|
|
@@ -1879,23 +1880,23 @@ var generatePropertyValue = (key, propSchema, isRequired, useRefImports) => {
|
|
|
1879
1880
|
const valueExpression = generateValidationExpression(key, propSchema, defaultValue, isRequired);
|
|
1880
1881
|
return isRequired ? valueExpression : generateOptionalInlineProperty(key, valueExpression);
|
|
1881
1882
|
};
|
|
1882
|
-
var generatePropertyEntries = (schema, useRefImports) => {
|
|
1883
|
+
var generatePropertyEntries = (schema, useRefImports, suffix) => {
|
|
1883
1884
|
if (!hasProperties(schema)) {
|
|
1884
1885
|
return [];
|
|
1885
1886
|
}
|
|
1886
1887
|
const entries = [];
|
|
1887
1888
|
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
1888
1889
|
const isRequired = isPropertyRequired(key, schema);
|
|
1889
|
-
const value = generatePropertyValue(key, propSchema, isRequired, useRefImports);
|
|
1890
|
+
const value = generatePropertyValue(key, propSchema, isRequired, useRefImports, suffix);
|
|
1890
1891
|
const isOptional = value.startsWith("...");
|
|
1891
1892
|
entries.push({ key, value, isOptional });
|
|
1892
1893
|
}
|
|
1893
1894
|
return entries;
|
|
1894
1895
|
};
|
|
1895
|
-
var generateFallbackValue = (_, propSchema, useRefImports) => {
|
|
1896
|
+
var generateFallbackValue = (_, propSchema, useRefImports, suffix) => {
|
|
1896
1897
|
if (useRefImports && hasRef(propSchema)) {
|
|
1897
1898
|
const ref = propSchema.$ref;
|
|
1898
|
-
const parserName = generateParserName(refToName(ref));
|
|
1899
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
1899
1900
|
return `${parserName}(undefined)`;
|
|
1900
1901
|
}
|
|
1901
1902
|
if (useRefImports && isSchemaObject3(propSchema) && propSchema.type === "array" && hasItems(propSchema) && hasRef(propSchema.items)) {
|
|
@@ -1938,7 +1939,7 @@ var generateFallbackValue = (_, propSchema, useRefImports) => {
|
|
|
1938
1939
|
return "undefined";
|
|
1939
1940
|
}
|
|
1940
1941
|
};
|
|
1941
|
-
var generateFallbackObject = (schema, useRefImports, typeName) => {
|
|
1942
|
+
var generateFallbackObject = (schema, useRefImports, typeName, suffix) => {
|
|
1942
1943
|
if (!hasProperties(schema)) {
|
|
1943
1944
|
return `{} as ${typeName}`;
|
|
1944
1945
|
}
|
|
@@ -1949,7 +1950,7 @@ var generateFallbackObject = (schema, useRefImports, typeName) => {
|
|
|
1949
1950
|
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
1950
1951
|
const isRequired = isPropertyRequired(key, schema);
|
|
1951
1952
|
if (isRequired) {
|
|
1952
|
-
const fallbackValue = generateFallbackValue(key, propSchema, useRefImports);
|
|
1953
|
+
const fallbackValue = generateFallbackValue(key, propSchema, useRefImports, suffix);
|
|
1953
1954
|
if (fallbackValue === "undefined") {
|
|
1954
1955
|
return `{} as ${typeName}`;
|
|
1955
1956
|
}
|
|
@@ -2017,11 +2018,11 @@ var toVarName = (key) => {
|
|
|
2017
2018
|
return `_${safe}`;
|
|
2018
2019
|
};
|
|
2019
2020
|
var shapeValidatorName = (typeName) => `validate${typeName}Shape`;
|
|
2020
|
-
var generatePropertyTypeCheck = (varName, schema, useRefImports) => {
|
|
2021
|
+
var generatePropertyTypeCheck = (varName, schema, useRefImports, suffix) => {
|
|
2021
2022
|
if (!isSchemaObject3(schema))
|
|
2022
2023
|
return null;
|
|
2023
2024
|
if (useRefImports && hasRef(schema)) {
|
|
2024
|
-
const refName = refToName(schema.$ref);
|
|
2025
|
+
const refName = refToName(schema.$ref, suffix);
|
|
2025
2026
|
return `${shapeValidatorName(refName)}(${varName})`;
|
|
2026
2027
|
}
|
|
2027
2028
|
if (hasEnum(schema) || hasOneOf(schema) || hasAnyOf(schema) || hasAllOf(schema) || hasRef(schema) || "not" in schema) {
|
|
@@ -2030,7 +2031,7 @@ var generatePropertyTypeCheck = (varName, schema, useRefImports) => {
|
|
|
2030
2031
|
if (!hasType(schema))
|
|
2031
2032
|
return null;
|
|
2032
2033
|
if (useRefImports && schema.type === "array" && hasItems(schema) && isSchemaObject3(schema.items) && hasRef(schema.items)) {
|
|
2033
|
-
const refName = refToName(schema.items.$ref);
|
|
2034
|
+
const refName = refToName(schema.items.$ref, suffix);
|
|
2034
2035
|
return `Array.isArray(${varName}) && ${varName}.every(${shapeValidatorName(refName)})`;
|
|
2035
2036
|
}
|
|
2036
2037
|
const checks = [];
|
|
@@ -2091,7 +2092,7 @@ var generatePropertyTypeCheck = (varName, schema, useRefImports) => {
|
|
|
2091
2092
|
var shouldCacheVariable = (propSchema, _canFastPath, _useRefImports) => {
|
|
2092
2093
|
return isSchemaObject3(propSchema);
|
|
2093
2094
|
};
|
|
2094
|
-
var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict) => {
|
|
2095
|
+
var generateObjectParser = (schema, typeName, useRefImports, suffix, logWarnings, strict) => {
|
|
2095
2096
|
const functionName = generateParserName(typeName);
|
|
2096
2097
|
if (!hasProperties(schema)) {
|
|
2097
2098
|
if (strict) {
|
|
@@ -2102,7 +2103,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2102
2103
|
}
|
|
2103
2104
|
return `export const ${functionName} = (input: unknown): ${typeName} => isObject(input) ? input as ${typeName} : {} as ${typeName};`;
|
|
2104
2105
|
}
|
|
2105
|
-
const fallbackObject = generateFallbackObject(schema, useRefImports, typeName);
|
|
2106
|
+
const fallbackObject = generateFallbackObject(schema, useRefImports, typeName, suffix);
|
|
2106
2107
|
const properties = Object.entries(schema.properties);
|
|
2107
2108
|
const lines = [];
|
|
2108
2109
|
lines.push(`export const ${functionName} = (input: unknown): ${typeName} => {`);
|
|
@@ -2125,7 +2126,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2125
2126
|
if (shouldUseRecordRefImport(propSchema, useRefImports)) {
|
|
2126
2127
|
canFastPath = false;
|
|
2127
2128
|
} else {
|
|
2128
|
-
const check = generatePropertyTypeCheck(varName, propSchema, useRefImports);
|
|
2129
|
+
const check = generatePropertyTypeCheck(varName, propSchema, useRefImports, suffix);
|
|
2129
2130
|
if (check === null) {
|
|
2130
2131
|
canFastPath = false;
|
|
2131
2132
|
} else {
|
|
@@ -2164,7 +2165,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2164
2165
|
if (useRefImports && isSchemaObject3(schema) && hasAllOf(schema)) {
|
|
2165
2166
|
for (const entry of schema.allOf) {
|
|
2166
2167
|
if (isSchemaObject3(entry) && hasRef(entry)) {
|
|
2167
|
-
const parserName = generateParserName(refToName(entry.$ref));
|
|
2168
|
+
const parserName = generateParserName(refToName(entry.$ref, suffix));
|
|
2168
2169
|
objectLines.push(` ...(${parserName}(input) as Record<string, unknown>),`);
|
|
2169
2170
|
}
|
|
2170
2171
|
}
|
|
@@ -2174,7 +2175,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2174
2175
|
const accessor = shouldCache ? varName : safeAccessor("input", key);
|
|
2175
2176
|
if (shouldUseRefImport(propSchema, useRefImports)) {
|
|
2176
2177
|
const ref = propSchema.$ref;
|
|
2177
|
-
const parserName = generateParserName(refToName(ref));
|
|
2178
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2178
2179
|
if (isRequired) {
|
|
2179
2180
|
objectLines.push(` ${safeKey2(key)}: ${parserName}(${accessor}),`);
|
|
2180
2181
|
} else {
|
|
@@ -2185,7 +2186,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2185
2186
|
if (shouldUseArrayRefImport(propSchema, useRefImports)) {
|
|
2186
2187
|
const items = propSchema.items;
|
|
2187
2188
|
const ref = items.$ref;
|
|
2188
|
-
const parserName = generateParserName(refToName(ref));
|
|
2189
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2189
2190
|
if (isRequired) {
|
|
2190
2191
|
objectLines.push(` ${safeKey2(key)}: validateArray(${accessor}, ${parserName}),`);
|
|
2191
2192
|
} else {
|
|
@@ -2196,7 +2197,7 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2196
2197
|
if (shouldUseRecordRefImport(propSchema, useRefImports)) {
|
|
2197
2198
|
const additionalProps = propSchema.additionalProperties;
|
|
2198
2199
|
const ref = additionalProps.$ref;
|
|
2199
|
-
const parserName = generateParserName(refToName(ref));
|
|
2200
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2200
2201
|
if (isRequired) {
|
|
2201
2202
|
objectLines.push(` ${safeKey2(key)}: validateRecord(${accessor}, ${parserName}),`);
|
|
2202
2203
|
} else {
|
|
@@ -2235,9 +2236,9 @@ var generateObjectParser = (schema, typeName, useRefImports, logWarnings, strict
|
|
|
2235
2236
|
}
|
|
2236
2237
|
return result;
|
|
2237
2238
|
};
|
|
2238
|
-
var generateCombinedObjectParser = (schema, typeName, useRefImports, logWarnings, strict) => {
|
|
2239
|
+
var generateCombinedObjectParser = (schema, typeName, useRefImports, suffix, logWarnings, strict) => {
|
|
2239
2240
|
const functionName = generateParserName(typeName);
|
|
2240
|
-
const entries = generatePropertyEntries(schema, useRefImports);
|
|
2241
|
+
const entries = generatePropertyEntries(schema, useRefImports, suffix);
|
|
2241
2242
|
const propertyLines = entries.map((entry) => {
|
|
2242
2243
|
if (entry.isOptional) {
|
|
2243
2244
|
return ` ${entry.value},`;
|
|
@@ -2245,17 +2246,17 @@ var generateCombinedObjectParser = (schema, typeName, useRefImports, logWarnings
|
|
|
2245
2246
|
return ` ${safeKey2(entry.key)}: ${entry.value},`;
|
|
2246
2247
|
});
|
|
2247
2248
|
if (!isSchemaObject3(schema) || !("patternProperties" in schema)) {
|
|
2248
|
-
return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict);
|
|
2249
|
+
return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict);
|
|
2249
2250
|
}
|
|
2250
2251
|
const patternProps = schema.patternProperties;
|
|
2251
2252
|
const patterns = Object.entries(patternProps);
|
|
2252
2253
|
const refPattern = patterns.find(([, ps]) => isSchemaObject3(ps) && hasRef(ps));
|
|
2253
2254
|
if (!refPattern || !useRefImports) {
|
|
2254
|
-
return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict);
|
|
2255
|
+
return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict);
|
|
2255
2256
|
}
|
|
2256
2257
|
const [pattern, patternSchema] = refPattern;
|
|
2257
2258
|
const ref = patternSchema.$ref;
|
|
2258
|
-
const parserName = generateParserName(refToName(ref));
|
|
2259
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2259
2260
|
const assignmentCode = `(result as Record<string, unknown>)[key] = ${parserName}(value);`;
|
|
2260
2261
|
const escapedPattern = escapeRegexPattern2(pattern);
|
|
2261
2262
|
const inputSpread = " ...input,";
|
|
@@ -2283,7 +2284,7 @@ ${objectProperties}
|
|
|
2283
2284
|
return result;
|
|
2284
2285
|
};`;
|
|
2285
2286
|
};
|
|
2286
|
-
var generateAdditionalPropertiesParser = (schema, typeName, useRefImports, strict) => {
|
|
2287
|
+
var generateAdditionalPropertiesParser = (schema, typeName, useRefImports, suffix, strict) => {
|
|
2287
2288
|
const functionName = generateParserName(typeName);
|
|
2288
2289
|
const additionalProps = schema.additionalProperties;
|
|
2289
2290
|
if (!additionalProps) {
|
|
@@ -2291,7 +2292,7 @@ var generateAdditionalPropertiesParser = (schema, typeName, useRefImports, stric
|
|
|
2291
2292
|
}
|
|
2292
2293
|
if (useRefImports && isSchemaObject3(additionalProps) && hasRef(additionalProps)) {
|
|
2293
2294
|
const ref = additionalProps.$ref;
|
|
2294
|
-
const parserName = generateParserName(refToName(ref));
|
|
2295
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2295
2296
|
if (strict) {
|
|
2296
2297
|
return `export const ${functionName} = (input: unknown): ${typeName} => {
|
|
2297
2298
|
if (!isObject(input)) throw new Error(\`[${typeName}] expected object, got \${input === null ? "null" : typeof input}\`);
|
|
@@ -2341,7 +2342,7 @@ var generateInlineValueParser = (schema) => {
|
|
|
2341
2342
|
var escapeRegexPattern2 = (pattern) => {
|
|
2342
2343
|
return pattern.replace(/\\/g, "\\\\").replace(/\//g, "\\/");
|
|
2343
2344
|
};
|
|
2344
|
-
var generatePatternPropertiesParser = (schema, typeName, useRefImports, strict) => {
|
|
2345
|
+
var generatePatternPropertiesParser = (schema, typeName, useRefImports, suffix, strict) => {
|
|
2345
2346
|
const functionName = generateParserName(typeName);
|
|
2346
2347
|
if (!("patternProperties" in schema) || typeof schema.patternProperties !== "object") {
|
|
2347
2348
|
return generateEmptyObjectParser(typeName, strict);
|
|
@@ -2355,7 +2356,7 @@ var generatePatternPropertiesParser = (schema, typeName, useRefImports, strict)
|
|
|
2355
2356
|
let patternAssignment = "(result as Record<string, unknown>)[key] = value;";
|
|
2356
2357
|
if (useRefImports && isSchemaObject3(patternSchema) && hasRef(patternSchema)) {
|
|
2357
2358
|
const ref = patternSchema.$ref;
|
|
2358
|
-
const parserName = generateParserName(refToName(ref));
|
|
2359
|
+
const parserName = generateParserName(refToName(ref, suffix));
|
|
2359
2360
|
patternAssignment = `(result as Record<string, unknown>)[key] = ${parserName}(value);`;
|
|
2360
2361
|
} else if (patternSchema === false) {
|
|
2361
2362
|
patternAssignment = "";
|
|
@@ -2378,7 +2379,7 @@ ${notObjectBranch}
|
|
|
2378
2379
|
return result;
|
|
2379
2380
|
};`;
|
|
2380
2381
|
};
|
|
2381
|
-
var generateConditionalParser = (schema, typeName) => {
|
|
2382
|
+
var generateConditionalParser = (schema, typeName, suffix) => {
|
|
2382
2383
|
const functionName = generateParserName(typeName);
|
|
2383
2384
|
const ifSchema = schema.if;
|
|
2384
2385
|
const thenSchema = schema.then;
|
|
@@ -2388,7 +2389,7 @@ var generateConditionalParser = (schema, typeName) => {
|
|
|
2388
2389
|
if (!thenHasRef || !elseHasRef) {
|
|
2389
2390
|
const mergedSchema = getConditionalObjectSchema2(schema);
|
|
2390
2391
|
if (mergedSchema) {
|
|
2391
|
-
return generateObjectParser(mergedSchema, typeName, false);
|
|
2392
|
+
return generateObjectParser(mergedSchema, typeName, false, suffix);
|
|
2392
2393
|
}
|
|
2393
2394
|
return generateEmptyObjectParser(typeName);
|
|
2394
2395
|
}
|
|
@@ -2396,15 +2397,15 @@ var generateConditionalParser = (schema, typeName) => {
|
|
|
2396
2397
|
if (!isRefCondition) {
|
|
2397
2398
|
const mergedSchema = getConditionalObjectSchema2(schema);
|
|
2398
2399
|
if (mergedSchema) {
|
|
2399
|
-
return generateObjectParser(mergedSchema, typeName, false);
|
|
2400
|
+
return generateObjectParser(mergedSchema, typeName, false, suffix);
|
|
2400
2401
|
}
|
|
2401
2402
|
return generateEmptyObjectParser(typeName);
|
|
2402
2403
|
}
|
|
2403
2404
|
const thenRef = thenSchema.$ref;
|
|
2404
2405
|
const elseRef = elseSchema.$ref;
|
|
2405
|
-
const thenParserName = generateParserName(refToName(thenRef));
|
|
2406
|
-
const elseParserName = generateParserName(refToName(elseRef));
|
|
2407
|
-
const thenTypeName = refToName(thenRef);
|
|
2406
|
+
const thenParserName = generateParserName(refToName(thenRef, suffix));
|
|
2407
|
+
const elseParserName = generateParserName(refToName(elseRef, suffix));
|
|
2408
|
+
const thenTypeName = refToName(thenRef, suffix);
|
|
2408
2409
|
return `export const ${functionName} = (input: unknown): ${typeName} | ${thenTypeName} =>
|
|
2409
2410
|
hasRef(input) ? ${thenParserName}(input) : ${elseParserName}(input)
|
|
2410
2411
|
`;
|
|
@@ -2477,7 +2478,8 @@ var selectParserStrategy = (schema, typeName, options) => {
|
|
|
2477
2478
|
const useRefImports = options?.useRefImports ?? false;
|
|
2478
2479
|
const logWarnings = options?.logWarnings ?? false;
|
|
2479
2480
|
const strict = options?.strict ?? false;
|
|
2480
|
-
|
|
2481
|
+
const suffix = options?.typeSuffix ?? "";
|
|
2482
|
+
if (typeName === `Schema${suffix}`) {
|
|
2481
2483
|
return generateSchemaObjectParser(typeName);
|
|
2482
2484
|
}
|
|
2483
2485
|
const isObjectLikeSchema2 = isObjectSchema2(schema) || isSchemaObject3(schema) && (("patternProperties" in schema) || ("additionalProperties" in schema));
|
|
@@ -2485,30 +2487,30 @@ var selectParserStrategy = (schema, typeName, options) => {
|
|
|
2485
2487
|
return generateNonObjectParser(typeName, schema, strict);
|
|
2486
2488
|
}
|
|
2487
2489
|
if (hasProperties(schema) && isSchemaObject3(schema) && "patternProperties" in schema) {
|
|
2488
|
-
return generateCombinedObjectParser(schema, typeName, useRefImports, logWarnings, strict);
|
|
2490
|
+
return generateCombinedObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict);
|
|
2489
2491
|
}
|
|
2490
2492
|
if (hasProperties(schema)) {
|
|
2491
|
-
return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict);
|
|
2493
|
+
return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict);
|
|
2492
2494
|
}
|
|
2493
2495
|
if (isSchemaObject3(schema) && "if" in schema && "then" in schema && "else" in schema) {
|
|
2494
|
-
return generateConditionalParser(schema, typeName);
|
|
2496
|
+
return generateConditionalParser(schema, typeName, suffix);
|
|
2495
2497
|
}
|
|
2496
2498
|
const conditionalObjectSchema = getConditionalObjectSchema2(schema);
|
|
2497
2499
|
if (conditionalObjectSchema) {
|
|
2498
|
-
return generateObjectParser(conditionalObjectSchema, typeName, useRefImports, logWarnings, strict);
|
|
2500
|
+
return generateObjectParser(conditionalObjectSchema, typeName, useRefImports, suffix, logWarnings, strict);
|
|
2499
2501
|
}
|
|
2500
2502
|
if (!isObjectLikeSchema2) {
|
|
2501
2503
|
return generateNonObjectParser(typeName, schema, strict);
|
|
2502
2504
|
}
|
|
2503
2505
|
if ("patternProperties" in schema) {
|
|
2504
|
-
return generatePatternPropertiesParser(schema, typeName, useRefImports, strict);
|
|
2506
|
+
return generatePatternPropertiesParser(schema, typeName, useRefImports, suffix, strict);
|
|
2505
2507
|
}
|
|
2506
2508
|
if ("additionalProperties" in schema && !hasProperties(schema)) {
|
|
2507
2509
|
const additionalProps = schema.additionalProperties;
|
|
2508
2510
|
if (additionalProps === true || additionalProps === false) {
|
|
2509
2511
|
return generateEmptyObjectParser(typeName, strict);
|
|
2510
2512
|
}
|
|
2511
|
-
return generateAdditionalPropertiesParser(schema, typeName, useRefImports, strict);
|
|
2513
|
+
return generateAdditionalPropertiesParser(schema, typeName, useRefImports, suffix, strict);
|
|
2512
2514
|
}
|
|
2513
2515
|
if ("type" in schema && schema.type === "object" && !hasProperties(schema)) {
|
|
2514
2516
|
return generateEmptyObjectParser(typeName, strict);
|
|
@@ -2518,7 +2520,7 @@ var selectParserStrategy = (schema, typeName, options) => {
|
|
|
2518
2520
|
var generateParserFunction = (schema, typeName, options) => {
|
|
2519
2521
|
return selectParserStrategy(schema, typeName, options);
|
|
2520
2522
|
};
|
|
2521
|
-
var generateShapeValidator = (schema, typeName, useRefImports) => {
|
|
2523
|
+
var generateShapeValidator = (schema, typeName, useRefImports, suffix = "") => {
|
|
2522
2524
|
const fnName = shapeValidatorName(typeName);
|
|
2523
2525
|
const stub = `export const ${fnName} = (_input: unknown): boolean => false;`;
|
|
2524
2526
|
if (!isSchemaObject3(schema))
|
|
@@ -2536,7 +2538,7 @@ var generateShapeValidator = (schema, typeName, useRefImports) => {
|
|
|
2536
2538
|
}
|
|
2537
2539
|
const accessor = safeAccessor("input", key);
|
|
2538
2540
|
const isRequired = isPropertyRequired(key, schema);
|
|
2539
|
-
const check = generatePropertyTypeCheck(accessor, propSchema, useRefImports);
|
|
2541
|
+
const check = generatePropertyTypeCheck(accessor, propSchema, useRefImports, suffix);
|
|
2540
2542
|
if (check === null) {
|
|
2541
2543
|
return stub;
|
|
2542
2544
|
}
|
|
@@ -2566,9 +2568,10 @@ var generateFile = (schema, typeName, options) => {
|
|
|
2566
2568
|
const selfRef = options?.selfRef;
|
|
2567
2569
|
const rootSchema = options?.rootSchema;
|
|
2568
2570
|
const helpersMode = options?.helpersMode ?? "package";
|
|
2569
|
-
const
|
|
2571
|
+
const typeSuffix = options?.typeSuffix ?? "";
|
|
2572
|
+
const typeDefinition = generateTypeDefinition(schema, typeName, { readonly: options?.readonly ?? false, typeSuffix });
|
|
2570
2573
|
if (typesOnly) {
|
|
2571
|
-
const imports2 = collectImports(schema, { typesOnly: true, selfRef, rootSchema });
|
|
2574
|
+
const imports2 = collectImports(schema, { typesOnly: true, selfRef, rootSchema, typeSuffix });
|
|
2572
2575
|
let result2 = "";
|
|
2573
2576
|
if (imports2.length > 0) {
|
|
2574
2577
|
result2 += imports2[0];
|
|
@@ -2584,15 +2587,16 @@ var generateFile = (schema, typeName, options) => {
|
|
|
2584
2587
|
}
|
|
2585
2588
|
const parserFunction = generateParserFunction(schema, typeName, {
|
|
2586
2589
|
useRefImports: true,
|
|
2590
|
+
typeSuffix,
|
|
2587
2591
|
...options?.logWarnings !== undefined ? { logWarnings: options.logWarnings } : {},
|
|
2588
2592
|
...options?.strict !== undefined ? { strict: options.strict } : {}
|
|
2589
2593
|
});
|
|
2590
|
-
const shapeValidator = generateShapeValidator(schema, typeName, true);
|
|
2594
|
+
const shapeValidator = generateShapeValidator(schema, typeName, true, typeSuffix);
|
|
2591
2595
|
const combinedFunctions = `${shapeValidator}
|
|
2592
2596
|
|
|
2593
2597
|
${parserFunction}`;
|
|
2594
2598
|
const helpers = collectHelpers(combinedFunctions, helpersMode, options?.helpersImportPrefix);
|
|
2595
|
-
const imports = [...collectImports(schema, { selfRef, rootSchema }), ...helpers.imports];
|
|
2599
|
+
const imports = [...collectImports(schema, { selfRef, rootSchema, typeSuffix }), ...helpers.imports];
|
|
2596
2600
|
let result = "";
|
|
2597
2601
|
if (imports.length > 0) {
|
|
2598
2602
|
result += imports[0];
|
|
@@ -2635,7 +2639,7 @@ var extractDynamicAnchorDefs = (schema) => {
|
|
|
2635
2639
|
}
|
|
2636
2640
|
return refs;
|
|
2637
2641
|
};
|
|
2638
|
-
var buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWarnings, strict, helpersMode = "package", helpersImportPrefix = "./", readonly = false) => {
|
|
2642
|
+
var buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWarnings, strict, helpersMode = "package", helpersImportPrefix = "./", readonly = false, typeSuffix = "") => {
|
|
2639
2643
|
rootSchema = upgradeDraft07Schema(rootSchema);
|
|
2640
2644
|
const files = [];
|
|
2641
2645
|
const processedRefs = new Set;
|
|
@@ -2651,6 +2655,7 @@ var buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWar
|
|
|
2651
2655
|
helpersMode,
|
|
2652
2656
|
helpersImportPrefix,
|
|
2653
2657
|
readonly,
|
|
2658
|
+
typeSuffix,
|
|
2654
2659
|
...logWarnings !== undefined ? { logWarnings } : {},
|
|
2655
2660
|
...strict !== undefined ? { strict } : {}
|
|
2656
2661
|
});
|
|
@@ -2677,7 +2682,7 @@ var buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWar
|
|
|
2677
2682
|
console.warn(`Warning: Could not resolve ref: ${ref}`);
|
|
2678
2683
|
continue;
|
|
2679
2684
|
}
|
|
2680
|
-
const typeName = refToName(ref);
|
|
2685
|
+
const typeName = refToName(ref, typeSuffix);
|
|
2681
2686
|
const filename = refToFilename(ref);
|
|
2682
2687
|
const processedSchema = resolveDynamicRefs(resolvedSchema, dynamicRefMap);
|
|
2683
2688
|
const extendedSchema = extensions ? applySchemaExtensions(processedSchema, filename, extensions) : processedSchema;
|
|
@@ -2688,6 +2693,7 @@ var buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWar
|
|
|
2688
2693
|
helpersMode,
|
|
2689
2694
|
helpersImportPrefix,
|
|
2690
2695
|
readonly,
|
|
2696
|
+
typeSuffix,
|
|
2691
2697
|
...logWarnings !== undefined ? { logWarnings } : {},
|
|
2692
2698
|
...strict !== undefined ? { strict } : {}
|
|
2693
2699
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amritk/generate-parsers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Generate TypeScript parsers and type definitions from JSON Schemas.",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"json-schema-typed": "^8.0.1",
|
|
52
|
-
"@amritk/helpers": "0.
|
|
52
|
+
"@amritk/helpers": "0.6.0",
|
|
53
53
|
"@amritk/generate-markdown": "0.2.1"
|
|
54
54
|
}
|
|
55
55
|
}
|