@spec2ts/openapi 3.1.3 → 4.0.1
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 +24 -21
- package/dist/bin/oapi2ts.d.mts +1 -0
- package/dist/bin/oapi2ts.mjs +8 -0
- package/dist/cli/index.d.mts +15 -0
- package/dist/cli/index.mjs +2 -0
- package/dist/command-BDMCeG0A.mjs +64 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2 -0
- package/dist/openapi-parser-3wx-i5_G.mjs +184 -0
- package/dist/openapi-parser-BJ3RQyRq.d.mts +48 -0
- package/package.json +72 -64
- package/bin/oapi2ts.js +0 -4
- package/cli/command.d.ts +0 -12
- package/cli/command.js +0 -72
- package/cli/index.d.ts +0 -1
- package/cli/index.js +0 -9
- package/index.d.ts +0 -1
- package/index.js +0 -17
- package/lib/core-parser.d.ts +0 -39
- package/lib/core-parser.js +0 -194
- package/lib/openapi-parser.d.ts +0 -10
- package/lib/openapi-parser.js +0 -29
package/README.md
CHANGED
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
- **AST-based:** Unlike other code generators `@spec2ts/openapi` does not use templates to generate code but uses TypeScript's built-in API to generate and pretty-print an abstract syntax tree.
|
|
12
|
+
- **Tree-shakeable:** Individually exported types allows you to bundle only the ones you actually use.
|
|
13
|
+
- **YAML or JSON:** Use YAML or JSON for your OpenAPI v3 specification.
|
|
14
|
+
- **External references:** Resolves automatically external references and bundle or import them in generated files.
|
|
15
|
+
- **Implementation agnostic:** Use generated types in any projet or framework.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
19
|
Install in your project:
|
|
20
|
+
|
|
20
21
|
```bash
|
|
21
22
|
npm install @spec2ts/openapi
|
|
22
23
|
```
|
|
@@ -56,32 +57,34 @@ async function generateSpec(path: string): Promise<string> {
|
|
|
56
57
|
## Implementations
|
|
57
58
|
|
|
58
59
|
- [x] Types for parameters:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
- [x] path
|
|
61
|
+
- [x] header
|
|
62
|
+
- [x] query
|
|
63
|
+
- [x] cookie
|
|
63
64
|
- [x] Types for requestBody
|
|
64
65
|
- [x] Types for responses
|
|
65
66
|
- [x] Automatic naming
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
- [x] From operationId
|
|
68
|
+
- [x] From path
|
|
68
69
|
- [x] Parameters merging
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
- [x] From path item
|
|
71
|
+
- [x] From operation
|
|
72
|
+
- [x] Override from operation
|
|
72
73
|
- [x] [Schema references](http://json-schema.org/latest/json-schema-core.html#rfc.section.7.2.2)
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
- [x] Local (filesystem) schema references
|
|
75
|
+
- [x] External (network) schema references
|
|
75
76
|
- [x] Modular architecture
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
- [x] Import local references
|
|
78
|
+
- [x] Embed external references
|
|
78
79
|
|
|
79
80
|
## Compatibility Matrix
|
|
80
81
|
|
|
81
82
|
| TypeScript version | spec2ts version |
|
|
82
|
-
|
|
83
|
-
| v3.x.x | v1 |
|
|
84
|
-
| v4.x.x | v2 |
|
|
83
|
+
| ------------------ | --------------- |
|
|
84
|
+
| v3.x.x | v1 |
|
|
85
|
+
| v4.x.x | v2 |
|
|
86
|
+
| v5.x.x | v3 |
|
|
87
|
+
| v6.x.x | v4 |
|
|
85
88
|
|
|
86
89
|
## License
|
|
87
90
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { i as usage, n as describe, r as handler, t as builder } from "../command-BDMCeG0A.mjs";
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
//#region src/bin/oapi2ts.ts
|
|
6
|
+
yargs(hideBin(process.argv)).command(usage, describe, builder, handler).help("help", "Show help usage").demandCommand().argv;
|
|
7
|
+
//#endregion
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { t as ParseOpenApiOptions } from "../openapi-parser-BJ3RQyRq.mjs";
|
|
2
|
+
import { Argv } from "yargs";
|
|
3
|
+
//#region src/cli/command.d.ts
|
|
4
|
+
interface BuildTsFromOpenApiOptions extends ParseOpenApiOptions {
|
|
5
|
+
input: string | string[];
|
|
6
|
+
output?: string;
|
|
7
|
+
ext?: string;
|
|
8
|
+
banner?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const usage = "$0 <input..>";
|
|
11
|
+
declare const describe = "Generate TypeScript types from OpenAPI specification";
|
|
12
|
+
declare function builder(argv: Argv): Argv<BuildTsFromOpenApiOptions>;
|
|
13
|
+
declare function handler(options: BuildTsFromOpenApiOptions): Promise<void>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { BuildTsFromOpenApiOptions, builder, describe, handler, usage };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { n as parseOpenApiFile } from "./openapi-parser-3wx-i5_G.mjs";
|
|
2
|
+
import { cli, printer } from "@spec2ts/core";
|
|
3
|
+
//#region src/cli/command.ts
|
|
4
|
+
const usage = "$0 <input..>";
|
|
5
|
+
const describe = "Generate TypeScript types from OpenAPI specification";
|
|
6
|
+
function builder(argv) {
|
|
7
|
+
return argv.positional("input", {
|
|
8
|
+
array: true,
|
|
9
|
+
type: "string",
|
|
10
|
+
describe: "Path to OpenAPI Specification(s) to convert to TypeScript",
|
|
11
|
+
demandOption: true
|
|
12
|
+
}).option("output", {
|
|
13
|
+
type: "string",
|
|
14
|
+
alias: "o",
|
|
15
|
+
describe: "Output directory for generated types"
|
|
16
|
+
}).option("ext", {
|
|
17
|
+
type: "string",
|
|
18
|
+
alias: "e",
|
|
19
|
+
describe: "Output extension for generated types",
|
|
20
|
+
choices: [".d.ts", ".ts"]
|
|
21
|
+
}).option("cwd", {
|
|
22
|
+
type: "string",
|
|
23
|
+
alias: "c",
|
|
24
|
+
describe: "Root directory for resolving $refs"
|
|
25
|
+
}).option("avoidAny", {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
describe: "Avoid the `any` type and use `unknown` instead"
|
|
28
|
+
}).option("enableDate", {
|
|
29
|
+
choices: [
|
|
30
|
+
true,
|
|
31
|
+
"strict",
|
|
32
|
+
"lax"
|
|
33
|
+
],
|
|
34
|
+
describe: "Build `Date` for format `date` and `date-time`"
|
|
35
|
+
}).option("lowerHeaders", {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
describe: "Lowercase headers keys to match Node.js standard"
|
|
38
|
+
}).option("banner", {
|
|
39
|
+
type: "string",
|
|
40
|
+
alias: "b",
|
|
41
|
+
describe: "Comment prepended to the top of each generated file"
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async function handler(options) {
|
|
45
|
+
const files = await cli.findFiles(options.input);
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const ast = await parseOpenApiFile(file, options);
|
|
48
|
+
const content = printer.printNodes(ast.all);
|
|
49
|
+
const output = cli.getOutputPath(file, options);
|
|
50
|
+
await cli.mkdirp(output);
|
|
51
|
+
await cli.writeFile(output, (options.banner || defaultBanner()) + "\n\n" + content);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function defaultBanner() {
|
|
55
|
+
return `/**
|
|
56
|
+
* DO NOT MODIFY
|
|
57
|
+
* Generated using @spec2ts/openapi.
|
|
58
|
+
* See https://www.npmjs.com/package/@spec2ts/openapi
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/* eslint-disable */`;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { usage as i, describe as n, handler as r, builder as t };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as parseParameters, a as ParamType, c as createOpenApiResult, d as getOperationName, f as getParamType, g as parseOperation, h as getSchemaFromContent, i as OApiParserContext, l as getContentDeclaration, m as getResponseName, n as parseOpenApi, o as ParseOpenApiResult, p as getPathName, r as parseOpenApiFile, s as addToOpenApiResult, t as ParseOpenApiOptions, u as getOperationIdentifier, v as parsePathItem, y as parseReference } from "./openapi-parser-BJ3RQyRq.mjs";
|
|
2
|
+
export { OApiParserContext, ParamType, ParseOpenApiOptions, ParseOpenApiResult, addToOpenApiResult, createOpenApiResult, getContentDeclaration, getOperationIdentifier, getOperationName, getParamType, getPathName, getResponseName, getSchemaFromContent, parseOpenApi, parseOpenApiFile, parseOperation, parseParameters, parsePathItem, parseReference };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as getContentDeclaration, c as getParamType, d as getSchemaFromContent, f as parseOperation, h as parseReference, i as createOpenApiResult, l as getPathName, m as parsePathItem, n as parseOpenApiFile, o as getOperationIdentifier, p as parseParameters, r as addToOpenApiResult, s as getOperationName, t as parseOpenApi, u as getResponseName } from "./openapi-parser-3wx-i5_G.mjs";
|
|
2
|
+
export { addToOpenApiResult, createOpenApiResult, getContentDeclaration, getOperationIdentifier, getOperationName, getParamType, getPathName, getResponseName, getSchemaFromContent, parseOpenApi, parseOpenApiFile, parseOperation, parseParameters, parsePathItem, parseReference };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import * as core from "@spec2ts/core";
|
|
2
|
+
import { createContext, createRefContext, getTypeFromProperties, getTypeFromSchema, pascalCase, resolveReference } from "@spec2ts/jsonschema";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import $RefParser from "@apidevtools/json-schema-ref-parser";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
//#region src/lib/core-parser.ts
|
|
7
|
+
const VERBS = [
|
|
8
|
+
"GET",
|
|
9
|
+
"PUT",
|
|
10
|
+
"POST",
|
|
11
|
+
"DELETE",
|
|
12
|
+
"OPTIONS",
|
|
13
|
+
"HEAD",
|
|
14
|
+
"PATCH",
|
|
15
|
+
"TRACE"
|
|
16
|
+
];
|
|
17
|
+
function parsePathItem(path, item, context, result) {
|
|
18
|
+
const baseParams = item.parameters && parseParameters(getPathName(path, context), item.parameters, void 0, context, result);
|
|
19
|
+
Object.entries(item).filter(([verb]) => VERBS.includes(verb.toUpperCase())).forEach(([verb, entry]) => parseOperation(path, verb, entry, baseParams, context, result));
|
|
20
|
+
}
|
|
21
|
+
function parseOperation(path, verb, operation, baseParams, context, result) {
|
|
22
|
+
const name = getOperationName(verb, path, operation.operationId, context);
|
|
23
|
+
if (operation.parameters) parseParameters(name, operation.parameters, baseParams, context, result);
|
|
24
|
+
if (operation.requestBody) {
|
|
25
|
+
const requestBody = resolveReference(operation.requestBody, context);
|
|
26
|
+
const decla = getContentDeclaration(name + "Body", requestBody.content, context);
|
|
27
|
+
if (decla) addToOpenApiResult(result, "body", decla);
|
|
28
|
+
}
|
|
29
|
+
if (operation.responses) {
|
|
30
|
+
const responses = resolveReference(operation.responses, context);
|
|
31
|
+
Object.entries(responses).forEach(([status, responseObj]) => {
|
|
32
|
+
const response = resolveReference(responseObj, context);
|
|
33
|
+
const decla = getContentDeclaration(getResponseName(name, status, context), response.content, context);
|
|
34
|
+
if (decla) addToOpenApiResult(result, "responses", decla);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function parseParameters(baseName, data, baseParams = {}, context, result) {
|
|
39
|
+
const params = [];
|
|
40
|
+
const query = [];
|
|
41
|
+
const headers = [];
|
|
42
|
+
const cookie = [];
|
|
43
|
+
const res = {};
|
|
44
|
+
data.forEach((item) => {
|
|
45
|
+
item = resolveReference(item, context);
|
|
46
|
+
switch (item.in) {
|
|
47
|
+
case "path":
|
|
48
|
+
params.push(item);
|
|
49
|
+
break;
|
|
50
|
+
case "header":
|
|
51
|
+
headers.push(item);
|
|
52
|
+
break;
|
|
53
|
+
case "query":
|
|
54
|
+
query.push(item);
|
|
55
|
+
break;
|
|
56
|
+
case "cookie":
|
|
57
|
+
cookie.push(item);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
addParams(params, "params");
|
|
62
|
+
addParams(headers, "headers");
|
|
63
|
+
addParams(query, "query");
|
|
64
|
+
addParams(cookie, "cookie");
|
|
65
|
+
return res;
|
|
66
|
+
function addParams(params, paramType) {
|
|
67
|
+
if (!params.length) return;
|
|
68
|
+
const name = baseName + pascalCase(paramType);
|
|
69
|
+
const type = getParamType(paramType, params, baseParams[paramType], context);
|
|
70
|
+
addToOpenApiResult(result, paramType, core.createTypeOrInterfaceDeclaration({
|
|
71
|
+
modifiers: [core.modifier.export],
|
|
72
|
+
name,
|
|
73
|
+
type
|
|
74
|
+
}));
|
|
75
|
+
res[paramType] = ts.factory.createTypeReferenceNode(name, void 0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function parseReference(ref, context) {
|
|
79
|
+
const type = getTypeFromSchema(ref.schema, createRefContext(ref, context));
|
|
80
|
+
context.aliases.push(core.createTypeOrInterfaceDeclaration({
|
|
81
|
+
modifiers: [core.modifier.export],
|
|
82
|
+
name: ref.name,
|
|
83
|
+
type
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
function getContentDeclaration(name, content, context) {
|
|
87
|
+
if (!content) return;
|
|
88
|
+
content = resolveReference(content, context);
|
|
89
|
+
const schema = getSchemaFromContent(content);
|
|
90
|
+
if (!schema) return;
|
|
91
|
+
const type = getTypeFromSchema(schema, context);
|
|
92
|
+
return core.createTypeOrInterfaceDeclaration({
|
|
93
|
+
modifiers: [core.modifier.export],
|
|
94
|
+
name,
|
|
95
|
+
type
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function getParamType(paramType, data, baseType, context) {
|
|
99
|
+
const required = [];
|
|
100
|
+
const props = {};
|
|
101
|
+
data.forEach((m) => {
|
|
102
|
+
let name = m.name;
|
|
103
|
+
if (paramType === "headers" && context.options.lowerHeaders) name = name.toLowerCase();
|
|
104
|
+
props[name] = m.schema || {};
|
|
105
|
+
if (m.required) required.push(name);
|
|
106
|
+
});
|
|
107
|
+
const type = getTypeFromProperties(props, required, false, paramType === "query" && typeof context.options.enableDateForQueryParams !== "undefined" ? {
|
|
108
|
+
...context,
|
|
109
|
+
options: {
|
|
110
|
+
...context.options,
|
|
111
|
+
enableDate: context.options.enableDateForQueryParams
|
|
112
|
+
}
|
|
113
|
+
} : context);
|
|
114
|
+
if (baseType) return ts.factory.createIntersectionTypeNode([baseType, type]);
|
|
115
|
+
return type;
|
|
116
|
+
}
|
|
117
|
+
function getSchemaFromContent(content) {
|
|
118
|
+
return content?.["application/json"]?.schema || content?.["application/x-www-form-urlencoded"]?.schema || content?.["multipart/form-data"]?.schema || content?.["*/*"]?.schema;
|
|
119
|
+
}
|
|
120
|
+
function getResponseName(operationName, statusCode, context) {
|
|
121
|
+
let name = operationName + "Response";
|
|
122
|
+
const status = parseInt(statusCode);
|
|
123
|
+
if (status >= 200 && status < 300) {
|
|
124
|
+
if ((context.names[name] = (context.names[name] || 0) + 1) > 1) name += statusCode;
|
|
125
|
+
} else if (!isNaN(status)) name += statusCode;
|
|
126
|
+
else name += pascalCase(statusCode);
|
|
127
|
+
return name;
|
|
128
|
+
}
|
|
129
|
+
function getOperationName(verb, path, operationId, context) {
|
|
130
|
+
const id = getOperationIdentifier(operationId);
|
|
131
|
+
if (id) return id;
|
|
132
|
+
return getPathName(`${verb} ${path}`, context);
|
|
133
|
+
}
|
|
134
|
+
function getPathName(path, context) {
|
|
135
|
+
path = path.replace(/\{(.+?)\}/, "by $1").replace(/\{(.+?)\}/g, "and $1");
|
|
136
|
+
let name = pascalCase(path);
|
|
137
|
+
const count = context.names[name] = (context.names[name] || 0) + 1;
|
|
138
|
+
if (count > 1) name += count;
|
|
139
|
+
return name;
|
|
140
|
+
}
|
|
141
|
+
function getOperationIdentifier(id) {
|
|
142
|
+
if (!id) return;
|
|
143
|
+
if (id.match(/[^\w\s]/)) return;
|
|
144
|
+
id = pascalCase(id);
|
|
145
|
+
if (core.isValidIdentifier(id)) return id;
|
|
146
|
+
}
|
|
147
|
+
function addToOpenApiResult(result, prop, statement) {
|
|
148
|
+
const statements = Array.isArray(statement) ? statement : [statement];
|
|
149
|
+
result[prop].push(...statements);
|
|
150
|
+
result.all.push(...statements);
|
|
151
|
+
}
|
|
152
|
+
function createOpenApiResult() {
|
|
153
|
+
return {
|
|
154
|
+
params: [],
|
|
155
|
+
query: [],
|
|
156
|
+
headers: [],
|
|
157
|
+
body: [],
|
|
158
|
+
responses: [],
|
|
159
|
+
models: [],
|
|
160
|
+
cookie: [],
|
|
161
|
+
import: [],
|
|
162
|
+
all: []
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/lib/openapi-parser.ts
|
|
167
|
+
async function parseOpenApiFile(file, options = {}) {
|
|
168
|
+
return parseOpenApi(await $RefParser.parse(file), {
|
|
169
|
+
cwd: path.resolve(path.dirname(file)) + "/",
|
|
170
|
+
...options
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async function parseOpenApi(spec, options = {}) {
|
|
174
|
+
if (!options.parseReference) options.parseReference = parseReference;
|
|
175
|
+
const context = await createContext(spec, options);
|
|
176
|
+
const result = createOpenApiResult();
|
|
177
|
+
Object.entries(spec.paths ?? {}).forEach(([path, item]) => {
|
|
178
|
+
parsePathItem(path, item, context, result);
|
|
179
|
+
});
|
|
180
|
+
addToOpenApiResult(result, "models", context.aliases);
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
export { getContentDeclaration as a, getParamType as c, getSchemaFromContent as d, parseOperation as f, parseReference as h, createOpenApiResult as i, getPathName as l, parsePathItem as m, parseOpenApiFile as n, getOperationIdentifier as o, parseParameters as p, addToOpenApiResult as r, getOperationName as s, parseOpenApi as t, getResponseName as u };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ParsedReference, ParserContext, ParserOptions } from "@spec2ts/jsonschema";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import { ContentObject, OpenAPIObject, OperationObject, ParameterObject, PathItemObject, ReferenceObject, SchemaObject } from "openapi3-ts/oas31";
|
|
4
|
+
//#region src/lib/core-parser.d.ts
|
|
5
|
+
interface ParseOpenApiResult {
|
|
6
|
+
import: ts.Statement[];
|
|
7
|
+
params: ts.Statement[];
|
|
8
|
+
query: ts.Statement[];
|
|
9
|
+
headers: ts.Statement[];
|
|
10
|
+
body: ts.Statement[];
|
|
11
|
+
responses: ts.Statement[];
|
|
12
|
+
models: ts.Statement[];
|
|
13
|
+
cookie: ts.Statement[];
|
|
14
|
+
all: ts.Statement[];
|
|
15
|
+
}
|
|
16
|
+
interface OApiParserContext extends ParserContext {
|
|
17
|
+
options: ParseOpenApiOptions;
|
|
18
|
+
}
|
|
19
|
+
declare function parsePathItem(path: string, item: PathItemObject, context: OApiParserContext, result: ParseOpenApiResult): void;
|
|
20
|
+
declare function parseOperation(path: string, verb: string, operation: OperationObject, baseParams: ParsedParams | undefined, context: OApiParserContext, result: ParseOpenApiResult): void;
|
|
21
|
+
type ParamType = "params" | "headers" | "query" | "cookie";
|
|
22
|
+
declare function parseParameters(baseName: string, data: Array<ReferenceObject | ParameterObject>, baseParams: ParsedParams | undefined, context: OApiParserContext, result: ParseOpenApiResult): ParsedParams;
|
|
23
|
+
declare function parseReference(ref: ParsedReference, context: ParserContext): void;
|
|
24
|
+
declare function getContentDeclaration(name: string, content: ReferenceObject | ContentObject | undefined, context: OApiParserContext): ts.Statement | undefined;
|
|
25
|
+
declare function getParamType(paramType: ParamType, data: ParameterObject[], baseType: ts.TypeReferenceNode | undefined, context: OApiParserContext): ts.TypeNode;
|
|
26
|
+
declare function getSchemaFromContent(content: ContentObject): SchemaObject | ReferenceObject | undefined;
|
|
27
|
+
declare function getResponseName(operationName: string, statusCode: string, context: OApiParserContext): string;
|
|
28
|
+
declare function getOperationName(verb: string, path: string, operationId: string | undefined, context: OApiParserContext): string;
|
|
29
|
+
declare function getPathName(path: string, context: OApiParserContext): string;
|
|
30
|
+
declare function getOperationIdentifier(id?: string): string | void;
|
|
31
|
+
declare function addToOpenApiResult(result: ParseOpenApiResult, prop: keyof ParseOpenApiResult, statement: ts.Statement | ts.Statement[]): void;
|
|
32
|
+
declare function createOpenApiResult(): ParseOpenApiResult;
|
|
33
|
+
interface ParsedParams {
|
|
34
|
+
params?: ts.TypeReferenceNode;
|
|
35
|
+
query?: ts.TypeReferenceNode;
|
|
36
|
+
headers?: ts.TypeReferenceNode;
|
|
37
|
+
cookie?: ts.TypeReferenceNode;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/lib/openapi-parser.d.ts
|
|
41
|
+
interface ParseOpenApiOptions extends ParserOptions {
|
|
42
|
+
lowerHeaders?: boolean;
|
|
43
|
+
enableDateForQueryParams?: boolean | "strict" | "lax";
|
|
44
|
+
}
|
|
45
|
+
declare function parseOpenApiFile(file: string, options?: ParseOpenApiOptions): Promise<ParseOpenApiResult>;
|
|
46
|
+
declare function parseOpenApi(spec: OpenAPIObject, options?: ParseOpenApiOptions): Promise<ParseOpenApiResult>;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { parseParameters as _, ParamType as a, createOpenApiResult as c, getOperationName as d, getParamType as f, parseOperation as g, getSchemaFromContent as h, OApiParserContext as i, getContentDeclaration as l, getResponseName as m, parseOpenApi as n, ParseOpenApiResult as o, getPathName as p, parseOpenApiFile as r, addToOpenApiResult as s, ParseOpenApiOptions as t, getOperationIdentifier as u, parsePathItem as v, parseReference as y };
|
package/package.json
CHANGED
|
@@ -1,69 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
"name": "@spec2ts/openapi",
|
|
3
|
+
"version": "4.0.1",
|
|
4
|
+
"description": "Utility to convert OpenAPI v3 specifications to Typescript using TypeScript native compiler",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ast",
|
|
7
|
+
"compile",
|
|
8
|
+
"compiler",
|
|
9
|
+
"interface",
|
|
10
|
+
"openapi",
|
|
11
|
+
"openapi3",
|
|
12
|
+
"share",
|
|
13
|
+
"spec",
|
|
14
|
+
"spec2ts",
|
|
15
|
+
"specification",
|
|
16
|
+
"transpile",
|
|
17
|
+
"typescript",
|
|
18
|
+
"typing"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://github.com/touchifyapp/spec2ts/blob/master/packages/openapi#readme",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Touchify <dev@touchify.co>",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/touchifyapp/spec2ts"
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"oapi2ts": "./dist/bin/oapi2ts.mjs"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist/**/*.mjs",
|
|
32
|
+
"dist/**/*.d.mts"
|
|
33
|
+
],
|
|
34
|
+
"type": "module",
|
|
35
|
+
"main": "dist/index.mjs",
|
|
36
|
+
"types": "dist/index.d.mts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"import": "./dist/index.mjs",
|
|
40
|
+
"types": "./dist/index.d.mts"
|
|
12
41
|
},
|
|
13
|
-
"
|
|
14
|
-
|
|
42
|
+
"./cli": {
|
|
43
|
+
"import": "./dist/cli/index.mjs",
|
|
44
|
+
"types": "./dist/cli/index.d.mts"
|
|
15
45
|
},
|
|
16
|
-
"bin": {
|
|
17
|
-
|
|
46
|
+
"./bin/oapi2ts": {
|
|
47
|
+
"import": "./dist/bin/oapi2ts.mjs",
|
|
48
|
+
"types": "./dist/bin/oapi2ts.d.mts"
|
|
18
49
|
},
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"yargs": "^17.7.2"
|
|
47
|
-
},
|
|
48
|
-
"devDependencies": {
|
|
49
|
-
"del-cli": "^5.1.0",
|
|
50
|
-
"eslint": "^8.49.0",
|
|
51
|
-
"jest": "^29.6.4"
|
|
52
|
-
},
|
|
53
|
-
"keywords": [
|
|
54
|
-
"openapi",
|
|
55
|
-
"specification",
|
|
56
|
-
"openapi3",
|
|
57
|
-
"spec",
|
|
58
|
-
"typescript",
|
|
59
|
-
"compile",
|
|
60
|
-
"compiler",
|
|
61
|
-
"ast",
|
|
62
|
-
"transpile",
|
|
63
|
-
"interface",
|
|
64
|
-
"typing",
|
|
65
|
-
"spec2ts",
|
|
66
|
-
"share"
|
|
67
|
-
],
|
|
68
|
-
"gitHead": "81f76779f541e0bc2ef8d7051a0121fff07916ae"
|
|
50
|
+
"./package.json": "./package.json"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "npm run lint && npm run build:ts",
|
|
57
|
+
"build:ts": "tsdown",
|
|
58
|
+
"test": "npm run lint && npm run format:check && npm run test:vitest",
|
|
59
|
+
"test:prepublish": "npm run lint && npm run test:vitest",
|
|
60
|
+
"test:vitest": "vitest run -c ../../vitest.config.ts",
|
|
61
|
+
"test:coverage": "npm run test -- -- --coverage",
|
|
62
|
+
"lint": "npm run lint:ts",
|
|
63
|
+
"lint:ts": "oxlint -c ../../oxlint.config.ts",
|
|
64
|
+
"lint:fix": "npm run lint -- -- --fix",
|
|
65
|
+
"format": "oxfmt -c ../../oxfmt.config.ts",
|
|
66
|
+
"format:check": "oxfmt -c ../../oxfmt.config.ts --check",
|
|
67
|
+
"prepublishOnly": "npm run test:prepublish && npm run build"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@apidevtools/json-schema-ref-parser": "^10.1.0",
|
|
71
|
+
"@spec2ts/core": "^4.0.1",
|
|
72
|
+
"@spec2ts/jsonschema": "^4.0.1",
|
|
73
|
+
"openapi3-ts": "^4.6.0",
|
|
74
|
+
"typescript": "^6.0.0",
|
|
75
|
+
"yargs": "^18.0.0"
|
|
76
|
+
}
|
|
69
77
|
}
|
package/bin/oapi2ts.js
DELETED
package/cli/command.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Argv } from "yargs";
|
|
2
|
-
import { ParseOpenApiOptions } from "../lib/openapi-parser";
|
|
3
|
-
export interface BuildTsFromOpenApiOptions extends ParseOpenApiOptions {
|
|
4
|
-
input: string | string[];
|
|
5
|
-
output?: string;
|
|
6
|
-
ext?: string;
|
|
7
|
-
banner?: string;
|
|
8
|
-
}
|
|
9
|
-
export declare const usage = "$0 <input..>";
|
|
10
|
-
export declare const describe = "Generate TypeScript types from OpenAPI specification";
|
|
11
|
-
export declare function builder(argv: Argv): Argv<BuildTsFromOpenApiOptions>;
|
|
12
|
-
export declare function handler(options: BuildTsFromOpenApiOptions): Promise<void>;
|
package/cli/command.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handler = exports.builder = exports.describe = exports.usage = void 0;
|
|
4
|
-
const core_1 = require("@spec2ts/core");
|
|
5
|
-
const openapi_parser_1 = require("../lib/openapi-parser");
|
|
6
|
-
exports.usage = "$0 <input..>";
|
|
7
|
-
exports.describe = "Generate TypeScript types from OpenAPI specification";
|
|
8
|
-
function builder(argv) {
|
|
9
|
-
return argv
|
|
10
|
-
.positional("input", {
|
|
11
|
-
array: true,
|
|
12
|
-
type: "string",
|
|
13
|
-
describe: "Path to OpenAPI Specification(s) to convert to TypeScript",
|
|
14
|
-
demandOption: true
|
|
15
|
-
})
|
|
16
|
-
.option("output", {
|
|
17
|
-
type: "string",
|
|
18
|
-
alias: "o",
|
|
19
|
-
describe: "Output directory for generated types"
|
|
20
|
-
})
|
|
21
|
-
.option("ext", {
|
|
22
|
-
type: "string",
|
|
23
|
-
alias: "e",
|
|
24
|
-
describe: "Output extension for generated types",
|
|
25
|
-
choices: [".d.ts", ".ts"]
|
|
26
|
-
})
|
|
27
|
-
.option("cwd", {
|
|
28
|
-
type: "string",
|
|
29
|
-
alias: "c",
|
|
30
|
-
describe: "Root directory for resolving $refs"
|
|
31
|
-
})
|
|
32
|
-
.option("avoidAny", {
|
|
33
|
-
type: "boolean",
|
|
34
|
-
describe: "Avoid the `any` type and use `unknown` instead"
|
|
35
|
-
})
|
|
36
|
-
.option("enableDate", {
|
|
37
|
-
choices: [true, "strict", "lax"],
|
|
38
|
-
describe: "Build `Date` for format `date` and `date-time`"
|
|
39
|
-
})
|
|
40
|
-
.option("lowerHeaders", {
|
|
41
|
-
type: "boolean",
|
|
42
|
-
describe: "Lowercase headers keys to match Node.js standard"
|
|
43
|
-
})
|
|
44
|
-
.option("banner", {
|
|
45
|
-
type: "string",
|
|
46
|
-
alias: "b",
|
|
47
|
-
describe: "Comment prepended to the top of each generated file"
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
exports.builder = builder;
|
|
51
|
-
async function handler(options) {
|
|
52
|
-
const files = await core_1.cli.findFiles(options.input);
|
|
53
|
-
for (const file of files) {
|
|
54
|
-
const ast = await (0, openapi_parser_1.parseOpenApiFile)(file, options);
|
|
55
|
-
const content = core_1.printer.printNodes(ast.all);
|
|
56
|
-
const output = core_1.cli.getOutputPath(file, options);
|
|
57
|
-
await core_1.cli.mkdirp(output);
|
|
58
|
-
await core_1.cli.writeFile(output, (options.banner || defaultBanner()) +
|
|
59
|
-
"\n\n" +
|
|
60
|
-
content);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
exports.handler = handler;
|
|
64
|
-
function defaultBanner() {
|
|
65
|
-
return `/**
|
|
66
|
-
* DO NOT MODIFY
|
|
67
|
-
* Generated using @spec2ts/openapi.
|
|
68
|
-
* See https://www.npmjs.com/package/@spec2ts/openapi
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/* eslint-disable */`;
|
|
72
|
-
}
|
package/cli/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/cli/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const yargs = require("yargs");
|
|
4
|
-
const command_1 = require("../cli/command");
|
|
5
|
-
yargs
|
|
6
|
-
.command(command_1.usage, command_1.describe, command_1.builder, command_1.handler)
|
|
7
|
-
.help("help", "Show help usage")
|
|
8
|
-
.demandCommand()
|
|
9
|
-
.argv;
|
package/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./lib/openapi-parser";
|
package/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./lib/openapi-parser"), exports);
|
package/lib/core-parser.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import * as ts from "typescript";
|
|
2
|
-
import type { SchemaObject, ReferenceObject, PathItemObject, OperationObject, ParameterObject, ContentObject } from "openapi3-ts/oas31";
|
|
3
|
-
import { ParserContext, ParsedReference } from "@spec2ts/jsonschema/lib/core-parser";
|
|
4
|
-
import type { ParseOpenApiOptions } from "./openapi-parser";
|
|
5
|
-
export interface ParseOpenApiResult {
|
|
6
|
-
import: ts.Statement[];
|
|
7
|
-
params: ts.Statement[];
|
|
8
|
-
query: ts.Statement[];
|
|
9
|
-
headers: ts.Statement[];
|
|
10
|
-
body: ts.Statement[];
|
|
11
|
-
responses: ts.Statement[];
|
|
12
|
-
models: ts.Statement[];
|
|
13
|
-
cookie: ts.Statement[];
|
|
14
|
-
all: ts.Statement[];
|
|
15
|
-
}
|
|
16
|
-
export interface OApiParserContext extends ParserContext {
|
|
17
|
-
options: ParseOpenApiOptions;
|
|
18
|
-
}
|
|
19
|
-
export declare function parsePathItem(path: string, item: PathItemObject, context: OApiParserContext, result: ParseOpenApiResult): void;
|
|
20
|
-
export declare function parseOperation(path: string, verb: string, operation: OperationObject, baseParams: ParsedParams | undefined, context: OApiParserContext, result: ParseOpenApiResult): void;
|
|
21
|
-
export type ParamType = "params" | "headers" | "query" | "cookie";
|
|
22
|
-
export declare function parseParameters(baseName: string, data: Array<ReferenceObject | ParameterObject>, baseParams: ParsedParams | undefined, context: OApiParserContext, result: ParseOpenApiResult): ParsedParams;
|
|
23
|
-
export declare function parseReference(ref: ParsedReference, context: ParserContext): void;
|
|
24
|
-
export declare function getContentDeclaration(name: string, content: ReferenceObject | ContentObject | undefined, context: OApiParserContext): ts.Statement | undefined;
|
|
25
|
-
export declare function getParamType(paramType: ParamType, data: ParameterObject[], baseType: ts.TypeReferenceNode | undefined, context: OApiParserContext): ts.TypeNode;
|
|
26
|
-
export declare function getSchemaFromContent(content: ContentObject): SchemaObject | ReferenceObject | undefined;
|
|
27
|
-
export declare function getResponseName(operationName: string, statusCode: string, context: OApiParserContext): string;
|
|
28
|
-
export declare function getOperationName(verb: string, path: string, operationId: string | undefined, context: OApiParserContext): string;
|
|
29
|
-
export declare function getPathName(path: string, context: OApiParserContext): string;
|
|
30
|
-
export declare function getOperationIdentifier(id?: string): string | void;
|
|
31
|
-
export declare function addToOpenApiResult(result: ParseOpenApiResult, prop: keyof ParseOpenApiResult, statement: ts.Statement | ts.Statement[]): void;
|
|
32
|
-
export declare function createOpenApiResult(): ParseOpenApiResult;
|
|
33
|
-
interface ParsedParams {
|
|
34
|
-
params?: ts.TypeReferenceNode;
|
|
35
|
-
query?: ts.TypeReferenceNode;
|
|
36
|
-
headers?: ts.TypeReferenceNode;
|
|
37
|
-
cookie?: ts.TypeReferenceNode;
|
|
38
|
-
}
|
|
39
|
-
export {};
|
package/lib/core-parser.js
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createOpenApiResult = exports.addToOpenApiResult = exports.getOperationIdentifier = exports.getPathName = exports.getOperationName = exports.getResponseName = exports.getSchemaFromContent = exports.getParamType = exports.getContentDeclaration = exports.parseReference = exports.parseParameters = exports.parseOperation = exports.parsePathItem = void 0;
|
|
4
|
-
const ts = require("typescript");
|
|
5
|
-
const core = require("@spec2ts/core");
|
|
6
|
-
const core_parser_1 = require("@spec2ts/jsonschema/lib/core-parser");
|
|
7
|
-
const VERBS = ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"];
|
|
8
|
-
function parsePathItem(path, item, context, result) {
|
|
9
|
-
const baseParams = item.parameters && parseParameters(getPathName(path, context), item.parameters, undefined, context, result);
|
|
10
|
-
Object.entries(item)
|
|
11
|
-
.filter(([verb,]) => VERBS.includes(verb.toUpperCase()))
|
|
12
|
-
.forEach(([verb, entry]) => parseOperation(path, verb, entry, baseParams, context, result));
|
|
13
|
-
}
|
|
14
|
-
exports.parsePathItem = parsePathItem;
|
|
15
|
-
function parseOperation(path, verb, operation, baseParams, context, result) {
|
|
16
|
-
const name = getOperationName(verb, path, operation.operationId, context);
|
|
17
|
-
if (operation.parameters) {
|
|
18
|
-
parseParameters(name, operation.parameters, baseParams, context, result);
|
|
19
|
-
}
|
|
20
|
-
if (operation.requestBody) {
|
|
21
|
-
const requestBody = (0, core_parser_1.resolveReference)(operation.requestBody, context);
|
|
22
|
-
const decla = getContentDeclaration(name + "Body", requestBody.content, context);
|
|
23
|
-
if (decla) {
|
|
24
|
-
addToOpenApiResult(result, "body", decla);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (operation.responses) {
|
|
28
|
-
const responses = (0, core_parser_1.resolveReference)(operation.responses, context);
|
|
29
|
-
Object.entries(responses).forEach(([status, responseObj]) => {
|
|
30
|
-
const response = (0, core_parser_1.resolveReference)(responseObj, context);
|
|
31
|
-
const decla = getContentDeclaration(getResponseName(name, status, context), response.content, context);
|
|
32
|
-
if (decla) {
|
|
33
|
-
addToOpenApiResult(result, "responses", decla);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
exports.parseOperation = parseOperation;
|
|
39
|
-
function parseParameters(baseName, data, baseParams = {}, context, result) {
|
|
40
|
-
const params = [];
|
|
41
|
-
const query = [];
|
|
42
|
-
const headers = [];
|
|
43
|
-
const cookie = [];
|
|
44
|
-
const res = {};
|
|
45
|
-
data.forEach(item => {
|
|
46
|
-
item = (0, core_parser_1.resolveReference)(item, context);
|
|
47
|
-
switch (item.in) {
|
|
48
|
-
case "path":
|
|
49
|
-
params.push(item);
|
|
50
|
-
break;
|
|
51
|
-
case "header":
|
|
52
|
-
headers.push(item);
|
|
53
|
-
break;
|
|
54
|
-
case "query":
|
|
55
|
-
query.push(item);
|
|
56
|
-
break;
|
|
57
|
-
case "cookie":
|
|
58
|
-
cookie.push(item);
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
addParams(params, "params");
|
|
63
|
-
addParams(headers, "headers");
|
|
64
|
-
addParams(query, "query");
|
|
65
|
-
addParams(cookie, "cookie");
|
|
66
|
-
return res;
|
|
67
|
-
function addParams(params, paramType) {
|
|
68
|
-
if (!params.length)
|
|
69
|
-
return;
|
|
70
|
-
const name = baseName + (0, core_parser_1.pascalCase)(paramType);
|
|
71
|
-
const type = getParamType(paramType, params, baseParams[paramType], context);
|
|
72
|
-
addToOpenApiResult(result, paramType, core.createTypeOrInterfaceDeclaration({
|
|
73
|
-
modifiers: [core.modifier.export],
|
|
74
|
-
name,
|
|
75
|
-
type
|
|
76
|
-
}));
|
|
77
|
-
res[paramType] = ts.factory.createTypeReferenceNode(name, undefined);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.parseParameters = parseParameters;
|
|
81
|
-
function parseReference(ref, context) {
|
|
82
|
-
const type = (0, core_parser_1.getTypeFromSchema)(ref.schema, (0, core_parser_1.createRefContext)(ref, context));
|
|
83
|
-
context.aliases.push(core.createTypeOrInterfaceDeclaration({
|
|
84
|
-
modifiers: [core.modifier.export],
|
|
85
|
-
name: ref.name,
|
|
86
|
-
type
|
|
87
|
-
}));
|
|
88
|
-
}
|
|
89
|
-
exports.parseReference = parseReference;
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region Utils
|
|
92
|
-
function getContentDeclaration(name, content, context) {
|
|
93
|
-
if (!content)
|
|
94
|
-
return;
|
|
95
|
-
content = (0, core_parser_1.resolveReference)(content, context);
|
|
96
|
-
const schema = getSchemaFromContent(content);
|
|
97
|
-
if (!schema)
|
|
98
|
-
return;
|
|
99
|
-
const type = (0, core_parser_1.getTypeFromSchema)(schema, context);
|
|
100
|
-
return core.createTypeOrInterfaceDeclaration({
|
|
101
|
-
modifiers: [core.modifier.export],
|
|
102
|
-
name,
|
|
103
|
-
type
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
exports.getContentDeclaration = getContentDeclaration;
|
|
107
|
-
function getParamType(paramType, data, baseType, context) {
|
|
108
|
-
const required = [];
|
|
109
|
-
const props = {};
|
|
110
|
-
data.forEach(m => {
|
|
111
|
-
let name = m.name;
|
|
112
|
-
if (paramType === "headers" && context.options.lowerHeaders) {
|
|
113
|
-
name = name.toLowerCase();
|
|
114
|
-
}
|
|
115
|
-
props[name] = m.schema || {};
|
|
116
|
-
if (m.required) {
|
|
117
|
-
required.push(name);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
const ctx = paramType === "query" && typeof context.options.enableDateForQueryParams !== "undefined"
|
|
121
|
-
? { ...context, options: { ...context.options, enableDate: context.options.enableDateForQueryParams } }
|
|
122
|
-
: context;
|
|
123
|
-
const type = (0, core_parser_1.getTypeFromProperties)(props, required, false, ctx);
|
|
124
|
-
if (baseType) {
|
|
125
|
-
return ts.factory.createIntersectionTypeNode([baseType, type]);
|
|
126
|
-
}
|
|
127
|
-
return type;
|
|
128
|
-
}
|
|
129
|
-
exports.getParamType = getParamType;
|
|
130
|
-
function getSchemaFromContent(content) {
|
|
131
|
-
var _a, _b, _c, _d;
|
|
132
|
-
return ((_a = content === null || content === void 0 ? void 0 : content["application/json"]) === null || _a === void 0 ? void 0 : _a.schema) ||
|
|
133
|
-
((_b = content === null || content === void 0 ? void 0 : content["application/x-www-form-urlencoded"]) === null || _b === void 0 ? void 0 : _b.schema) ||
|
|
134
|
-
((_c = content === null || content === void 0 ? void 0 : content["multipart/form-data"]) === null || _c === void 0 ? void 0 : _c.schema) ||
|
|
135
|
-
((_d = content === null || content === void 0 ? void 0 : content["*/*"]) === null || _d === void 0 ? void 0 : _d.schema);
|
|
136
|
-
}
|
|
137
|
-
exports.getSchemaFromContent = getSchemaFromContent;
|
|
138
|
-
function getResponseName(operationName, statusCode, context) {
|
|
139
|
-
let name = operationName + "Response";
|
|
140
|
-
const status = parseInt(statusCode);
|
|
141
|
-
if (status >= 200 && status < 300) {
|
|
142
|
-
const count = (context.names[name] = (context.names[name] || 0) + 1);
|
|
143
|
-
if (count > 1) {
|
|
144
|
-
name += statusCode;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
else if (!isNaN(status)) {
|
|
148
|
-
name += statusCode;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// default
|
|
152
|
-
name += (0, core_parser_1.pascalCase)(statusCode);
|
|
153
|
-
}
|
|
154
|
-
return name;
|
|
155
|
-
}
|
|
156
|
-
exports.getResponseName = getResponseName;
|
|
157
|
-
function getOperationName(verb, path, operationId, context) {
|
|
158
|
-
const id = getOperationIdentifier(operationId);
|
|
159
|
-
if (id) {
|
|
160
|
-
return id;
|
|
161
|
-
}
|
|
162
|
-
return getPathName(`${verb} ${path}`, context);
|
|
163
|
-
}
|
|
164
|
-
exports.getOperationName = getOperationName;
|
|
165
|
-
function getPathName(path, context) {
|
|
166
|
-
path = path.replace(/\{(.+?)\}/, "by $1").replace(/\{(.+?)\}/g, "and $1");
|
|
167
|
-
let name = (0, core_parser_1.pascalCase)(path);
|
|
168
|
-
const count = (context.names[name] = (context.names[name] || 0) + 1);
|
|
169
|
-
if (count > 1) {
|
|
170
|
-
name += count;
|
|
171
|
-
}
|
|
172
|
-
return name;
|
|
173
|
-
}
|
|
174
|
-
exports.getPathName = getPathName;
|
|
175
|
-
function getOperationIdentifier(id) {
|
|
176
|
-
if (!id)
|
|
177
|
-
return;
|
|
178
|
-
if (id.match(/[^\w\s]/))
|
|
179
|
-
return;
|
|
180
|
-
id = (0, core_parser_1.pascalCase)(id);
|
|
181
|
-
if (core.isValidIdentifier(id))
|
|
182
|
-
return id;
|
|
183
|
-
}
|
|
184
|
-
exports.getOperationIdentifier = getOperationIdentifier;
|
|
185
|
-
function addToOpenApiResult(result, prop, statement) {
|
|
186
|
-
const statements = Array.isArray(statement) ? statement : [statement];
|
|
187
|
-
result[prop].push(...statements);
|
|
188
|
-
result.all.push(...statements);
|
|
189
|
-
}
|
|
190
|
-
exports.addToOpenApiResult = addToOpenApiResult;
|
|
191
|
-
function createOpenApiResult() {
|
|
192
|
-
return { params: [], query: [], headers: [], body: [], responses: [], models: [], cookie: [], import: [], all: [] };
|
|
193
|
-
}
|
|
194
|
-
exports.createOpenApiResult = createOpenApiResult;
|
package/lib/openapi-parser.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { OpenAPIObject } from "openapi3-ts/oas31";
|
|
2
|
-
import { ParserOptions } from "@spec2ts/jsonschema/lib/core-parser";
|
|
3
|
-
import { ParseOpenApiResult } from "./core-parser";
|
|
4
|
-
export { ParseOpenApiResult };
|
|
5
|
-
export interface ParseOpenApiOptions extends ParserOptions {
|
|
6
|
-
lowerHeaders?: boolean;
|
|
7
|
-
enableDateForQueryParams?: boolean | "strict" | "lax";
|
|
8
|
-
}
|
|
9
|
-
export declare function parseOpenApiFile(file: string, options?: ParseOpenApiOptions): Promise<ParseOpenApiResult>;
|
|
10
|
-
export declare function parseOpenApi(spec: OpenAPIObject, options?: ParseOpenApiOptions): Promise<ParseOpenApiResult>;
|
package/lib/openapi-parser.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseOpenApi = exports.parseOpenApiFile = void 0;
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const json_schema_ref_parser_1 = require("@apidevtools/json-schema-ref-parser");
|
|
6
|
-
const core_parser_1 = require("@spec2ts/jsonschema/lib/core-parser");
|
|
7
|
-
const core_parser_2 = require("./core-parser");
|
|
8
|
-
async function parseOpenApiFile(file, options = {}) {
|
|
9
|
-
const schema = await json_schema_ref_parser_1.default.parse(file);
|
|
10
|
-
return parseOpenApi(schema, {
|
|
11
|
-
cwd: path.resolve(path.dirname(file)) + "/",
|
|
12
|
-
...options
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
exports.parseOpenApiFile = parseOpenApiFile;
|
|
16
|
-
async function parseOpenApi(spec, options = {}) {
|
|
17
|
-
var _a;
|
|
18
|
-
if (!options.parseReference) {
|
|
19
|
-
options.parseReference = core_parser_2.parseReference;
|
|
20
|
-
}
|
|
21
|
-
const context = await (0, core_parser_1.createContext)(spec, options);
|
|
22
|
-
const result = (0, core_parser_2.createOpenApiResult)();
|
|
23
|
-
Object.entries((_a = spec.paths) !== null && _a !== void 0 ? _a : {}).forEach(([path, item]) => {
|
|
24
|
-
(0, core_parser_2.parsePathItem)(path, item, context, result);
|
|
25
|
-
});
|
|
26
|
-
(0, core_parser_2.addToOpenApiResult)(result, "models", context.aliases);
|
|
27
|
-
return result;
|
|
28
|
-
}
|
|
29
|
-
exports.parseOpenApi = parseOpenApi;
|