codegen-openapi-ts 0.9.0-alpha.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +152 -63
- package/bin/cli.js +54 -0
- package/bin/index.js +43 -34
- package/dist/index.js +2 -1
- package/package.json +25 -29
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -1,85 +1,174 @@
|
|
|
1
|
-
#
|
|
1
|
+
# codegen-openapi-ts (alpha)
|
|
2
2
|
|
|
3
3
|
[![NPM][npm-image]][npm-url]
|
|
4
|
-
[![License]
|
|
5
|
-
|
|
6
|
-
[![Coverage][coverage-image]][coverage-url]
|
|
7
|
-
[![Downloads][downloads-image]][downloads-url]
|
|
8
|
-
[![Build][build-image]][build-url]
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+

|
|
9
6
|
|
|
10
|
-
> Node.js library that generates
|
|
7
|
+
> Node.js library that generates TypeScript clients from OpenAPI/Swagger specifications.
|
|
8
|
+
|
|
9
|
+
This project is a fork of [OpenAPI Typescript Codegen](https://github.com/ferdikoomen/openapi-typescript-codegen) by [Ferdi Koomen](https://github.com/ferdikoomen). It adds conversion helpers, a config-file driven CLI, URL/method mapping, model-name mapping, proxy support, and custom append templates.
|
|
10
|
+
|
|
11
|
+
> ⚠️ **This branch is an alpha release (`v0.9.0-alpha.6`).** The API, config shape, and generated output may still change before `1.0.0`.
|
|
11
12
|
|
|
12
13
|
## Why?
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
- Frontend ❤️ OpenAPI, but we do not want to use Java codegen in our builds
|
|
14
16
|
- Quick, lightweight, robust and framework-agnostic 🚀
|
|
15
|
-
- Supports
|
|
16
|
-
- Supports
|
|
17
|
-
- Supports
|
|
18
|
-
- Supports
|
|
19
|
-
- Supports
|
|
20
|
-
- Supports
|
|
21
|
-
- Supports
|
|
22
|
-
- Supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/)
|
|
17
|
+
- Supports TypeScript client generation
|
|
18
|
+
- Supports conversion from Swagger 1.x/2.x and other formats to OpenAPI via [`api-spec-converter`](https://github.com/LucyBot-Inc/api-spec-converter)
|
|
19
|
+
- Supports JSON and YAML input files and URLs
|
|
20
|
+
- Supports Fetch, Node-Fetch, Axios, and XHR HTTP clients
|
|
21
|
+
- Supports config-file driven generation with `defineConfig`
|
|
22
|
+
- Supports selecting only specific paths/methods and proxying them
|
|
23
|
+
- Supports external references via [`@apidevtools/json-schema-ref-parser`](https://github.com/APIDevTools/json-schema-ref-parser)
|
|
23
24
|
|
|
24
25
|
## Install
|
|
25
26
|
|
|
27
|
+
```bash
|
|
28
|
+
npm install codegen-openapi-ts --save-dev
|
|
26
29
|
```
|
|
27
|
-
|
|
30
|
+
|
|
31
|
+
## CLI usage
|
|
32
|
+
|
|
33
|
+
`codegen-openapi-ts` is driven by a config file.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
$ codegen-openapi-ts --help
|
|
37
|
+
Usage: codegen-openapi-ts [options]
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
-V, --version output the version number
|
|
41
|
+
--config <value> Path to config file (default: "codegen.config.js")
|
|
42
|
+
-h, --help display help for command
|
|
28
43
|
```
|
|
29
44
|
|
|
30
|
-
|
|
45
|
+
Create a `codegen.config.js` in your project root:
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
const { defineConfig } = require('codegen-openapi-ts');
|
|
49
|
+
|
|
50
|
+
module.exports = defineConfig({
|
|
51
|
+
// Optional: path to a Handlebars file appended to every generated service
|
|
52
|
+
appendTemplate: './custom-append.hbs',
|
|
53
|
+
|
|
54
|
+
services: [
|
|
55
|
+
{
|
|
56
|
+
source: 'https://example.com/openapi.json',
|
|
57
|
+
from: 'openapi_3', // or 'swagger_1', 'swagger_2', 'api_blueprint', 'io_docs', 'google', 'raml', 'wadl'
|
|
58
|
+
output: 'src/api-types/example-api',
|
|
31
59
|
|
|
60
|
+
// Optional: global path proxy
|
|
61
|
+
proxyConfig: (path) => path.replace('/api/', '/backend/'),
|
|
62
|
+
|
|
63
|
+
// Optional: rename models in the stringified spec before generation
|
|
64
|
+
modelNameMapping: (json) => json.replace(/some\.long\.name/g, 'ShortName'),
|
|
65
|
+
|
|
66
|
+
// Optional: pick and rename specific paths/methods
|
|
67
|
+
urlMethodMapping: [
|
|
68
|
+
{ originalUrl: '/pokemon-list', method: 'get', methodName: 'GetPokemonList' },
|
|
69
|
+
{ originalUrl: '/pokemon-detail/{id}', method: 'get', methodName: 'GetPokemonDetail', proxyUrl: '/proxy/pokemon-detail/{id}' }
|
|
70
|
+
],
|
|
71
|
+
|
|
72
|
+
// Optional: only generate paths listed in urlMethodMapping
|
|
73
|
+
selectedOnly: true
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
});
|
|
32
77
|
```
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
--name <value> Custom client class name
|
|
43
|
-
--useOptions Use options instead of arguments
|
|
44
|
-
--useUnionTypes Use union types instead of enums
|
|
45
|
-
--exportCore <value> Write core files to disk (default: true)
|
|
46
|
-
--exportServices <value> Write services to disk (default: true)
|
|
47
|
-
--exportModels <value> Write models to disk (default: true)
|
|
48
|
-
--exportSchemas <value> Write schemas to disk (default: false)
|
|
49
|
-
--indent <value> Indentation options [4, 2, tab] (default: "4")
|
|
50
|
-
--postfixServices Service name postfix (default: "Service")
|
|
51
|
-
--postfixModels Model name postfix
|
|
52
|
-
--request <value> Path to custom request file
|
|
53
|
-
-h, --help display help for command
|
|
54
|
-
|
|
55
|
-
Examples
|
|
56
|
-
$ openapi --input ./spec.json --output ./generated
|
|
57
|
-
$ openapi --input ./spec.json --output ./generated --client xhr
|
|
78
|
+
|
|
79
|
+
Add a script to `package.json`:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"scripts": {
|
|
84
|
+
"codegen": "codegen-openapi-ts"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
58
87
|
```
|
|
59
88
|
|
|
60
|
-
|
|
61
|
-
===
|
|
89
|
+
Then run:
|
|
62
90
|
|
|
63
|
-
|
|
91
|
+
```bash
|
|
92
|
+
npm run codegen
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Programmatic API
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const { generate, convertAndGenerate } = require('codegen-openapi-ts');
|
|
99
|
+
|
|
100
|
+
// Generate directly from an OpenAPI spec
|
|
101
|
+
await generate({
|
|
102
|
+
input: './spec.json',
|
|
103
|
+
output: './generated',
|
|
104
|
+
httpClient: 'fetch', // 'fetch' | 'xhr' | 'node' | 'axios'
|
|
105
|
+
clientName: 'MyClient',
|
|
106
|
+
useUnionTypes: true,
|
|
107
|
+
exportCore: true,
|
|
108
|
+
exportServices: true,
|
|
109
|
+
exportModels: true,
|
|
110
|
+
exportSchemas: false,
|
|
111
|
+
indent: '4', // '4' | '2' | 'tab'
|
|
112
|
+
postfixServices: 'Service',
|
|
113
|
+
postfixModels: ''
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Convert from another spec format and generate with mappings
|
|
117
|
+
await convertAndGenerate(
|
|
118
|
+
{ from: 'swagger_2', source: 'https://example.com/swagger.json' },
|
|
119
|
+
{ input: './api-schema.json', output: './generated', useUnionTypes: true },
|
|
120
|
+
[
|
|
121
|
+
{ originalUrl: '/users', method: 'get', methodName: 'GetUsers' }
|
|
122
|
+
],
|
|
123
|
+
true, // selectedOnly
|
|
124
|
+
(json) => json.replace(/OldName/g, 'NewName'), // modelNameMapping
|
|
125
|
+
'', // appendTemplate
|
|
126
|
+
(path) => path.replace('/v1/', '/v2/') // proxyConfig
|
|
127
|
+
);
|
|
128
|
+
```
|
|
64
129
|
|
|
65
|
-
|
|
66
|
-
|
|
130
|
+
## Options
|
|
131
|
+
|
|
132
|
+
| Option | Type | Default | Description |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| `input` | `string \| object` | — | OpenAPI spec path, URL, or parsed object |
|
|
135
|
+
| `output` | `string` | — | Output directory |
|
|
136
|
+
| `httpClient` | `HttpClient` | `'fetch'` | `'fetch'`, `'xhr'`, `'node'`, `'axios'` |
|
|
137
|
+
| `clientName` | `string` | — | Custom client class name |
|
|
138
|
+
| `useOptions` | `boolean` | `false` | Use options argument for service methods |
|
|
139
|
+
| `useUnionTypes` | `boolean` | `false` | Use union types instead of enums |
|
|
140
|
+
| `exportCore` | `boolean` | `true` | Write `core/` files |
|
|
141
|
+
| `exportServices` | `boolean` | `true` | Write `services/` files |
|
|
142
|
+
| `exportModels` | `boolean` | `true` | Write `models/` files |
|
|
143
|
+
| `exportSchemas` | `boolean` | `false` | Write `schemas/` files |
|
|
144
|
+
| `indent` | `Indent \| '4' \| '2' \| 'tab'` | `'4'` | Indentation style |
|
|
145
|
+
| `postfixServices` | `string` | `'Service'` | Postfix for service names |
|
|
146
|
+
| `postfixModels` | `string` | `''` | Postfix for model names |
|
|
147
|
+
| `request` | `string` | — | Path to a custom request file |
|
|
148
|
+
| `write` | `boolean` | `true` | Write files to disk |
|
|
149
|
+
| `selectedOnly` | `boolean` | `false` | Only generate selected paths (V3) |
|
|
150
|
+
| `appendTemplate` | `string` | — | Path to a Handlebars template appended to services |
|
|
151
|
+
|
|
152
|
+
## Output folder
|
|
153
|
+
|
|
154
|
+
The current CLI and `generate()` entry point create:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
output/
|
|
158
|
+
├── models/ # API schema models
|
|
159
|
+
├── services/ # API service classes
|
|
160
|
+
└── index.ts # barrel exports
|
|
161
|
+
```
|
|
67
162
|
|
|
68
|
-
|
|
163
|
+
The lower-level writer API can also produce `core/` (runtime request helpers, `OpenAPI` config, `CancelablePromise`, etc.) and `schemas/` folders, but these are not generated by the default entry points in this alpha release.
|
|
69
164
|
|
|
70
|
-
|
|
165
|
+
## Alpha caveats
|
|
71
166
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
167
|
+
- `convertAndGenerate()` writes a temporary `api-schema.json` to your project root and also stores a copy inside `node_modules/@apidevtools/json-schema-ref-parser/dist/` for `$ref` resolution.
|
|
168
|
+
- The CLI hardcodes `useOptions: true` and `useUnionTypes: true` for config-file generation.
|
|
169
|
+
- `useOptions`, `exportCore`, and `exportSchemas` are accepted by the programmatic API but currently forced to `false` internally. Use the lower-level writer API if you need direct control over these flags.
|
|
75
170
|
|
|
76
|
-
[npm-url]: https://npmjs.org/package/openapi-
|
|
77
|
-
[npm-image]: https://img.shields.io/npm/v/openapi-
|
|
78
|
-
[
|
|
79
|
-
[
|
|
80
|
-
[coverage-url]: https://codecov.io/gh/ferdikoomen/openapi-typescript-codegen
|
|
81
|
-
[coverage-image]: https://img.shields.io/codecov/c/github/ferdikoomen/openapi-typescript-codegen.svg
|
|
82
|
-
[downloads-url]: http://npm-stat.com/charts.html?package=openapi-typescript-codegen
|
|
83
|
-
[downloads-image]: http://img.shields.io/npm/dm/openapi-typescript-codegen.svg
|
|
84
|
-
[build-url]: https://circleci.com/gh/ferdikoomen/openapi-typescript-codegen/tree/master
|
|
85
|
-
[build-image]: https://circleci.com/gh/ferdikoomen/openapi-typescript-codegen/tree/master.svg?style=svg
|
|
171
|
+
[npm-url]: https://npmjs.org/package/codegen-openapi-ts
|
|
172
|
+
[npm-image]: https://img.shields.io/npm/v/codegen-openapi-ts.svg
|
|
173
|
+
[build-url]: https://github.com/devteaa/codegen-openapi-ts/actions/workflows/CI.yml
|
|
174
|
+
[build-image]: https://github.com/devteaa/codegen-openapi-ts/actions/workflows/CI.yml/badge.svg
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
|
|
6
|
+
import { generate } from '../dist/index.js';
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const pkg = require('../package.json');
|
|
10
|
+
|
|
11
|
+
const params = program
|
|
12
|
+
.name('openapi')
|
|
13
|
+
.usage('[options]')
|
|
14
|
+
.version(pkg.version)
|
|
15
|
+
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
|
|
16
|
+
.requiredOption('-o, --output <value>', 'Output directory (required)')
|
|
17
|
+
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node, axios]', 'fetch')
|
|
18
|
+
.option('--name <value>', 'Custom client class name')
|
|
19
|
+
.option('--useOptions', 'Use options instead of arguments')
|
|
20
|
+
.option('--useUnionTypes', 'Use union types instead of enums')
|
|
21
|
+
.option('--exportCore <value>', 'Write core files to disk', true)
|
|
22
|
+
.option('--exportServices <value>', 'Write services to disk', true)
|
|
23
|
+
.option('--exportModels <value>', 'Write models to disk', true)
|
|
24
|
+
.option('--exportSchemas <value>', 'Write schemas to disk', false)
|
|
25
|
+
.option('--indent <value>', 'Indentation options [4, 2, tabs]', '4')
|
|
26
|
+
.option('--postfixServices <value>', 'Service name postfix', 'Service')
|
|
27
|
+
.option('--postfixModels <value>', 'Model name postfix')
|
|
28
|
+
.option('--request <value>', 'Path to custom request file')
|
|
29
|
+
.parse(process.argv)
|
|
30
|
+
.opts();
|
|
31
|
+
|
|
32
|
+
generate({
|
|
33
|
+
input: params.input,
|
|
34
|
+
output: params.output,
|
|
35
|
+
httpClient: params.client,
|
|
36
|
+
clientName: params.name,
|
|
37
|
+
useOptions: params.useOptions,
|
|
38
|
+
useUnionTypes: params.useUnionTypes,
|
|
39
|
+
exportCore: JSON.parse(params.exportCore) === true,
|
|
40
|
+
exportServices: JSON.parse(params.exportServices) === true,
|
|
41
|
+
exportModels: JSON.parse(params.exportModels) === true,
|
|
42
|
+
exportSchemas: JSON.parse(params.exportSchemas) === true,
|
|
43
|
+
indent: params.indent,
|
|
44
|
+
postfixServices: params.postfixServices,
|
|
45
|
+
postfixModels: params.postfixModels,
|
|
46
|
+
request: params.request,
|
|
47
|
+
})
|
|
48
|
+
.then(() => {
|
|
49
|
+
process.exit(0);
|
|
50
|
+
})
|
|
51
|
+
.catch(error => {
|
|
52
|
+
console.error(error);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
package/bin/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { program } from 'commander';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { pathToFileURL } from 'url';
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
+
import { convertAndGenerate } from '../dist/index.js';
|
|
9
|
+
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
8
11
|
const pkg = require('../package.json');
|
|
9
|
-
const OpenAPI = require(path.resolve(__dirname, '../dist/index.js'));
|
|
10
12
|
|
|
11
|
-
const appRoot = process.cwd().split('/node_modules')[0]
|
|
13
|
+
const appRoot = process.cwd().split('/node_modules')[0];
|
|
12
14
|
|
|
13
15
|
const params = program
|
|
14
16
|
.name('codegen-openapi-ts')
|
|
@@ -18,34 +20,41 @@ const params = program
|
|
|
18
20
|
.parse(process.argv)
|
|
19
21
|
.opts();
|
|
20
22
|
|
|
21
|
-
async function
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
async function loadConfig(configPath) {
|
|
24
|
+
const absolutePath = path.resolve(appRoot, configPath);
|
|
25
|
+
const configUrl = pathToFileURL(absolutePath).href;
|
|
26
|
+
const module = await import(configUrl);
|
|
27
|
+
return module.default ?? module;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function generateOnConfig() {
|
|
31
|
+
try {
|
|
32
|
+
const configFile = await loadConfig(params.config);
|
|
33
|
+
|
|
34
|
+
for (const configService of configFile.services) {
|
|
35
|
+
console.log('Generating ' + configService.source);
|
|
36
|
+
|
|
37
|
+
await convertAndGenerate(
|
|
38
|
+
{
|
|
39
|
+
from: configService.from,
|
|
40
|
+
source: configService.source,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
input: 'api-schema.json',
|
|
44
|
+
output: configService.output || 'output',
|
|
45
|
+
useOptions: true,
|
|
46
|
+
useUnionTypes: true,
|
|
47
|
+
},
|
|
48
|
+
configService.urlMethodMapping || [],
|
|
49
|
+
configService.selectedOnly || false,
|
|
50
|
+
configService.modelNameMapping,
|
|
51
|
+
configFile.appendTemplate,
|
|
52
|
+
configService.proxyConfig
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.log(err);
|
|
45
57
|
}
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.log(err)
|
|
48
|
-
}
|
|
49
58
|
}
|
|
50
59
|
|
|
51
|
-
generateOnConfig()
|
|
60
|
+
generateOnConfig();
|