ts-openapi-codegen 2.1.0-beta.3 → 2.1.0-beta.5

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 (3) hide show
  1. package/README.md +10 -946
  2. package/README.rus.md +10 -946
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,7 +14,6 @@
14
14
  ![lines-image]
15
15
  ![Minimum node.js version](https://badgen.net/npm/node/next)
16
16
 
17
-
18
17
  > Node.js library that generates Typescript clients based on the OpenAPI specification.
19
18
 
20
19
  ## Why?
@@ -28,959 +27,24 @@
28
27
  - Supports tsc and @babel/plugin-transform-typescript
29
28
  - Supports customization names of models
30
29
  - Supports external references using [`swagger-parser`](https://github.com/APIDevTools/swagger-parser/)
30
+ - Supports strict OpenAPI diagnostics with JSON reports (`--strict-openapi`, `--report-file`)
31
+ - Supports generator plugins (`plugins`) including built-in `x-typescript-type`
31
32
  - Supports binary request/response generation (`format: binary` -> `Blob`)
32
33
 
33
34
  ## Install
34
35
 
35
- ```
36
- npm install ts-openapi-codegen --save-dev
37
- ```
38
-
39
-
40
- ## Usage
41
-
42
- The CLI tool supports six commands: `generate`, `check-config`, `update-config`, `init`, `preview-changes`, and `analyze-diff`.
43
-
44
- ### Command: `generate`
45
-
46
- Generates TypeScript client code based on OpenAPI specifications.
47
-
48
- **Basic usage:**
49
- ```bash
50
- openapi generate --input ./spec.json --output ./dist
51
- ```
52
-
53
- **All available options:**
54
-
55
- | Option | Short | Type | Default | Description |
56
- |--------|-------|------|---------|-------------|
57
- | `--input` | `-i` | string | - | OpenAPI specification (path, URL, or string content) - **required** |
58
- | `--output` | `-o` | string | - | Output directory - **required** |
59
- | `--openapi-config` | `-ocn` | string | `openapi.config.json` | Path to configuration file |
60
- | `--outputCore` | `-oc` | string | `{output}` | Output directory for core files |
61
- | `--outputServices` | `-os` | string | `{output}` | Output directory for services |
62
- | `--outputModels` | `-om` | string | `{output}` | Output directory for models |
63
- | `--outputSchemas` | `-osm` | string | `{output}` | Output directory for schemas |
64
- | `--httpClient` | `-c` | string | `fetch` | HTTP client to generate: `fetch`, `xhr`, `node`, or `axios` |
65
- | `--useOptions` | - | boolean | `false` | Use options instead of arguments |
66
- | `--useUnionTypes` | - | boolean | `false` | Use union types instead of enums |
67
- | `--excludeCoreServiceFiles` | - | boolean | `false` | Exclude generation of core and service files |
68
- | `--request` | - | string | - | Path to custom request file |
69
- | `--customExecutorPath` | - | string | - | Path to custom `createExecutorAdapter` module |
70
- | `--interfacePrefix` | - | string | `I` | Prefix for interface models |
71
- | `--enumPrefix` | - | string | `E` | Prefix for enum models |
72
- | `--typePrefix` | - | string | `T` | Prefix for type models |
73
- | `--useCancelableRequest` | - | boolean | `false` | Use cancelable promise as return type |
74
- | `--sortByRequired` | `-s` | boolean | `false` | Use extended sorting strategy for function arguments |
75
- | `--useSeparatedIndexes` | - | boolean | `false` | Use separate index files for core, models, schemas, and services |
76
- | `--strict-openapi` | - | boolean | `false` | Enable strict OpenAPI diagnostics and fail generation when strict errors are found |
77
- | `--report-file` | - | string | `./openapi-report.json` | Path to strict OpenAPI diagnostics report JSON file |
78
- | `--logLevel` | `-l` | string | `error` | Logging level: `info`, `warn`, or `error` |
79
- | `--logTarget` | `-t` | string | `console` | Logging target: `console` or `file` |
80
- | `--validationLibrary` | - | string | `none` | Validation library for schema generation: `none`, `zod`, `joi`, `yup`, or `jsonschema` |
81
- | `--emptySchemaStrategy` | - | string | `keep` | Strategy for empty schemas: `keep`, `semantic`, or `skip` |
82
- | `--modelsMode` | - | string | `interfaces` | Models generation mode: `interfaces` or `classes` |
83
- | `--useHistory` | - | boolean | `false` | Apply diff report annotations during generation |
84
- | `--diffReport` | - | string | `./openapi-diff-report.json` | Path to diff report JSON |
85
- | `--useProjectPrettier` | - | boolean | `false` | Use the project’s Prettier config to format generated code |
86
- | `--useEslintFix` | - | boolean | `false` | Run ESLint `--fix` on generated files after write (requires `eslint` in the project) |
87
-
88
- **Examples:**
89
- ```bash
90
- # Basic generation
91
- openapi generate --input ./spec.json --output ./dist
92
-
93
- # With custom HTTP client
94
- openapi generate --input ./spec.json --output ./dist --httpClient axios
95
-
96
- # With configuration file
97
- openapi generate --openapi-config ./my-config.json
98
-
99
- # With all options via CLI
100
- openapi generate \
101
- --input ./spec.json \
102
- --output ./dist \
103
- --httpClient fetch \
104
- --useOptions \
105
- --useUnionTypes \
106
- --logLevel info
107
- ```
108
-
109
- ### Command: `check-config`
110
-
111
- Validates the configuration file structure and values.
112
-
113
- **Usage:**
114
- ```bash
115
- openapi check-config
116
- openapi check-config --openapi-config ./custom-config.json
117
- ```
118
-
119
- **Options:**
120
- - `--openapi-config` / `-ocn` - Path to configuration file (default: `openapi.config.json`)
121
-
122
- ### Command: `update-config`
123
-
124
- Updates the configuration file to the latest supported schema version.
125
-
126
- **Usage:**
127
- ```bash
128
- openapi update-config
129
- openapi update-config --openapi-config ./custom-config.json
130
- ```
131
-
132
- **Options:**
133
- - `--openapi-config` / `-ocn` - Path to configuration file (default: `openapi.config.json`)
134
-
135
- ### Command: `init`
136
-
137
- Generates a configuration file template.
138
-
139
- **Usage:**
140
- ```bash
141
- # Generate config using default settings
142
- openapi init
143
-
144
- # Custom config file name
145
- openapi init --openapi-config ./my-config.json
146
-
147
- # Specify directory with OpenAPI specs
148
- openapi init --specs-dir ./openapi
149
- ```
150
-
151
- **Options:**
152
- - `--openapi-config` / `-ocn` - Path to output configuration file (default: `openapi.config.json`)
153
- - `--specs-dir` / `-sd` - Directory with OpenAPI specification files (default: `./openapi`)
154
- - `--request` - Path to custom request file
155
- - `--useCancelableRequest` - Generate cancelable request handling
156
- - `--useInteractiveMode` - Enable interactive mode for guided setup
157
-
158
- ### Command: `preview-changes`
159
-
160
- Previews differences between already generated code and newly generated output without overwriting your current generated directory.
161
-
162
- **Usage:**
163
- ```bash
164
- openapi preview-changes
165
- openapi preview-changes --openapi-config ./custom-config.json
166
- ```
167
-
168
- **Options:**
169
- - `--openapi-config` / `-ocn` - Path to configuration file (default: `openapi.config.json`)
170
- - `--generated-dir` / `-gd` - Directory with current generated files (default: `./generated`)
171
- - `--preview-dir` / `-pd` - Temporary preview generation directory (default: `./.ts-openapi-codegen-preview-changes`)
172
- - `--diff-dir` / `-dd` - Directory for diff reports (default: `./.ts-openapi-codegen-diff-changes`)
173
-
174
- ### Command: `analyze-diff`
175
-
176
- Analyzes differences between two OpenAPI specifications and produces a JSON report.
177
-
178
- **Usage:**
179
- ```bash
180
- openapi analyze-diff --input ./openapi/current.yaml --compare-with ./openapi/previous.yaml --output-report ./openapi-diff-report.json
181
- openapi analyze-diff --input ./openapi/spec.yaml --git HEAD~1
182
- ```
183
-
184
- **Options:**
185
- - `--input` / `-i` - Path to current OpenAPI specification file (required)
186
- - `--compare-with` - Path to previous OpenAPI specification file
187
- - `--git` - Git ref to read previous specification version from (e.g. `HEAD~1`)
188
- - `--output-report` - Path to save JSON diff report (default: `./openapi-diff-report.json`)
189
-
190
- #### Miracles and confirmation
191
-
192
- The diff report can contain a `miracles` section with detected renames/type-coercions. Only confirmed miracles are applied in generation.
193
-
194
- **How to confirm miracles:**
195
- 1. Run `analyze-diff` and open the generated report (default: `./openapi-diff-report.json`).
196
- 2. Find the entry in `miracles` you want to accept.
197
- 3. Change `"status": "auto-generated"` to `"status": "confirmed"` and commit the report.
198
-
199
- Example (excerpt):
200
- ```json
201
- {
202
- "miracles": [
203
- {
204
- "oldPath": "$.components.schemas.User.properties.user_name",
205
- "newPath": "$.components.schemas.User.properties.userName",
206
- "type": "RENAME",
207
- "confidence": 0.85,
208
- "status": "confirmed"
209
- }
210
- ]
211
- }
212
- ```
213
-
214
- ### Configuration File
215
-
216
- Instead of passing all options via CLI, you can use a configuration file. Create `openapi.config.json` in your project root:
217
-
218
- **Single options format:**
219
- ```json
220
- {
221
- "input": "./spec.json",
222
- "output": "./dist",
223
- "client": "fetch",
224
- "useOptions": false,
225
- "useUnionTypes": false,
226
- "excludeCoreServiceFiles": false,
227
- "interfacePrefix": "I",
228
- "enumPrefix": "E",
229
- "typePrefix": "T",
230
- "useCancelableRequest": false,
231
- "sortByRequired": false,
232
- "useSeparatedIndexes": false,
233
- "request": "./custom-request.ts",
234
- "customExecutorPath": "./custom/createExecutorAdapter.ts",
235
- "modelsMode": "interfaces",
236
- "useHistory": false,
237
- "diffReport": "./openapi-diff-report.json",
238
- "models": {
239
- "mode": "interfaces"
240
- },
241
- "analyze": {
242
- "useHistory": false,
243
- "reportPath": "./openapi-diff-report.json"
244
- },
245
- "miracles": {
246
- "enabled": true,
247
- "confidence": 1,
248
- "types": ["RENAME", "TYPE_COERCION"]
249
- }
250
- }
251
- ```
252
-
253
- **Multi-options format (with common block):**
254
- ```json
255
- {
256
- "output": "./dist",
257
- "client": "fetch",
258
- "excludeCoreServiceFiles": true,
259
- "items": [
260
- {
261
- "input": "./first.yml"
262
- },
263
- {
264
- "input": "./second.yml",
265
- "output": "./dist-v2"
266
- }
267
- ]
268
- }
269
- ```
270
-
271
- **Array format (multiple configs):**
272
- ```json
273
- [
274
- {
275
- "input": "./first.yml",
276
- "output": "./dist",
277
- "client": "xhr"
278
- },
279
- {
280
- "input": "./second.yml",
281
- "output": "./dist",
282
- "client": "fetch"
283
- }
284
- ]
285
- ```
286
-
287
- | Name | Type | Default | Description |
288
- |------|------|---------|-------------|
289
- | `input` | string | - | OpenAPI specification path/URL (required for items) |
290
- | `output` | string | - | Output directory (required) |
291
- | `outputCore` | string | `{output}` | Output directory for core files |
292
- | `outputServices` | string | `{output}` | Output directory for services |
293
- | `outputModels` | string | `{output}` | Output directory for models |
294
- | `outputSchemas` | string | `{output}` | Output directory for schemas |
295
- | `client` | string | `fetch` | HTTP client: `fetch`, `xhr`, `node`, or `axios` |
296
- | `useOptions` | boolean | `false` | Use options instead of arguments |
297
- | `useUnionTypes` | boolean | `false` | Use union types instead of enums |
298
- | `excludeCoreServiceFiles` | boolean | `false` | Exclude core and service files generation |
299
- | `request` | string | - | Path to custom request file |
300
- | `customExecutorPath` | string | - | Path to custom `createExecutorAdapter` module |
301
- | `interfacePrefix` | string | `I` | Prefix for interface models |
302
- | `enumPrefix` | string | `E` | Prefix for enum models |
303
- | `typePrefix` | string | `T` | Prefix for type models |
304
- | `useCancelableRequest` | boolean | `false` | Use cancelable promise as return type |
305
- | `sortByRequired` | boolean | `false` | Extended sorting strategy for arguments |
306
- | `useSeparatedIndexes` | boolean | `false` | Use separate index files |
307
- | `strictOpenapi` | boolean | `false` | Enable strict OpenAPI diagnostics and fail generation on strict errors |
308
- | `reportFile` | string | `./openapi-report.json` | Path to strict OpenAPI diagnostics report JSON file |
309
- | `items` | array | - | Array of configurations (for multi-options format) |
310
- | `validationLibrary` | string | `none` | Validation library for schema generation: `none`, `zod`, `joi`, `yup`, or `jsonschema` |
311
- | `emptySchemaStrategy` | string | `keep` | Strategy for empty schemas: `keep`, `semantic`, or `skip` |
312
- | `modelsMode` | string | `interfaces` | Models generation mode: `interfaces` or `classes` |
313
- | `useHistory` | boolean | `false` | Apply diff report annotations during generation |
314
- | `diffReport` | string | `./openapi-diff-report.json` | Path to diff report JSON |
315
- | `models` | object | - | Models config section (e.g. `mode`) |
316
- | `analyze` | object | - | Analyze config section (e.g. reportPath, useHistory, ignore) |
317
- | `miracles` | object | - | Miracles config section (enabled, confidence, types) |
318
-
319
- **Note:** You can use the `init` command to generate a template configuration file.
320
-
321
- ## Examples
322
-
323
- ### Using CLI commands
324
-
325
- **Basic generation:**
326
- ```bash
327
- openapi generate --input ./spec.json --output ./dist
328
- ```
329
-
330
- **With configuration file:**
331
- ```bash
332
- # First, create config file
333
- openapi init
334
-
335
- # Then generate
336
- openapi generate
337
- ```
338
-
339
- **With DTO models (classes mode):**
340
- ```bash
341
- openapi generate --input ./spec.json --output ./dist --modelsMode classes
342
- ```
343
-
344
- **Generate diff report:**
345
- ```bash
346
- openapi analyze-diff --input ./openapi/current.yaml --compare-with ./openapi/previous.yaml --output-report ./openapi-diff-report.json
347
- ```
348
-
349
- **Check configuration:**
350
36
  ```bash
351
- openapi check-config
352
- openapi update-config
353
- ```
354
-
355
- **Preview changes before applying:**
356
- ```bash
357
- openapi preview-changes
358
- ```
359
-
360
- ### Using NPX
361
-
362
- ```bash
363
- npx ts-openapi-codegen generate --input ./spec.json --output ./dist
364
- ```
365
-
366
- ### Using package.json scripts
367
-
368
- **package.json**
369
- ```json
370
- {
371
- "scripts": {
372
- "generate": "openapi generate --input ./spec.json --output ./dist",
373
- "generate:config": "openapi generate",
374
- "check-config": "openapi check-config",
375
- "update-config": "openapi update-config",
376
- "init-config": "openapi init",
377
- "preview-changes": "openapi preview-changes"
378
- }
379
- }
380
- ```
381
-
382
- ### Node.js API
383
-
384
- ```javascript
385
- const OpenAPI = require('ts-openapi-codegen');
386
-
387
- OpenAPI.generate({
388
- input: './spec.json',
389
- output: './dist'
390
- });
391
-
392
- // Or by providing the content of the spec directly 🚀
393
- OpenAPI.generate({
394
- input: require('./spec.json'),
395
- output: './dist'
396
- });
397
- ```
398
-
399
-
400
- ## Features
401
-
402
- ### HTTP Clients
403
-
404
- The generator supports multiple HTTP clients:
405
- - **fetch** (default) - Browser Fetch API
406
- - **xhr** - XMLHttpRequest
407
- - **node** - Node.js compatible client using `node-fetch`
408
- - **axios** - Axios HTTP client
409
-
410
- Select the client using the `--httpClient` option or `client` property in config file.
411
-
412
- ### Argument style vs. Object style `--useOptions`
413
- There's no [named parameter](https://en.wikipedia.org/wiki/Named_parameter) in JavaScript or TypeScript, because of
414
- that, we offer the flag `--useOptions` to generate code in two different styles.
415
-
416
- **Argument-style:**
417
- ```typescript
418
- function createUser(name: string, password: string, type?: string, address?: string) {
419
- // ...
420
- }
421
-
422
- // Usage
423
- createUser('Jack', '123456', undefined, 'NY US');
424
- ```
425
-
426
- **Object-style:**
427
- ```typescript
428
- function createUser({ name, password, type, address }: {
429
- name: string,
430
- password: string,
431
- type?: string
432
- address?: string
433
- }) {
434
- // ...
435
- }
436
-
437
- // Usage
438
- createUser({
439
- name: 'Jack',
440
- password: '123456',
441
- address: 'NY US'
442
- });
443
- ```
444
-
445
- ### Enums vs. Union Types `--useUnionTypes`
446
- The OpenAPI spec allows you to define [enums](https://swagger.io/docs/specification/data-models/enums/) inside the
447
- data model. By default, we convert these enums definitions to [TypeScript enums](https://www.typescriptlang.org/docs/handbook/enums.html).
448
- However, these enums are merged inside the namespace of the model, this is unsupported by Babel, [see docs](https://babeljs.io/docs/en/babel-plugin-transform-typescript#impartial-namespace-support).
449
- Because we also want to support projects that use Babel [@babel/plugin-transform-typescript](https://babeljs.io/docs/en/babel-plugin-transform-typescript),
450
- we offer the flag `--useUnionTypes` to generate [union types](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-types)
451
- instead of the traditional enums. The difference can be seen below:
452
-
453
- **Enums:**
454
- ```typescript
455
- // Model
456
- export interface Order {
457
- id?: number;
458
- quantity?: number;
459
- status?: Order.status;
460
- }
461
-
462
- export namespace Order {
463
- export enum status {
464
- PLACED = 'placed',
465
- APPROVED = 'approved',
466
- DELIVERED = 'delivered',
467
- }
468
- }
469
-
470
- // Usage
471
- const order: Order = {
472
- id: 1,
473
- quantity: 40,
474
- status: Order.status.PLACED
475
- }
476
- ```
477
-
478
- **Union Types:**
479
- ```typescript
480
- // Model
481
- export interface Order {
482
- id?: number;
483
- quantity?: number;
484
- status?: 'placed' | 'approved' | 'delivered';
485
- }
486
-
487
- // Usage
488
- const order: Order = {
489
- id: 1,
490
- quantity: 40,
491
- status: 'placed'
492
- }
493
- ```
494
-
495
- ### Validation schemas `--validationLibrary`
496
- By default, the OpenAPI generator only exports interfaces for your models. These interfaces will help you during
497
- development, but will not be available in JavaScript during runtime. However, OpenAPI allows you to define properties
498
- that can be useful during runtime, for instance: `maxLength` of a string or a `pattern` to match, etc.
499
-
500
- The `--validationLibrary` parameter allows you to generate runtime validation schemas using popular validation libraries:
501
- - **none** (default) - No validation schemas generated
502
- - **zod** - Generate Zod validation schemas
503
- - **joi** - Generate Joi validation schemas
504
- - **yup** - Generate Yup validation schemas
505
- - **jsonschema** - Generate JSON Schema validation schemas
506
-
507
- When `--useHistory` is enabled and a diff report marks a type change, validators will attempt to coerce values:
508
- - **Zod** uses `z.coerce.*`
509
- - **Joi** uses `Joi.alternatives().try(...)`
510
- - **Yup** uses `.transform(...)`
511
- - **JSON Schema (AJV)** enables `coerceTypes`
512
-
513
- ### Models mode `--modelsMode`
514
-
515
- By default, models are generated as TypeScript interfaces/types. When `--modelsMode classes` is used, the generator produces:
516
- - `*Raw` interfaces matching the API JSON
517
- - `*Dto` classes with getters, defaults, recursive constructors, and `toJSON()`
518
-
519
- The output is consolidated into a single `models.ts` file, and `BaseDto`/`dtoUtils` are emitted in `core`.
520
-
521
- Let's say we have the following model:
522
-
523
- ```json
524
- {
525
- "MyModel": {
526
- "required": [
527
- "key",
528
- "name"
529
- ],
530
- "type": "object",
531
- "properties": {
532
- "key": {
533
- "maxLength": 64,
534
- "pattern": "^[a-zA-Z0-9_]*$",
535
- "type": "string"
536
- },
537
- "name": {
538
- "maxLength": 255,
539
- "type": "string"
540
- },
541
- "enabled": {
542
- "type": "boolean",
543
- "readOnly": true
544
- },
545
- "modified": {
546
- "type": "string",
547
- "format": "date-time",
548
- "readOnly": true
549
- }
550
- }
551
- }
552
- }
553
- ```
554
-
555
- **With Zod (`--validationLibrary zod`):**
556
-
557
- ```ts
558
- import { z } from 'zod';
559
-
560
- export const MyModelSchema = z.object({
561
- key: z.string().max(64).regex(/^[a-zA-Z0-9_]*$/),
562
- name: z.string().max(255),
563
- enabled: z.boolean().readonly().optional(),
564
- modified: z.string().datetime().readonly().optional(),
565
- });
566
-
567
- export type MyModel = z.infer<typeof MyModelSchema>;
568
-
569
- export function validateMyModel(data: unknown): MyModel {
570
- return MyModelSchema.parse(data);
571
- }
572
-
573
- export function safeValidateMyModel(data: unknown): { success: true; data: MyModel } | { success: false; error: z.ZodError } {
574
- const result = MyModelSchema.safeParse(data);
575
- if (result.success) {
576
- return { success: true, data: result.data };
577
- }
578
- return { success: false, error: result.error };
579
- }
580
- ```
581
-
582
- **With Joi (`--validationLibrary joi`):**
583
-
584
- ```ts
585
- import Joi from 'joi';
586
-
587
- export const MyModelSchema = Joi.object({
588
- key: Joi.string().max(64).pattern(/^[a-zA-Z0-9_]*$/).required(),
589
- name: Joi.string().max(255).required(),
590
- enabled: Joi.boolean().readonly(),
591
- modified: Joi.string().isoDate().readonly(),
592
- });
593
- ```
594
-
595
- **With Yup (`--validationLibrary yup`):**
596
-
597
- ```ts
598
- import * as yup from 'yup';
599
-
600
- export const MyModelSchema = yup.object({
601
- key: yup.string().max(64).matches(/^[a-zA-Z0-9_]*$/).required(),
602
- name: yup.string().max(255).required(),
603
- enabled: yup.boolean().readonly(),
604
- modified: yup.string().datetime().readonly(),
605
- });
606
- ```
607
-
608
- **With JSON Schema (`--validationLibrary jsonschema`):**
609
-
610
- ```ts
611
- export const MyModelSchema = {
612
- type: 'object',
613
- required: ['key', 'name'],
614
- properties: {
615
- key: {
616
- type: 'string',
617
- maxLength: 64,
618
- pattern: '^[a-zA-Z0-9_]*$',
619
- },
620
- name: {
621
- type: 'string',
622
- maxLength: 255,
623
- },
624
- enabled: {
625
- type: 'boolean',
626
- readOnly: true,
627
- },
628
- modified: {
629
- type: 'string',
630
- format: 'date-time',
631
- readOnly: true,
632
- },
633
- },
634
- };
635
- ```
636
- These validation schemas can be used for form generation, input validation, and runtime type checking in your application.
637
-
638
- ### Cancelable promise `--useCancelableRequest`
639
- By default, the OpenAPI generator generates services for accessing the API that use non-cancellable requests. Therefore, we have added the ability to switch the generator to generate canceled API requests. To do this, use the flag `--useCancelableRequest`.
640
- An example of a cancelled request would look like this:
641
-
642
- ```typescript
643
- export function request<T>(config: TOpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> {
644
- return new CancelablePromise(async(resolve, reject, onCancel) => {
645
- const url = `${config.BASE}${options.path}`.replace('{api-version}', config.VERSION);
646
- try {
647
- if (!onCancel.isCancelled) {
648
- const response = await sendRequest(options, url, config, onCancel);
649
- const responseBody = await getResponseBody(response);
650
- const responseHeader = getResponseHeader(response, options.responseHeader);
651
- const result: ApiResult = {
652
- url,
653
- ok: response.ok,
654
- status: response.status,
655
- statusText: response.statusText,
656
- body: responseHeader || responseBody,
657
- };
658
-
659
- catchErrors(options, result);
660
- resolve(result.body);
661
- }
662
- } catch (e) {
663
- reject(e);
664
- }
665
- });
666
- }
667
- ```
668
-
669
- ### RequestExecutor
670
-
671
- Starting from version **2.0.0** the generated services use the `RequestExecutor` interface
672
- instead of direct calls to the `request` core function.
673
-
674
- The `RequestExecutor` is a single HTTP logic integration point responsible for executing requests
675
- and extending client behavior. It allows you to:
676
- - use any transport (fetch/axios/xhr/custom);
677
- - Centrally handle requests, responses, and errors;
678
- - expand the client's behavior without changing the generated services.
679
-
680
- #### Interceptors
681
-
682
- `RequestExecutor` supports **interceptors**, which allow you to implement additional
683
- logic at different stages of the request lifecycle.:
684
-
685
- - `onRequest` — modification of the request before sending (headers, auth, logging);
686
- - `onResponse` — processing successful responses;
687
- - `onError` — centralized error handling.
688
-
689
- Interceptors are applied at the executor level and are automatically used by all
690
- generated services.
691
-
692
- ```ts
693
- import { createClient } from './generated';
694
-
695
- const client = createClient({
696
- interceptors: {
697
- onRequest: [
698
- (config) => ({
699
- ...config,
700
- headers: {
701
- ...config.headers,
702
- Authorization: 'Bearer token',
703
- },
704
- }),
705
- ],
706
- onError: [
707
- (error) => {
708
- console.error(error);
709
- throw error;
710
- },
711
- ],
712
- },
713
- });
714
- ```
715
-
716
- #### Custom implementation of RequestExecutor with interceptors
717
-
718
- A custom `RequestExecutor` can be used together with interceptors.
719
- In this case, the executor is responsible only for the transport and execution of the request,
720
- while the interceptors are responsible for the extensible business logic (authorization, logging, error handling).
721
-
722
- ```ts
723
- import type { RequestExecutor, RequestConfig } from './generated/core/executor/requestExecutor';
724
- import { withInterceptors } from './generated/core/interceptors/withInterceptors';
725
- import { SimpleService } from './generated/services/SimpleService';
726
-
727
- interface MyCustomOptions {
728
- timeout?: number;
729
- }
730
-
731
- const baseExecutor: RequestExecutor<MyCustomOptions> = {
732
- async request<T>(config: RequestConfig, options?: MyCustomOptions): Promise<T> {
733
- const response = await fetch(config.url, {
734
- method: config.method,
735
- headers: config.headers,
736
- body: config.body ? JSON.stringify(config.body) : undefined,
737
- signal: options?.timeout
738
- ? AbortSignal.timeout(options.timeout)
739
- : undefined,
740
- });
741
-
742
- if (!response.ok) {
743
- throw new Error(`Request failed: ${response.status}`);
744
- }
745
-
746
- return response.json();
747
- },
748
- };
749
-
750
- // Wrapping the executor interceptors
751
- const executor = withInterceptors(baseExecutor, {
752
- onRequest: [
753
- (config) => ({
754
- ...config,
755
- headers: {
756
- ...config.headers,
757
- Authorization: 'Bearer token',
758
- },
759
- }),
760
- ],
761
- onError: [
762
- (error) => {
763
- console.error(error);
764
- throw error;
765
- },
766
- ],
767
- });
768
-
769
- const service = new SimpleService(executor);
770
- await service.getCallWithoutParametersAndResponse({ timeout: 5000 });
771
- ```
772
-
773
- #### Using generated `createClient` with `customExecutorPath` and `executorFactory`
774
-
775
- If you set `customExecutorPath` in generation config, `createClient.ts` imports your custom
776
- `createExecutorAdapter` and uses it as the default executor.
777
-
778
- You can additionally pass `executorFactory` at runtime to wrap/extend this default executor
779
- (for retry, tracing, metrics, etc.) without changing generated services.
780
-
781
- ```ts
782
- import { createClient } from './generated';
783
-
784
- const client = createClient({
785
- executorFactory: ({ openApiConfig, createDefaultExecutor }) => {
786
- const baseExecutor = createDefaultExecutor();
787
-
788
- return {
789
- async request<TResponse>(config, options) {
790
- console.debug('Request to', openApiConfig.BASE, config.path);
791
- return baseExecutor.request<TResponse>(config, options);
792
- },
793
- };
794
- },
795
- });
796
- ```
797
-
798
- ### Sorting strategy for function arguments `--sortByRequired`
799
- By default, the OpenAPI generator sorts the parameters of service functions according to a simplified scheme. If you need a more strict sorting option, then you need to use the `--sortByRequired` flag. The simplified sorting option is similar to the one used in version 0.2.3 of the OpenAPI generator. This flag allows you to upgrade to a new version of the generator if you are "stuck" on version 0.2.3.
800
-
801
- ### Separate index files `--useSeparatedIndexes`
802
- By default, the generator creates a single index file that exports all generated code. With the `--useSeparatedIndexes` flag, you can generate separate index files for core, models, schemas, and services, which can help with better code organization and tree-shaking.
803
-
804
- ### Enum with custom names and descriptions
805
- You can use `x-enum-varnames` and `x-enum-descriptions` in your spec to generate enum with custom names and descriptions.
806
- It's not in official [spec](https://github.com/OAI/OpenAPI-Specification/issues/681) yet. But it's a supported extension
807
- that can help developers use more meaningful enumerators.
808
- ```json
809
- {
810
- "EnumWithStrings": {
811
- "description": "This is a simple enum with strings",
812
- "enum": [
813
- 0,
814
- 1,
815
- 2
816
- ],
817
- "x-enum-varnames": [
818
- "Success",
819
- "Warning",
820
- "Error"
821
- ],
822
- "x-enum-descriptions": [
823
- "Used when the status of something is successful",
824
- "Used when the status of something has a warning",
825
- "Used when the status of something has an error"
826
- ]
827
- }
828
- }
829
- ```
830
-
831
- Generated code:
832
- ```typescript
833
- enum EnumWithStrings {
834
- /*
835
- * Used when the status of something is successful
836
- */
837
- Success = 0,
838
- /*
839
- * Used when the status of something has a warning
840
- */
841
- Waring = 1,
842
- /*
843
- * Used when the status of something has an error
844
- */
845
- Error = 2,
846
- }
847
- ```
848
-
849
-
850
- ### Nullable in OpenAPI v2
851
- In the OpenAPI v3 spec you can create properties that can be NULL, by providing a `nullable: true` in your schema.
852
- However, the v2 spec does not allow you to do this. You can use the unofficial `x-nullable` in your specification
853
- to generate nullable properties in OpenApi v2.
854
-
855
- ```json
856
- {
857
- "ModelWithNullableString": {
858
- "required": ["requiredProp"],
859
- "description": "This is a model with one string property",
860
- "type": "object",
861
- "properties": {
862
- "prop": {
863
- "description": "This is a simple string property",
864
- "type": "string",
865
- "x-nullable": true
866
- },
867
- "requiredProp": {
868
- "description": "This is a simple string property",
869
- "type": "string",
870
- "x-nullable": true
871
- }
872
- }
873
- }
874
- }
875
- ```
876
-
877
- Generated code:
878
- ```typescript
879
- interface ModelWithNullableString {
880
- prop?: string | null,
881
- requiredProp: string | null,
882
- }
883
- ```
884
-
885
-
886
- ### Authorization
887
- The OpenAPI generator supports Bearer Token authorization. In order to enable the sending
888
- of tokens in each request you can set the token using the global OpenAPI configuration:
889
-
890
- ```typescript
891
- import { OpenAPI } from './generated';
892
-
893
- OpenAPI.TOKEN = 'some-bearer-token';
894
- ```
895
-
896
- Alternatively, we also support an async method that provides the token for each request.
897
- You can simply assign this method to the same `TOKEN `property in the global OpenAPI object.
898
-
899
- ```typescript
900
- import { OpenAPI } from './generated';
901
-
902
- const getToken = async () => {
903
- // Some code that requests a token...
904
- return 'SOME_TOKEN';
905
- }
906
-
907
- OpenAPI.TOKEN = getToken;
908
- ```
909
-
910
- ### References
911
-
912
- Local references to schema definitions (those beginning with `#/definitions/schemas/`)
913
- will be converted to type references to the equivalent, generated top-level type.
914
-
915
- The OpenAPI generator also supports external references, which allows you to break
916
- down your openapi.yml into multiple sub-files, or incorporate third-party schemas
917
- as part of your types to ensure everything is able to be TypeScript generated.
918
-
919
- External references may be:
920
- * *relative references* - references to other files at the same location e.g.
921
- `{ $ref: 'schemas/customer.yml' }`
922
- * *remote references* - fully qualified references to another remote location
923
- e.g. `{ $ref: 'https://myexampledomain.com/schemas/customer_schema.yml' }`
924
-
925
- For remote references, both files (when the file is on the current filesystem)
926
- and http(s) URLs are supported.
927
-
928
- External references may also contain internal paths in the external schema (e.g.
929
- `schemas/collection.yml#/definitions/schemas/Customer`) and back-references to
930
- the base openapi file or between files (so that you can reference another
931
- schema in the main file as a type of an object or array property, for example).
932
-
933
- At start-up, an OpenAPI or Swagger file with external references will be "bundled",
934
- so that all external references and back-references will be resolved (but local
935
- references preserved).
936
-
937
- FAQ
938
- ===
939
-
940
- ### Babel support
941
- If you use enums inside your models / definitions then those enums are by default inside a namespace with the same name
942
- as your model. This is called declaration merging. However, the [@babel/plugin-transform-typescript](https://babeljs.io/docs/en/babel-plugin-transform-typescript)
943
- does not support these namespaces, so if you are using babel in your project please use the `--useUnionTypes` flag
944
- to generate union types instead of traditional enums. More info can be found here: [Enums vs. Union Types](#enums-vs-union-types---useuniontypes).
945
-
946
- **Note:** If you are using Babel 7 and Typescript 3.8 (or higher) then you should enable the `onlyRemoveTypeImports` to
947
- ignore any 'type only' imports, see https://babeljs.io/docs/en/babel-preset-typescript#onlyremovetypeimports for more info
948
-
949
- ```javascript
950
- module.exports = {
951
- presets: [
952
- ['@babel/preset-typescript', {
953
- onlyRemoveTypeImports: true,
954
- }],
955
- ],
956
- };
957
- ```
958
-
959
-
960
- ### Node.js support
961
- By default, this library will generate a client that is compatible with the (browser based) [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),
962
- however this client will not work inside the Node.js environment. If you want to generate a Node.js compatible client then
963
- you can specify `--httpClient node` in the openapi call:
964
-
965
- `openapi generate --input ./spec.json --output ./dist --httpClient node`
966
-
967
- This will generate a client that uses [`node-fetch`](https://www.npmjs.com/package/node-fetch) internally. However,
968
- in order to compile and run this client, you will need to install the `node-fetch` dependencies:
969
-
970
- ```
971
- npm install @types/node-fetch --save-dev
972
- npm install node-fetch --save-dev
973
- npm install form-data --save-dev
37
+ npm install ts-openapi-codegen --save-dev
974
38
  ```
975
39
 
976
- In order to compile the project and resolve the imports, you will need to enable the `allowSyntheticDefaultImports`
977
- in your `tsconfig.json` file.
40
+ ## Documentation
978
41
 
979
- ```json
980
- {
981
- "allowSyntheticDefaultImports": true
982
- }
983
- ```
42
+ - [Usage](docs/en/usage.md)
43
+ - [Configuration file](docs/en/configuration.md)
44
+ - [Examples](docs/en/examples.md)
45
+ - [Features](docs/en/features.md)
46
+ - [Русская версия README](README.rus.md)
47
+ - [Русская документация](docs/ru/usage.md)
984
48
 
985
49
  [npm-url]: https://www.npmjs.com/package/ts-openapi-codegen
986
50
  [npm-image]: https://img.shields.io/npm/v/ts-openapi-codegen.svg