@travetto/openapi 3.0.2 → 3.1.0-rc.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/README.md +20 -25
- package/package.json +6 -6
- package/src/config.ts +4 -7
- package/src/service.ts +1 -1
- package/src/spec-generate.ts +1 -1
- package/support/bin/help.ts +57 -0
- package/support/bin/presets.ts +22 -0
- package/support/cli.openapi_client.ts +34 -96
- package/support/cli.openapi_spec.ts +23 -23
- package/support/bin/generate.ts +0 -11
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<!-- This file was generated by @travetto/doc and should not be modified directly -->
|
|
2
|
-
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/openapi/DOC.
|
|
2
|
+
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/openapi/DOC.tsx and execute "npx trv doc" to rebuild -->
|
|
3
3
|
# OpenAPI Specification
|
|
4
|
+
|
|
4
5
|
## OpenAPI integration support for the Travetto framework
|
|
5
6
|
|
|
6
7
|
**Install: @travetto/openapi**
|
|
@@ -12,7 +13,7 @@ npm install @travetto/openapi
|
|
|
12
13
|
yarn add @travetto/openapi
|
|
13
14
|
```
|
|
14
15
|
|
|
15
|
-
In the [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") module, the controllers and endpoints can be described via decorators, comments, or typings. This only provides the general metadata internally. This is not sufficient to generate a usable API doc, and so this module exists to bridge that gap.
|
|
16
|
+
In the [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") module, the controllers and endpoints can be described via decorators, comments, or typings. This only provides the general metadata internally. This is not sufficient to generate a usable API doc, and so this module exists to bridge that gap.
|
|
16
17
|
|
|
17
18
|
The module is provides an [OpenAPI](https://github.com/OAI/OpenAPI-Specification) v3.x representation of the API metadata provided via the [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") and [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding.") modules.
|
|
18
19
|
|
|
@@ -23,9 +24,9 @@ All of the high level configurations can be found in the following structure:
|
|
|
23
24
|
|
|
24
25
|
**Code: Config: OpenAPI Configuration**
|
|
25
26
|
```typescript
|
|
26
|
-
import type { ServerObject, ContactObject, LicenseObject } from 'openapi3-ts
|
|
27
|
+
import type { ServerObject, ContactObject, LicenseObject } from 'openapi3-ts';
|
|
27
28
|
|
|
28
|
-
import { Config
|
|
29
|
+
import { Config } from '@travetto/config';
|
|
29
30
|
import { path, RootIndex } from '@travetto/manifest';
|
|
30
31
|
import { GlobalEnv } from '@travetto/base';
|
|
31
32
|
import { Required } from '@travetto/schema';
|
|
@@ -70,7 +71,7 @@ export class ApiHostConfig {
|
|
|
70
71
|
/**
|
|
71
72
|
* OpenAPI Version
|
|
72
73
|
*/
|
|
73
|
-
openapi = '3.0
|
|
74
|
+
openapi = '3.1.0';
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
/**
|
|
@@ -81,12 +82,10 @@ export class ApiSpecConfig {
|
|
|
81
82
|
/**
|
|
82
83
|
* Where to output file to
|
|
83
84
|
*/
|
|
84
|
-
@EnvVar('TRV_OPENAPI_OUTPUT')
|
|
85
85
|
output: string = 'openapi.yml';
|
|
86
86
|
/**
|
|
87
87
|
* Should file be generated at runtime
|
|
88
88
|
*/
|
|
89
|
-
@EnvVar('TRV_OPENAPI_PERSIST')
|
|
90
89
|
persist?: boolean;
|
|
91
90
|
/**
|
|
92
91
|
* Skip emitting all routes
|
|
@@ -98,14 +97,14 @@ export class ApiSpecConfig {
|
|
|
98
97
|
exposeAllSchemas: boolean = false;
|
|
99
98
|
|
|
100
99
|
async postConstruct(): Promise<void> {
|
|
101
|
-
this.output = path.
|
|
100
|
+
this.output = path.resolve(this.output);
|
|
102
101
|
if (!this.output || this.output === '-') {
|
|
103
102
|
this.persist = false;
|
|
104
103
|
} else {
|
|
105
104
|
this.persist ??= GlobalEnv.dynamic;
|
|
106
105
|
}
|
|
107
106
|
if (this.persist) {
|
|
108
|
-
if (!/[.](json|ya?ml)$/.test(this.output)) { // Assume a folder
|
|
107
|
+
if (!/[.](json|ya?ml) $/.test(this.output)) { // Assume a folder
|
|
109
108
|
this.output = path.resolve(this.output, 'openapi.yml');
|
|
110
109
|
}
|
|
111
110
|
}
|
|
@@ -114,20 +113,20 @@ export class ApiSpecConfig {
|
|
|
114
113
|
```
|
|
115
114
|
|
|
116
115
|
## Spec Generation
|
|
117
|
-
The framework, when in watch mode, will generate the [OpenAPI](https://github.com/OAI/OpenAPI-Specification) specification in either [JSON](https://www.json.org) or [YAML](https://en.wikipedia.org/wiki/YAML). This module integrates with the file watching paradigm and can regenerate the openapi spec as changes to endpoints and models are made during development. The output format is defined by the suffix of the output file, `.yaml` or `.json`.
|
|
116
|
+
The framework, when in watch mode, will generate the [OpenAPI](https://github.com/OAI/OpenAPI-Specification) specification in either [JSON](https://www.json.org) or [YAML](https://en.wikipedia.org/wiki/YAML). This module integrates with the file watching paradigm and can regenerate the openapi spec as changes to endpoints and models are made during development. The output format is defined by the suffix of the output file, `.yaml` or `.json`.
|
|
118
117
|
|
|
119
118
|
## CLI - openapi:spec
|
|
120
|
-
|
|
121
119
|
The module provides a command for the [Command Line Interface](https://github.com/travetto/travetto/tree/main/module/cli#readme "CLI infrastructure for Travetto framework") to allow scripting file generation.
|
|
122
120
|
|
|
123
121
|
**Terminal: OpenAPI usage**
|
|
124
122
|
```bash
|
|
125
123
|
$ trv openapi:spec --help
|
|
126
124
|
|
|
127
|
-
Usage:
|
|
125
|
+
Usage: openapi:spec [options]
|
|
128
126
|
|
|
129
127
|
Options:
|
|
130
|
-
-o, --output <
|
|
128
|
+
-o, --output <string> Output files
|
|
129
|
+
-m, --module <string> Module to run for
|
|
131
130
|
-h, --help display help for command
|
|
132
131
|
```
|
|
133
132
|
|
|
@@ -136,26 +135,22 @@ The command will run your application, in non-server mode, to collect all the ro
|
|
|
136
135
|
**Note**: The module supports generating the OpenAPI spec in real-time while listening for changes to routes and models.
|
|
137
136
|
|
|
138
137
|
## CLI - openapi:client
|
|
139
|
-
|
|
140
138
|
The module provides a command for the [Command Line Interface](https://github.com/travetto/travetto/tree/main/module/cli#readme "CLI infrastructure for Travetto framework") to allow client generation from the API structure.
|
|
141
139
|
|
|
142
140
|
**Terminal: OpenAPI usage**
|
|
143
141
|
```bash
|
|
144
142
|
$ trv openapi:client --help
|
|
145
143
|
|
|
146
|
-
Usage:
|
|
144
|
+
Usage: openapi:client [options] <format:string>
|
|
147
145
|
|
|
148
146
|
Options:
|
|
149
|
-
-x, --extended-help
|
|
150
|
-
-a, --additional-properties <
|
|
151
|
-
-i, --input <
|
|
152
|
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
-
|
|
156
|
-
"arcsine/openapi-generator:latest")
|
|
157
|
-
-w, --watch Watch for file changes
|
|
158
|
-
-h, --help display help for command
|
|
147
|
+
-x, --extended-help Show Extended Help
|
|
148
|
+
-a, --additional-properties <string> Additional Properties (default: [])
|
|
149
|
+
-i, --input <string> Input file (default: "./openapi.yml")
|
|
150
|
+
-o, --output <string> Output folder (default: "./api-client")
|
|
151
|
+
-d, --docker-image <string> Docker Image to user (default: "arcsine/openapi-generator:latest")
|
|
152
|
+
-w, --watch Watch for file changes
|
|
153
|
+
-h, --help display help for command
|
|
159
154
|
|
|
160
155
|
Available Presets
|
|
161
156
|
----------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/openapi",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-rc.0",
|
|
4
4
|
"description": "OpenAPI integration support for the Travetto framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rest",
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
"directory": "module/openapi"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@travetto/config": "^3.0.
|
|
30
|
-
"@travetto/rest": "^3.0.
|
|
31
|
-
"@travetto/schema": "^3.0.
|
|
32
|
-
"@travetto/yaml": "^3.0.
|
|
29
|
+
"@travetto/config": "^3.1.0-rc.0",
|
|
30
|
+
"@travetto/rest": "^3.1.0-rc.0",
|
|
31
|
+
"@travetto/schema": "^3.1.0-rc.0",
|
|
32
|
+
"@travetto/yaml": "^3.1.0-rc.0",
|
|
33
33
|
"openapi3-ts": "^3.1.2"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@travetto/cli": "^3.0.
|
|
36
|
+
"@travetto/cli": "^3.1.0-rc.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependenciesMeta": {
|
|
39
39
|
"@travetto/cli": {
|
package/src/config.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { ServerObject, ContactObject, LicenseObject } from 'openapi3-ts
|
|
1
|
+
import type { ServerObject, ContactObject, LicenseObject } from 'openapi3-ts';
|
|
2
2
|
|
|
3
|
-
import { Config
|
|
3
|
+
import { Config } from '@travetto/config';
|
|
4
4
|
import { path, RootIndex } from '@travetto/manifest';
|
|
5
5
|
import { GlobalEnv } from '@travetto/base';
|
|
6
6
|
import { Required } from '@travetto/schema';
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* API Information, infers as much as possible from the package.json
|
|
11
10
|
*/
|
|
@@ -46,7 +45,7 @@ export class ApiHostConfig {
|
|
|
46
45
|
/**
|
|
47
46
|
* OpenAPI Version
|
|
48
47
|
*/
|
|
49
|
-
openapi = '3.0
|
|
48
|
+
openapi = '3.1.0';
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
/**
|
|
@@ -57,12 +56,10 @@ export class ApiSpecConfig {
|
|
|
57
56
|
/**
|
|
58
57
|
* Where to output file to
|
|
59
58
|
*/
|
|
60
|
-
@EnvVar('TRV_OPENAPI_OUTPUT')
|
|
61
59
|
output: string = 'openapi.yml';
|
|
62
60
|
/**
|
|
63
61
|
* Should file be generated at runtime
|
|
64
62
|
*/
|
|
65
|
-
@EnvVar('TRV_OPENAPI_PERSIST')
|
|
66
63
|
persist?: boolean;
|
|
67
64
|
/**
|
|
68
65
|
* Skip emitting all routes
|
|
@@ -74,7 +71,7 @@ export class ApiSpecConfig {
|
|
|
74
71
|
exposeAllSchemas: boolean = false;
|
|
75
72
|
|
|
76
73
|
async postConstruct(): Promise<void> {
|
|
77
|
-
this.output = path.
|
|
74
|
+
this.output = path.resolve(this.output);
|
|
78
75
|
if (!this.output || this.output === '-') {
|
|
79
76
|
this.persist = false;
|
|
80
77
|
} else {
|
package/src/service.ts
CHANGED
package/src/spec-generate.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Readable } from 'stream';
|
|
|
2
2
|
import type {
|
|
3
3
|
SchemaObject, SchemasObject, ParameterObject, OperationObject,
|
|
4
4
|
RequestBodyObject, TagObject, PathsObject
|
|
5
|
-
} from 'openapi3-ts
|
|
5
|
+
} from 'openapi3-ts';
|
|
6
6
|
|
|
7
7
|
import { ControllerRegistry, EndpointConfig, ControllerConfig, ParamConfig, EndpointIOType } from '@travetto/rest';
|
|
8
8
|
import { Class } from '@travetto/base';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
import { path, RootIndex } from '@travetto/manifest';
|
|
4
|
+
import { cliTpl } from '@travetto/cli';
|
|
5
|
+
import { OpenApiClientPresets } from './presets';
|
|
6
|
+
import { ExecUtil } from '@travetto/base';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Help utility for openapi client command
|
|
10
|
+
*/
|
|
11
|
+
export class OpenApiClientHelp {
|
|
12
|
+
|
|
13
|
+
static async getListOfFormats(dockerImage: string): Promise<string[]> {
|
|
14
|
+
const formatCache = path.resolve(RootIndex.manifest.workspacePath, RootIndex.manifest.toolFolder, 'trv-openapi-formats.json');
|
|
15
|
+
if (!await fs.stat(formatCache).catch(() => false)) {
|
|
16
|
+
const stdout = ExecUtil.spawn('docker', ['run', '--rm', dockerImage, 'list']);
|
|
17
|
+
const res = await stdout.result;
|
|
18
|
+
const lines = res.stdout
|
|
19
|
+
.split('DOCUMENTATION')[0]
|
|
20
|
+
.trim()
|
|
21
|
+
.split(/\n/g)
|
|
22
|
+
.filter(x => /^\s+-/.test(x) && !/\((beta|experimental)\)/.test(x))
|
|
23
|
+
.map(x => x.replace(/^\s+-\s+/, '').trim());
|
|
24
|
+
|
|
25
|
+
await fs.mkdir(path.dirname(formatCache), { recursive: true });
|
|
26
|
+
await fs.writeFile(formatCache, JSON.stringify([...lines.sort(),]));
|
|
27
|
+
}
|
|
28
|
+
const list: string[] = JSON.parse(await fs.readFile(formatCache, 'utf8'));
|
|
29
|
+
return list;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static async help(dockerImage: string, extendedHelp: boolean): Promise<string[]> {
|
|
33
|
+
const presets = await OpenApiClientPresets.getPresets();
|
|
34
|
+
const presetLen = Math.max(...Object.keys(presets).map(x => x.length));
|
|
35
|
+
const presetEntries = Object
|
|
36
|
+
.entries(presets)
|
|
37
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
38
|
+
.map(([k, [cmd, v]]) => [`@travetto/${k}`.padEnd(presetLen + 5), [cmd, OpenApiClientPresets.presetMap(v)]] as const);
|
|
39
|
+
|
|
40
|
+
const presetText = [
|
|
41
|
+
cliTpl`${{ subtitle: 'Available Presets' }}`,
|
|
42
|
+
'----------------------------------',
|
|
43
|
+
...presetEntries.map(([k, [cmd, param]]) => cliTpl`* ${{ input: k }} -- ${{ identifier: cmd }} ${{ param }}`),
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
if (extendedHelp) {
|
|
47
|
+
const formats = await this.getListOfFormats(dockerImage);
|
|
48
|
+
presetText.push(
|
|
49
|
+
'',
|
|
50
|
+
cliTpl`${{ subtitle: 'Available Formats' }}`,
|
|
51
|
+
'----------------------------------',
|
|
52
|
+
...formats.map(x => cliTpl`* ${{ input: x }}`)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return presetText;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FileResourceProvider } from '@travetto/base';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Presets utility for openapi client command
|
|
5
|
+
*/
|
|
6
|
+
export class OpenApiClientPresets {
|
|
7
|
+
|
|
8
|
+
static #presets: Record<string, [string, object] | [string]>;
|
|
9
|
+
static #resources = new FileResourceProvider(['@travetto/openapi#support/resources']);
|
|
10
|
+
|
|
11
|
+
static async getPresets(): Promise<Record<string, [string, object] | [string]>> {
|
|
12
|
+
if (!this.#presets) {
|
|
13
|
+
const text = await this.#resources.read('presets.json');
|
|
14
|
+
this.#presets = JSON.parse(text);
|
|
15
|
+
}
|
|
16
|
+
return this.#presets;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static presetMap(prop?: object): string {
|
|
20
|
+
return !prop || Object.keys(prop).length === 0 ? '' : Object.entries(prop).map(([k, v]) => `${k}=${v}`).join(',');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,130 +1,68 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
-
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
-
import cp from 'child_process';
|
|
4
2
|
|
|
5
|
-
import { path
|
|
6
|
-
import { ExecUtil,
|
|
7
|
-
import {
|
|
3
|
+
import { path } from '@travetto/manifest';
|
|
4
|
+
import { ExecUtil, ShutdownManager } from '@travetto/base';
|
|
5
|
+
import { CliCommandShape, CliCommand, CliFlag } from '@travetto/cli';
|
|
6
|
+
|
|
7
|
+
import { OpenApiClientHelp } from './bin/help';
|
|
8
|
+
import { OpenApiClientPresets } from './bin/presets';
|
|
8
9
|
|
|
9
|
-
type Options = {
|
|
10
|
-
extendedHelp: OptionConfig<boolean>;
|
|
11
|
-
props: ListOptionConfig<string>;
|
|
12
|
-
input: OptionConfig<string>;
|
|
13
|
-
output: OptionConfig<string>;
|
|
14
|
-
dockerImage: OptionConfig<string>;
|
|
15
|
-
watch: OptionConfig<boolean>;
|
|
16
|
-
};
|
|
17
10
|
/**
|
|
18
11
|
* CLI for generating the cli client
|
|
19
12
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
getListOfFormats(): string[] {
|
|
38
|
-
const formatCache = path.resolve(RootIndex.manifest.workspacePath, RootIndex.manifest.outputFolder, 'trv-openapi-formats.json');
|
|
39
|
-
if (!existsSync(formatCache)) {
|
|
40
|
-
const stdout = cp.execSync(`docker run --rm ${this.cmd.dockerImage} list`, { stdio: ['pipe', 'pipe'], encoding: 'utf8' }).trim();
|
|
41
|
-
const lines = stdout
|
|
42
|
-
.split('DOCUMENTATION')[0]
|
|
43
|
-
.trim()
|
|
44
|
-
.split(/\n/g)
|
|
45
|
-
.filter(x => /^\s+-/.test(x) && !/\((beta|experimental)\)/.test(x))
|
|
46
|
-
.map(x => x.replace(/^\s+-\s+/, '').trim());
|
|
47
|
-
|
|
48
|
-
writeFileSync(formatCache, JSON.stringify([...lines.sort(),]));
|
|
49
|
-
}
|
|
50
|
-
const list: string[] = JSON.parse(readFileSync(formatCache, 'utf8'));
|
|
51
|
-
return list;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getOptions(): Options {
|
|
55
|
-
return {
|
|
56
|
-
extendedHelp: this.boolOption({ name: 'extended-help', short: 'x', desc: 'Show Extended Help' }),
|
|
57
|
-
props: this.listOption({ name: 'additional-properties', short: 'a', desc: 'Additional Properties' }),
|
|
58
|
-
input: this.option({ desc: 'Input file', def: './openapi.yml', combine: v => path.resolve(v), completion: true }),
|
|
59
|
-
output: this.option({ desc: 'Output folder', def: './api-client', combine: v => path.resolve(v), completion: true }),
|
|
60
|
-
dockerImage: this.option({ desc: 'Docker Image to use', def: 'arcsine/openapi-generator:latest' }),
|
|
61
|
-
watch: this.boolOption({ desc: 'Watch for file changes' })
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async help(): Promise<string> {
|
|
66
|
-
const presets = await this.getPresets();
|
|
67
|
-
const presetLen = Math.max(...Object.keys(presets).map(x => x.length));
|
|
68
|
-
const presetEntries = Object
|
|
69
|
-
.entries(presets)
|
|
70
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
71
|
-
.map(([k, [cmd, v]]) => [`@travetto/${k}`.padEnd(presetLen + 5), [cmd, this.presetMap(v)]] as const);
|
|
72
|
-
|
|
73
|
-
const presetText = cliTpl`
|
|
74
|
-
${{ subtitle: 'Available Presets' }}
|
|
75
|
-
----------------------------------
|
|
76
|
-
${presetEntries.map(([k, [cmd, param]]) => cliTpl`* ${{ input: k }} -- ${{ identifier: cmd }} ${{ param }}`).join('\n')}`;
|
|
77
|
-
|
|
78
|
-
const formatText = cliTpl`
|
|
79
|
-
${{ subtitle: 'Available Formats' }}
|
|
80
|
-
----------------------------------
|
|
81
|
-
${this.getListOfFormats().map(x => cliTpl`* ${{ input: x }}`).join('\n')} `;
|
|
82
|
-
|
|
83
|
-
return this.cmd.extendedHelp ? `${presetText}\n${formatText}` : presetText;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
getArgs(): string {
|
|
87
|
-
return '<format-or-preset>';
|
|
13
|
+
@CliCommand()
|
|
14
|
+
export class OpenApiClientCommand implements CliCommandShape {
|
|
15
|
+
@CliFlag({ desc: 'Show Extended Help', short: '-x' })
|
|
16
|
+
extendedHelp?: boolean;
|
|
17
|
+
@CliFlag({ desc: 'Additional Properties', short: '-a', name: '--additional-properties' })
|
|
18
|
+
props: string[] = [];
|
|
19
|
+
@CliFlag({ desc: 'Input file' })
|
|
20
|
+
input = './openapi.yml';
|
|
21
|
+
@CliFlag({ desc: 'Output folder' })
|
|
22
|
+
output = './api-client';
|
|
23
|
+
@CliFlag({ desc: 'Docker Image to user' })
|
|
24
|
+
dockerImage = 'arcsine/openapi-generator:latest';
|
|
25
|
+
@CliFlag({ desc: 'Watch for file changes' })
|
|
26
|
+
watch?: boolean;
|
|
27
|
+
|
|
28
|
+
async help(): Promise<string[]> {
|
|
29
|
+
return OpenApiClientHelp.help(this.dockerImage, this.extendedHelp ?? false);
|
|
88
30
|
}
|
|
89
31
|
|
|
90
|
-
async
|
|
91
|
-
if (!format) {
|
|
92
|
-
return this.showHelp('Format is required');
|
|
93
|
-
}
|
|
94
|
-
|
|
32
|
+
async main(format: string): Promise<void> {
|
|
95
33
|
// Ensure its there
|
|
96
|
-
await fs.mkdir(this.
|
|
34
|
+
await fs.mkdir(this.output, { recursive: true });
|
|
97
35
|
|
|
98
|
-
let propMap = Object.fromEntries(this.
|
|
36
|
+
let propMap = Object.fromEntries(this.props?.map(p => p.split('=')) ?? []);
|
|
99
37
|
|
|
100
38
|
if (format.startsWith('@travetto/')) {
|
|
101
39
|
const key = format.split('@travetto/')[1];
|
|
102
|
-
const [fmt, props] = (await
|
|
40
|
+
const [fmt, props] = (await OpenApiClientPresets.getPresets())[key];
|
|
103
41
|
format = fmt;
|
|
104
42
|
propMap = { ...props, ...propMap };
|
|
105
43
|
}
|
|
106
44
|
|
|
107
|
-
const propList =
|
|
45
|
+
const propList = OpenApiClientPresets.presetMap(propMap);
|
|
108
46
|
|
|
109
47
|
const args = [
|
|
110
48
|
'run',
|
|
111
49
|
'--user', `${process.geteuid?.()}:${process.getgid?.()}`,
|
|
112
|
-
'-v', `${this.
|
|
113
|
-
'-v', `${path.dirname(this.
|
|
50
|
+
'-v', `${this.output}:/workspace`,
|
|
51
|
+
'-v', `${path.dirname(this.input)}:/input`,
|
|
114
52
|
'-it',
|
|
115
53
|
'--rm',
|
|
116
|
-
this.
|
|
54
|
+
this.dockerImage,
|
|
117
55
|
'generate',
|
|
118
56
|
'--skip-validate-spec',
|
|
119
57
|
'--remove-operation-id-prefix',
|
|
120
58
|
'-g', format,
|
|
121
59
|
'-o', '/workspace',
|
|
122
|
-
'-i', `/input/${path.basename(this.
|
|
123
|
-
...(this.
|
|
60
|
+
'-i', `/input/${path.basename(this.input)}`,
|
|
61
|
+
...(this.watch ? ['-w'] : []),
|
|
124
62
|
...(propList ? ['--additional-properties', propList] : [])
|
|
125
63
|
];
|
|
126
64
|
|
|
127
65
|
const { result } = ExecUtil.spawn('docker', args, { stdio: [0, 1, 2] });
|
|
128
|
-
await result.catch(err =>
|
|
66
|
+
await result.catch(err => ShutdownManager.exit(1));
|
|
129
67
|
}
|
|
130
68
|
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { RootIndex } from '@travetto/manifest';
|
|
3
|
-
import { ExecUtil, GlobalEnvConfig } from '@travetto/base';
|
|
1
|
+
import fs from 'fs/promises';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
3
|
+
import { CliCommandShape, CliCommand } from '@travetto/cli';
|
|
4
|
+
import { GlobalEnvConfig } from '@travetto/base';
|
|
5
|
+
import { RootRegistry } from '@travetto/registry';
|
|
6
|
+
import { DependencyRegistry } from '@travetto/di';
|
|
7
|
+
import { path } from '@travetto/manifest';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* CLI for outputting the open api spec to a local file
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
@CliCommand({ fields: ['module'] })
|
|
13
|
+
export class OpenApiSpecCommand implements CliCommandShape {
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
15
|
+
/** Output files */
|
|
16
|
+
output?: string;
|
|
18
17
|
|
|
19
18
|
envInit(): GlobalEnvConfig {
|
|
20
|
-
return {
|
|
21
|
-
debug: false,
|
|
22
|
-
set: { API_SPEC_OUTPUT: this.cmd.output }
|
|
23
|
-
};
|
|
19
|
+
return { debug: false };
|
|
24
20
|
}
|
|
25
21
|
|
|
26
|
-
async
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
22
|
+
async main(): Promise<void> {
|
|
23
|
+
const { OpenApiService } = await import('../src/service.js');
|
|
24
|
+
|
|
25
|
+
await RootRegistry.init();
|
|
26
|
+
|
|
27
|
+
const instance = await DependencyRegistry.getInstance(OpenApiService);
|
|
28
|
+
const result = instance.spec;
|
|
32
29
|
|
|
33
|
-
if (this.
|
|
34
|
-
console.log!(result);
|
|
30
|
+
if (this.output === '-' || !this.output) {
|
|
31
|
+
console.log!(JSON.stringify(result, null, 2));
|
|
32
|
+
} else {
|
|
33
|
+
await fs.mkdir(path.dirname(this.output), { recursive: true });
|
|
34
|
+
await fs.writeFile(this.output, JSON.stringify(result, null, 2), 'utf8');
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
package/support/bin/generate.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { DependencyRegistry } from '@travetto/di';
|
|
2
|
-
import { RootRegistry } from '@travetto/registry';
|
|
3
|
-
|
|
4
|
-
import { OpenApiService } from '../../src/service';
|
|
5
|
-
|
|
6
|
-
export async function main(): Promise<unknown> {
|
|
7
|
-
await RootRegistry.init();
|
|
8
|
-
|
|
9
|
-
const instance = await DependencyRegistry.getInstance(OpenApiService);
|
|
10
|
-
return instance.spec;
|
|
11
|
-
}
|