codegen-openapi-ts 0.9.0-alpha.5 → 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 CHANGED
File without changes
package/README.md CHANGED
@@ -1,85 +1,174 @@
1
- # OpenAPI Typescript Codegen
1
+ # codegen-openapi-ts (alpha)
2
2
 
3
3
  [![NPM][npm-image]][npm-url]
4
- [![License][license-image]][license-url]
5
- [![Coverage][coverage-image]][coverage-url]
6
- [![Coverage][coverage-image]][coverage-url]
7
- [![Downloads][downloads-image]][downloads-url]
8
- [![Build][build-image]][build-url]
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ ![Build](https://github.com/devteaa/codegen-openapi-ts/actions/workflows/CI.yml/badge.svg)
9
6
 
10
- > Node.js library that generates Typescript clients based on the OpenAPI specification.
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
- - Frontend ❤️ OpenAPI, but we do not want to use JAVA codegen in our builds
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 generation of TypeScript clients
16
- - Supports generations of Fetch, Node-Fetch, Axios, Angular and XHR http clients
17
- - Supports OpenAPI specification v2.0 and v3.0
18
- - Supports JSON and YAML files for input
19
- - Supports generation through CLI, Node.js and NPX
20
- - Supports tsc and @babel/plugin-transform-typescript
21
- - Supports aborting of requests (cancelable promise pattern)
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
- npm install openapi-typescript-codegen --save-dev
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
- ## Usage
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
- $ openapi --help
34
-
35
- Usage: openapi [options]
36
-
37
- Options:
38
- -V, --version output the version number
39
- -i, --input <value> OpenAPI specification, can be a path, url or string content (required)
40
- -o, --output <value> Output directory (required)
41
- -c, --client <value> HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch")
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
- Documentation
61
- ===
89
+ Then run:
62
90
 
63
- The main documentation can be found in the [openapi-typescript-codegen/wiki](https://github.com/ferdikoomen/openapi-typescript-codegen/wiki)
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
- Sponsors
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
- If you or your company use the OpenAPI Typescript Codegen, please consider supporting me. By sponsoring I can free up time to give this project some love! Details can be found here: https://github.com/sponsors/ferdikoomen
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
- If you're from an enterprise looking for a fully managed SDK generation, please consider our sponsor:
165
+ ## Alpha caveats
71
166
 
72
- <a href="https://speakeasyapi.dev/?utm_source=ferdi+repo&utm_medium=github+sponsorship">
73
- <img alt="speakeasy" src="https://storage.googleapis.com/speakeasy-design-assets/ferdi-sponsorship.png" width="640"/>
74
- </a>
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-typescript-codegen
77
- [npm-image]: https://img.shields.io/npm/v/openapi-typescript-codegen.svg
78
- [license-url]: LICENSE
79
- [license-image]: http://img.shields.io/npm/l/openapi-typescript-codegen.svg
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
- 'use strict';
3
+ import { program } from 'commander';
4
+ import { createRequire } from 'module';
5
+ import path from 'path';
6
+ import { pathToFileURL } from 'url';
4
7
 
5
- const path = require('path');
6
- const { program } = require('commander');
7
- const esmConfig = require('esm-config');
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 generateOnConfig () {
22
- try {
23
- const configFile = await esmConfig(path.join(appRoot, params.config))
24
-
25
- for (const configService of configFile.services) {
26
- console.log('Generating ' + configService.source)
27
-
28
- await OpenAPI.convertAndGenerate(
29
- {
30
- from: configService.from,
31
- source: configService.source
32
- },
33
- {
34
- input: 'api-schema.json',
35
- output: configService.output || 'output',
36
- useOptions: true,
37
- useUnionTypes: true,
38
- },
39
- configService.urlMethodMapping || [],
40
- configService.selectedOnly || false,
41
- configService.modelNameMapping,
42
- configFile.appendTemplate,
43
- configService.proxyConfig
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();