swagger-typescript-api 11.0.0--alpha-6 β†’ 11.0.0--beta-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,506 +1,510 @@
1
- # swagger-typescript-api
2
-
3
- [![NPM badge](https://img.shields.io/npm/v/swagger-typescript-api.svg)](https://www.npmjs.com/package/swagger-typescript-api)
4
- [![CI](https://github.com/acacode/swagger-typescript-api/actions/workflows/main.yml/badge.svg?branch=next)](https://github.com/acacode/swagger-typescript-api/actions/workflows/main.yml) <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
5
- [![All Contributors](https://img.shields.io/badge/all_contributors-31-orange.svg)](#contributors)
6
- <!-- ALL-CONTRIBUTORS-BADGE:END -->
7
-
8
- <img src="https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/swagger-typescript-api-logo.png" align="left"
9
- title="swagger-typescript-api logo by js2me" width="93" height="180">
10
-
11
- Generate api via swagger scheme.
12
- Supports OA 3.0, 2.0, JSON, yaml
13
- Generated api module use [**Fetch Api**](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) or [**Axios**](https://github.com/axios/axios) to make requests.
14
-
15
- <br>
16
- <br>
17
-
18
- Any questions you can ask [**here**](https://github.com/acacode/swagger-typescript-api/issues) or in [**our slack**](https://join.slack.com/t/acacode/shared_invite/enQtOTQ5ODgyODQzMzYwLWYxOGI1MzQ3Yzg1ZWI5ZTI5NzNiZjExZTE5OWI1YjQ4NjBiNTk4NWVlNjM5YmU1ZWI2ZDkyMzZkZGIxNjA5NTQ)(**#swagger-typescript-api** channel)
19
-
20
- <br>
21
-
22
- ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/components-converter-example.jpg)
23
-
24
- πŸ‘€ This project is looking for a code maintainer πŸ‘€
25
- P.S. If you are creating the PR, please check your changes with using command `npm run prepare`
26
- P.S. If you want to contribute please use branch `next`. All PRs which will have target `master` will be declined
27
-
28
- ## πŸ‘€ Examples
29
-
30
- All examples you can find [**here**](https://github.com/acacode/swagger-typescript-api/tree/master/tests)
31
-
32
- ## πŸ“„ Usage
33
-
34
- ```muse
35
- Usage: sta [options]
36
- Usage: swagger-typescript-api [options]
37
-
38
- Options:
39
- -v, --version output the current version
40
- -p, --path <string> path/url to swagger scheme
41
- -o, --output <string> output path of typescript api file (default: "./")
42
- -n, --name <string> name of output typescript api file (default: "Api.ts")
43
- -t, --templates <string> path to folder containing templates
44
- -d, --default-as-success use "default" response status code as success response too.
45
- some swagger schemas use "default" response status code as success response type by default. (default: false)
46
- -r, --responses generate additional information about request responses
47
- also add typings for bad responses (default: false)
48
- --union-enums generate all "enum" types as union types (T1 | T2 | TN) (default: false)
49
- --add-readonly generate readonly properties (default: false)
50
- --route-types generate type definitions for API routes (default: false)
51
- --no-client do not generate an API class
52
- --enum-names-as-values use values in 'x-enumNames' as enum values (not only as keys) (default: false)
53
- --extract-request-params extract request params to data contract (Also combine path params and query params into one object) (default: false)
54
- --extract-request-body extract request body type to data contract (default: false)
55
- --extract-response-body extract response body type to data contract (default: false)
56
- --extract-response-error extract response error type to data contract (default: false)
57
- --modular generate separated files for http client, data contracts, and routes (default: false)
58
- --js generate js api module with declaration file (default: false)
59
- --module-name-index <number> determines which path index should be used for routes separation (example: GET:/fruites/getFruit -> index:0 -> moduleName -> fruites) (default: 0)
60
- --module-name-first-tag splits routes based on the first tag (default: false)
61
- --disableStrictSSL disabled strict SSL (default: false)
62
- --disableProxy disabled proxy (default: false)
63
- --axios generate axios http client (default: false)
64
- --unwrap-response-data unwrap the data item from the response (default: false)
65
- --disable-throw-on-error Do not throw an error when response.ok is not true (default: false)
66
- --single-http-client Ability to send HttpClient instance to Api constructor (default: false)
67
- --silent Output only errors to console (default: false)
68
- --default-response <type> default type for empty response schema (default: "void")
69
- --type-prefix <string> data contract name prefix (default: "")
70
- --type-suffix <string> data contract name suffix (default: "")
71
- --clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
72
- --api-class-name <string> name of the api class
73
- --patch fix up small errors in the swagger source definition (default: false)
74
- --debug additional information about processes inside this tool (default: false)
75
- --another-array-type generate array types as Array<Type> (by default Type[]) (default: false)
76
- -h, --help display help for command
77
- ```
78
-
79
- Also you can use `npx`:
80
- ```
81
- npx swagger-typescript-api -p ./swagger.json -o ./src -n myApi.ts
82
- ```
83
-
84
- You can use this package from nodejs:
85
- ```js
86
- const { generateApi } = require('swagger-typescript-api');
87
- const path = require("path");
88
- const fs = require("fs");
89
-
90
- /* NOTE: all fields are optional expect one of `output`, `url`, `spec` */
91
- generateApi({
92
- name: "MySuperbApi.ts",
93
- output: path.resolve(process.cwd(), "./src/__generated__"),
94
- url: 'http://api.com/swagger.json',
95
- input: path.resolve(process.cwd(), './foo/swagger.json'),
96
- spec: {
97
- swagger: "2.0",
98
- info: {
99
- version: "1.0.0",
100
- title: "Swagger Petstore",
101
- },
102
- // ...
103
- },
104
- templates: path.resolve(process.cwd(), './api-templates'),
105
- httpClientType: "axios", // or "fetch"
106
- defaultResponseAsSuccess: false,
107
- generateRouteTypes: false,
108
- generateResponses: true,
109
- toJS: false,
110
- extractRequestParams: false,
111
- extractRequestBody: false,
112
- unwrapResponseData: false,
113
- prettier: { // By default prettier config is load from your project
114
- printWidth: 120,
115
- tabWidth: 2,
116
- trailingComma: "all",
117
- parser: "typescript",
118
- },
119
- defaultResponseType: "void",
120
- singleHttpClient: true,
121
- cleanOutput: false,
122
- enumNamesAsValues: false,
123
- moduleNameFirstTag: false,
124
- generateUnionEnums: false,
125
- addReadonly: false,
126
- extraTemplates: [],
127
- anotherArrayType: false,
128
- codeGenConstructs: (constructs) => ({
129
- ...constructs,
130
- RecordType: (key, value) => `MyRecord<key, value>`
131
- }),
132
- primitiveTypeConstructs: (constructs) => ({
133
- ...constructs,
134
- string: {
135
- 'date-time': 'Date'
136
- }
137
- }),
138
- hooks: {
139
- onCreateComponent: (component) => {},
140
- onCreateRequestParams: (rawType) => {},
141
- onCreateRoute: (routeData) => {},
142
- onCreateRouteName: (routeNameInfo, rawRouteInfo) => {},
143
- onFormatRouteName: (routeInfo, templateRouteName) => {},
144
- onFormatTypeName: (typeName, rawTypeName) => {},
145
- onInit: (configuration) => {},
146
- onParseSchema: (originalSchema, parsedSchema) => {},
147
- onPrepareConfig: (currentConfiguration) => {},
148
- }
149
- })
150
- .then(({ files, configuration }) => {
151
- files.forEach(({ content, name }) => {
152
- fs.writeFile(path, content);
153
- });
154
- })
155
- .catch(e => console.error(e))
156
-
157
- ```
158
-
159
-
160
- ## πŸ’Ž options
161
- ### **`--templates`**
162
- This option needed for cases when you don't want to use the default `swagger-typescript-api` output structure
163
- You can create custom templates with extensions `.ejs` or `.eta`
164
-
165
- Templates:
166
- - `api.ejs` - *(generates file)* Api class module (locations: [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default/api.ejs), [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular/api.ejs))
167
- - `data-contracts.ejs` - *(generates file)* all types (data contracts) from swagger schema (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/data-contracts.ejs))
168
- - `http-client.ejs` - *(generates file)* HttpClient class module (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/http-client.ejs))
169
- - `procedure-call.ejs` - *(subtemplate)* route in Api class (locations: [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default/procedure-call.ejs), [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular/procedure-call.ejs))
170
- - `route-docs.ejs` - *(generates file)* documentation for route in Api class (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-docs.ejs))
171
- - `route-name.ejs` - *(subtemplate)* route name for route in Api class (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-name.ejs))
172
- - `route-type.ejs` - *(`--route-types` option)* *(subtemplate)* (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-type.ejs))
173
- - `route-types.ejs` - *(`--route-types` option)* *(subtemplate)* (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-types.ejs))
174
- - `data-contract-jsdoc.ejs` - *(subtemplate)* generates JSDOC for data contract (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/data-contract-jsdoc.ejs))
175
-
176
- [//]: # (- `enum-data-contract.ejs` - *&#40;subtemplate&#41;* generates `enum` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/enum-data-contract.ejs&#41;&#41;)
177
- [//]: # (- `interface-data-contract.ejs` - *&#40;subtemplate&#41;* generates `interface` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/interface-data-contract.ejs&#41;&#41;)
178
- [//]: # (- `type-data-contract.ejs` - *&#40;subtemplate&#41;* generates `type` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/type-data-contract.ejs&#41;&#41;)
179
-
180
-
181
- How to use it:
182
- 1. copy `swagger-typescript-api` templates into your place in project
183
- - from [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default) for single api file
184
- - from [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular) for multiple api files (with `--modular` option)
185
- - from [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base) for base templates (templates using both in default and modular)
186
- 1. add `--templates PATH_TO_YOUR_TEMPLATES` option
187
- 2. modify [ETA](https://eta.js.org/docs/syntax) templates as you like
188
-
189
- NOTE:
190
- Eta has special directive to render template in your Eta templates - `includeFile(pathToTemplate, payload)`
191
- If you want to use some default templates from this tool you can use path prefixes: `@base`, `@default`, `@modular`.
192
- `@base` - [path to base templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base)
193
- `@default` - [path to single api file templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default)
194
- `@modular` - [path to multiple api files templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular)
195
- Examples:
196
- - `includeFile("@base/data-contracts.ejs", { ...yourData, ...it })`
197
- - `includeFile("@default/api.ejs", { ...yourData, ...it })`
198
- - `includeFile("@default/procedure-call.ejs", { ...yourData, ...it })`
199
- - `includeFile("@modular/api.ejs", { ...yourData, ...it })`
200
- - `includeFile("@modular/procedure-call.ejs", { ...yourData, ...it })`
201
- - `includeFile("@base/route-docs.ejs", { ...yourData, ...it })`
202
- - `includeFile("@base/route-name.ejs", { ...yourData, ...it })`
203
- - `includeFile("@base/route-type.ejs", { ...yourData, ...it })`
204
- - `includeFile("@base/route-types.ejs", { ...yourData, ...it })`
205
-
206
- ### **`--module-name-index`**
207
- This option should be used in cases when you have api with one global prefix like `/api`
208
- Example:
209
- `GET:/api/fruits/getFruits`
210
- `POST:/api/fruits/addFruits`
211
- `GET:/api/vegetables/addVegetable`
212
- with `--module-name-index 0` Api class will have one property `api`
213
- When we change it to `--module-name-index 1` then Api class have two properties `fruits` and `vegetables`
214
-
215
- ### **`--module-name-first-tag`**
216
- This option will group your API operations based on their first tag - mirroring how the Swagger UI groups displayed operations
217
-
218
-
219
- ## Modification internal codegen structs with NodeJS API:
220
-
221
- You are able to modify TypeScript internal structs using for generating output with using `generateApi` options `codeGenConstructs` and `primitiveTypeConstructs`.
222
-
223
- ### `codeGenConstructs`
224
-
225
- This option has type `(struct: CodeGenConstruct) => Partial<CodeGenConstruct>`.
226
-
227
- ```ts
228
- generateApi({
229
- // ...
230
- codeGenConstructs: (struct) => ({
231
- Keyword: {
232
- Number: "number",
233
- String: "string",
234
- Boolean: "boolean",
235
- Any: "any",
236
- Void: "void",
237
- Unknown: "unknown",
238
- Null: "null",
239
- Undefined: "undefined",
240
- Object: "object",
241
- File: "File",
242
- Date: "Date",
243
- Type: "type",
244
- Enum: "enum",
245
- Interface: "interface",
246
- Array: "Array",
247
- Record: "Record",
248
- Intersection: "&",
249
- Union: "|",
250
- },
251
- CodeGenKeyword: {
252
- UtilRequiredKeys: "UtilRequiredKeys",
253
- },
254
- /**
255
- * $A[] or Array<$A>
256
- */
257
- ArrayType: (content) => {
258
- if (this.anotherArrayType) {
259
- return `Array<${content}>`;
260
- }
261
-
262
- return `(${content})[]`;
263
- },
264
- /**
265
- * "$A"
266
- */
267
- StringValue: (content) => `"${content}"`,
268
- /**
269
- * $A
270
- */
271
- BooleanValue: (content) => `${content}`,
272
- /**
273
- * $A
274
- */
275
- NumberValue: (content) => `${content}`,
276
- /**
277
- * $A
278
- */
279
- NullValue: (content) => content,
280
- /**
281
- * $A1 | $A2
282
- */
283
- UnionType: (contents) => _.join(_.uniq(contents), ` | `),
284
- /**
285
- * ($A1)
286
- */
287
- ExpressionGroup: (content) => (content ? `(${content})` : ""),
288
- /**
289
- * $A1 & $A2
290
- */
291
- IntersectionType: (contents) => _.join(_.uniq(contents), ` & `),
292
- /**
293
- * Record<$A1, $A2>
294
- */
295
- RecordType: (key, value) => `Record<${key}, ${value}>`,
296
- /**
297
- * readonly $key?:$value
298
- */
299
- TypeField: ({ readonly, key, optional, value }) =>
300
- _.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
301
- /**
302
- * [key: $A1]: $A2
303
- */
304
- InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
305
- /**
306
- * $A1 = $A2
307
- */
308
- EnumField: (key, value) => `${key} = ${value}`,
309
- /**
310
- * $A0.key = $A0.value,
311
- * $A1.key = $A1.value,
312
- * $AN.key = $AN.value,
313
- */
314
- EnumFieldsWrapper: (contents) =>
315
- _.map(contents, ({ key, value }) => ` ${key} = ${value}`).join(",\n"),
316
- /**
317
- * {\n $A \n}
318
- */
319
- ObjectWrapper: (content) => `{\n${content}\n}`,
320
- /**
321
- * /** $A *\/
322
- */
323
- MultilineComment: (contents, formatFn) =>
324
- [
325
- ...(contents.length === 1
326
- ? [`/** ${contents[0]} */`]
327
- : ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
328
- ].map((part) => `${formatFn ? formatFn(part) : part}\n`),
329
- /**
330
- * $A1<...$A2.join(,)>
331
- */
332
- TypeWithGeneric: (typeName, genericArgs) => {
333
- return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
334
- },
335
- })
336
- })
337
- ```
338
-
339
- For example, if you need to generate output `Record<string, any>` instead of `object` you can do it with using following code:
340
-
341
- ```ts
342
- generateApi({
343
- // ...
344
- codeGenConstructs: (struct) => ({
345
- Keyword: {
346
- Object: "Record<string, any>",
347
- }
348
- })
349
- })
350
- ```
351
-
352
- ### `primitiveTypeConstructs`
353
-
354
- It is type mapper or translator swagger schema objects. `primitiveTypeConstructs` translates `type`/`format` schema fields to typescript structs.
355
- This option has type
356
- ```ts
357
- type PrimitiveTypeStructValue =
358
- | string
359
- | ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
360
-
361
- type PrimitiveTypeStruct = Record<
362
- "integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
363
- string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
364
- >
365
-
366
- declare const primitiveTypeConstructs: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>
367
-
368
- generateApi({
369
- // ...
370
- primitiveTypeConstructs: (struct) => ({
371
- integer: () => "number",
372
- number: () => "number",
373
- boolean: () => "boolean",
374
- object: () => "object",
375
- file: () => "File",
376
- string: {
377
- $default: () => "string",
378
-
379
- /** formats */
380
- binary: () => "File",
381
- file: () => "File",
382
- "date-time": () => "string",
383
- time: () => "string",
384
- date: () => "string",
385
- duration: () => "string",
386
- email: () => "string",
387
- "idn-email": () => "string",
388
- "idn-hostname": () => "string",
389
- ipv4: () => "string",
390
- ipv6: () => "string",
391
- uuid: () => "string",
392
- uri: () => "string",
393
- "uri-reference": () => "string",
394
- "uri-template": () => "string",
395
- "json-pointer": () => "string",
396
- "relative-json-pointer": () => "string",
397
- regex: () => "string",
398
- },
399
- array: (schema, parser) => {
400
- const content = parser.getInlineParseContent(schema.items);
401
- return parser.checkAndAddNull(schema, `(${content})[]`);
402
- },
403
- })
404
- })
405
- ```
406
-
407
- For example, if you need to change `"string"/"date-time"` default output as `string` to `Date` you can do it with using following code:
408
-
409
- ```ts
410
-
411
- generateApi({
412
- primitiveTypeConstructs: (struct) => ({
413
- string: {
414
- "date-time": "Date",
415
- },
416
- })
417
- })
418
-
419
- ```
420
-
421
- See more about [swagger schema type/format data here](https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times)
422
-
423
- ## πŸ“„ Mass media
424
-
425
- - [5 Lessons learned about swagger-typescript-api](https://christo8989.medium.com/5-lessons-learned-about-swagger-typescript-api-511240b34c1)
426
- - [Why Swagger schemes are needed in frontend development ?](https://dev.to/js2me/why-swagger-schemes-are-needed-in-frontend-development-2cb4)
427
- - [Migration en douceur vers TypeScript (French)](https://www.premieroctet.com/blog/migration-typescript/)
428
- - [swagger-typescript-api usage (Japanese)](https://zenn.dev/watahaya/articles/2f4a716c47903b)
429
-
430
- ## πŸ› οΈ Contribution
431
-
432
- ❗❗❗ Please use the `next` branch :)
433
-
434
- If you need to check your changes at schemas in `tests` folder before create a PR just run command `npm run test-all`
435
-
436
- ## Contributors ✨
437
-
438
- Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
439
-
440
- <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
441
- <!-- prettier-ignore-start -->
442
- <!-- markdownlint-disable -->
443
- <table>
444
- <tbody>
445
- <tr>
446
- <td align="center"><a href="https://github.com/js2me"><img src="https://avatars1.githubusercontent.com/u/16340911?v=4?s=100" width="100px;" alt="Sergey S. Volkov"/><br /><sub><b>Sergey S. Volkov</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=js2me" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=js2me" title="Documentation">πŸ“–</a> <a href="#design-js2me" title="Design">🎨</a> <a href="#example-js2me" title="Examples">πŸ’‘</a> <a href="#maintenance-js2me" title="Maintenance">🚧</a> <a href="#ideas-js2me" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ajs2me" title="Bug reports">πŸ›</a></td>
447
- <td align="center"><a href="https://github.com/andrefilimono"><img src="https://avatars0.githubusercontent.com/u/7794526?v=4?s=100" width="100px;" alt="Filimonov Andrey"/><br /><sub><b>Filimonov Andrey</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=andrefilimono" title="Code">πŸ’»</a> <a href="#ideas-andrefilimono" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-andrefilimono" title="Design">🎨</a></td>
448
- <td align="center"><a href="https://github.com/Fl0pZz"><img src="https://avatars2.githubusercontent.com/u/9510124?v=4?s=100" width="100px;" alt="Rafael Fakhreev"/><br /><sub><b>Rafael Fakhreev</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=Fl0pZz" title="Code">πŸ’»</a> <a href="#ideas-Fl0pZz" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
449
- <td align="center"><a href="https://azzola.dev"><img src="https://avatars3.githubusercontent.com/u/1297597?v=4?s=100" width="100px;" alt="Lucas Azzola"/><br /><sub><b>Lucas Azzola</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=azz" title="Code">πŸ’»</a> <a href="#ideas-azz" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-azz" title="Design">🎨</a></td>
450
- <td align="center"><a href="https://github.com/JennieJi"><img src="https://avatars3.githubusercontent.com/u/1913045?v=4?s=100" width="100px;" alt="Jennie"/><br /><sub><b>Jennie</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=JennieJi" title="Code">πŸ’»</a> <a href="#ideas-JennieJi" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
451
- <td align="center"><a href="https://github.com/jomarquez21"><img src="https://avatars1.githubusercontent.com/u/16705169?v=4?s=100" width="100px;" alt="Jose Enrique Marquez"/><br /><sub><b>Jose Enrique Marquez</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jomarquez21" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ajomarquez21" title="Bug reports">πŸ›</a></td>
452
- <td align="center"><a href="https://glassechidna.com.au"><img src="https://avatars1.githubusercontent.com/u/482276?v=4?s=100" width="100px;" alt="Benjamin Dobell"/><br /><sub><b>Benjamin Dobell</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=Benjamin-Dobell" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ABenjamin-Dobell" title="Bug reports">πŸ›</a></td>
453
- </tr>
454
- <tr>
455
- <td align="center"><a href="http://fixate.it"><img src="https://avatars0.githubusercontent.com/u/1510520?v=4?s=100" width="100px;" alt="Larry Botha"/><br /><sub><b>Larry Botha</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=larrybotha" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Alarrybotha" title="Bug reports">πŸ›</a></td>
456
- <td align="center"><a href="https://github.com/nikalun"><img src="https://avatars3.githubusercontent.com/u/13102962?v=4?s=100" width="100px;" alt="Nikolay Lukinykh"/><br /><sub><b>Nikolay Lukinykh</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=nikalun" title="Code">πŸ’»</a> <a href="#ideas-nikalun" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Anikalun" title="Bug reports">πŸ›</a></td>
457
- <td align="center"><a href="https://github.com/Mvbraathen"><img src="https://avatars0.githubusercontent.com/u/16756739?v=4?s=100" width="100px;" alt="Marius BrΓ₯then"/><br /><sub><b>Marius BrΓ₯then</b></sub></a><br /><a href="#security-Mvbraathen" title="Security">πŸ›‘οΈ</a></td>
458
- <td align="center"><a href="https://github.com/xesjkeee"><img src="https://avatars2.githubusercontent.com/u/17751886?v=4?s=100" width="100px;" alt="Evgeny Vlasov"/><br /><sub><b>Evgeny Vlasov</b></sub></a><br /><a href="#ideas-xesjkeee" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
459
- <td align="center"><a href="https://github.com/kel666"><img src="https://avatars1.githubusercontent.com/u/2040661?v=4?s=100" width="100px;" alt="Fabio"/><br /><sub><b>Fabio</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Akel666" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=kel666" title="Code">πŸ’»</a></td>
460
- <td align="center"><a href="https://github.com/Fabiencdp"><img src="https://avatars.githubusercontent.com/u/6182473?v=4?s=100" width="100px;" alt="Fabien"/><br /><sub><b>Fabien</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AFabiencdp" title="Bug reports">πŸ›</a></td>
461
- <td align="center"><a href="https://about.me/julienrousseau"><img src="https://avatars.githubusercontent.com/u/3296671?v=4?s=100" width="100px;" alt="Rousseau Julien"/><br /><sub><b>Rousseau Julien</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ARoXuS" title="Bug reports">πŸ›</a></td>
462
- </tr>
463
- <tr>
464
- <td align="center"><a href="http://sebastianarias.dev"><img src="https://avatars.githubusercontent.com/u/9751266?v=4?s=100" width="100px;" alt="SebastiΓ‘n Arias"/><br /><sub><b>SebastiΓ‘n Arias</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ALarox" title="Bug reports">πŸ›</a></td>
465
- <td align="center"><a href="https://github.com/Styn"><img src="https://avatars.githubusercontent.com/u/6705137?v=4?s=100" width="100px;" alt="Stijn Lammens"/><br /><sub><b>Stijn Lammens</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AStyn" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=Styn" title="Code">πŸ’»</a></td>
466
- <td align="center"><a href="http://emilecantin.com"><img src="https://avatars.githubusercontent.com/u/885486?v=4?s=100" width="100px;" alt="Emile Cantin"/><br /><sub><b>Emile Cantin</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Aemilecantin" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=emilecantin" title="Code">πŸ’»</a></td>
467
- <td align="center"><a href="https://github.com/armsnyder"><img src="https://avatars.githubusercontent.com/u/9969202?v=4?s=100" width="100px;" alt="Adam Snyder"/><br /><sub><b>Adam Snyder</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=armsnyder" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Aarmsnyder" title="Bug reports">πŸ›</a></td>
468
- <td align="center"><a href="https://github.com/jnpoyser"><img src="https://avatars.githubusercontent.com/u/7920428?v=4?s=100" width="100px;" alt="James Poyser"/><br /><sub><b>James Poyser</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jnpoyser" title="Code">πŸ’»</a> <a href="#ideas-jnpoyser" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
469
- <td align="center"><a href="http://ru.linkedin.com/in/lisikhin"><img src="https://avatars.githubusercontent.com/u/475367?v=4?s=100" width="100px;" alt="Alexey"/><br /><sub><b>Alexey</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ANihisil" title="Bug reports">πŸ›</a></td>
470
- <td align="center"><a href="http://imaniu.com"><img src="https://avatars.githubusercontent.com/u/50100681?v=4?s=100" width="100px;" alt="江麻妞"/><br /><sub><b>江麻妞</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jiangmaniu" title="Code">πŸ’»</a></td>
471
- </tr>
472
- <tr>
473
- <td align="center"><a href="https://kspr.dev"><img src="https://avatars.githubusercontent.com/u/5294519?v=4?s=100" width="100px;" alt="Kasper Moskwiak"/><br /><sub><b>Kasper Moskwiak</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=kmoskwiak" title="Code">πŸ’»</a> <a href="#ideas-kmoskwiak" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
474
- <td align="center"><a href="https://github.com/baggoedw"><img src="https://avatars.githubusercontent.com/u/92381702?v=4?s=100" width="100px;" alt="baggoedw"/><br /><sub><b>baggoedw</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=baggoedw" title="Code">πŸ’»</a></td>
475
- <td align="center"><a href="https://marcusdunn.github.io"><img src="https://avatars.githubusercontent.com/u/51931484?v=4?s=100" width="100px;" alt="Marcus Dunn"/><br /><sub><b>Marcus Dunn</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=MarcusDunn" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AMarcusDunn" title="Bug reports">πŸ›</a></td>
476
- <td align="center"><a href="https://www.danielplayfaircal.com/"><img src="https://avatars.githubusercontent.com/u/1217649?v=4?s=100" width="100px;" alt="Daniel Playfair Cal"/><br /><sub><b>Daniel Playfair Cal</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=hedgepigdaniel" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ahedgepigdaniel" title="Bug reports">πŸ›</a></td>
477
- <td align="center"><a href="https://www.linkedin.com/in/patrick-shaw/"><img src="https://avatars.githubusercontent.com/u/5153619?v=4?s=100" width="100px;" alt="Patrick Shaw"/><br /><sub><b>Patrick Shaw</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/pulls?q=is%3Apr+reviewed-by%3APatrickShaw" title="Reviewed Pull Requests">πŸ‘€</a></td>
478
- <td align="center"><a href="https://www.linkedin.com/in/jinkwon-lee"><img src="https://avatars.githubusercontent.com/u/1798916?v=4?s=100" width="100px;" alt="JK"/><br /><sub><b>JK</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jinkwon" title="Code">πŸ’»</a></td>
479
- <td align="center"><a href="https://github.com/RoCat"><img src="https://avatars.githubusercontent.com/u/3562317?v=4?s=100" width="100px;" alt="RoCat"/><br /><sub><b>RoCat</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=RoCat" title="Code">πŸ’»</a> <a href="#ideas-RoCat" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-RoCat" title="Design">🎨</a></td>
480
- </tr>
481
- <tr>
482
- <td align="center"><a href="https://github.com/ApacheEx"><img src="https://avatars.githubusercontent.com/u/1918108?v=4?s=100" width="100px;" alt="Oleg Kuzava"/><br /><sub><b>Oleg Kuzava</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=ApacheEx" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AApacheEx" title="Bug reports">πŸ›</a></td>
483
- <td align="center"><a href="http://nikz.se"><img src="https://avatars.githubusercontent.com/u/7352072?v=4?s=100" width="100px;" alt="Niklas Frank"/><br /><sub><b>Niklas Frank</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=nksfrank" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Anksfrank" title="Bug reports">πŸ›</a></td>
484
- <td align="center"><a href="https://quentinbrunet.com"><img src="https://avatars.githubusercontent.com/u/20137632?v=4?s=100" width="100px;" alt="Quentin Brunet"/><br /><sub><b>Quentin Brunet</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=qboot" title="Code">πŸ’»</a></td>
485
- </tr>
486
- </tbody>
487
- </table>
488
-
489
- <!-- markdownlint-restore -->
490
- <!-- prettier-ignore-end -->
491
-
492
- <!-- ALL-CONTRIBUTORS-LIST:END -->
493
-
494
- This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
495
-
496
- ## πŸš€ How it looks
497
-
498
- ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/npx.gif)
499
-
500
- ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/auth-example.gif)
501
-
502
- ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/typings1.gif)
503
-
504
-
505
- ## πŸ“ License
506
- Licensed under the [MIT License](https://github.com/acacode/swagger-typescript-api/blob/master/LICENSE).
1
+ # swagger-typescript-api
2
+
3
+ [![NPM badge](https://img.shields.io/npm/v/swagger-typescript-api.svg)](https://www.npmjs.com/package/swagger-typescript-api)
4
+ [![CI](https://github.com/acacode/swagger-typescript-api/actions/workflows/main.yml/badge.svg?branch=next)](https://github.com/acacode/swagger-typescript-api/actions/workflows/main.yml) <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
5
+ [![All Contributors](https://img.shields.io/badge/all_contributors-31-orange.svg)](#contributors)
6
+ <!-- ALL-CONTRIBUTORS-BADGE:END -->
7
+
8
+ <img src="https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/swagger-typescript-api-logo.png" align="left"
9
+ title="swagger-typescript-api logo by js2me" width="93" height="180">
10
+
11
+ Generate api via swagger scheme.
12
+ Supports OA 3.0, 2.0, JSON, yaml
13
+ Generated api module use [**Fetch Api**](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) or [**Axios**](https://github.com/axios/axios) to make requests.
14
+
15
+ <br>
16
+ <br>
17
+
18
+ Any questions you can ask [**here**](https://github.com/acacode/swagger-typescript-api/issues) or in [**our slack**](https://join.slack.com/t/acacode/shared_invite/enQtOTQ5ODgyODQzMzYwLWYxOGI1MzQ3Yzg1ZWI5ZTI5NzNiZjExZTE5OWI1YjQ4NjBiNTk4NWVlNjM5YmU1ZWI2ZDkyMzZkZGIxNjA5NTQ)(**#swagger-typescript-api** channel)
19
+
20
+ <br>
21
+
22
+ ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/components-converter-example.jpg)
23
+
24
+ πŸ‘€ This project is looking for a code maintainer πŸ‘€
25
+ P.S. If you are creating the PR, please check your changes with using command `npm run prepare`
26
+ P.S. If you want to contribute please use branch `next`. All PRs which will have target `master` will be declined
27
+
28
+ ## πŸ‘€ Examples
29
+
30
+ All examples you can find [**here**](https://github.com/acacode/swagger-typescript-api/tree/master/tests)
31
+
32
+ ## πŸ“„ Usage
33
+
34
+ ```muse
35
+ Usage: sta [options]
36
+ Usage: swagger-typescript-api [options]
37
+
38
+ Options:
39
+ -v, --version output the current version
40
+ -p, --path <string> path/url to swagger scheme
41
+ -o, --output <string> output path of typescript api file (default: "./")
42
+ -n, --name <string> name of output typescript api file (default: "Api.ts")
43
+ -t, --templates <string> path to folder containing templates
44
+ -d, --default-as-success use "default" response status code as success response too.
45
+ some swagger schemas use "default" response status code as success response type by default. (default: false)
46
+ -r, --responses generate additional information about request responses
47
+ also add typings for bad responses (default: false)
48
+ --union-enums generate all "enum" types as union types (T1 | T2 | TN) (default: false)
49
+ --add-readonly generate readonly properties (default: false)
50
+ --route-types generate type definitions for API routes (default: false)
51
+ --no-client do not generate an API class
52
+ --enum-names-as-values use values in 'x-enumNames' as enum values (not only as keys) (default: false)
53
+ --extract-request-params extract request params to data contract (Also combine path params and query params into one object) (default: false)
54
+ --extract-request-body extract request body type to data contract (default: false)
55
+ --extract-response-body extract response body type to data contract (default: false)
56
+ --extract-response-error extract response error type to data contract (default: false)
57
+ --modular generate separated files for http client, data contracts, and routes (default: false)
58
+ --js generate js api module with declaration file (default: false)
59
+ --module-name-index <number> determines which path index should be used for routes separation (example: GET:/fruites/getFruit -> index:0 -> moduleName -> fruites) (default: 0)
60
+ --module-name-first-tag splits routes based on the first tag (default: false)
61
+ --disableStrictSSL disabled strict SSL (default: false)
62
+ --disableProxy disabled proxy (default: false)
63
+ --axios generate axios http client (default: false)
64
+ --unwrap-response-data unwrap the data item from the response (default: false)
65
+ --disable-throw-on-error Do not throw an error when response.ok is not true (default: false)
66
+ --single-http-client Ability to send HttpClient instance to Api constructor (default: false)
67
+ --silent Output only errors to console (default: false)
68
+ --default-response <type> default type for empty response schema (default: "void")
69
+ --type-prefix <string> data contract name prefix (default: "")
70
+ --type-suffix <string> data contract name suffix (default: "")
71
+ --clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
72
+ --api-class-name <string> name of the api class
73
+ --patch fix up small errors in the swagger source definition (default: false)
74
+ --debug additional information about processes inside this tool (default: false)
75
+ --another-array-type generate array types as Array<Type> (by default Type[]) (default: false)
76
+ -h, --help display help for command
77
+ ```
78
+
79
+ Also you can use `npx`:
80
+ ```
81
+ npx swagger-typescript-api -p ./swagger.json -o ./src -n myApi.ts
82
+ ```
83
+
84
+ You can use this package from nodejs:
85
+ ```js
86
+ const { generateApi } = require('swagger-typescript-api');
87
+ const path = require("path");
88
+ const fs = require("fs");
89
+
90
+ /* NOTE: all fields are optional expect one of `output`, `url`, `spec` */
91
+ generateApi({
92
+ name: "MySuperbApi.ts",
93
+ // set to `false` to prevent the tool from writing to disk
94
+ output: path.resolve(process.cwd(), "./src/__generated__"),
95
+ url: 'http://api.com/swagger.json',
96
+ input: path.resolve(process.cwd(), './foo/swagger.json'),
97
+ spec: {
98
+ swagger: "2.0",
99
+ info: {
100
+ version: "1.0.0",
101
+ title: "Swagger Petstore",
102
+ },
103
+ // ...
104
+ },
105
+ templates: path.resolve(process.cwd(), './api-templates'),
106
+ httpClientType: "axios", // or "fetch"
107
+ defaultResponseAsSuccess: false,
108
+ generateClient: true,
109
+ generateRouteTypes: false,
110
+ generateResponses: true,
111
+ toJS: false,
112
+ extractRequestParams: false,
113
+ extractRequestBody: false,
114
+ unwrapResponseData: false,
115
+ prettier: { // By default prettier config is load from your project
116
+ printWidth: 120,
117
+ tabWidth: 2,
118
+ trailingComma: "all",
119
+ parser: "typescript",
120
+ },
121
+ defaultResponseType: "void",
122
+ singleHttpClient: true,
123
+ cleanOutput: false,
124
+ enumNamesAsValues: false,
125
+ moduleNameFirstTag: false,
126
+ generateUnionEnums: false,
127
+ typePrefix: '',
128
+ typeSuffix: '',
129
+ addReadonly: false,
130
+ extraTemplates: [],
131
+ anotherArrayType: false,
132
+ codeGenConstructs: (constructs) => ({
133
+ ...constructs,
134
+ RecordType: (key, value) => `MyRecord<key, value>`
135
+ }),
136
+ primitiveTypeConstructs: (constructs) => ({
137
+ ...constructs,
138
+ string: {
139
+ 'date-time': 'Date'
140
+ }
141
+ }),
142
+ hooks: {
143
+ onCreateComponent: (component) => {},
144
+ onCreateRequestParams: (rawType) => {},
145
+ onCreateRoute: (routeData) => {},
146
+ onCreateRouteName: (routeNameInfo, rawRouteInfo) => {},
147
+ onFormatRouteName: (routeInfo, templateRouteName) => {},
148
+ onFormatTypeName: (typeName, rawTypeName) => {},
149
+ onInit: (configuration) => {},
150
+ onParseSchema: (originalSchema, parsedSchema) => {},
151
+ onPrepareConfig: (currentConfiguration) => {},
152
+ }
153
+ })
154
+ .then(({ files, configuration }) => {
155
+ files.forEach(({ content, name }) => {
156
+ fs.writeFile(path, content);
157
+ });
158
+ })
159
+ .catch(e => console.error(e))
160
+
161
+ ```
162
+
163
+
164
+ ## πŸ’Ž options
165
+ ### **`--templates`**
166
+ This option needed for cases when you don't want to use the default `swagger-typescript-api` output structure
167
+ You can create custom templates with extensions `.ejs` or `.eta`
168
+
169
+ Templates:
170
+ - `api.ejs` - *(generates file)* Api class module (locations: [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default/api.ejs), [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular/api.ejs))
171
+ - `data-contracts.ejs` - *(generates file)* all types (data contracts) from swagger schema (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/data-contracts.ejs))
172
+ - `http-client.ejs` - *(generates file)* HttpClient class module (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/http-client.ejs))
173
+ - `procedure-call.ejs` - *(subtemplate)* route in Api class (locations: [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default/procedure-call.ejs), [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular/procedure-call.ejs))
174
+ - `route-docs.ejs` - *(generates file)* documentation for route in Api class (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-docs.ejs))
175
+ - `route-name.ejs` - *(subtemplate)* route name for route in Api class (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-name.ejs))
176
+ - `route-type.ejs` - *(`--route-types` option)* *(subtemplate)* (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-type.ejs))
177
+ - `route-types.ejs` - *(`--route-types` option)* *(subtemplate)* (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/route-types.ejs))
178
+ - `data-contract-jsdoc.ejs` - *(subtemplate)* generates JSDOC for data contract (locations: [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/data-contract-jsdoc.ejs))
179
+
180
+ [//]: # (- `enum-data-contract.ejs` - *&#40;subtemplate&#41;* generates `enum` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/enum-data-contract.ejs&#41;&#41;)
181
+ [//]: # (- `interface-data-contract.ejs` - *&#40;subtemplate&#41;* generates `interface` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/interface-data-contract.ejs&#41;&#41;)
182
+ [//]: # (- `type-data-contract.ejs` - *&#40;subtemplate&#41;* generates `type` data contract &#40;locations: [/templates/base]&#40;https://github.com/acacode/swagger-typescript-api/tree/next/templates/base/type-data-contract.ejs&#41;&#41;)
183
+
184
+
185
+ How to use it:
186
+ 1. copy `swagger-typescript-api` templates into your place in project
187
+ - from [/templates/default](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default) for single api file
188
+ - from [/templates/modular](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular) for multiple api files (with `--modular` option)
189
+ - from [/templates/base](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base) for base templates (templates using both in default and modular)
190
+ 1. add `--templates PATH_TO_YOUR_TEMPLATES` option
191
+ 2. modify [ETA](https://eta.js.org/docs/syntax) templates as you like
192
+
193
+ NOTE:
194
+ Eta has special directive to render template in your Eta templates - `includeFile(pathToTemplate, payload)`
195
+ If you want to use some default templates from this tool you can use path prefixes: `@base`, `@default`, `@modular`.
196
+ `@base` - [path to base templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/base)
197
+ `@default` - [path to single api file templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/default)
198
+ `@modular` - [path to multiple api files templates](https://github.com/acacode/swagger-typescript-api/tree/next/templates/modular)
199
+ Examples:
200
+ - `includeFile("@base/data-contracts.ejs", { ...yourData, ...it })`
201
+ - `includeFile("@default/api.ejs", { ...yourData, ...it })`
202
+ - `includeFile("@default/procedure-call.ejs", { ...yourData, ...it })`
203
+ - `includeFile("@modular/api.ejs", { ...yourData, ...it })`
204
+ - `includeFile("@modular/procedure-call.ejs", { ...yourData, ...it })`
205
+ - `includeFile("@base/route-docs.ejs", { ...yourData, ...it })`
206
+ - `includeFile("@base/route-name.ejs", { ...yourData, ...it })`
207
+ - `includeFile("@base/route-type.ejs", { ...yourData, ...it })`
208
+ - `includeFile("@base/route-types.ejs", { ...yourData, ...it })`
209
+
210
+ ### **`--module-name-index`**
211
+ This option should be used in cases when you have api with one global prefix like `/api`
212
+ Example:
213
+ `GET:/api/fruits/getFruits`
214
+ `POST:/api/fruits/addFruits`
215
+ `GET:/api/vegetables/addVegetable`
216
+ with `--module-name-index 0` Api class will have one property `api`
217
+ When we change it to `--module-name-index 1` then Api class have two properties `fruits` and `vegetables`
218
+
219
+ ### **`--module-name-first-tag`**
220
+ This option will group your API operations based on their first tag - mirroring how the Swagger UI groups displayed operations
221
+
222
+
223
+ ## Modification internal codegen structs with NodeJS API:
224
+
225
+ You are able to modify TypeScript internal structs using for generating output with using `generateApi` options `codeGenConstructs` and `primitiveTypeConstructs`.
226
+
227
+ ### `codeGenConstructs`
228
+
229
+ This option has type `(struct: CodeGenConstruct) => Partial<CodeGenConstruct>`.
230
+
231
+ ```ts
232
+ generateApi({
233
+ // ...
234
+ codeGenConstructs: (struct) => ({
235
+ Keyword: {
236
+ Number: "number",
237
+ String: "string",
238
+ Boolean: "boolean",
239
+ Any: "any",
240
+ Void: "void",
241
+ Unknown: "unknown",
242
+ Null: "null",
243
+ Undefined: "undefined",
244
+ Object: "object",
245
+ File: "File",
246
+ Date: "Date",
247
+ Type: "type",
248
+ Enum: "enum",
249
+ Interface: "interface",
250
+ Array: "Array",
251
+ Record: "Record",
252
+ Intersection: "&",
253
+ Union: "|",
254
+ },
255
+ CodeGenKeyword: {
256
+ UtilRequiredKeys: "UtilRequiredKeys",
257
+ },
258
+ /**
259
+ * $A[] or Array<$A>
260
+ */
261
+ ArrayType: (content) => {
262
+ if (this.anotherArrayType) {
263
+ return `Array<${content}>`;
264
+ }
265
+
266
+ return `(${content})[]`;
267
+ },
268
+ /**
269
+ * "$A"
270
+ */
271
+ StringValue: (content) => `"${content}"`,
272
+ /**
273
+ * $A
274
+ */
275
+ BooleanValue: (content) => `${content}`,
276
+ /**
277
+ * $A
278
+ */
279
+ NumberValue: (content) => `${content}`,
280
+ /**
281
+ * $A
282
+ */
283
+ NullValue: (content) => content,
284
+ /**
285
+ * $A1 | $A2
286
+ */
287
+ UnionType: (contents) => _.join(_.uniq(contents), ` | `),
288
+ /**
289
+ * ($A1)
290
+ */
291
+ ExpressionGroup: (content) => (content ? `(${content})` : ""),
292
+ /**
293
+ * $A1 & $A2
294
+ */
295
+ IntersectionType: (contents) => _.join(_.uniq(contents), ` & `),
296
+ /**
297
+ * Record<$A1, $A2>
298
+ */
299
+ RecordType: (key, value) => `Record<${key}, ${value}>`,
300
+ /**
301
+ * readonly $key?:$value
302
+ */
303
+ TypeField: ({ readonly, key, optional, value }) =>
304
+ _.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
305
+ /**
306
+ * [key: $A1]: $A2
307
+ */
308
+ InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
309
+ /**
310
+ * $A1 = $A2
311
+ */
312
+ EnumField: (key, value) => `${key} = ${value}`,
313
+ /**
314
+ * $A0.key = $A0.value,
315
+ * $A1.key = $A1.value,
316
+ * $AN.key = $AN.value,
317
+ */
318
+ EnumFieldsWrapper: (contents) =>
319
+ _.map(contents, ({ key, value }) => ` ${key} = ${value}`).join(",\n"),
320
+ /**
321
+ * {\n $A \n}
322
+ */
323
+ ObjectWrapper: (content) => `{\n${content}\n}`,
324
+ /**
325
+ * /** $A *\/
326
+ */
327
+ MultilineComment: (contents, formatFn) =>
328
+ [
329
+ ...(contents.length === 1
330
+ ? [`/** ${contents[0]} */`]
331
+ : ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
332
+ ].map((part) => `${formatFn ? formatFn(part) : part}\n`),
333
+ /**
334
+ * $A1<...$A2.join(,)>
335
+ */
336
+ TypeWithGeneric: (typeName, genericArgs) => {
337
+ return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
338
+ },
339
+ })
340
+ })
341
+ ```
342
+
343
+ For example, if you need to generate output `Record<string, any>` instead of `object` you can do it with using following code:
344
+
345
+ ```ts
346
+ generateApi({
347
+ // ...
348
+ codeGenConstructs: (struct) => ({
349
+ Keyword: {
350
+ Object: "Record<string, any>",
351
+ }
352
+ })
353
+ })
354
+ ```
355
+
356
+ ### `primitiveTypeConstructs`
357
+
358
+ It is type mapper or translator swagger schema objects. `primitiveTypeConstructs` translates `type`/`format` schema fields to typescript structs.
359
+ This option has type
360
+ ```ts
361
+ type PrimitiveTypeStructValue =
362
+ | string
363
+ | ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
364
+
365
+ type PrimitiveTypeStruct = Record<
366
+ "integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
367
+ string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
368
+ >
369
+
370
+ declare const primitiveTypeConstructs: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>
371
+
372
+ generateApi({
373
+ // ...
374
+ primitiveTypeConstructs: (struct) => ({
375
+ integer: () => "number",
376
+ number: () => "number",
377
+ boolean: () => "boolean",
378
+ object: () => "object",
379
+ file: () => "File",
380
+ string: {
381
+ $default: () => "string",
382
+
383
+ /** formats */
384
+ binary: () => "File",
385
+ file: () => "File",
386
+ "date-time": () => "string",
387
+ time: () => "string",
388
+ date: () => "string",
389
+ duration: () => "string",
390
+ email: () => "string",
391
+ "idn-email": () => "string",
392
+ "idn-hostname": () => "string",
393
+ ipv4: () => "string",
394
+ ipv6: () => "string",
395
+ uuid: () => "string",
396
+ uri: () => "string",
397
+ "uri-reference": () => "string",
398
+ "uri-template": () => "string",
399
+ "json-pointer": () => "string",
400
+ "relative-json-pointer": () => "string",
401
+ regex: () => "string",
402
+ },
403
+ array: (schema, parser) => {
404
+ const content = parser.getInlineParseContent(schema.items);
405
+ return parser.checkAndAddNull(schema, `(${content})[]`);
406
+ },
407
+ })
408
+ })
409
+ ```
410
+
411
+ For example, if you need to change `"string"/"date-time"` default output as `string` to `Date` you can do it with using following code:
412
+
413
+ ```ts
414
+
415
+ generateApi({
416
+ primitiveTypeConstructs: (struct) => ({
417
+ string: {
418
+ "date-time": "Date",
419
+ },
420
+ })
421
+ })
422
+
423
+ ```
424
+
425
+ See more about [swagger schema type/format data here](https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times)
426
+
427
+ ## πŸ“„ Mass media
428
+
429
+ - [5 Lessons learned about swagger-typescript-api](https://christo8989.medium.com/5-lessons-learned-about-swagger-typescript-api-511240b34c1)
430
+ - [Why Swagger schemes are needed in frontend development ?](https://dev.to/js2me/why-swagger-schemes-are-needed-in-frontend-development-2cb4)
431
+ - [Migration en douceur vers TypeScript (French)](https://www.premieroctet.com/blog/migration-typescript/)
432
+ - [swagger-typescript-api usage (Japanese)](https://zenn.dev/watahaya/articles/2f4a716c47903b)
433
+
434
+ ## πŸ› οΈ Contribution
435
+
436
+ ❗❗❗ Please use the `next` branch :)
437
+
438
+ If you need to check your changes at schemas in `tests` folder before create a PR just run command `npm run test-all`
439
+
440
+ ## Contributors ✨
441
+
442
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
443
+
444
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
445
+ <!-- prettier-ignore-start -->
446
+ <!-- markdownlint-disable -->
447
+ <table>
448
+ <tbody>
449
+ <tr>
450
+ <td align="center"><a href="https://github.com/js2me"><img src="https://avatars1.githubusercontent.com/u/16340911?v=4?s=100" width="100px;" alt="Sergey S. Volkov"/><br /><sub><b>Sergey S. Volkov</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=js2me" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=js2me" title="Documentation">πŸ“–</a> <a href="#design-js2me" title="Design">🎨</a> <a href="#example-js2me" title="Examples">πŸ’‘</a> <a href="#maintenance-js2me" title="Maintenance">🚧</a> <a href="#ideas-js2me" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ajs2me" title="Bug reports">πŸ›</a></td>
451
+ <td align="center"><a href="https://github.com/andrefilimono"><img src="https://avatars0.githubusercontent.com/u/7794526?v=4?s=100" width="100px;" alt="Filimonov Andrey"/><br /><sub><b>Filimonov Andrey</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=andrefilimono" title="Code">πŸ’»</a> <a href="#ideas-andrefilimono" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-andrefilimono" title="Design">🎨</a></td>
452
+ <td align="center"><a href="https://github.com/Fl0pZz"><img src="https://avatars2.githubusercontent.com/u/9510124?v=4?s=100" width="100px;" alt="Rafael Fakhreev"/><br /><sub><b>Rafael Fakhreev</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=Fl0pZz" title="Code">πŸ’»</a> <a href="#ideas-Fl0pZz" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
453
+ <td align="center"><a href="https://azzola.dev"><img src="https://avatars3.githubusercontent.com/u/1297597?v=4?s=100" width="100px;" alt="Lucas Azzola"/><br /><sub><b>Lucas Azzola</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=azz" title="Code">πŸ’»</a> <a href="#ideas-azz" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-azz" title="Design">🎨</a></td>
454
+ <td align="center"><a href="https://github.com/JennieJi"><img src="https://avatars3.githubusercontent.com/u/1913045?v=4?s=100" width="100px;" alt="Jennie"/><br /><sub><b>Jennie</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=JennieJi" title="Code">πŸ’»</a> <a href="#ideas-JennieJi" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
455
+ <td align="center"><a href="https://github.com/jomarquez21"><img src="https://avatars1.githubusercontent.com/u/16705169?v=4?s=100" width="100px;" alt="Jose Enrique Marquez"/><br /><sub><b>Jose Enrique Marquez</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jomarquez21" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ajomarquez21" title="Bug reports">πŸ›</a></td>
456
+ <td align="center"><a href="https://glassechidna.com.au"><img src="https://avatars1.githubusercontent.com/u/482276?v=4?s=100" width="100px;" alt="Benjamin Dobell"/><br /><sub><b>Benjamin Dobell</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=Benjamin-Dobell" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ABenjamin-Dobell" title="Bug reports">πŸ›</a></td>
457
+ </tr>
458
+ <tr>
459
+ <td align="center"><a href="http://fixate.it"><img src="https://avatars0.githubusercontent.com/u/1510520?v=4?s=100" width="100px;" alt="Larry Botha"/><br /><sub><b>Larry Botha</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=larrybotha" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Alarrybotha" title="Bug reports">πŸ›</a></td>
460
+ <td align="center"><a href="https://github.com/nikalun"><img src="https://avatars3.githubusercontent.com/u/13102962?v=4?s=100" width="100px;" alt="Nikolay Lukinykh"/><br /><sub><b>Nikolay Lukinykh</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=nikalun" title="Code">πŸ’»</a> <a href="#ideas-nikalun" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Anikalun" title="Bug reports">πŸ›</a></td>
461
+ <td align="center"><a href="https://github.com/Mvbraathen"><img src="https://avatars0.githubusercontent.com/u/16756739?v=4?s=100" width="100px;" alt="Marius BrΓ₯then"/><br /><sub><b>Marius BrΓ₯then</b></sub></a><br /><a href="#security-Mvbraathen" title="Security">πŸ›‘οΈ</a></td>
462
+ <td align="center"><a href="https://github.com/xesjkeee"><img src="https://avatars2.githubusercontent.com/u/17751886?v=4?s=100" width="100px;" alt="Evgeny Vlasov"/><br /><sub><b>Evgeny Vlasov</b></sub></a><br /><a href="#ideas-xesjkeee" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
463
+ <td align="center"><a href="https://github.com/kel666"><img src="https://avatars1.githubusercontent.com/u/2040661?v=4?s=100" width="100px;" alt="Fabio"/><br /><sub><b>Fabio</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Akel666" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=kel666" title="Code">πŸ’»</a></td>
464
+ <td align="center"><a href="https://github.com/Fabiencdp"><img src="https://avatars.githubusercontent.com/u/6182473?v=4?s=100" width="100px;" alt="Fabien"/><br /><sub><b>Fabien</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AFabiencdp" title="Bug reports">πŸ›</a></td>
465
+ <td align="center"><a href="https://about.me/julienrousseau"><img src="https://avatars.githubusercontent.com/u/3296671?v=4?s=100" width="100px;" alt="Rousseau Julien"/><br /><sub><b>Rousseau Julien</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ARoXuS" title="Bug reports">πŸ›</a></td>
466
+ </tr>
467
+ <tr>
468
+ <td align="center"><a href="http://sebastianarias.dev"><img src="https://avatars.githubusercontent.com/u/9751266?v=4?s=100" width="100px;" alt="SebastiΓ‘n Arias"/><br /><sub><b>SebastiΓ‘n Arias</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ALarox" title="Bug reports">πŸ›</a></td>
469
+ <td align="center"><a href="https://github.com/Styn"><img src="https://avatars.githubusercontent.com/u/6705137?v=4?s=100" width="100px;" alt="Stijn Lammens"/><br /><sub><b>Stijn Lammens</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AStyn" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=Styn" title="Code">πŸ’»</a></td>
470
+ <td align="center"><a href="http://emilecantin.com"><img src="https://avatars.githubusercontent.com/u/885486?v=4?s=100" width="100px;" alt="Emile Cantin"/><br /><sub><b>Emile Cantin</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Aemilecantin" title="Bug reports">πŸ›</a> <a href="https://github.com/acacode/swagger-typescript-api/commits?author=emilecantin" title="Code">πŸ’»</a></td>
471
+ <td align="center"><a href="https://github.com/armsnyder"><img src="https://avatars.githubusercontent.com/u/9969202?v=4?s=100" width="100px;" alt="Adam Snyder"/><br /><sub><b>Adam Snyder</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=armsnyder" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Aarmsnyder" title="Bug reports">πŸ›</a></td>
472
+ <td align="center"><a href="https://github.com/jnpoyser"><img src="https://avatars.githubusercontent.com/u/7920428?v=4?s=100" width="100px;" alt="James Poyser"/><br /><sub><b>James Poyser</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jnpoyser" title="Code">πŸ’»</a> <a href="#ideas-jnpoyser" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
473
+ <td align="center"><a href="http://ru.linkedin.com/in/lisikhin"><img src="https://avatars.githubusercontent.com/u/475367?v=4?s=100" width="100px;" alt="Alexey"/><br /><sub><b>Alexey</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3ANihisil" title="Bug reports">πŸ›</a></td>
474
+ <td align="center"><a href="http://imaniu.com"><img src="https://avatars.githubusercontent.com/u/50100681?v=4?s=100" width="100px;" alt="江麻妞"/><br /><sub><b>江麻妞</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jiangmaniu" title="Code">πŸ’»</a></td>
475
+ </tr>
476
+ <tr>
477
+ <td align="center"><a href="https://kspr.dev"><img src="https://avatars.githubusercontent.com/u/5294519?v=4?s=100" width="100px;" alt="Kasper Moskwiak"/><br /><sub><b>Kasper Moskwiak</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=kmoskwiak" title="Code">πŸ’»</a> <a href="#ideas-kmoskwiak" title="Ideas, Planning, & Feedback">πŸ€”</a></td>
478
+ <td align="center"><a href="https://github.com/baggoedw"><img src="https://avatars.githubusercontent.com/u/92381702?v=4?s=100" width="100px;" alt="baggoedw"/><br /><sub><b>baggoedw</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=baggoedw" title="Code">πŸ’»</a></td>
479
+ <td align="center"><a href="https://marcusdunn.github.io"><img src="https://avatars.githubusercontent.com/u/51931484?v=4?s=100" width="100px;" alt="Marcus Dunn"/><br /><sub><b>Marcus Dunn</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=MarcusDunn" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AMarcusDunn" title="Bug reports">πŸ›</a></td>
480
+ <td align="center"><a href="https://www.danielplayfaircal.com/"><img src="https://avatars.githubusercontent.com/u/1217649?v=4?s=100" width="100px;" alt="Daniel Playfair Cal"/><br /><sub><b>Daniel Playfair Cal</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=hedgepigdaniel" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Ahedgepigdaniel" title="Bug reports">πŸ›</a></td>
481
+ <td align="center"><a href="https://www.linkedin.com/in/patrick-shaw/"><img src="https://avatars.githubusercontent.com/u/5153619?v=4?s=100" width="100px;" alt="Patrick Shaw"/><br /><sub><b>Patrick Shaw</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/pulls?q=is%3Apr+reviewed-by%3APatrickShaw" title="Reviewed Pull Requests">πŸ‘€</a></td>
482
+ <td align="center"><a href="https://www.linkedin.com/in/jinkwon-lee"><img src="https://avatars.githubusercontent.com/u/1798916?v=4?s=100" width="100px;" alt="JK"/><br /><sub><b>JK</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=jinkwon" title="Code">πŸ’»</a></td>
483
+ <td align="center"><a href="https://github.com/RoCat"><img src="https://avatars.githubusercontent.com/u/3562317?v=4?s=100" width="100px;" alt="RoCat"/><br /><sub><b>RoCat</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=RoCat" title="Code">πŸ’»</a> <a href="#ideas-RoCat" title="Ideas, Planning, & Feedback">πŸ€”</a> <a href="#design-RoCat" title="Design">🎨</a></td>
484
+ </tr>
485
+ <tr>
486
+ <td align="center"><a href="https://github.com/ApacheEx"><img src="https://avatars.githubusercontent.com/u/1918108?v=4?s=100" width="100px;" alt="Oleg Kuzava"/><br /><sub><b>Oleg Kuzava</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=ApacheEx" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3AApacheEx" title="Bug reports">πŸ›</a></td>
487
+ <td align="center"><a href="http://nikz.se"><img src="https://avatars.githubusercontent.com/u/7352072?v=4?s=100" width="100px;" alt="Niklas Frank"/><br /><sub><b>Niklas Frank</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=nksfrank" title="Code">πŸ’»</a> <a href="https://github.com/acacode/swagger-typescript-api/issues?q=author%3Anksfrank" title="Bug reports">πŸ›</a></td>
488
+ <td align="center"><a href="https://quentinbrunet.com"><img src="https://avatars.githubusercontent.com/u/20137632?v=4?s=100" width="100px;" alt="Quentin Brunet"/><br /><sub><b>Quentin Brunet</b></sub></a><br /><a href="https://github.com/acacode/swagger-typescript-api/commits?author=qboot" title="Code">πŸ’»</a></td>
489
+ </tr>
490
+ </tbody>
491
+ </table>
492
+
493
+ <!-- markdownlint-restore -->
494
+ <!-- prettier-ignore-end -->
495
+
496
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
497
+
498
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
499
+
500
+ ## πŸš€ How it looks
501
+
502
+ ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/npx.gif)
503
+
504
+ ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/auth-example.gif)
505
+
506
+ ![](https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/typings1.gif)
507
+
508
+
509
+ ## πŸ“ License
510
+ Licensed under the [MIT License](https://github.com/acacode/swagger-typescript-api/blob/master/LICENSE).