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