@amritk/generate-parsers 0.6.3 → 0.7.1

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.
Files changed (56) hide show
  1. package/dist/generators/build-schema.d.ts +9 -10
  2. package/dist/generators/build-schema.d.ts.map +1 -0
  3. package/dist/generators/build-schema.js +118 -0
  4. package/dist/generators/generate-default-from-pattern.d.ts +1 -0
  5. package/dist/generators/generate-default-from-pattern.d.ts.map +1 -0
  6. package/dist/generators/generate-default-from-pattern.js +33 -0
  7. package/dist/generators/generate-discriminated-union-validation.d.ts +1 -0
  8. package/dist/generators/generate-discriminated-union-validation.d.ts.map +1 -0
  9. package/dist/generators/generate-discriminated-union-validation.js +38 -0
  10. package/dist/generators/generate-enum-check.d.ts +1 -0
  11. package/dist/generators/generate-enum-check.d.ts.map +1 -0
  12. package/dist/generators/generate-enum-check.js +8 -0
  13. package/dist/generators/generate-files.d.ts +2 -1
  14. package/dist/generators/generate-files.d.ts.map +1 -0
  15. package/dist/generators/generate-files.js +74 -0
  16. package/dist/generators/generate-non-discriminated-union-validation.d.ts +1 -0
  17. package/dist/generators/generate-non-discriminated-union-validation.d.ts.map +1 -0
  18. package/dist/generators/generate-non-discriminated-union-validation.js +28 -0
  19. package/dist/generators/generate-parser-function.d.ts +1 -0
  20. package/dist/generators/generate-parser-function.d.ts.map +1 -0
  21. package/dist/generators/generate-parser-function.js +1070 -0
  22. package/dist/generators/generate-schema-checks.d.ts +1 -0
  23. package/dist/generators/generate-schema-checks.d.ts.map +1 -0
  24. package/dist/generators/generate-schema-checks.js +99 -0
  25. package/dist/generators/generate-strict-assertion.d.ts +1 -0
  26. package/dist/generators/generate-strict-assertion.d.ts.map +1 -0
  27. package/dist/generators/generate-strict-assertion.js +179 -0
  28. package/dist/generators/generate-validation-expression.d.ts +1 -0
  29. package/dist/generators/generate-validation-expression.d.ts.map +1 -0
  30. package/dist/generators/generate-validation-expression.js +267 -0
  31. package/dist/helpers/apply-schema-extensions.d.ts +2 -1
  32. package/dist/helpers/apply-schema-extensions.d.ts.map +1 -0
  33. package/dist/helpers/apply-schema-extensions.js +51 -0
  34. package/dist/helpers/collect-helpers.d.ts +1 -0
  35. package/dist/helpers/collect-helpers.d.ts.map +1 -0
  36. package/dist/helpers/collect-helpers.js +48 -0
  37. package/dist/helpers/collect-imports.d.ts +1 -0
  38. package/dist/helpers/collect-imports.d.ts.map +1 -0
  39. package/dist/helpers/collect-imports.js +216 -0
  40. package/dist/helpers/find-discriminator.d.ts +1 -0
  41. package/dist/helpers/find-discriminator.d.ts.map +1 -0
  42. package/dist/helpers/find-discriminator.js +33 -0
  43. package/dist/helpers/get-default-value.d.ts +1 -0
  44. package/dist/helpers/get-default-value.d.ts.map +1 -0
  45. package/dist/helpers/get-default-value.js +74 -0
  46. package/dist/helpers/get-discriminator-value.d.ts +1 -0
  47. package/dist/helpers/get-discriminator-value.d.ts.map +1 -0
  48. package/dist/helpers/get-discriminator-value.js +19 -0
  49. package/dist/index.d.ts +2 -1
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +1 -2783
  52. package/dist/types/schema-extensions.d.ts +1 -0
  53. package/dist/types/schema-extensions.d.ts.map +1 -0
  54. package/dist/types/schema-extensions.js +0 -0
  55. package/package.json +7 -7
  56. package/src/generators/build-schema.ts +22 -173
@@ -1,6 +1,6 @@
1
1
  import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
2
- import type { HelpersMode } from '#helpers/collect-helpers';
3
- import type { SchemaExtensions } from '#types/schema-extensions';
2
+ import type { HelpersMode } from '../helpers/collect-helpers.js';
3
+ import type { SchemaExtensions } from '../types/schema-extensions.js';
4
4
  /**
5
5
  * Represents a generated file with its filename and content.
6
6
  */
@@ -9,15 +9,13 @@ export type GeneratedFile = {
9
9
  content: string;
10
10
  };
11
11
  /**
12
- * Builds all TypeScript files from a JSON Schema by traversing
13
- * all $ref references recursively.
12
+ * Builds all TypeScript files from a JSON Schema by traversing its entire
13
+ * `$ref` / `$dynamicRef` graph (via the shared `@amritk/helpers/walk-ref-graph`
14
+ * walker, which also seeds `$dynamicAnchor` definitions and rewrites
15
+ * `$dynamicRef` to `$ref`).
14
16
  *
15
- * Starting from the root schema, this function:
16
- * 1. Generates a TypeScript file for the root type
17
- * 2. Extracts all $ref references from the schema
18
- * 3. Extracts all definitions with $dynamicAnchor (JSON Schema 2020-12 feature)
19
- * 4. Resolves each ref and generates a TypeScript file for it
20
- * 5. Recursively processes nested refs until all are handled
17
+ * For the root schema and each reachable definition this function generates a
18
+ * TypeScript file, then emits an `index.ts` barrel re-exporting them all.
21
19
  *
22
20
  * @param rootSchema - The root JSON Schema to build from
23
21
  * @param rootTypeName - The name for the root type (e.g., "Document")
@@ -76,3 +74,4 @@ export type GeneratedFile = {
76
74
  * ```
77
75
  */
78
76
  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[]>;
77
+ //# sourceMappingURL=build-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-schema.d.ts","sourceRoot":"","sources":["../../src/generators/build-schema.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,0BAA0B,CAAA;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAahE;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,eAAO,MAAM,WAAW,eACV,UAAU,gBACR,MAAM,eACP,gBAAgB,cACjB,OAAO,gBACL,OAAO,WACZ,OAAO,gBACH,WAAW,4EAIvB,OAAO,CAAC,aAAa,EAAE,CAyCzB,CAAA"}
@@ -0,0 +1,118 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname, resolve as resolvePath } from 'node:path';
4
+ import { generateIndexBarrel } from '@amritk/helpers/generate-index-barrel';
5
+ import { walkRefGraph } from '@amritk/helpers/walk-ref-graph';
6
+ import { applySchemaExtensions } from '../helpers/apply-schema-extensions.js';
7
+ import { generateFile } from './generate-files.js';
8
+ /** Locate the @amritk/helpers package on disk so we can copy its runtime
9
+ * helper source files into the generated output when in embedded mode. */
10
+ const readHelperSource = async (helper) => {
11
+ const require = createRequire(import.meta.url);
12
+ const helpersPkgPath = require.resolve('@amritk/helpers/package.json');
13
+ const helpersRoot = dirname(helpersPkgPath);
14
+ return readFile(resolvePath(helpersRoot, 'src', `${helper}.ts`), 'utf-8');
15
+ };
16
+ /**
17
+ * Builds all TypeScript files from a JSON Schema by traversing its entire
18
+ * `$ref` / `$dynamicRef` graph (via the shared `@amritk/helpers/walk-ref-graph`
19
+ * walker, which also seeds `$dynamicAnchor` definitions and rewrites
20
+ * `$dynamicRef` to `$ref`).
21
+ *
22
+ * For the root schema and each reachable definition this function generates a
23
+ * TypeScript file, then emits an `index.ts` barrel re-exporting them all.
24
+ *
25
+ * @param rootSchema - The root JSON Schema to build from
26
+ * @param rootTypeName - The name for the root type (e.g., "Document")
27
+ * @param extensions - Optional map of custom extension properties to add to specific definitions.
28
+ * Keys are definition names (matching $defs keys), values are records of extension property
29
+ * names to their JSON Schema definitions. Extensions are merged as optional properties before
30
+ * type and parser generation.
31
+ * @param typesOnly - When true, only generate TypeScript type definitions without parser functions.
32
+ * @param logWarnings - When true, the generated parsers emit a console.warn for every input key
33
+ * that is not declared in the schema's properties.
34
+ * @param strict - When true, the generated parsers throw on type/shape mismatches
35
+ * (wrong type, missing required property, enum/pattern/min/max violations) instead
36
+ * of coercing invalid input to default values.
37
+ * @param helpersMode - `'package'` (default) emits `import ... from '@amritk/helpers/...'`.
38
+ * `'embedded'` emits `import ... from './_helpers/...'` and appends the helper sources
39
+ * as additional `GeneratedFile` entries so the output directory is self-contained.
40
+ * @param helpersImportPrefix - Relative path prefix to the `_helpers/` directory in
41
+ * embedded mode. Defaults to `'./'`. The recursive multi-schema build passes `'../'`,
42
+ * `'../../'`, etc. so nested parsers can import from a single shared `_helpers/`
43
+ * directory while the helper sources are emitted once at the output root.
44
+ * @param readonly - When true, every property, array, and record in the generated type
45
+ * definitions is emitted as `readonly`.
46
+ * @param typeSuffix - Suffix appended to every type/parser name derived from a `$ref`
47
+ * (e.g. `'Object'` → `ContactObject`). Defaults to `''` (no suffix). The root type name
48
+ * is used verbatim and is not affected by this suffix.
49
+ * @returns An array of generated TypeScript files
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const schema = {
54
+ * type: "object",
55
+ * properties: {
56
+ * info: { $ref: "#/$defs/info" }
57
+ * },
58
+ * $defs: {
59
+ * info: {
60
+ * type: "object",
61
+ * properties: {
62
+ * title: { type: "string" }
63
+ * }
64
+ * }
65
+ * }
66
+ * };
67
+ *
68
+ * const files = buildSchema(schema, "Document");
69
+ *
70
+ * // Types-only mode — no parser functions or runtime helpers included:
71
+ * const typesFiles = buildSchema(schema, "Document", undefined, true);
72
+ *
73
+ * // With extensions:
74
+ * const filesWithExtensions = buildSchema(schema, "Document", {
75
+ * info: {
76
+ * 'x-internal': { type: 'boolean' },
77
+ * },
78
+ * });
79
+ * ```
80
+ */
81
+ export const buildSchema = async (rootSchema, rootTypeName, extensions, typesOnly, logWarnings, strict, helpersMode = 'package', helpersImportPrefix = './', readonly = false, typeSuffix = '') => {
82
+ const files = [];
83
+ const usedHelpers = new Set();
84
+ walkRefGraph(rootSchema, rootTypeName, { typeSuffix }, (node) => {
85
+ // `index` is reserved for the barrel below, so never let a definition of
86
+ // that name overwrite it.
87
+ if (node.filename === 'index')
88
+ return;
89
+ // Extensions are keyed by definition name, which is the node's filename for
90
+ // both the root (the lowercased root type name) and every `$ref` target.
91
+ const extended = extensions ? applySchemaExtensions(node.schema, node.filename, extensions) : node.schema;
92
+ const result = generateFile(extended, node.typeName, {
93
+ typesOnly: typesOnly ?? false,
94
+ rootSchema: node.rootSchema,
95
+ helpersMode,
96
+ helpersImportPrefix,
97
+ readonly,
98
+ typeSuffix,
99
+ ...(node.ref !== undefined ? { selfRef: node.ref } : {}),
100
+ ...(logWarnings !== undefined ? { logWarnings } : {}),
101
+ ...(strict !== undefined ? { strict } : {}),
102
+ });
103
+ files.push({ filename: `${node.filename}.ts`, content: result.content });
104
+ for (const helper of result.usedHelpers)
105
+ usedHelpers.add(helper);
106
+ });
107
+ // In embedded mode, ship the runtime helper source files alongside the parsers so
108
+ // the output directory is self-contained (no `@amritk/helpers` install required).
109
+ // typesOnly skips parser generation entirely, so no runtime helpers are needed.
110
+ if (helpersMode === 'embedded' && !typesOnly) {
111
+ for (const helper of usedHelpers) {
112
+ const source = await readHelperSource(helper);
113
+ files.push({ filename: `_helpers/${helper}.ts`, content: source });
114
+ }
115
+ }
116
+ files.push({ filename: 'index.ts', content: generateIndexBarrel(files, { typesOnly: typesOnly ?? false }) });
117
+ return files;
118
+ };
@@ -3,3 +3,4 @@
3
3
  * Recognizes common patterns and returns appropriate defaults.
4
4
  */
5
5
  export declare const generateDefaultFromPattern: (pattern: string) => string | null;
6
+ //# sourceMappingURL=generate-default-from-pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-default-from-pattern.d.ts","sourceRoot":"","sources":["../../src/generators/generate-default-from-pattern.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,0BAA0B,YAAa,MAAM,KAAG,MAAM,GAAG,IAkCrE,CAAA"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Generates a best-guess default value from a regex pattern.
3
+ * Recognizes common patterns and returns appropriate defaults.
4
+ */
5
+ export const generateDefaultFromPattern = (pattern) => {
6
+ // Email pattern
7
+ if (pattern.includes('@') || (pattern.includes('[a-zA-Z0-9]') && pattern.includes('\\.'))) {
8
+ return '"user@example.com"';
9
+ }
10
+ // UUID pattern
11
+ if ((pattern.includes('[0-9a-f]') && pattern.includes('{8}')) || pattern.includes('\\-')) {
12
+ if (pattern.match(/[0-9a-f].*\{8\}/i) || pattern.match(/[0-9a-fA-F]{8}/)) {
13
+ return '"00000000-0000-0000-0000-000000000000"';
14
+ }
15
+ }
16
+ // URL pattern
17
+ if (pattern.includes('https?') || pattern.includes('http')) {
18
+ return '"https://example.com"';
19
+ }
20
+ // Semver pattern (3.1.x, x.y.z, etc)
21
+ if (pattern.match(/\d.*\\\.\.*\d/)) {
22
+ return '"1.0.0"';
23
+ }
24
+ // ISO date pattern
25
+ if (pattern.includes('\\d{4}') && pattern.includes('\\d{2}')) {
26
+ return '"2000-01-01"';
27
+ }
28
+ // Phone number patterns
29
+ if (pattern.includes('\\d{3}') && (pattern.includes('\\d{4}') || pattern.includes('\\d{7}'))) {
30
+ return '"+1234567890"';
31
+ }
32
+ return null;
33
+ };
@@ -4,3 +4,4 @@ import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
4
4
  * Uses a discriminator property to efficiently choose the correct schema.
5
5
  */
6
6
  export declare const generateDiscriminatedUnionValidation: (accessor: string, schemas: readonly JSONSchema[], discriminatorKey: string, defaultValue: string, isRequired: boolean) => string;
7
+ //# sourceMappingURL=generate-discriminated-union-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-discriminated-union-validation.d.ts","sourceRoot":"","sources":["../../src/generators/generate-discriminated-union-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAMjE;;;GAGG;AACH,eAAO,MAAM,oCAAoC,aACrC,MAAM,WACP,SAAS,UAAU,EAAE,oBACZ,MAAM,gBACV,MAAM,cACR,OAAO,KAClB,MAqCF,CAAA"}
@@ -0,0 +1,38 @@
1
+ import { getDefaultValue } from '../helpers/get-default-value.js';
2
+ import { getDiscriminatorValue } from '../helpers/get-discriminator-value.js';
3
+ import { generateSchemaChecks } from './generate-schema-checks.js';
4
+ /**
5
+ * Generates a discriminated union validation expression.
6
+ * Uses a discriminator property to efficiently choose the correct schema.
7
+ */
8
+ export const generateDiscriminatedUnionValidation = (accessor, schemas, discriminatorKey, defaultValue, isRequired) => {
9
+ const cases = [];
10
+ for (const schema of schemas) {
11
+ const discriminatorValue = getDiscriminatorValue(schema, discriminatorKey);
12
+ if (discriminatorValue !== null) {
13
+ const schemaDefault = getDefaultValue(schema);
14
+ const checks = generateSchemaChecks(accessor, schema);
15
+ if (checks.length > 0) {
16
+ // checks[0] is safe: we guard with checks.length > 0 above
17
+ let combinedChecks = checks[0];
18
+ for (let i = 1; i < checks.length; i++) {
19
+ combinedChecks += ' && ' + checks[i];
20
+ }
21
+ cases.push(`${accessor}?.${discriminatorKey} === ${JSON.stringify(discriminatorValue)} && ${combinedChecks} ? ${accessor} : ${schemaDefault}`);
22
+ }
23
+ else {
24
+ cases.push(`${accessor}?.${discriminatorKey} === ${JSON.stringify(discriminatorValue)} ? ${accessor} : ${schemaDefault}`);
25
+ }
26
+ }
27
+ }
28
+ if (cases.length === 0) {
29
+ return isRequired ? `${accessor} ?? ${defaultValue}` : accessor;
30
+ }
31
+ // Chain the cases together with ternary operators using a for loop instead of .reduce()
32
+ // cases[0] is safe: we guard with cases.length === 0 above
33
+ let result = cases[0];
34
+ for (let i = 1; i < cases.length; i++) {
35
+ result = cases[i] + ' : ' + result;
36
+ }
37
+ return result;
38
+ };
@@ -3,3 +3,4 @@
3
3
  * Returns a string that checks if the value is in the allowed enum values.
4
4
  */
5
5
  export declare const generateEnumCheck: (accessor: string, enumValues: readonly unknown[]) => string;
6
+ //# sourceMappingURL=generate-enum-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-enum-check.d.ts","sourceRoot":"","sources":["../../src/generators/generate-enum-check.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,aAAc,MAAM,cAAc,SAAS,OAAO,EAAE,KAAG,MAGpF,CAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generates an enum validation check expression.
3
+ * Returns a string that checks if the value is in the allowed enum values.
4
+ */
5
+ export const generateEnumCheck = (accessor, enumValues) => {
6
+ const serializedEnum = JSON.stringify(enumValues);
7
+ return `${serializedEnum}.includes(${accessor} as never)`;
8
+ };
@@ -1,5 +1,5 @@
1
1
  import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
2
- import { type HelpersMode, type RuntimeHelperName } from '#helpers/collect-helpers';
2
+ import { type HelpersMode, type RuntimeHelperName } from '../helpers/collect-helpers.js';
3
3
  /**
4
4
  * Options for controlling what gets generated in a file.
5
5
  */
@@ -91,3 +91,4 @@ export type GeneratedFileContent = {
91
91
  */
92
92
  export declare const generateFile: (schema: JSONSchema, typeName: string, options?: GenerateFileOptions) => GeneratedFileContent;
93
93
  export {};
94
+ //# sourceMappingURL=generate-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-files.d.ts","sourceRoot":"","sources":["../../src/generators/generate-files.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAA;AAKjC;;GAEG;AACH,KAAK,mBAAmB,GAAG;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IACrC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAA;CACrD,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,YAAY,WACf,UAAU,YACR,MAAM,YACN,mBAAmB,KAC5B,oBA+CF,CAAA"}
@@ -0,0 +1,74 @@
1
+ import { generateTypeDefinition } from '@amritk/helpers/generate-type-definition';
2
+ import { collectHelpers, } from '../helpers/collect-helpers.js';
3
+ import { collectImports } from '../helpers/collect-imports.js';
4
+ import { generateParserFunction, generateShapeValidator } from './generate-parser-function.js';
5
+ /**
6
+ * Generates a complete TypeScript file from a JSON Schema.
7
+ *
8
+ * The generated file contains imports, type definition, and parser function.
9
+ * When typesOnly is true, only the type definition is emitted without any parser.
10
+ *
11
+ * @param schema - The JSON Schema to generate code from
12
+ * @param typeName - The name to use for the generated TypeScript type
13
+ * @param options - Optional settings to control what gets generated
14
+ * @returns The generated file content and the set of runtime helpers it references
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const schema = {
19
+ * type: "object",
20
+ * properties: {
21
+ * name: { type: "string" },
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 typeDefinition = generateTypeDefinition(schema, typeName, { readonly: options?.readonly ?? false, typeSuffix });
41
+ if (typesOnly) {
42
+ // In types-only mode, skip the parser function and use type-only imports
43
+ const imports = collectImports(schema, { typesOnly: true, selfRef, rootSchema, typeSuffix });
44
+ let result = '';
45
+ if (imports.length > 0) {
46
+ result += imports[0];
47
+ for (let i = 1; i < imports.length; i++) {
48
+ result += '\n' + imports[i];
49
+ }
50
+ result += '\n\n';
51
+ }
52
+ return { content: result + typeDefinition, usedHelpers: new Set() };
53
+ }
54
+ const parserFunction = generateParserFunction(schema, typeName, {
55
+ useRefImports: true,
56
+ typeSuffix,
57
+ ...(options?.logWarnings !== undefined ? { logWarnings: options.logWarnings } : {}),
58
+ ...(options?.strict !== undefined ? { strict: options.strict } : {}),
59
+ });
60
+ const shapeValidator = generateShapeValidator(schema, typeName, true, typeSuffix);
61
+ const combinedFunctions = `${shapeValidator}\n\n${parserFunction}`;
62
+ const helpers = collectHelpers(combinedFunctions, helpersMode, options?.helpersImportPrefix);
63
+ const imports = [...collectImports(schema, { selfRef, rootSchema, typeSuffix }), ...helpers.imports];
64
+ // Build file output using string concatenation instead of array join for performance
65
+ let result = '';
66
+ if (imports.length > 0) {
67
+ result += imports[0];
68
+ for (let i = 1; i < imports.length; i++) {
69
+ result += '\n' + imports[i];
70
+ }
71
+ result += '\n\n';
72
+ }
73
+ return { content: result + typeDefinition + '\n\n' + combinedFunctions, usedHelpers: helpers.used };
74
+ };
@@ -4,3 +4,4 @@ import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
4
4
  * Tries each schema in order until one matches.
5
5
  */
6
6
  export declare const generateNonDiscriminatedUnionValidation: (accessor: string, schemas: readonly JSONSchema[], defaultValue: string, isRequired: boolean) => string;
7
+ //# sourceMappingURL=generate-non-discriminated-union-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-non-discriminated-union-validation.d.ts","sourceRoot":"","sources":["../../src/generators/generate-non-discriminated-union-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAIjE;;;GAGG;AACH,eAAO,MAAM,uCAAuC,aACxC,MAAM,WACP,SAAS,UAAU,EAAE,gBAChB,MAAM,cACR,OAAO,KAClB,MA0BF,CAAA"}
@@ -0,0 +1,28 @@
1
+ import { generateSchemaChecks } from './generate-schema-checks.js';
2
+ /**
3
+ * Generates a non-discriminated union validation expression.
4
+ * Tries each schema in order until one matches.
5
+ */
6
+ export const generateNonDiscriminatedUnionValidation = (accessor, schemas, defaultValue, isRequired) => {
7
+ const cases = [];
8
+ for (const schema of schemas) {
9
+ const checks = generateSchemaChecks(accessor, schema);
10
+ if (checks.length > 0) {
11
+ let combinedChecks = checks[0];
12
+ for (let i = 1; i < checks.length; i++) {
13
+ combinedChecks += ' && ' + checks[i];
14
+ }
15
+ cases.push('(' + combinedChecks + ')');
16
+ }
17
+ }
18
+ if (cases.length === 0) {
19
+ return isRequired ? `${accessor} ?? ${defaultValue}` : accessor;
20
+ }
21
+ // Try each schema in order
22
+ let combinedCheck = cases[0];
23
+ for (let i = 1; i < cases.length; i++) {
24
+ combinedCheck += ' || ' + cases[i];
25
+ }
26
+ const finalDefault = isRequired ? defaultValue : 'undefined';
27
+ return `(${combinedCheck}) ? ${accessor} : ${finalDefault}`;
28
+ };
@@ -56,3 +56,4 @@ export declare const shapeValidatorFunctionName: (typeName: string) => string;
56
56
  */
57
57
  export declare const generateShapeValidator: (schema: JSONSchema, typeName: string, useRefImports: boolean, suffix?: string) => string;
58
58
  export {};
59
+ //# sourceMappingURL=generate-parser-function.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-parser-function.d.ts","sourceRoot":"","sources":["../../src/generators/generate-parser-function.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAMjE;;GAEG;AACH,KAAK,qBAAqB,GAAG;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;IAChC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAqqCD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,WACzB,UAAU,YACR,MAAM,YACN,qBAAqB,KAC9B,MAEF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,aAAc,MAAM,KAAG,MAAsC,CAAA;AAEpG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,WACzB,UAAU,YACR,MAAM,iBACD,OAAO,sBAErB,MAyDF,CAAA"}