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.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +93 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +70 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +87 -0
- package/.github/dependabot.yml +76 -0
- package/.github/workflows/ci.yml +143 -0
- package/.github/workflows/release.yml +65 -0
- package/.husky/commit-msg +2 -0
- package/.husky/pre-commit +5 -0
- package/.lintstagedrc.json +4 -0
- package/.nvmrc +1 -0
- package/.prettierrc.json +7 -0
- package/.releaserc.json +159 -0
- package/CHANGELOG.md +24 -0
- package/CONTRIBUTING.md +274 -0
- package/LICENCE +201 -0
- package/README.md +263 -0
- package/SECURITY.md +108 -0
- package/codecov.yml +29 -0
- package/commitlint.config.mjs +28 -0
- package/dist/scripts/update-manifest.js +31 -0
- package/dist/src/assets/manifest.json +5 -0
- package/dist/src/cli.js +60 -0
- package/dist/src/generator.js +55 -0
- package/dist/src/http/fetch-client.js +141 -0
- package/dist/src/interfaces/code-generator.js +1 -0
- package/dist/src/interfaces/file-reader.js +1 -0
- package/dist/src/polyfills/fetch.js +18 -0
- package/dist/src/services/code-generator.service.js +419 -0
- package/dist/src/services/file-reader.service.js +25 -0
- package/dist/src/services/file-writer.service.js +32 -0
- package/dist/src/services/import-builder.service.js +45 -0
- package/dist/src/services/type-builder.service.js +42 -0
- package/dist/src/types/http.js +10 -0
- package/dist/src/types/openapi.js +173 -0
- package/dist/src/utils/error-handler.js +11 -0
- package/dist/src/utils/execution-time.js +3 -0
- package/dist/src/utils/manifest.js +9 -0
- package/dist/src/utils/reporter.js +15 -0
- package/dist/src/utils/signal-handler.js +12 -0
- package/dist/src/utils/tty.js +3 -0
- package/dist/tests/integration/cli.test.js +25 -0
- package/dist/tests/unit/generator.test.js +29 -0
- package/dist/vitest.config.js +38 -0
- package/eslint.config.mjs +33 -0
- package/package.json +102 -0
- package/samples/openapi.json +1 -0
- package/samples/saris-openapi.json +7122 -0
- package/samples/swagger-petstore.yaml +802 -0
- package/samples/swagger-saris.yaml +3585 -0
- package/samples/test-logical.yaml +50 -0
- package/scripts/update-manifest.js +31 -0
- package/scripts/update-manifest.ts +47 -0
- package/src/assets/manifest.json +5 -0
- package/src/cli.ts +68 -0
- package/src/generator.ts +61 -0
- package/src/http/fetch-client.ts +181 -0
- package/src/interfaces/code-generator.ts +25 -0
- package/src/interfaces/file-reader.ts +15 -0
- package/src/polyfills/fetch.ts +26 -0
- package/src/services/code-generator.service.ts +775 -0
- package/src/services/file-reader.service.ts +29 -0
- package/src/services/file-writer.service.ts +36 -0
- package/src/services/import-builder.service.ts +64 -0
- package/src/services/type-builder.service.ts +77 -0
- package/src/types/http.ts +35 -0
- package/src/types/openapi.ts +202 -0
- package/src/utils/error-handler.ts +13 -0
- package/src/utils/execution-time.ts +3 -0
- package/src/utils/manifest.ts +17 -0
- package/src/utils/reporter.ts +16 -0
- package/src/utils/signal-handler.ts +14 -0
- package/src/utils/tty.ts +3 -0
- package/tests/integration/cli.test.ts +29 -0
- package/tests/unit/generator.test.ts +36 -0
- package/tsconfig.json +44 -0
- package/vitest.config.ts +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# zod-codegen
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/zod-codegen)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://github.com/julienandreu/zod-codegen/actions)
|
|
7
|
+
[](https://codecov.io/gh/julienandreu/zod-codegen)
|
|
8
|
+
|
|
9
|
+
A powerful TypeScript code generator that creates **Zod schemas** and **type-safe clients** from OpenAPI specifications.
|
|
10
|
+
|
|
11
|
+
## 🚀 Features
|
|
12
|
+
|
|
13
|
+
- **🔥 Zod Schema Generation**: Automatically generate Zod validation schemas from OpenAPI specs
|
|
14
|
+
- **🎯 Type-Safe**: Full TypeScript support with generated types
|
|
15
|
+
- **📡 Multiple Formats**: Support for OpenAPI 3.x, Swagger 2.0, JSON, and YAML
|
|
16
|
+
- **🌐 Remote Files**: Fetch OpenAPI specs from URLs
|
|
17
|
+
- **⚡ Fast**: Optimized for performance with minimal dependencies
|
|
18
|
+
- **🔧 Configurable**: Flexible output options and customization
|
|
19
|
+
- **📦 CLI & Programmatic**: Use as a CLI tool or integrate into your build process
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
22
|
+
|
|
23
|
+
### Global Installation (CLI)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g zod-codegen
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Project Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install --save-dev zod-codegen
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🔧 Usage
|
|
36
|
+
|
|
37
|
+
### Command Line Interface
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Generate from local file
|
|
41
|
+
zod-codegen --input ./openapi.json --output ./generated
|
|
42
|
+
|
|
43
|
+
# Generate from URL
|
|
44
|
+
zod-codegen --input https://api.example.com/openapi.json --output ./api
|
|
45
|
+
|
|
46
|
+
# Generate with custom output directory
|
|
47
|
+
zod-codegen -i ./swagger.yaml -o ./src/generated
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### CLI Options
|
|
51
|
+
|
|
52
|
+
| Option | Alias | Description | Default |
|
|
53
|
+
| ----------- | ----- | ----------------------------------- | ----------- |
|
|
54
|
+
| `--input` | `-i` | Path or URL to OpenAPI file | Required |
|
|
55
|
+
| `--output` | `-o` | Directory to output generated files | `generated` |
|
|
56
|
+
| `--help` | `-h` | Show help | |
|
|
57
|
+
| `--version` | `-v` | Show version | |
|
|
58
|
+
|
|
59
|
+
### Programmatic Usage
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import {Generator} from 'zod-codegen';
|
|
63
|
+
|
|
64
|
+
const generator = new Generator();
|
|
65
|
+
|
|
66
|
+
// Generate from local file
|
|
67
|
+
await generator.generate({
|
|
68
|
+
input: './openapi.json',
|
|
69
|
+
output: './generated',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Generate from URL
|
|
73
|
+
await generator.generate({
|
|
74
|
+
input: 'https://api.example.com/openapi.json',
|
|
75
|
+
output: './api',
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 📁 Generated Output
|
|
80
|
+
|
|
81
|
+
The generator creates the following structure:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
generated/
|
|
85
|
+
├── schemas/ # Zod validation schemas
|
|
86
|
+
│ ├── user.schema.ts
|
|
87
|
+
│ └── product.schema.ts
|
|
88
|
+
├── types/ # TypeScript type definitions
|
|
89
|
+
│ ├── user.types.ts
|
|
90
|
+
│ └── product.types.ts
|
|
91
|
+
└── client/ # Type-safe API client
|
|
92
|
+
└── api.client.ts
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 🎯 Example
|
|
96
|
+
|
|
97
|
+
Given this OpenAPI specification:
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
openapi: 3.0.0
|
|
101
|
+
info:
|
|
102
|
+
title: User API
|
|
103
|
+
version: 1.0.0
|
|
104
|
+
paths:
|
|
105
|
+
/users:
|
|
106
|
+
get:
|
|
107
|
+
responses:
|
|
108
|
+
'200':
|
|
109
|
+
content:
|
|
110
|
+
application/json:
|
|
111
|
+
schema:
|
|
112
|
+
type: object
|
|
113
|
+
properties:
|
|
114
|
+
id:
|
|
115
|
+
type: integer
|
|
116
|
+
name:
|
|
117
|
+
type: string
|
|
118
|
+
email:
|
|
119
|
+
type: string
|
|
120
|
+
format: email
|
|
121
|
+
required: [id, name, email]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Generated Zod Schema** (`schemas/user.schema.ts`):
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import {z} from 'zod';
|
|
128
|
+
|
|
129
|
+
export const UserSchema = z.object({
|
|
130
|
+
id: z.number().int(),
|
|
131
|
+
name: z.string(),
|
|
132
|
+
email: z.string().email(),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export type User = z.infer<typeof UserSchema>;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Generated Types** (`types/user.types.ts`):
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
export interface User {
|
|
142
|
+
id: number;
|
|
143
|
+
name: string;
|
|
144
|
+
email: string;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Generated Client** (`client/api.client.ts`):
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import {UserSchema, type User} from '../schemas/user.schema.js';
|
|
152
|
+
|
|
153
|
+
export class ApiClient {
|
|
154
|
+
async getUsers(): Promise<User[]> {
|
|
155
|
+
const response = await fetch('/api/users');
|
|
156
|
+
const data = await response.json();
|
|
157
|
+
return UserSchema.array().parse(data);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🛠️ Development
|
|
163
|
+
|
|
164
|
+
### Prerequisites
|
|
165
|
+
|
|
166
|
+
- Node.js ≥ 18.0.0
|
|
167
|
+
- npm or yarn
|
|
168
|
+
|
|
169
|
+
### Setup
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Clone the repository
|
|
173
|
+
git clone https://github.com/julienandreu/zod-codegen.git
|
|
174
|
+
cd zod-codegen
|
|
175
|
+
|
|
176
|
+
# Install dependencies
|
|
177
|
+
npm install
|
|
178
|
+
|
|
179
|
+
# Build the project
|
|
180
|
+
npm run build
|
|
181
|
+
|
|
182
|
+
# Run tests
|
|
183
|
+
npm test
|
|
184
|
+
|
|
185
|
+
# Run linting
|
|
186
|
+
npm run lint
|
|
187
|
+
|
|
188
|
+
# Format code
|
|
189
|
+
npm run format
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Testing
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Run all tests
|
|
196
|
+
npm test
|
|
197
|
+
|
|
198
|
+
# Run tests in watch mode
|
|
199
|
+
npm run test:watch
|
|
200
|
+
|
|
201
|
+
# Run tests with coverage
|
|
202
|
+
npm run test:coverage
|
|
203
|
+
|
|
204
|
+
# Run tests with UI
|
|
205
|
+
npm run test:ui
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Available Scripts
|
|
209
|
+
|
|
210
|
+
| Script | Description |
|
|
211
|
+
| ----------------------- | ----------------------------------------------- |
|
|
212
|
+
| `npm run build` | Build the project |
|
|
213
|
+
| `npm run build:watch` | Build in watch mode |
|
|
214
|
+
| `npm run dev` | Development mode with example |
|
|
215
|
+
| `npm test` | Run tests |
|
|
216
|
+
| `npm run test:watch` | Run tests in watch mode |
|
|
217
|
+
| `npm run test:coverage` | Run tests with coverage |
|
|
218
|
+
| `npm run lint` | Lint and fix code |
|
|
219
|
+
| `npm run format` | Format code with Prettier |
|
|
220
|
+
| `npm run type-check` | Type check without emitting |
|
|
221
|
+
| `npm run validate` | Run all checks (lint, format, type-check, test) |
|
|
222
|
+
| `npm run clean` | Clean build artifacts |
|
|
223
|
+
|
|
224
|
+
## 📋 Requirements
|
|
225
|
+
|
|
226
|
+
- **Node.js**: ≥ 18.0.0
|
|
227
|
+
- **TypeScript**: ≥ 5.0.0
|
|
228
|
+
- **Zod**: ≥ 3.20.0
|
|
229
|
+
|
|
230
|
+
## 🤝 Contributing
|
|
231
|
+
|
|
232
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
233
|
+
|
|
234
|
+
### Quick Start for Contributors
|
|
235
|
+
|
|
236
|
+
1. Fork the repository
|
|
237
|
+
2. Create your feature branch: `git checkout -b feature/amazing-feature`
|
|
238
|
+
3. Make your changes
|
|
239
|
+
4. Run tests: `npm test`
|
|
240
|
+
5. Run validation: `npm run validate`
|
|
241
|
+
6. Commit your changes: `git commit -m 'feat: add amazing feature'`
|
|
242
|
+
7. Push to the branch: `git push origin feature/amazing-feature`
|
|
243
|
+
8. Open a Pull Request
|
|
244
|
+
|
|
245
|
+
## 📝 License
|
|
246
|
+
|
|
247
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
248
|
+
|
|
249
|
+
## 🙏 Acknowledgments
|
|
250
|
+
|
|
251
|
+
- [Zod](https://zod.dev/) - TypeScript-first schema validation
|
|
252
|
+
- [OpenAPI Specification](https://www.openapis.org/) - API specification standard
|
|
253
|
+
- [TypeScript](https://www.typescriptlang.org/) - Typed JavaScript
|
|
254
|
+
|
|
255
|
+
## 📞 Support
|
|
256
|
+
|
|
257
|
+
- 🐛 **Bug reports**: [GitHub Issues](https://github.com/julienandreu/zod-codegen/issues)
|
|
258
|
+
- 💬 **Questions**: [GitHub Discussions](https://github.com/julienandreu/zod-codegen/discussions)
|
|
259
|
+
- 📧 **Email**: [julienandreu@me.com](mailto:julienandreu@me.com)
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
Made with ❤️ by [Julien Andreu](https://github.com/julienandreu)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
We actively support the following versions of zod-codegen:
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| ------- | ------------------ |
|
|
9
|
+
| 1.x.x | :white_check_mark: |
|
|
10
|
+
| 0.1.x | :white_check_mark: |
|
|
11
|
+
|
|
12
|
+
## Reporting a Vulnerability
|
|
13
|
+
|
|
14
|
+
The zod-codegen team takes security bugs seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
|
|
15
|
+
|
|
16
|
+
### How to Report Security Issues
|
|
17
|
+
|
|
18
|
+
**Please do not report security vulnerabilities through public GitHub issues.**
|
|
19
|
+
|
|
20
|
+
Instead, please report them via email to: [julienandreu@me.com](mailto:julienandreu@me.com)
|
|
21
|
+
|
|
22
|
+
Please include the following information in your report:
|
|
23
|
+
|
|
24
|
+
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
|
25
|
+
- Full paths of source file(s) related to the manifestation of the issue
|
|
26
|
+
- The location of the affected source code (tag/branch/commit or direct URL)
|
|
27
|
+
- Any special configuration required to reproduce the issue
|
|
28
|
+
- Step-by-step instructions to reproduce the issue
|
|
29
|
+
- Proof-of-concept or exploit code (if possible)
|
|
30
|
+
- Impact of the issue, including how an attacker might exploit the issue
|
|
31
|
+
|
|
32
|
+
This information will help us triage your report more quickly.
|
|
33
|
+
|
|
34
|
+
### Response Timeline
|
|
35
|
+
|
|
36
|
+
- **Initial Response**: We will acknowledge receipt of your vulnerability report within 48 hours.
|
|
37
|
+
- **Progress Updates**: We will send you regular updates about our progress, at least every 7 days.
|
|
38
|
+
- **Resolution**: We aim to resolve critical vulnerabilities within 30 days of the initial report.
|
|
39
|
+
|
|
40
|
+
### Disclosure Policy
|
|
41
|
+
|
|
42
|
+
When we receive a security bug report, we will:
|
|
43
|
+
|
|
44
|
+
1. Confirm the problem and determine the affected versions
|
|
45
|
+
2. Audit code to find any potential similar problems
|
|
46
|
+
3. Prepare fixes for all supported versions
|
|
47
|
+
4. Release new versions as soon as possible
|
|
48
|
+
5. Prominently announce the issue in the release notes
|
|
49
|
+
|
|
50
|
+
### Bug Bounty Program
|
|
51
|
+
|
|
52
|
+
Currently, we do not offer a paid bug bounty program. We express our gratitude to security researchers through:
|
|
53
|
+
|
|
54
|
+
- Public acknowledgment in our security advisories (if desired)
|
|
55
|
+
- Recognition in our project documentation
|
|
56
|
+
- Direct communication and thanks from our team
|
|
57
|
+
|
|
58
|
+
## Security Best Practices
|
|
59
|
+
|
|
60
|
+
When using zod-codegen, please follow these security best practices:
|
|
61
|
+
|
|
62
|
+
### Input Validation
|
|
63
|
+
|
|
64
|
+
- Always validate OpenAPI specifications from untrusted sources
|
|
65
|
+
- Be cautious when processing large or complex OpenAPI files
|
|
66
|
+
- Consider file size limits and timeout mechanisms
|
|
67
|
+
|
|
68
|
+
### Output Security
|
|
69
|
+
|
|
70
|
+
- Review generated code before using in production
|
|
71
|
+
- Ensure generated validation schemas are appropriate for your use case
|
|
72
|
+
- Test generated code thoroughly
|
|
73
|
+
|
|
74
|
+
### Dependencies
|
|
75
|
+
|
|
76
|
+
- Keep zod-codegen and its dependencies up to date
|
|
77
|
+
- Regularly audit your dependency tree for known vulnerabilities
|
|
78
|
+
- Use tools like `npm audit` to check for security issues
|
|
79
|
+
|
|
80
|
+
## Known Security Considerations
|
|
81
|
+
|
|
82
|
+
### OpenAPI Processing
|
|
83
|
+
|
|
84
|
+
- **File Size**: Very large OpenAPI files may consume significant memory
|
|
85
|
+
- **Circular References**: Complex schemas with circular references are handled but may impact performance
|
|
86
|
+
- **Remote Files**: When fetching OpenAPI specs from URLs, ensure the sources are trusted
|
|
87
|
+
|
|
88
|
+
### Generated Code
|
|
89
|
+
|
|
90
|
+
- **Validation Logic**: Generated Zod schemas provide runtime validation but should be part of a broader security strategy
|
|
91
|
+
- **Type Safety**: While generated TypeScript types provide compile-time safety, always validate runtime data
|
|
92
|
+
|
|
93
|
+
## Security Updates
|
|
94
|
+
|
|
95
|
+
Security updates will be clearly marked in our release notes and will be given priority in our release schedule. We recommend:
|
|
96
|
+
|
|
97
|
+
- Subscribing to release notifications
|
|
98
|
+
- Keeping your installation up to date
|
|
99
|
+
- Testing updates in a development environment before production deployment
|
|
100
|
+
|
|
101
|
+
## Contact
|
|
102
|
+
|
|
103
|
+
For questions about this security policy, please contact:
|
|
104
|
+
|
|
105
|
+
- Email: [julienandreu@me.com](mailto:julienandreu@me.com)
|
|
106
|
+
- GitHub: [@julienandreu](https://github.com/julienandreu)
|
|
107
|
+
|
|
108
|
+
Thank you for helping keep zod-codegen and our users safe!
|
package/codecov.yml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
coverage:
|
|
2
|
+
status:
|
|
3
|
+
project:
|
|
4
|
+
default:
|
|
5
|
+
target: 80%
|
|
6
|
+
threshold: 2%
|
|
7
|
+
base: auto
|
|
8
|
+
patch:
|
|
9
|
+
default:
|
|
10
|
+
target: 80%
|
|
11
|
+
threshold: 2%
|
|
12
|
+
base: auto
|
|
13
|
+
|
|
14
|
+
ignore:
|
|
15
|
+
- 'dist/'
|
|
16
|
+
- 'coverage/'
|
|
17
|
+
- 'node_modules/'
|
|
18
|
+
- '**/*.d.ts'
|
|
19
|
+
- '**/*.config.*'
|
|
20
|
+
- '**/*.test.*'
|
|
21
|
+
- '**/*.spec.*'
|
|
22
|
+
- 'scripts/'
|
|
23
|
+
- 'samples/'
|
|
24
|
+
- '.github/'
|
|
25
|
+
|
|
26
|
+
comment:
|
|
27
|
+
layout: 'reach,diff,flags,tree'
|
|
28
|
+
behavior: default
|
|
29
|
+
require_changes: false
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
extends: ['@commitlint/config-conventional'],
|
|
3
|
+
rules: {
|
|
4
|
+
'type-enum': [
|
|
5
|
+
2,
|
|
6
|
+
'always',
|
|
7
|
+
[
|
|
8
|
+
'feat',
|
|
9
|
+
'fix',
|
|
10
|
+
'docs',
|
|
11
|
+
'style',
|
|
12
|
+
'refactor',
|
|
13
|
+
'perf',
|
|
14
|
+
'test',
|
|
15
|
+
'build',
|
|
16
|
+
'ci',
|
|
17
|
+
'chore',
|
|
18
|
+
'revert',
|
|
19
|
+
],
|
|
20
|
+
],
|
|
21
|
+
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
|
|
22
|
+
'subject-empty': [2, 'never'],
|
|
23
|
+
'subject-full-stop': [2, 'never', '.'],
|
|
24
|
+
'header-max-length': [2, 'always', 100],
|
|
25
|
+
'footer-max-line-length': [0],
|
|
26
|
+
'footer-leading-blank': [0],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
/**
|
|
5
|
+
* Type guard for the package.json object
|
|
6
|
+
*
|
|
7
|
+
* @param input Unknown input
|
|
8
|
+
* @returns true if the input is an event object
|
|
9
|
+
*/
|
|
10
|
+
export function isPackageJson(input) {
|
|
11
|
+
const event = z
|
|
12
|
+
.object({
|
|
13
|
+
name: z.string(),
|
|
14
|
+
version: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
})
|
|
17
|
+
.strict()
|
|
18
|
+
.catchall(z.any())
|
|
19
|
+
.required();
|
|
20
|
+
const { success } = event.safeParse(input);
|
|
21
|
+
return success;
|
|
22
|
+
}
|
|
23
|
+
const sourcePath = resolve(__dirname, '..', 'package.json');
|
|
24
|
+
const data = JSON.parse(readFileSync(sourcePath, 'utf8'));
|
|
25
|
+
if (!isPackageJson(data)) {
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const { name, version, description } = data;
|
|
29
|
+
const targetPath = resolve(__dirname, '..', 'src', 'assets', 'manifest.json');
|
|
30
|
+
writeFileSync(targetPath, JSON.stringify({ name, version, description }, null, 2));
|
|
31
|
+
process.exit(0);
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import yargs from 'yargs';
|
|
3
|
+
import { hideBin } from 'yargs/helpers';
|
|
4
|
+
import { Generator } from './generator.js';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
import loudRejection from 'loud-rejection';
|
|
9
|
+
import { handleErrors } from './utils/error-handler.js';
|
|
10
|
+
import { handleSignals } from './utils/signal-handler.js';
|
|
11
|
+
import debug from 'debug';
|
|
12
|
+
import { isManifest } from './utils/manifest.js';
|
|
13
|
+
import { Reporter } from './utils/reporter.js';
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const manifestData = JSON.parse(readFileSync(join(__dirname, 'assets', 'manifest.json'), 'utf-8'));
|
|
16
|
+
if (!isManifest(manifestData)) {
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const { name, description, version } = manifestData;
|
|
20
|
+
const reporter = new Reporter(process.stdout);
|
|
21
|
+
const startTime = process.hrtime.bigint();
|
|
22
|
+
debug(`${name}:${String(process.pid)}`);
|
|
23
|
+
loudRejection();
|
|
24
|
+
handleSignals(process, startTime);
|
|
25
|
+
handleErrors(process, startTime);
|
|
26
|
+
const argv = yargs(hideBin(process.argv))
|
|
27
|
+
.scriptName(name)
|
|
28
|
+
.usage(`${description}\n\nUsage: $0 [options]`)
|
|
29
|
+
.version(version)
|
|
30
|
+
.option('input', {
|
|
31
|
+
alias: 'i',
|
|
32
|
+
type: 'string',
|
|
33
|
+
description: 'Path or URL to OpenAPI file',
|
|
34
|
+
demandOption: true,
|
|
35
|
+
})
|
|
36
|
+
.option('output', {
|
|
37
|
+
alias: 'o',
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'Directory to output the generated files',
|
|
40
|
+
default: 'generated',
|
|
41
|
+
})
|
|
42
|
+
.help()
|
|
43
|
+
.parseSync();
|
|
44
|
+
const { input, output } = argv;
|
|
45
|
+
void (async () => {
|
|
46
|
+
try {
|
|
47
|
+
const generator = new Generator(name, version, reporter, input, output);
|
|
48
|
+
const exitCode = await generator.run();
|
|
49
|
+
process.exit(exitCode);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof Error) {
|
|
53
|
+
reporter.error(`Fatal error: ${error.message}`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
reporter.error('An unknown fatal error occurred');
|
|
57
|
+
}
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
})();
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { OpenApiFileParserService, SyncFileReaderService } from './services/file-reader.service.js';
|
|
2
|
+
import { TypeScriptCodeGeneratorService } from './services/code-generator.service.js';
|
|
3
|
+
import { SyncFileWriterService } from './services/file-writer.service.js';
|
|
4
|
+
export class Generator {
|
|
5
|
+
_name;
|
|
6
|
+
_version;
|
|
7
|
+
reporter;
|
|
8
|
+
inputPath;
|
|
9
|
+
_outputDir;
|
|
10
|
+
fileReader = new SyncFileReaderService();
|
|
11
|
+
fileParser = new OpenApiFileParserService();
|
|
12
|
+
codeGenerator = new TypeScriptCodeGeneratorService();
|
|
13
|
+
fileWriter;
|
|
14
|
+
outputPath;
|
|
15
|
+
constructor(_name, _version, reporter, inputPath, _outputDir) {
|
|
16
|
+
this._name = _name;
|
|
17
|
+
this._version = _version;
|
|
18
|
+
this.reporter = reporter;
|
|
19
|
+
this.inputPath = inputPath;
|
|
20
|
+
this._outputDir = _outputDir;
|
|
21
|
+
this.fileWriter = new SyncFileWriterService(this._name, this._version, inputPath);
|
|
22
|
+
this.outputPath = this.fileWriter.resolveOutputPath(this._outputDir);
|
|
23
|
+
}
|
|
24
|
+
async run() {
|
|
25
|
+
try {
|
|
26
|
+
const rawSource = this.readFile();
|
|
27
|
+
const openApiSpec = this.parseFile(rawSource);
|
|
28
|
+
const generatedCode = this.generateCode(openApiSpec);
|
|
29
|
+
this.writeFile(generatedCode);
|
|
30
|
+
this.reporter.log(`✅ Generated types successfully at: ${this.outputPath}`);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof Error) {
|
|
35
|
+
this.reporter.error(`❌ Error: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.reporter.error('❌ An unknown error occurred');
|
|
39
|
+
}
|
|
40
|
+
return Promise.resolve(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
readFile() {
|
|
44
|
+
return this.fileReader.readFile(this.inputPath);
|
|
45
|
+
}
|
|
46
|
+
parseFile(source) {
|
|
47
|
+
return this.fileParser.parse(source);
|
|
48
|
+
}
|
|
49
|
+
generateCode(spec) {
|
|
50
|
+
return this.codeGenerator.generate(spec);
|
|
51
|
+
}
|
|
52
|
+
writeFile(content) {
|
|
53
|
+
this.fileWriter.writeFile(this.outputPath, content);
|
|
54
|
+
}
|
|
55
|
+
}
|