schemantic 0.3.0 โ†’ 0.4.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 (124) hide show
  1. package/CHANGELOG.md +196 -174
  2. package/LICENSE +21 -21
  3. package/README.md +88 -830
  4. package/dist/cli/index.d.ts +4 -1
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +185 -61
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/core/configuration.d.ts +6 -0
  9. package/dist/core/configuration.d.ts.map +1 -0
  10. package/dist/core/configuration.js +64 -0
  11. package/dist/core/configuration.js.map +1 -0
  12. package/dist/core/index.d.ts +1 -0
  13. package/dist/core/index.d.ts.map +1 -1
  14. package/dist/core/index.js +1 -0
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/core/output-writer.d.ts +7 -0
  17. package/dist/core/output-writer.d.ts.map +1 -0
  18. package/dist/core/output-writer.js +255 -0
  19. package/dist/core/output-writer.js.map +1 -0
  20. package/dist/core/schemantic.d.ts +8 -2
  21. package/dist/core/schemantic.d.ts.map +1 -1
  22. package/dist/core/schemantic.js +196 -71
  23. package/dist/core/schemantic.js.map +1 -1
  24. package/dist/generators/api-client-generator.d.ts +9 -20
  25. package/dist/generators/api-client-generator.d.ts.map +1 -1
  26. package/dist/generators/api-client-generator.js +364 -424
  27. package/dist/generators/api-client-generator.js.map +1 -1
  28. package/dist/generators/base.d.ts.map +1 -1
  29. package/dist/generators/base.js +7 -25
  30. package/dist/generators/base.js.map +1 -1
  31. package/dist/generators/enum-generator.d.ts.map +1 -1
  32. package/dist/generators/enum-generator.js +30 -3
  33. package/dist/generators/enum-generator.js.map +1 -1
  34. package/dist/generators/hook-generator.d.ts +3 -17
  35. package/dist/generators/hook-generator.d.ts.map +1 -1
  36. package/dist/generators/hook-generator.js +51 -445
  37. package/dist/generators/hook-generator.js.map +1 -1
  38. package/dist/generators/naming.d.ts +10 -0
  39. package/dist/generators/naming.d.ts.map +1 -0
  40. package/dist/generators/naming.js +331 -0
  41. package/dist/generators/naming.js.map +1 -0
  42. package/dist/generators/object-generator.d.ts +0 -4
  43. package/dist/generators/object-generator.d.ts.map +1 -1
  44. package/dist/generators/object-generator.js +13 -101
  45. package/dist/generators/object-generator.js.map +1 -1
  46. package/dist/generators/primitive-generator.d.ts +1 -13
  47. package/dist/generators/primitive-generator.d.ts.map +1 -1
  48. package/dist/generators/primitive-generator.js +11 -76
  49. package/dist/generators/primitive-generator.js.map +1 -1
  50. package/dist/generators/projections.d.ts +10 -0
  51. package/dist/generators/projections.d.ts.map +1 -0
  52. package/dist/generators/projections.js +65 -0
  53. package/dist/generators/projections.js.map +1 -0
  54. package/dist/generators/schema-type.d.ts +23 -0
  55. package/dist/generators/schema-type.d.ts.map +1 -0
  56. package/dist/generators/schema-type.js +233 -0
  57. package/dist/generators/schema-type.js.map +1 -0
  58. package/dist/parsers/base.d.ts +2 -0
  59. package/dist/parsers/base.d.ts.map +1 -1
  60. package/dist/parsers/base.js +12 -2
  61. package/dist/parsers/base.js.map +1 -1
  62. package/dist/parsers/factory.d.ts.map +1 -1
  63. package/dist/parsers/factory.js +2 -1
  64. package/dist/parsers/factory.js.map +1 -1
  65. package/dist/parsers/openapi.d.ts +4 -0
  66. package/dist/parsers/openapi.d.ts.map +1 -1
  67. package/dist/parsers/openapi.js +107 -20
  68. package/dist/parsers/openapi.js.map +1 -1
  69. package/dist/plugins/branded-types.d.ts.map +1 -1
  70. package/dist/plugins/branded-types.js +231 -365
  71. package/dist/plugins/branded-types.js.map +1 -1
  72. package/dist/plugins/builtin.d.ts.map +1 -1
  73. package/dist/plugins/builtin.js +6 -141
  74. package/dist/plugins/builtin.js.map +1 -1
  75. package/dist/plugins/index.d.ts +4 -0
  76. package/dist/plugins/index.d.ts.map +1 -1
  77. package/dist/plugins/index.js +17 -0
  78. package/dist/plugins/index.js.map +1 -1
  79. package/dist/plugins/loader.d.ts +5 -1
  80. package/dist/plugins/loader.d.ts.map +1 -1
  81. package/dist/plugins/loader.js +42 -5
  82. package/dist/plugins/loader.js.map +1 -1
  83. package/dist/plugins/manager.d.ts.map +1 -1
  84. package/dist/plugins/manager.js +7 -7
  85. package/dist/plugins/manager.js.map +1 -1
  86. package/dist/plugins/performance-monitoring.d.ts +31 -1
  87. package/dist/plugins/performance-monitoring.d.ts.map +1 -1
  88. package/dist/plugins/performance-monitoring.js +146 -207
  89. package/dist/plugins/performance-monitoring.js.map +1 -1
  90. package/dist/plugins/request-deduplication.d.ts.map +1 -1
  91. package/dist/plugins/request-deduplication.js +151 -586
  92. package/dist/plugins/request-deduplication.js.map +1 -1
  93. package/dist/plugins/zod-validation.d.ts +23 -15
  94. package/dist/plugins/zod-validation.d.ts.map +1 -1
  95. package/dist/plugins/zod-validation.js +390 -268
  96. package/dist/plugins/zod-validation.js.map +1 -1
  97. package/dist/types/core.d.ts +20 -3
  98. package/dist/types/core.d.ts.map +1 -1
  99. package/dist/types/core.js +2 -0
  100. package/dist/types/core.js.map +1 -1
  101. package/dist/types/openapi.d.ts +14 -1
  102. package/dist/types/openapi.d.ts.map +1 -1
  103. package/docs/ADVANCED_PLUGINS_IMPLEMENTATION.md +24 -355
  104. package/docs/ADVANCED_PLUGIN_DEVELOPMENT.md +33 -309
  105. package/docs/API.md +80 -601
  106. package/docs/AUDIT.md +49 -0
  107. package/docs/CONFIGURATION.md +81 -715
  108. package/docs/FASTAPI_TUTORIAL.md +109 -1497
  109. package/docs/NAMING_MIGRATION.md +59 -0
  110. package/docs/PLUGINS.md +49 -687
  111. package/docs/PLUGIN_DEVELOPMENT.md +53 -720
  112. package/docs/REAUDIT.md +399 -0
  113. package/docs/RELEASING.md +88 -0
  114. package/docs/REMEDIATION.md +58 -0
  115. package/docs/superpowers/plans/2026-10-10-audit-remediation.md +113 -0
  116. package/package.json +114 -95
  117. package/dist/__tests__/setup.d.ts +0 -6
  118. package/dist/__tests__/setup.d.ts.map +0 -1
  119. package/dist/__tests__/setup.js +0 -30
  120. package/dist/__tests__/setup.js.map +0 -1
  121. package/dist/__tests__/test-config.d.ts +0 -36
  122. package/dist/__tests__/test-config.d.ts.map +0 -1
  123. package/dist/__tests__/test-config.js +0 -562
  124. package/dist/__tests__/test-config.js.map +0 -1
package/README.md CHANGED
@@ -1,830 +1,88 @@
1
- # Schemantic
2
-
3
- [![npm version](https://badge.fury.io/js/schemantic.svg)](https://badge.fury.io/js/schemantic)
4
- [![CI/CD](https://github.com/cstannahill/schemantic/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/cstannahill/schemantic/actions/workflows/ci-cd.yml)
5
- [![npm downloads](https://img.shields.io/npm/dm/schemantic.svg)](https://www.npmjs.com/package/schemantic)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
- [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green?logo=node.js)](https://nodejs.org/)
9
- [![OpenAPI](https://img.shields.io/badge/OpenAPI-3.x-85EA2D?logo=swagger&logoColor=white)](https://swagger.io/specification/)
10
-
11
- A fully typed, extensible, modular TypeScript type generator for OpenAPI schemas (great with FastAPI). Generate TypeScript types, API clients, and optional hooks with sensible defaults.
12
-
13
- > **Status**: Production Ready ๐Ÿš€ | **Maintenance**: Actively Maintained โœ… | **Support**: Community & Issues ๐Ÿ’ฌ | **Version**: v0.2.0
14
-
15
- ## Features
16
-
17
- - ๐Ÿ”ง **Zero Configuration** - Works out of the box with FastAPI applications
18
- - ๐ŸŽฏ **Fully Typed** - Generates comprehensive TypeScript types with no `any` types
19
- - ๐Ÿงฉ **Modular Architecture** - Extensible plugin system for custom generators
20
- - ๐Ÿš€ **Fast & Efficient** - Optimized for large schemas and complex APIs
21
- - ๐Ÿ“ฆ **Multiple Outputs** - Types, API clients, React hooks, and more
22
- - ๐Ÿ” **Schema Validation** - Built-in OpenAPI schema validation
23
- - ๐ŸŽจ **Customizable** - Flexible naming conventions and type mappings
24
- - ๐Ÿ“š **Well Documented** - Comprehensive documentation and examples
25
-
26
- ## Installation
27
-
28
- ```bash
29
- npm install schemantic
30
- ```
31
-
32
- ## Quick Start
33
-
34
- ### CLI Usage
35
-
36
- Generate types and API client from your OpenAPI schema:
37
-
38
- ```bash
39
- # From URL (recommended)
40
- npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated
41
-
42
- # From file (local snapshot)
43
- npx schemantic generate --file ./schema.json --output ./src/generated
44
-
45
- # With React hooks
46
- npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated --hooks
47
-
48
- # With custom options
49
- npx schemantic generate \
50
- --url http://localhost:8000/openapi.json \
51
- --output ./src/generated \
52
- --naming camelCase \
53
- --prefix "MyAPI" \
54
- --suffix Type
55
- ```
56
-
57
- ### Where to get your OpenAPI schema
58
-
59
- You can point Schemantic at any reachable OpenAPI 3.x JSON. Common frameworks expose it at predictable URLs:
60
-
61
- - FastAPI (default): http://localhost:8000/openapi.json
62
- - ASP.NET Core (.NET): https://localhost:5001/swagger/v1/swagger.json
63
-
64
- Grab a local snapshot if you prefer generating from a file:
65
-
66
- ```bash
67
- # FastAPI
68
- curl -s http://localhost:8000/openapi.json -o ./openapi-schema.json
69
-
70
- # ASP.NET Core (.NET)
71
- curl -k -s https://localhost:5001/swagger/v1/swagger.json -o ./openapi-schema.json
72
-
73
- # Generate from the snapshot
74
- npx schemantic generate --file ./openapi-schema.json --output ./src/generated --client --types
75
- ```
76
-
77
- Notes:
78
-
79
- - On .NET dev certs (HTTPS), use `-k` with curl to skip certificate verification locally.
80
- - In ASP.NET Core, ensure Swagger is enabled in Development (AddSwaggerGen/UseSwagger) and the Swagger endpoint exposes `/swagger/v1/swagger.json`.
81
-
82
- ### Programmatic Usage
83
-
84
- ```typescript
85
- import { Schemantic, SchemanticConfig } from "schemantic";
86
-
87
- const config: SchemanticConfig = {
88
- schemaUrl: "http://localhost:8000/openapi.json",
89
- outputDir: "./src/generated",
90
- generateTypes: true,
91
- generateApiClient: true,
92
- useStrictTypes: true,
93
- namingConvention: "camelCase",
94
- };
95
-
96
- const Schemantic = new Schemantic(config);
97
- Note: React hooks generation is temporarily disabled in the CLI and built-in plugin list due to a known issue causing generation corruption in some schemas. We are tracking a fix โ€” in the meantime, enable hooks by manually enabling the `react-hooks` plugin in your config after reviewing the risks.
98
-
99
- const result = await Schemantic.generate();
100
-
101
- if (result.success) {
102
- console.log(`Generated ${result.generatedFiles.length} files`);
103
- console.log(`Types: ${result.statistics.totalTypes}`);
104
- console.log(`Endpoints: ${result.statistics.totalEndpoints}`);
105
- }
106
- ```
107
-
108
- ## Configuration
109
-
110
- ### Basic Configuration
111
-
112
- ```typescript
113
- const config: SchemanticConfig = {
114
- // Input sources (choose one)
115
- schemaUrl: "http://localhost:8000/openapi.json",
116
- schemaFile: "./schema.json",
117
- schemaData: {
118
- /* OpenAPI schema object */
119
- },
120
-
121
- // Output configuration
122
- outputDir: "./src/generated",
123
- outputFileName: "api-client.ts",
124
-
125
- // Generation options
126
- generateTypes: true,
127
- generateApiClient: true,
128
- generateHooks: false, // Enable React hooks generation
129
-
130
- // TypeScript configuration
131
- useStrictTypes: true,
132
- useOptionalChaining: true,
133
- useNullishCoalescing: true,
134
-
135
- // Naming conventions
136
- namingConvention: "camelCase", // 'camelCase' | 'snake_case' | 'PascalCase'
137
- // By default, Schemantic prefixes type names with "API". Customize if desired:
138
- // By default no prefix is added. Set a value here to add one, e.g. "MyAPI":
139
- typePrefix: "",
140
- typeSuffix: "Type",
141
-
142
- // Customization
143
- customTypeMappings: {
144
- uuid: "string",
145
- datetime: "Date",
146
- },
147
-
148
- // Filtering
149
- excludePaths: ["/health", "/docs"],
150
- includePaths: ["/api/v1/*"],
151
- excludeSchemas: ["Error"],
152
- includeSchemas: ["User", "Product"],
153
-
154
- // Plugin configuration
155
- plugins: [
156
- { name: "jsdoc", enabled: true },
157
- { name: "validation", enabled: true },
158
- ],
159
- };
160
- ```
161
-
162
- ### CLI Reference
163
-
164
- #### Commands
165
-
166
- ```bash
167
- # Generate types and API client
168
- npx schemantic generate [source] [options]
169
- npx schemantic gen [source] [options]
170
-
171
- # Validate OpenAPI schema
172
- npx schemantic validate [source] [options]
173
- npx schemantic check [source] [options]
174
-
175
- # Manage plugins
176
- npx schemantic plugin list
177
- npx schemantic plugin load <path>
178
-
179
- # Initialize configuration
180
- npx schemantic init [directory] [options]
181
-
182
- # Get help
183
- npx schemantic --help
184
- npx schemantic generate --help
185
- ```
186
-
187
- #### Generate Command Options
188
-
189
- ```bash
190
- # Input options
191
- --url, -u <url> OpenAPI schema URL
192
- --file, -f <file> OpenAPI schema file path
193
-
194
- # Output options
195
- --output, -o <dir> Output directory (default: ./src/generated)
196
-
197
- # Generation options
198
- --types Generate types only
199
- --client Generate API client only
200
- --hooks Generate React hooks factory
201
- --watch Watch for changes and regenerate
202
-
203
- # TypeScript options
204
- --strict Use strict TypeScript types (default: true)
205
- --naming <convention> Naming convention (camelCase|snake_case|PascalCase)
206
-
207
- # Customization
208
- # Customization
209
- --prefix <prefix> Type name prefix (default: none)
210
- --suffix <suffix> Type name suffix
211
- --exclude-paths <paths> Exclude paths (comma-separated)
212
- --include-paths <paths> Include paths (comma-separated)
213
- --exclude-schemas <schemas> Exclude schemas (comma-separated)
214
- --include-schemas <schemas> Include schemas (comma-separated)
215
-
216
- # Plugin options
217
- --plugins <plugins> Enable plugins (comma-separated)
218
- --config, -c <file> Configuration file path
219
-
220
- # Global options
221
- --interactive, -i Run in interactive mode
222
- --verbose, -v Verbose output
223
- --quiet, -q Quiet output
224
- --no-color Disable colored output
225
- ```
226
-
227
- #### Validate Command Options
228
-
229
- ```bash
230
- --url, -u <url> OpenAPI schema URL
231
- --file, -f <file> OpenAPI schema file path
232
- --fix Attempt to fix common issues
233
- ```
234
-
235
- #### Init Command Options
236
-
237
- ```bash
238
- --template, -t <template> Configuration template (default)
239
- --yes Skip interactive prompts
240
- ```
241
-
242
- ### CLI Examples
243
-
244
- #### Basic Usage
245
-
246
- ```bash
247
- # Generate from live FastAPI server
248
- npx schemantic generate --url http://localhost:8000/openapi.json
249
-
250
- # Generate from local schema file
251
- npx schemantic generate --file ./openapi-schema.json
252
-
253
- # Custom output directory
254
- npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/api
255
-
256
- # Generate with React hooks
257
- npx schemantic generate --url http://localhost:8000/openapi.json --hooks
258
-
259
- # Interactive mode (guided setup)
260
- npx schemantic generate --interactive
261
- ```
262
-
263
- #### Advanced Usage
264
-
265
- ```bash
266
- # Custom naming and prefixes
267
- npx schemantic generate \
268
- --url http://localhost:8000/openapi.json \
269
- --naming PascalCase \
270
- --prefix "MyAPI" \
271
- --suffix "DTO"
272
-
273
- # Filter paths and schemas
274
- npx schemantic generate \
275
- --url http://localhost:8000/openapi.json \
276
- --include-paths "/api/v1/*,/auth/*" \
277
- --exclude-paths "/health,/docs" \
278
- --exclude-schemas "Error,ValidationError"
279
-
280
- # Enable plugins
281
- npx schemantic generate \
282
- --url http://localhost:8000/openapi.json \
283
- --plugins jsdoc,validation
284
-
285
- # Use configuration file
286
- npx schemantic generate --config ./schemantic.config.json
287
-
288
- # Watch mode for development
289
- npx schemantic generate --url http://localhost:8000/openapi.json --watch
290
-
291
- # Generate specific outputs
292
- npx schemantic generate --url http://localhost:8000/openapi.json --types --client
293
- npx schemantic generate --url http://localhost:8000/openapi.json --hooks
294
- ```
295
-
296
- #### Validation
297
-
298
- ```bash
299
- # Validate schema
300
- npx schemantic validate --url http://localhost:8000/openapi.json
301
-
302
- # Validate local file
303
- npx schemantic validate --file ./openapi-schema.json
304
-
305
- # Validate with auto-fix attempts
306
- npx schemantic validate --file ./openapi-schema.json --fix
307
- ```
308
-
309
- #### Configuration Management
310
-
311
- ```bash
312
- # Initialize new project configuration
313
- npx schemantic init
314
-
315
- # Initialize with default settings
316
- npx schemantic init --yes
317
-
318
- # Initialize in specific directory
319
- npx schemantic init ./my-project
320
-
321
- # Initialize with template
322
- npx schemantic init --template react
323
- ```
324
-
325
- #### Plugin Management
326
-
327
- ```bash
328
- # List available plugins
329
- npx schemantic plugin list
330
-
331
- # Load custom plugin
332
- npx schemantic plugin load ./my-custom-plugin.js
333
- npx schemantic plugin load @my-org/Schemantic-plugin
334
- ```
335
-
336
- ## Generated Output
337
-
338
- ### Types
339
-
340
- ```typescript
341
- // Generated from OpenAPI schema (no prefix by default)
342
- export interface User {
343
- id: string;
344
- email: string;
345
- firstName: string;
346
- lastName: string;
347
- createdAt: string;
348
- updatedAt: string;
349
- }
350
-
351
- export interface CreateUserRequest {
352
- email: string;
353
- firstName: string;
354
- lastName: string;
355
- }
356
-
357
- export interface UpdateUserRequest {
358
- email?: string;
359
- firstName?: string;
360
- lastName?: string;
361
- }
362
-
363
- export enum UserRole {
364
- ADMIN = "admin",
365
- USER = "user",
366
- MODERATOR = "moderator",
367
- }
368
- ```
369
-
370
- ### API Client
371
-
372
- ### React Hooks (optional)
373
-
374
- Enable hook generation with `--hooks` (CLI) or `generateHooks: true` (config). A `hooks.ts` file will export `createApiHooks(client)` which returns per-endpoint hooks.
375
-
376
- Example:
377
-
378
- ```typescript
379
- import { ECommerceApiClient, createApiHooks } from "./src/generated";
380
-
381
- const client = new ECommerceApiClient({ baseUrl: "http://localhost:8000" });
382
- const { useGetProductsProductsGetQuery, useCreateOrderOrdersPostMutation } =
383
- createApiHooks(client);
384
-
385
- function ProductsList() {
386
- const { data, loading, error, refetch } = useGetProductsProductsGetQuery({
387
- query: { page: 1, size: 20 },
388
- });
389
- // ... render
390
- }
391
- ```
392
-
393
- Notes:
394
-
395
- - Hooks mirror the client method signatures: path params, query params, optional body (for mutations), then `RequestInit` as the last arg.
396
- - The generated `index.ts` re-exports `createApiHooks` when hooks are enabled.
397
-
398
- ```typescript
399
- // Actual name is derived from your API title; example below shows a generic name.
400
- export class MyApiApiClient {
401
- private baseUrl: string;
402
- private config: ApiClientConfig;
403
-
404
- constructor(config: ApiClientConfig) {
405
- this.baseUrl = config.baseUrl.replace(/\/$/, "");
406
- this.config = {
407
- timeout: 30000,
408
- retries: 3,
409
- retryDelay: 1000,
410
- ...config,
411
- };
412
- }
413
-
414
- async getUsers(): Promise<APIUser[]> {
415
- const url = new URL(`${this.baseUrl}/users`);
416
- const response = await fetch(url.toString(), {
417
- method: "GET",
418
- headers: {
419
- ...this.config.headers,
420
- },
421
- });
422
-
423
- if (!response.ok) {
424
- throw new ApiClientError(
425
- `Request failed: ${response.status} ${response.statusText}`,
426
- response.status,
427
- response
428
- );
429
- }
430
-
431
- return response.json();
432
- }
433
-
434
- async createUser(body: APICreateUserRequest): Promise<APIUser> {
435
- const url = new URL(`${this.baseUrl}/users`);
436
- const response = await fetch(url.toString(), {
437
- method: "POST",
438
- headers: {
439
- ...this.config.headers,
440
- "Content-Type": "application/json",
441
- },
442
- body: JSON.stringify(body),
443
- });
444
-
445
- if (!response.ok) {
446
- throw new ApiClientError(
447
- `Request failed: ${response.status} ${response.statusText}`,
448
- response.status,
449
- response
450
- );
451
- }
452
-
453
- return response.json();
454
- }
455
- }
456
- ```
457
-
458
- ## Plugin System
459
-
460
- Schemantic includes a powerful plugin system for extending functionality:
461
-
462
- ### Built-in Plugins
463
-
464
- - **jsdoc** - Adds JSDoc comments to generated types
465
- - **validation** - Adds validation decorators for class-validator
466
- - **react-hooks** - Generates React hooks for API endpoints
467
- - **strict-mode** - Adds TypeScript strict mode enhancements
468
-
469
- ### Using Plugins
470
-
471
- ```typescript
472
- // Enable plugins via configuration
473
- const config: SchemanticConfig = {
474
- // ... other config
475
- plugins: [
476
- { name: 'jsdoc', enabled: true },
477
- { name: 'validation', enabled: true },
478
- { name: 'react-hooks', enabled: true },
479
- ],
480
- };
481
-
482
- // Or via CLI
483
- npx schemantic generate --plugins jsdoc,validation,react-hooks
484
- ```
485
-
486
- ### Creating Custom Plugins
487
-
488
- ```typescript
489
- import { SchemanticPlugin, GenerationContext, GeneratedType } from "schemantic";
490
-
491
- const customPlugin: SchemanticPlugin = {
492
- name: "custom-plugin",
493
- version: "1.0.0",
494
- description: "Custom plugin for special transformations",
495
-
496
- beforeTypeGeneration: async (
497
- typeName: string,
498
- schema: any,
499
- context: GenerationContext
500
- ) => {
501
- // Transform schema before generation
502
- console.log(`Generating type: ${typeName}`);
503
- },
504
-
505
- afterTypeGeneration: async (
506
- typeName: string,
507
- generatedType: GeneratedType,
508
- context: GenerationContext
509
- ) => {
510
- // Modify generated type
511
- generatedType.content = `// Custom comment\n${generatedType.content}`;
512
- },
513
-
514
- transformSchema: (schema: any, context: GenerationContext) => {
515
- // Transform schema
516
- return schema;
517
- },
518
-
519
- customTypeGenerators: {
520
- "custom-type": (schema: any, context: GenerationContext) => {
521
- // Custom type generator
522
- return {
523
- name: "CustomType",
524
- content: "export type CustomType = string;",
525
- dependencies: [],
526
- exports: ["CustomType"],
527
- isInterface: false,
528
- isEnum: false,
529
- isUnion: false,
530
- sourceSchema: schema,
531
- };
532
- },
533
- },
534
- };
535
- ```
536
-
537
- ๐Ÿ“š **[Complete Plugin Development Guide](./docs/PLUGIN_DEVELOPMENT.md)** - Learn how to create custom plugins
538
-
539
- ๐Ÿ“– **[Plugin API Reference](./docs/PLUGINS.md)** - Built-in plugins and usage examples
540
-
541
- ## FastAPI Integration
542
-
543
- ### Basic FastAPI Setup
544
-
545
- ```python
546
- from fastapi import FastAPI
547
- from pydantic import BaseModel
548
- from typing import List, Optional
549
-
550
- app = FastAPI(
551
- title="My API",
552
- description="API description",
553
- version="1.0.0",
554
- )
555
-
556
- class User(BaseModel):
557
- id: str
558
- email: str
559
- first_name: str
560
- last_name: str
561
- created_at: str
562
- updated_at: str
563
-
564
- class CreateUserRequest(BaseModel):
565
- email: str
566
- first_name: str
567
- last_name: str
568
-
569
- @app.get("/users", response_model=List[User])
570
- async def get_users():
571
- # Your implementation
572
- pass
573
-
574
- @app.post("/users", response_model=User)
575
- async def create_user(user: CreateUserRequest):
576
- # Your implementation
577
- pass
578
- ```
579
-
580
- ### Generate Types
581
-
582
- ```bash
583
- # Start your FastAPI server
584
- uvicorn main:app --reload
585
-
586
- # Generate types
587
- npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated
588
- ```
589
-
590
- ## Advanced Usage
591
-
592
- ### Custom Type Mappings
593
-
594
- ```typescript
595
- const config: SchemanticConfig = {
596
- // ... other config
597
- customTypeMappings: {
598
- uuid: "string",
599
- datetime: "Date",
600
- decimal: "number",
601
- email: "string",
602
- },
603
- };
604
- ```
605
-
606
- ### Path and Schema Filtering
607
-
608
- ```typescript
609
- const config: SchemanticConfig = {
610
- // ... other config
611
- excludePaths: ["/health", "/docs", "/redoc"],
612
- includePaths: ["/api/v1/*"],
613
- excludeSchemas: ["Error", "ValidationError"],
614
- includeSchemas: ["User", "Product", "Order"],
615
- };
616
- ```
617
-
618
- ### Configuration Files
619
-
620
- Create a `schemantic.config.json` file:
621
-
622
- ```json
623
- {
624
- "schemaUrl": "http://localhost:8000/openapi.json",
625
- "outputDir": "./generated",
626
- "generateTypes": true,
627
- "generateApiClient": true,
628
- "useStrictTypes": true,
629
- "namingConvention": "camelCase",
630
- "plugins": [
631
- { "name": "jsdoc", "enabled": true },
632
- { "name": "validation", "enabled": true }
633
- ]
634
- }
635
- ```
636
-
637
- Use with CLI:
638
-
639
- ```bash
640
- npx schemantic generate --config schemantic.config.json
641
- ```
642
-
643
- ## Validation
644
-
645
- Validate your OpenAPI schema before generation:
646
-
647
- ```bash
648
- # Validate schema
649
- npx schemantic validate --url http://localhost:8000/openapi.json
650
-
651
- # Validate with verbose output
652
- npx schemantic validate --file schema.json --verbose
653
- ```
654
-
655
- ## Examples
656
-
657
- ### React Application
658
-
659
- ```typescript
660
- // Import from the generated index barrel
661
- import { MyApiApiClient } from "./generated";
662
- import type { APIUser } from "./generated";
663
-
664
- const apiClient = new MyApiApiClient({
665
- baseUrl: "http://localhost:8000",
666
- headers: {
667
- Authorization: `Bearer ${token}`,
668
- },
669
- });
670
-
671
- // Use in React component
672
- const UsersPage = () => {
673
- const [users, setUsers] = useState<APIUser[]>([]);
674
-
675
- useEffect(() => {
676
- const fetchUsers = async () => {
677
- try {
678
- const usersData = await apiClient.getUsers();
679
- setUsers(usersData);
680
- } catch (error) {
681
- console.error("Failed to fetch users:", error);
682
- }
683
- };
684
-
685
- fetchUsers();
686
- }, []);
687
-
688
- return (
689
- <div>
690
- {users.map((user) => (
691
- <div key={user.id}>
692
- {user.firstName} {user.lastName} - {user.email}
693
- </div>
694
- ))}
695
- </div>
696
- );
697
- };
698
- ```
699
-
700
- ### Node.js Application
701
-
702
- ```typescript
703
- import { MyApiApiClient } from "./generated";
704
-
705
- const apiClient = new MyApiApiClient({
706
- baseUrl: "http://localhost:8000",
707
- });
708
-
709
- // Use in Node.js application
710
- const main = async () => {
711
- try {
712
- const users = await apiClient.getUsers();
713
- console.log("Users:", users);
714
-
715
- const newUser = await apiClient.createUser({
716
- email: "user@example.com",
717
- firstName: "John",
718
- lastName: "Doe",
719
- });
720
- console.log("Created user:", newUser);
721
- } catch (error) {
722
- console.error("API error:", error);
723
- }
724
- };
725
-
726
- main();
727
- ```
728
-
729
- ## Tutorials
730
-
731
- ๐Ÿš€ **[Complete FastAPI Tutorial](./docs/FASTAPI_TUTORIAL.md)** - Build a full-stack e-commerce app with FastAPI, Schemantic, and React. Includes authentication, database models, type-safe API client, and React hooks.
732
-
733
- ## Contributing
734
-
735
- We welcome contributions! Here's how you can help:
736
-
737
- ### ๐Ÿ› Bug Reports
738
-
739
- Found a bug? Please [open an issue](https://github.com/Cstannahill/schemantic/issues/new) with:
740
-
741
- - Clear description of the problem
742
- - Steps to reproduce
743
- - Expected vs actual behavior
744
- - Your environment (Node.js version, OS, etc.)
745
-
746
- ### ๐Ÿ’ก Feature Requests
747
-
748
- Have an idea? [Start a discussion](https://github.com/Cstannahill/schemantic/discussions) or [open an issue](https://github.com/Cstannahill/schemantic/issues/new)!
749
-
750
- ### ๐Ÿ”ง Development Setup
751
-
752
- ```bash
753
- # Clone the repository
754
- git clone https://github.com/Cstannahill/schemantic.git
755
-
756
- cd schemantic
757
-
758
- # Install dependencies
759
- npm install
760
-
761
- # Build the project
762
- npm run build
763
-
764
- # Run tests
765
- npm test
766
-
767
- # Run tests in watch mode
768
- npm run test:watch
769
-
770
- # Run linting
771
- npm run lint
772
-
773
- # Fix linting issues automatically
774
- npm run lint:fix
775
- ```
776
-
777
- ### ๐Ÿงช Testing
778
-
779
- - Write tests for new features
780
- - Ensure all tests pass: `npm test`
781
- - Check test coverage: `npm run test:coverage`
782
- - Test with real FastAPI applications in `local-test/`
783
-
784
- ### ๐Ÿ“ Documentation
785
-
786
- - Update README.md for new features
787
- - Add examples to documentation
788
- - Update API documentation in `docs/`
789
-
790
- ### ๐Ÿš€ Pull Requests
791
-
792
- 1. Fork the repository
793
- 2. Create a feature branch: `git checkout -b feature/amazing-feature`
794
- 3. Make your changes
795
- 4. Add tests and documentation
796
- 5. Ensure all checks pass
797
- 6. Commit with clear messages
798
- 7. Push and create a Pull Request
799
-
800
- ## Support & Community
801
-
802
- - ๐Ÿ“– **[Documentation](./docs/)** - Comprehensive guides and API reference
803
- - ๐Ÿ› **[Issue Tracker](https://github.com/Cstannahill/schemantic/issues)** - Bug reports and feature requests
804
- - ๐Ÿ’ฌ **[Discussions](https://github.com/Cstannahill/schemantic/discussions)** - Community help and ideas
805
- - ๏ฟฝ **[Plugin Development](./docs/PLUGIN_DEVELOPMENT.md)** - Create custom generators
806
- - ๐Ÿ“š **[FastAPI Tutorial](./docs/FASTAPI_TUTORIAL.md)** - Complete integration guide
807
-
808
- ### Getting Help
809
-
810
- 1. Check the [documentation](./docs/) first
811
- 2. Search [existing issues](https://github.com/Cstannahill/schemantic/issues)
812
- 3. Ask in [discussions](https://github.com/Cstannahill/schemantic/discussions)
813
- 4. Create a new issue with detailed information
814
-
815
- ## Roadmap
816
-
817
- - [ ] Support for OpenAPI 3.1 features
818
- - [ ] GraphQL schema support
819
- - [ ] Additional framework integrations (Express, NestJS)
820
- - [ ] VS Code extension
821
- - [ ] Enhanced React Query integration
822
- - [ ] Performance optimizations for large schemas
823
-
824
- ## License
825
-
826
- MIT License - see [LICENSE](LICENSE) file for details.
827
-
828
- ## Changelog
829
-
830
- See [CHANGELOG.md](CHANGELOG.md) for a list of changes and version history.
1
+ # Schemantic
2
+
3
+ Generate TypeScript models, a fetch API client, and optional plain React hooks from OpenAPI JSON. The package requires Node.js 20 or newer. Generated browser clients use fetch; React is required only when hooks are enabled.
4
+
5
+ ```sh
6
+ npm install --save-dev schemantic
7
+ npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/generated
8
+ ```
9
+
10
+ The default output is `types.ts`, `conversion.ts`, `api-client.ts`, and `index.ts`. Hooks are off by default. `--client` includes its required model types; `--types` selects models only. Use `--hooks` with client generation to emit `hooks.ts`.
11
+
12
+ For a schema titled `Users API`, the class is `UsersApiClient`. Client names are derived from `info.title`; inspect your generated export.
13
+
14
+ ```ts
15
+ import { UsersApiClient as ApiClient } from './generated/index.js';
16
+
17
+ const client = new ApiClient({ baseUrl: 'http://localhost:8000' });
18
+ client.setAuthToken('your-token');
19
+ // Method names and arguments come from the schema's operations.
20
+ client.clearAuthToken();
21
+ ```
22
+
23
+ Generate from a local file, initialize a config, or validate without writing generated files:
24
+
25
+ ```sh
26
+ npx schemantic generate ./openapi.json --output ./src/generated
27
+ npx schemantic init --yes
28
+ npx schemantic validate ./openapi.json
29
+ ```
30
+
31
+ `init` creates configuration exclusively: an existing file requires explicit `--force`. Templates are `default` (models/client), `types` (models only), and `react` (models/client/hooks). Set a schema source in the initialized configuration before running bare `generate`.
32
+
33
+ The CLI discovers `schemantic.config.json`, `.cjs`, or `.js` in the current directory, in that order. `generate` and `validate` accept `--config [file]`. Precedence is defaults, config, explicit CLI options. Config-relative schema/output/plugin file paths resolve beside the config; explicit CLI paths resolve from the working directory. Use `--verbose` to inspect the effective source, output, generation flags, and plugin selection.
34
+
35
+ Programmatic use:
36
+
37
+ ```ts
38
+ import { Schemantic } from 'schemantic';
39
+
40
+ const generator = new Schemantic({
41
+ schemaFile: './openapi.json',
42
+ outputDir: './src/generated',
43
+ });
44
+ const result = await generator.generate();
45
+ if (!result.success) throw new Error(result.errors.map(error => error.message).join('\n'));
46
+ ```
47
+
48
+ ## Supported scope
49
+
50
+ OpenAPI `3.0.x` and `3.1.x` JSON documents are supported, including local JSON Pointer references. YAML and references to external files/URLs are rejected explicitly. OpenAPI `3.2+` is unsupported. Valid OpenAPI can contain features beyond the supported generator subset; validation diagnostics are part of the support contract. TypeScript dictionary types with declared properties use a widened index value union; use runtime validation when exact additional-property constraints matter.
51
+
52
+ Parameter serialization supports simple path/header values, flat form/deepObject queries and space/pipe-delimited arrays. Complex cookies, matrix/label styles, nested encodings and per-property form encodings are rejected explicitly. Cookie parameters depend on the fetch runtime's header policy; browsers manage cookies through credentials. JSON Schema conditionals, `contains` and unevaluated-property keywords are outside the validator subset. Validation checks document structure and references; it is not a complete OpenAPI/JSON Schema standards validator.
53
+
54
+ Generated relative imports include `.js` extensions for TypeScript NodeNext and bundler resolution. Plain React hooks provide `loading`, `data`, `error`, and `refetch` or `mutate`/`reset`; they are not a TanStack Query adapter. `generateQueries`, automatic schema repair, TypeScript config loading, and automatic endpoint middleware are unavailable. Do not enable the removed `react-hooks` plugin: use `generateHooks`/`--hooks`.
55
+
56
+ Validation, caching, branding, and timing plugins provide explicit helpers. Install Zod 4 in the consuming project when enabling validation or schema-backed branded helpers. Endpoints do not automatically call those helpers. See [plugins](docs/PLUGINS.md) for the integration contract and experimental boundaries; no benchmark percentage improvements are claimed.
57
+
58
+ The [re-audit](docs/REAUDIT.md) records reproduced defects and acceptance requirements from before the current corrections. Application properties use camelCase by default, while PascalCase names identify types/classes and schema wire names remain intact at HTTP boundaries. `propertyNaming: "preserve"` keeps wire property names in application types. Generated schema-aware `conversion.ts` helpers convert declared properties recursively and keep dictionary keys, enum values, nulls, and binary objects unchanged; conversion is not runtime validation. See [configuration](docs/CONFIGURATION.md) and the [naming migration design](docs/NAMING_MIGRATION.md).
59
+
60
+ ## Documentation
61
+
62
+ - [Configuration](docs/CONFIGURATION.md)
63
+ - [API](docs/API.md)
64
+ - [FastAPI tutorial](docs/FASTAPI_TUTORIAL.md)
65
+ - [Plugins](docs/PLUGINS.md)
66
+ - [Plugin development](docs/PLUGIN_DEVELOPMENT.md)
67
+ - [Advanced plugin development](docs/ADVANCED_PLUGIN_DEVELOPMENT.md)
68
+ - [Advanced plugin capabilities](docs/ADVANCED_PLUGINS_IMPLEMENTATION.md)
69
+
70
+ ## Development and release
71
+
72
+ ```sh
73
+ npm ci
74
+ npm test -- --runInBand
75
+ npm run lint
76
+ npm pack --dry-run --ignore-scripts --json
77
+ ```
78
+
79
+ Tests build the package first. CI is configured for Node 20/22/24 on Linux, Windows, and macOS, plus coverage, 36 generated fixture combinations, an installed-package consumer, live FastAPI requests, dependency auditing, and separate CodeQL analysis. Hosted results are available in GitHub Actions after the workflows run.
80
+
81
+ Prepare a release locally, review and merge the three changed files, then publish its matching GitHub Release:
82
+
83
+ ```sh
84
+ npm run release:prepare -- minor --dry-run
85
+ npm run release:prepare -- minor
86
+ ```
87
+
88
+ Preparation updates `package.json`, `package-lock.json`, and `CHANGELOG.md`. It never commits, tags, pushes, or publishes. The GitHub Release workflow verifies the exact tagged commit and publishes the same archive tested by an installed consumer, using npm trusted publishing. Follow the [release guide](docs/RELEASING.md) for the one-time npm setup, prereleases, and retries.