zod-codegen 1.0.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.
Files changed (76) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +93 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.yml +70 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +87 -0
  4. package/.github/dependabot.yml +76 -0
  5. package/.github/workflows/ci.yml +143 -0
  6. package/.github/workflows/release.yml +65 -0
  7. package/.husky/commit-msg +2 -0
  8. package/.husky/pre-commit +5 -0
  9. package/.lintstagedrc.json +4 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierrc.json +7 -0
  12. package/.releaserc.json +159 -0
  13. package/CHANGELOG.md +24 -0
  14. package/CONTRIBUTING.md +274 -0
  15. package/LICENCE +201 -0
  16. package/README.md +263 -0
  17. package/SECURITY.md +108 -0
  18. package/codecov.yml +29 -0
  19. package/commitlint.config.mjs +28 -0
  20. package/dist/scripts/update-manifest.js +31 -0
  21. package/dist/src/assets/manifest.json +5 -0
  22. package/dist/src/cli.js +60 -0
  23. package/dist/src/generator.js +55 -0
  24. package/dist/src/http/fetch-client.js +141 -0
  25. package/dist/src/interfaces/code-generator.js +1 -0
  26. package/dist/src/interfaces/file-reader.js +1 -0
  27. package/dist/src/polyfills/fetch.js +18 -0
  28. package/dist/src/services/code-generator.service.js +419 -0
  29. package/dist/src/services/file-reader.service.js +25 -0
  30. package/dist/src/services/file-writer.service.js +32 -0
  31. package/dist/src/services/import-builder.service.js +45 -0
  32. package/dist/src/services/type-builder.service.js +42 -0
  33. package/dist/src/types/http.js +10 -0
  34. package/dist/src/types/openapi.js +173 -0
  35. package/dist/src/utils/error-handler.js +11 -0
  36. package/dist/src/utils/execution-time.js +3 -0
  37. package/dist/src/utils/manifest.js +9 -0
  38. package/dist/src/utils/reporter.js +15 -0
  39. package/dist/src/utils/signal-handler.js +12 -0
  40. package/dist/src/utils/tty.js +3 -0
  41. package/dist/tests/integration/cli.test.js +25 -0
  42. package/dist/tests/unit/generator.test.js +29 -0
  43. package/dist/vitest.config.js +38 -0
  44. package/eslint.config.mjs +33 -0
  45. package/package.json +102 -0
  46. package/samples/openapi.json +1 -0
  47. package/samples/saris-openapi.json +7122 -0
  48. package/samples/swagger-petstore.yaml +802 -0
  49. package/samples/swagger-saris.yaml +3585 -0
  50. package/samples/test-logical.yaml +50 -0
  51. package/scripts/update-manifest.js +31 -0
  52. package/scripts/update-manifest.ts +47 -0
  53. package/src/assets/manifest.json +5 -0
  54. package/src/cli.ts +68 -0
  55. package/src/generator.ts +61 -0
  56. package/src/http/fetch-client.ts +181 -0
  57. package/src/interfaces/code-generator.ts +25 -0
  58. package/src/interfaces/file-reader.ts +15 -0
  59. package/src/polyfills/fetch.ts +26 -0
  60. package/src/services/code-generator.service.ts +775 -0
  61. package/src/services/file-reader.service.ts +29 -0
  62. package/src/services/file-writer.service.ts +36 -0
  63. package/src/services/import-builder.service.ts +64 -0
  64. package/src/services/type-builder.service.ts +77 -0
  65. package/src/types/http.ts +35 -0
  66. package/src/types/openapi.ts +202 -0
  67. package/src/utils/error-handler.ts +13 -0
  68. package/src/utils/execution-time.ts +3 -0
  69. package/src/utils/manifest.ts +17 -0
  70. package/src/utils/reporter.ts +16 -0
  71. package/src/utils/signal-handler.ts +14 -0
  72. package/src/utils/tty.ts +3 -0
  73. package/tests/integration/cli.test.ts +29 -0
  74. package/tests/unit/generator.test.ts +36 -0
  75. package/tsconfig.json +44 -0
  76. package/vitest.config.ts +39 -0
@@ -0,0 +1,45 @@
1
+ import * as ts from 'typescript';
2
+ import { z } from 'zod';
3
+ const IsTypeImport = z.boolean();
4
+ const ImportedElement = z.record(z.string(), IsTypeImport);
5
+ const ImportOptions = z.object({
6
+ defaultImport: ImportedElement.optional(),
7
+ namedImports: ImportedElement.optional(),
8
+ });
9
+ export class TypeScriptImportBuilderService {
10
+ buildImports() {
11
+ return [
12
+ this.createImport('zod', {
13
+ defaultImport: { z: false },
14
+ }),
15
+ this.createImport('path-to-regexp', {
16
+ namedImports: { compile: false },
17
+ }),
18
+ ];
19
+ }
20
+ createImport(target, options) {
21
+ const safeOptions = ImportOptions.parse(options);
22
+ const [defaultImport] = Object.entries(safeOptions.defaultImport ?? {})[0] ?? [undefined, false];
23
+ const { success: hasDefaultImport } = z.string().safeParse(defaultImport);
24
+ const safeNameImports = ImportedElement.safeParse(safeOptions.namedImports);
25
+ const namedImportList = safeNameImports.success ? Object.entries(safeNameImports.data) : [];
26
+ // Create import specifiers for named imports
27
+ const namedImports = namedImportList.length > 0
28
+ ? ts.factory.createNamedImports(namedImportList.map(([name, isTypeImport = false]) => {
29
+ return ts.factory.createImportSpecifier(isTypeImport, undefined, ts.factory.createIdentifier(name));
30
+ }))
31
+ : undefined;
32
+ // Check if we have any imports at all
33
+ const hasAnyImports = hasDefaultImport || namedImports;
34
+ // For side effects imports, we can pass undefined as the import clause
35
+ // For imports with bindings, we need to create the clause differently
36
+ return ts.factory.createImportDeclaration(undefined, hasAnyImports
37
+ ? {
38
+ kind: ts.SyntaxKind.ImportClause,
39
+ isTypeOnly: false,
40
+ name: hasDefaultImport && defaultImport ? ts.factory.createIdentifier(defaultImport) : undefined,
41
+ namedBindings: namedImports,
42
+ }
43
+ : undefined, ts.factory.createStringLiteral(target, true), undefined);
44
+ }
45
+ }
@@ -0,0 +1,42 @@
1
+ import * as ts from 'typescript';
2
+ export class TypeScriptTypeBuilderService {
3
+ buildType(type) {
4
+ switch (type) {
5
+ case 'string':
6
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
7
+ case 'number':
8
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
9
+ case 'boolean':
10
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
11
+ case 'unknown':
12
+ default:
13
+ return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
14
+ }
15
+ }
16
+ createProperty(name, type, isReadonly = false) {
17
+ const createIdentifier = name.startsWith('#') ? 'createPrivateIdentifier' : 'createIdentifier';
18
+ return ts.factory.createPropertyDeclaration(isReadonly ? [ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)] : undefined, ts.factory[createIdentifier](name), undefined, this.buildType(type), undefined);
19
+ }
20
+ createParameter(name, type, defaultValue, isOptional = false) {
21
+ return ts.factory.createParameterDeclaration(undefined, undefined, ts.factory.createIdentifier(this.sanitizeIdentifier(name)), isOptional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, typeof type === 'string' ? this.buildType(type) : type, defaultValue);
22
+ }
23
+ createGenericType(name) {
24
+ return ts.factory.createTypeParameterDeclaration(undefined, ts.factory.createIdentifier(name), undefined, undefined);
25
+ }
26
+ sanitizeIdentifier(name) {
27
+ let sanitized = name.replace(/[^a-zA-Z0-9_]/g, '_');
28
+ if (/^[0-9]/.test(sanitized)) {
29
+ sanitized = '_' + sanitized;
30
+ }
31
+ if (sanitized.length === 0) {
32
+ sanitized = '_';
33
+ }
34
+ return sanitized;
35
+ }
36
+ toCamelCase(word) {
37
+ return word.charAt(0).toLowerCase() + word.slice(1);
38
+ }
39
+ toPascalCase(word) {
40
+ return word.charAt(0).toUpperCase() + word.slice(1);
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ export class HttpError extends Error {
2
+ status;
3
+ response;
4
+ constructor(message, status, response) {
5
+ super(message);
6
+ this.status = status;
7
+ this.response = response;
8
+ this.name = 'HttpError';
9
+ }
10
+ }
@@ -0,0 +1,173 @@
1
+ import { z } from 'zod';
2
+ export const Reference = z.object({
3
+ $ref: z.string().optional(),
4
+ });
5
+ const BaseSchemaProperties = z.object({
6
+ $ref: z.string().optional(),
7
+ title: z.string().optional(),
8
+ multipleOf: z.number().positive().optional(),
9
+ maximum: z.number().optional(),
10
+ exclusiveMaximum: z.boolean().optional(),
11
+ minimum: z.number().optional(),
12
+ exclusiveMinimum: z.boolean().optional(),
13
+ maxLength: z.number().int().nonnegative().optional(),
14
+ minLength: z.number().int().nonnegative().optional(),
15
+ pattern: z.string().optional(),
16
+ maxItems: z.number().int().nonnegative().optional(),
17
+ minItems: z.number().int().nonnegative().optional(),
18
+ uniqueItems: z.boolean().optional(),
19
+ maxProperties: z.number().int().nonnegative().optional(),
20
+ minProperties: z.number().int().nonnegative().optional(),
21
+ required: z.array(z.string()).optional(),
22
+ enum: z.array(z.unknown()).optional(),
23
+ type: z.string().optional(),
24
+ allOf: z.array(z.unknown()).optional(),
25
+ oneOf: z.array(z.unknown()).optional(),
26
+ anyOf: z.array(z.unknown()).optional(),
27
+ not: z.unknown().optional(),
28
+ additionalProperties: z.unknown().optional(),
29
+ description: z.string().optional(),
30
+ format: z.string().optional(),
31
+ default: z.unknown().optional(),
32
+ nullable: z.boolean().optional(),
33
+ discriminator: Reference.optional(),
34
+ readOnly: z.boolean().optional(),
35
+ writeOnly: z.boolean().optional(),
36
+ xml: z
37
+ .object({
38
+ name: z.string().optional(),
39
+ wrapped: z.boolean().optional(),
40
+ })
41
+ .optional(),
42
+ externalDocs: Reference.optional(),
43
+ example: z.unknown().optional(),
44
+ deprecated: z.boolean().optional(),
45
+ });
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ export const SchemaProperties = z.lazy(() => BaseSchemaProperties.extend({
48
+ properties: z.record(z.string(), SchemaProperties).optional(),
49
+ items: SchemaProperties.optional(),
50
+ }));
51
+ const ServerVariable = z.object({
52
+ default: z.string(),
53
+ description: z.string().optional(),
54
+ enum: z.array(z.string()).optional(),
55
+ });
56
+ const Server = z.object({
57
+ url: z.string().url(),
58
+ description: z.string().optional(),
59
+ variables: z.record(z.string(), ServerVariable).optional(),
60
+ });
61
+ export const Parameter = z.object({
62
+ $ref: z.string().optional(),
63
+ name: z.string(),
64
+ in: z.enum(['query', 'header', 'path', 'cookie']),
65
+ description: z.string().optional(),
66
+ required: z.boolean().optional(),
67
+ deprecated: z.boolean().optional(),
68
+ allowEmptyValue: z.boolean().optional(),
69
+ style: z.string().optional(),
70
+ explode: z.boolean().optional(),
71
+ allowReserved: z.boolean().optional(),
72
+ schema: SchemaProperties.optional(),
73
+ });
74
+ const ResponseHeader = z.object({
75
+ $ref: z.string().optional(),
76
+ description: z.string().optional(),
77
+ required: z.boolean().optional(),
78
+ deprecated: z.boolean().optional(),
79
+ allowEmptyValue: z.boolean().optional(),
80
+ style: z.string().optional(),
81
+ explode: z.boolean().optional(),
82
+ allowReserved: z.boolean().optional(),
83
+ schema: Reference.optional(),
84
+ });
85
+ const MediaType = z.object({
86
+ schema: z.unknown().optional(),
87
+ });
88
+ export const Response = z.object({
89
+ $ref: z.string().optional(),
90
+ description: z.string(),
91
+ headers: z.record(z.string(), ResponseHeader).optional(),
92
+ content: z.record(z.string(), MediaType).optional(),
93
+ });
94
+ export const RequestBody = z.object({
95
+ $ref: z.string().optional(),
96
+ description: z.string().optional(),
97
+ required: z.boolean().optional(),
98
+ content: z.record(z.string(), MediaType).optional(),
99
+ });
100
+ export const MethodSchema = z.object({
101
+ summary: z.string().optional(),
102
+ description: z.string().optional(),
103
+ operationId: z.string().optional(),
104
+ parameters: z.array(Parameter).optional(),
105
+ requestBody: RequestBody.optional(),
106
+ responses: z.record(z.string(), Response).optional(),
107
+ tags: z.array(z.string()).optional(),
108
+ deprecated: z.boolean().optional(),
109
+ });
110
+ export const PathItem = z.object({
111
+ $ref: z.string().optional(),
112
+ summary: z.string().optional(),
113
+ description: z.string().optional(),
114
+ get: MethodSchema.optional(),
115
+ post: MethodSchema.optional(),
116
+ put: MethodSchema.optional(),
117
+ patch: MethodSchema.optional(),
118
+ delete: MethodSchema.optional(),
119
+ head: MethodSchema.optional(),
120
+ options: MethodSchema.optional(),
121
+ trace: MethodSchema.optional(),
122
+ parameters: z.array(Parameter).optional(),
123
+ });
124
+ const Info = z.object({
125
+ title: z.string().min(1),
126
+ version: z.string().min(1),
127
+ description: z.string().optional(),
128
+ termsOfService: z.string().url().optional(),
129
+ contact: z
130
+ .object({
131
+ name: z.string().optional(),
132
+ email: z.string().email().optional(),
133
+ url: z.string().url().optional(),
134
+ })
135
+ .optional(),
136
+ license: z
137
+ .object({
138
+ name: z.string().min(1),
139
+ url: z.string().url().optional(),
140
+ })
141
+ .optional(),
142
+ });
143
+ const SecurityRequirement = z.record(z.string(), z.array(z.string()));
144
+ const Tag = z.object({
145
+ name: z.string().min(1),
146
+ description: z.string().optional(),
147
+ externalDocs: Reference.optional(),
148
+ });
149
+ const ExternalDocumentation = z.object({
150
+ description: z.string().optional(),
151
+ url: z.string().url(),
152
+ });
153
+ const Components = z.object({
154
+ schemas: z.record(z.string(), SchemaProperties).optional(),
155
+ responses: z.record(z.string(), Response).optional(),
156
+ parameters: z.record(z.string(), Parameter).optional(),
157
+ examples: z.record(z.string(), Reference).optional(),
158
+ requestBodies: z.record(z.string(), RequestBody).optional(),
159
+ headers: z.record(z.string(), ResponseHeader).optional(),
160
+ securitySchemes: z.record(z.string(), Reference).optional(),
161
+ links: z.record(z.string(), Reference).optional(),
162
+ callbacks: z.record(z.string(), Reference).optional(),
163
+ });
164
+ export const OpenApiSpec = z.object({
165
+ openapi: z.string().regex(/^3\.\d+\.\d+$/, 'OpenAPI version must be in format 3.x.x'),
166
+ info: Info,
167
+ servers: z.array(Server).optional(),
168
+ paths: z.record(z.string(), PathItem),
169
+ components: Components.optional(),
170
+ security: z.array(SecurityRequirement).optional(),
171
+ tags: z.array(Tag).optional(),
172
+ externalDocs: ExternalDocumentation.optional(),
173
+ });
@@ -0,0 +1,11 @@
1
+ import { getExecutionTime } from './execution-time.js';
2
+ export const errorReceived = (process, startTime) => () => {
3
+ console.log(`Done after ${String(getExecutionTime(startTime))}s`);
4
+ process.exit(1);
5
+ };
6
+ export const handleErrors = (process, startTime) => {
7
+ const catchErrors = ['unhandledRejection', 'uncaughtException'];
8
+ catchErrors.map((event) => {
9
+ return process.on(event, errorReceived(process, startTime));
10
+ });
11
+ };
@@ -0,0 +1,3 @@
1
+ export function getExecutionTime(startTime) {
2
+ return Number(process.hrtime.bigint() - startTime) / 1000000000;
3
+ }
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ const ManifestSchema = z.object({
3
+ name: z.string().min(1),
4
+ version: z.string().min(1),
5
+ description: z.string().min(1),
6
+ });
7
+ export function isManifest(input) {
8
+ return ManifestSchema.safeParse(input).success;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { format } from 'node:util';
2
+ export class Reporter {
3
+ _stdout;
4
+ constructor(_stdout) {
5
+ this._stdout = _stdout;
6
+ this.log = this.log.bind(this);
7
+ this.error = this.error.bind(this);
8
+ }
9
+ log(...args) {
10
+ this._stdout.write(format(...args) + '\n');
11
+ }
12
+ error(...args) {
13
+ this._stdout.write(format(...args) + '\n');
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ import { getExecutionTime } from './execution-time.js';
2
+ export const signalReceived = (process, startTime, event) => () => {
3
+ console.log(`Done after ${String(getExecutionTime(startTime))}s`);
4
+ process.kill(process.pid, event);
5
+ process.exit(1);
6
+ };
7
+ export const handleSignals = (process, startTime) => {
8
+ const catchSignals = ['SIGTERM', 'SIGINT', 'SIGUSR2'];
9
+ catchSignals.map((event) => {
10
+ return process.once(event, signalReceived(process, startTime, event));
11
+ });
12
+ };
@@ -0,0 +1,3 @@
1
+ export function isTTY(process) {
2
+ return process.stdout.isTTY || false;
3
+ }
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { execSync } from 'node:child_process';
3
+ import { resolve } from 'node:path';
4
+ describe('CLI Integration', () => {
5
+ describe('--help', () => {
6
+ it('should display help information', () => {
7
+ const result = execSync('npm run build && node ./dist/src/cli.js --help', {
8
+ encoding: 'utf-8',
9
+ cwd: resolve(__dirname, '../..'),
10
+ });
11
+ expect(result).toContain('Usage:');
12
+ expect(result).toContain('--input');
13
+ expect(result).toContain('--output');
14
+ });
15
+ });
16
+ describe('--version', () => {
17
+ it('should display version information', () => {
18
+ const result = execSync('npm run build && node ./dist/src/cli.js --version', {
19
+ encoding: 'utf-8',
20
+ cwd: resolve(__dirname, '../..'),
21
+ });
22
+ expect(result).toMatch(/\d+\.\d+\.\d+/);
23
+ });
24
+ });
25
+ });
@@ -0,0 +1,29 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { Generator } from '../../src/generator.js';
3
+ describe('Generator', () => {
4
+ let generator;
5
+ let mockReporter;
6
+ beforeEach(() => {
7
+ // Create a mock reporter
8
+ mockReporter = {
9
+ info: vi.fn(),
10
+ error: vi.fn(),
11
+ warn: vi.fn(),
12
+ success: vi.fn(),
13
+ };
14
+ generator = new Generator('test-app', '1.0.0', mockReporter, './test-input.json', './test-output');
15
+ });
16
+ describe('constructor', () => {
17
+ it('should create a new Generator instance', () => {
18
+ expect(generator).toBeInstanceOf(Generator);
19
+ });
20
+ });
21
+ describe('run', () => {
22
+ it('should be a function', () => {
23
+ expect(typeof generator.run).toBe('function');
24
+ });
25
+ it('should have the run method defined', () => {
26
+ expect(generator).toHaveProperty('run');
27
+ });
28
+ });
29
+ });
@@ -0,0 +1,38 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import { resolve } from 'node:path';
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
8
+ exclude: ['node_modules', 'dist', 'coverage'],
9
+ coverage: {
10
+ provider: 'v8',
11
+ reporter: ['text', 'json', 'html', 'lcov'],
12
+ exclude: [
13
+ 'coverage/**',
14
+ 'dist/**',
15
+ 'node_modules/**',
16
+ '**/*.d.ts',
17
+ '**/*.config.*',
18
+ '**/*.test.*',
19
+ '**/*.spec.*',
20
+ 'scripts/**',
21
+ 'samples/**',
22
+ ],
23
+ thresholds: {
24
+ global: {
25
+ branches: 80,
26
+ functions: 80,
27
+ lines: 80,
28
+ statements: 80,
29
+ },
30
+ },
31
+ },
32
+ },
33
+ resolve: {
34
+ alias: {
35
+ '@': resolve(__dirname, 'src'),
36
+ },
37
+ },
38
+ });
@@ -0,0 +1,33 @@
1
+ import eslint from '@eslint/js';
2
+ import { defineConfig } from 'eslint/config';
3
+ import tseslint from 'typescript-eslint';
4
+
5
+ export default defineConfig([
6
+ {
7
+ ignores: [
8
+ '**/*.mjs',
9
+ 'dist/**/*',
10
+ 'node_modules/**/*',
11
+ ],
12
+ },
13
+ eslint.configs.recommended,
14
+ tseslint.configs.strictTypeChecked,
15
+ tseslint.configs.stylisticTypeChecked,
16
+ {
17
+ languageOptions: {
18
+ parserOptions: {
19
+ projectService: true,
20
+ },
21
+ },
22
+ rules: {
23
+ quotes: ['error', 'single', { avoidEscape: true }],
24
+ 'sort-imports': [
25
+ 'error',
26
+ {
27
+ ignoreCase: true,
28
+ ignoreDeclarationSort: true,
29
+ },
30
+ ],
31
+ },
32
+ },
33
+ ]);
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "author": "Julien Andreu <julienandreu@me.com>",
3
+ "bin": {
4
+ "zod-codegen": "dist/src/cli.js"
5
+ },
6
+ "bugs": {
7
+ "url": "https://github.com/julienandreu/zod-codegen/issues"
8
+ },
9
+ "dependencies": {
10
+ "@apidevtools/swagger-parser": "^10.1.0",
11
+ "debug": "^4.3.7",
12
+ "js-yaml": "^4.1.0",
13
+ "jsonpath": "^1.1.1",
14
+ "loud-rejection": "^2.2.0",
15
+ "openapi-types": "^12.1.3",
16
+ "openapi-typescript": "^7.4.0",
17
+ "path-to-regexp": "^8.2.0",
18
+ "prettier": "^3.3.3",
19
+ "typescript": "^5.7.2",
20
+ "url-pattern": "^1.0.3",
21
+ "yargs": "^18.0.0",
22
+ "zod": "^3.23.8"
23
+ },
24
+ "description": "A powerful TypeScript code generator that creates Zod schemas and type-safe clients from OpenAPI specifications",
25
+ "keywords": [
26
+ "zod",
27
+ "openapi",
28
+ "swagger",
29
+ "codegen",
30
+ "typescript",
31
+ "type-safe",
32
+ "api",
33
+ "schema",
34
+ "validation"
35
+ ],
36
+ "devDependencies": {
37
+ "@commitlint/cli": "^19.8.1",
38
+ "@commitlint/config-conventional": "^19.8.1",
39
+ "@eslint/js": "^9.17.0",
40
+ "@semantic-release/changelog": "^6.0.3",
41
+ "@semantic-release/git": "^10.0.1",
42
+ "@types/debug": "^4.1.12",
43
+ "@types/jest": "^30.0.0",
44
+ "@types/js-yaml": "^4.0.9",
45
+ "@types/jsonpath": "^0.2.4",
46
+ "@types/node": "^22.10.2",
47
+ "@types/yargs": "^17.0.33",
48
+ "@vitest/coverage-v8": "^3.2.4",
49
+ "eslint": "^9.17.0",
50
+ "eslint-config-prettier": "^9.1.0",
51
+ "husky": "^9.1.7",
52
+ "lint-staged": "^16.1.6",
53
+ "semantic-release": "^24.2.8",
54
+ "ts-node": "^10.9.2",
55
+ "typescript-eslint": "^8.18.1",
56
+ "undici": "^6.21.0",
57
+ "vitest": "^3.2.4"
58
+ },
59
+ "optionalDependencies": {
60
+ "undici": "^6.21.0"
61
+ },
62
+ "homepage": "https://github.com/julienandreu/zod-codegen",
63
+ "license": "MIT",
64
+ "name": "zod-codegen",
65
+ "type": "module",
66
+ "exports": {
67
+ ".": {
68
+ "types": "./dist/src/generator-v2.d.ts",
69
+ "import": "./dist/src/generator-v2.js",
70
+ "require": "./dist/src/generator-v2.js"
71
+ }
72
+ },
73
+ "repository": {
74
+ "type": "git",
75
+ "url": "git+ssh://git@github.com/julienandreu/zod-codegen.git"
76
+ },
77
+ "engines": {
78
+ "node": ">=20.0.0"
79
+ },
80
+ "scripts": {
81
+ "build": "rm -rf dist && tsc --project tsconfig.json && cp -r src/assets dist/src/ && chmod +x ./dist/src/cli.js",
82
+ "build:watch": "tsc --project tsconfig.json --watch",
83
+ "dev": "npm run build && node ./dist/src/cli.js --input ./samples/saris-openapi.json && npm run format && npm run lint",
84
+ "lint": "eslint src --fix",
85
+ "lint:check": "eslint src",
86
+ "format": "prettier src --write --log-level error",
87
+ "format:check": "prettier src --check",
88
+ "type-check": "tsc -p ./tsconfig.json --noEmit",
89
+ "test": "vitest run",
90
+ "test:watch": "vitest",
91
+ "test:coverage": "vitest run --coverage",
92
+ "test:ui": "vitest --ui",
93
+ "manifest:update": "ts-node scripts/update-manifest.ts",
94
+ "prepare": "husky",
95
+ "prepublishOnly": "npm run build && npm run test && npm run lint:check && npm run type-check",
96
+ "clean": "rm -rf dist coverage node_modules/.cache",
97
+ "validate": "npm run type-check && npm run lint:check && npm run format:check && npm run test",
98
+ "release": "semantic-release",
99
+ "release:dry": "semantic-release --dry-run"
100
+ },
101
+ "version": "1.0.0"
102
+ }