Skip to content

Commit a163999

Browse files
js2meJennieJi
andauthored
Release 1.12.0 (#77)
* fix: handling x-omitempty property for definition properties (#68) * Complete #69 add spec option to convert schema object (#70) * chore: rename exception message for specProperty test * fix: enums with spaces throw an error * chore: remove "const enum" from client.mustache * fix: problem of additional properties #76 * fix: problem of anyOf complex type (intersection of primitive ts types) * fix: problem of pattern fields treating as operations #75 * docs: update CHANGELOG * bump: update project version to 1.12.0 * fix: problem of typings "spec" property for generateApi function Co-authored-by: Jennie <[email protected]>
1 parent 7a23584 commit a163999

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2564
-1783
lines changed

.vscode/launch.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,23 @@
1010
"request": "launch",
1111
"cwd": "${workspaceFolder}",
1212
"runtimeExecutable": "npm",
13-
"runtimeArgs": ["run-script", "generate:debug"],
14-
"port": 9229
13+
"runtimeArgs": ["run-script", "generate:debug"]
1514
},
1615
{
1716
"name": "Debug JSON CLI",
1817
"type": "node",
1918
"request": "launch",
2019
"cwd": "${workspaceFolder}",
2120
"runtimeExecutable": "npm",
22-
"runtimeArgs": ["run-script", "cli:debug:json"],
23-
"port": 9229
21+
"runtimeArgs": ["run-script", "cli:debug:json"]
2422
},
2523
{
2624
"name": "Debug YAML CLI",
2725
"type": "node",
2826
"request": "launch",
2927
"cwd": "${workspaceFolder}",
3028
"runtimeExecutable": "npm",
31-
"runtimeArgs": ["run-script", "cli:debug:yaml"],
32-
"port": 9229
29+
"runtimeArgs": ["run-script", "cli:debug:yaml"]
3330
}
3431
]
3532
}

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
# next release
22

33

4+
# 1.12.0
5+
6+
Features:
7+
- Can provide ability to generate from swagger JSON directly not from a file? #69 (Thanks @JennieJi)
8+
9+
Fixes:
10+
- handling `x-omitempty` property for definition properties #68
11+
- Additional properties map to empty interfaces (OpenAPI v3) #76
12+
- Pattern fields in Path Item Object are treated as operations #75
13+
- Remove const enum from default template #73
14+
- enums with spaces throw an error #71
15+
16+
417
# 1.11.0
518

619
Features:

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,29 @@ generateApi({
7171
.then(sourceFile => fs.writeFile(path, sourceFile))
7272
.catch(e => console.error(e))
7373

74+
// example with parsed schema
75+
generateApi({
76+
name: "ApiModule.ts", // name of output typescript file
77+
spec: {
78+
swagger: "2.0",
79+
info: {
80+
version: "1.0.0",
81+
title: "Swagger Petstore",
82+
},
83+
host: "petstore.swagger.io",
84+
basePath: "/api",
85+
schemes: ["http"],
86+
consumes: ["application/json"],
87+
produces: ["application/json"],
88+
paths: {
89+
// ...
90+
}
91+
// ...
92+
}
93+
})
94+
.then(sourceFile => fs.writeFile(path, sourceFile))
95+
.catch(e => console.error(e))
96+
7497
```
7598

7699
## 📄 Mass media

index.d.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ interface GenerateApiParams {
99
*/
1010
url: string;
1111

12+
/**
13+
* swagger schema JSON
14+
*/
15+
spec: import("swagger-schema-official").Spec;
16+
1217
/**
1318
* default 'api.ts'
1419
*/
@@ -47,5 +52,12 @@ interface GenerateApiParams {
4752
generateResponses?: boolean;
4853
}
4954

50-
export declare function generateApi(params: Omit<GenerateApiParams, "url">): Promise<string>;
51-
export declare function generateApi(params: Omit<GenerateApiParams, "input">): Promise<string>;
55+
export declare function generateApi(
56+
params: Omit<GenerateApiParams, "url" | "spec">,
57+
): Promise<string>;
58+
export declare function generateApi(
59+
params: Omit<GenerateApiParams, "input" | "spec">,
60+
): Promise<string>;
61+
export declare function generateApi(
62+
params: Omit<GenerateApiParams, "input" | "url">,
63+
): Promise<string>;

package-lock.json

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
{
22
"name": "swagger-typescript-api",
3-
"version": "1.11.0",
3+
"version": "1.12.0",
44
"description": "Create typescript api module from swagger schema",
55
"scripts": {
66
"cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
77
"cli:yaml": "node index.js -r -d -p ./swagger-test-cli.yaml -n swagger-test-cli.ts",
8-
"cli:debug:json": "node --nolazy --inspect-brk=9229 index.js -p ./swagger-test-cli.json -n swagger-test-cli.ts --union-enums",
9-
"cli:debug:yaml": "node --nolazy --inspect-brk=9229 index.js -p ./swagger-test-cli.yaml -n swagger-test-cli.ts",
8+
"cli:debug:json": "node --nolazy index.js -p ./swagger-test-cli.json -n swagger-test-cli.ts --union-enums",
9+
"cli:debug:yaml": "node --nolazy index.js -p ./swagger-test-cli.yaml -n swagger-test-cli.ts",
1010
"cli:help": "node index.js -h",
11-
"test:all": "npm-run-all generate validate test:routeTypes test:noClient test:defaultAsSuccess test:responses test:templates test:unionEnums --continue-on-error",
11+
"test:all": "npm-run-all generate validate test:routeTypes test:noClient test:defaultAsSuccess test:responses test:templates test:unionEnums test:specProperty --continue-on-error",
1212
"generate": "node tests/generate.js",
13-
"generate:debug": "node --nolazy --inspect-brk=9229 tests/generate.js",
13+
"generate:debug": "node --nolazy tests/generate.js",
1414
"validate": "node tests/validate.js",
15-
"validate:debug": "node --nolazy --inspect-brk=9229 tests/validate.js",
15+
"validate:debug": "node --nolazy tests/validate.js",
1616
"test:routeTypes": "node tests/spec/routeTypes/test.js",
1717
"test:noClient": "node tests/spec/noClient/test.js",
1818
"test:defaultAsSuccess": "node tests/spec/defaultAsSuccess/test.js",
1919
"test:templates": "node tests/spec/templates/test.js",
2020
"test:unionEnums": "node tests/spec/unionEnums/test.js",
21-
"test:responses": "node tests/spec/responses/test.js"
21+
"test:responses": "node tests/spec/responses/test.js",
22+
"test:specProperty": "node tests/spec/specProperty/test.js"
2223
},
2324
"author": "acacode",
2425
"license": "MIT",
@@ -34,12 +35,14 @@
3435
"typescript": "^3.9.3"
3536
},
3637
"dependencies": {
38+
"@types/swagger-schema-official": "2.0.21",
3739
"axios": "^0.19.2",
3840
"commander": "^5.1.0",
3941
"js-yaml": "^3.13.1",
4042
"lodash": "^4.17.15",
4143
"mustache": "^4.0.1",
4244
"prettier": "^2.0.5",
45+
"swagger-schema-official": "2.0.0-bab6bed",
4346
"swagger2openapi": "^6.0.3"
4447
},
4548
"bin": {

src/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const { parseSchemas } = require("./schema");
1414
const { parseRoutes, groupRoutes } = require("./routes");
1515
const { createApiConfig } = require("./apiConfig");
1616
const { getModelType } = require("./modelTypes");
17-
const { getSwaggerObject, fixSwaggerScheme } = require("./swagger");
17+
const { getSwaggerObject, fixSwaggerScheme, convertSwaggerObject } = require("./swagger");
1818
const { createComponentsMap, filterComponentsMap } = require("./components");
1919
const { createFile, pathIsExist } = require("./files");
2020
const { addToConfig, config } = require("./config");
@@ -34,6 +34,7 @@ module.exports = {
3434
input,
3535
output,
3636
url,
37+
spec,
3738
name,
3839
templates = resolve(__dirname, config.templates),
3940
generateResponses = config.generateResponses,
@@ -51,7 +52,7 @@ module.exports = {
5152
templates,
5253
generateUnionEnums,
5354
});
54-
getSwaggerObject(input, url)
55+
(spec ? convertSwaggerObject(spec) : getSwaggerObject(input, url))
5556
.then(({ usageSchema, originalSchema }) => {
5657
const { apiTemplate, clientTemplate, routeTypesTemplate } = getTemplates();
5758

src/routes.js

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,27 +170,36 @@ const convertRouteParamsIntoObject = (params) =>
170170
},
171171
);
172172

173+
const createRequestsMap = (requestInfoByMethodsMap) => {
174+
const parameters = _.get(requestInfoByMethodsMap, "parameters");
175+
176+
return _.reduce(
177+
requestInfoByMethodsMap,
178+
(acc, requestInfo, method) => {
179+
if (method.startsWith("x-") || ["parameters", "$ref"].includes(method)) {
180+
return acc;
181+
}
182+
183+
acc[method] = {
184+
...requestInfo,
185+
parameters: _.compact(_.concat(parameters, requestInfo.parameters)),
186+
};
187+
188+
return acc;
189+
},
190+
{},
191+
);
192+
};
193+
173194
const parseRoutes = ({ paths }, parsedSchemas) =>
174195
_.entries(paths).reduce((routes, [route, requestInfoByMethodsMap]) => {
175-
parameters = _.get(requestInfoByMethodsMap, "parameters");
176-
177-
// TODO: refactor that hell
178-
requestInfoByMethodsMap = _.reduce(
179-
_.omit(requestInfoByMethodsMap, "parameters"),
180-
(acc, requestInfo, method) => {
181-
acc[method] = {
182-
...requestInfo,
183-
parameters: _.compact(_.concat(parameters, requestInfo.parameters)),
184-
};
196+
if (route.startsWith("x-")) return routes;
185197

186-
return acc;
187-
},
188-
{},
189-
);
198+
const requestsMap = createRequestsMap(requestInfoByMethodsMap);
190199

191200
return [
192201
...routes,
193-
..._.map(requestInfoByMethodsMap, (requestInfo, method) => {
202+
..._.map(requestsMap, (requestInfo, method) => {
194203
const {
195204
operationId,
196205
requestBody,

src/schema.js

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const types = {
2828
// dateTime: "Date",
2929
};
3030

31+
const jsPrimitiveTypes = _.uniq(["number", "string", "boolean"]);
3132
const jsEmptyTypes = _.uniq(["null", "undefined"]);
3233
const formDataTypes = _.uniq([types.file, types.string.binary]);
3334

@@ -45,8 +46,8 @@ const getTypeAlias = (rawSchema) => {
4546
};
4647

4748
const getInternalSchemaType = (schema) => {
48-
if (schema.enum) return "enum";
49-
if (schema.properties) return "object";
49+
if (!_.isEmpty(schema.enum)) return "enum";
50+
if (!_.isEmpty(schema.properties)) return "object";
5051
if (schema.allOf || schema.oneOf || schema.anyOf || schema.not) return "complex";
5152

5253
return "primitive";
@@ -75,19 +76,26 @@ const getType = (schema) => {
7576
return primitiveType ? checkAndAddNull(schema, primitiveType) : DEFAULT_PRIMITIVE_TYPE;
7677
};
7778

79+
const isRequired = (property) => {
80+
if (property["x-omitempty"] === false) {
81+
return true;
82+
}
83+
84+
if (config.convertedFromSwagger2) {
85+
return typeof property.nullable === "undefined" ? property.required : !property.nullable;
86+
}
87+
return !!property.required;
88+
};
89+
7890
const getObjectTypeContent = (properties) => {
7991
return _.map(properties, (property, name) => {
80-
const isRequired = config.convertedFromSwagger2
81-
? typeof property.nullable === "undefined"
82-
? property.required
83-
: !property.nullable
84-
: !!property.required;
92+
const required = isRequired(property);
8593
return {
8694
$$raw: property,
8795
description: property.description,
88-
isRequired,
96+
isRequired: required,
8997
field: `${isValidName(name) ? name : `"${name}"`}${
90-
isRequired ? "" : "?"
98+
required ? "" : "?"
9199
}: ${getInlineParseContent(property)}`,
92100
};
93101
});
@@ -108,7 +116,9 @@ const complexSchemaParsers = {
108116
anyOf: (schema) => {
109117
// T1 | T2 | (T1 & T2)
110118
const combined = _.map(schema.anyOf, complexTypeGetter);
111-
const nonEmptyTypesCombined = combined.filter((type) => !jsEmptyTypes.includes(type));
119+
const nonEmptyTypesCombined = combined.filter(
120+
(type) => !jsEmptyTypes.includes(type) && !jsPrimitiveTypes.includes(type),
121+
);
112122
return checkAndAddNull(
113123
schema,
114124
`${combined.join(" | ")}` +
@@ -153,9 +163,9 @@ const schemaParsers = {
153163
name: typeName,
154164
description: formatDescription(schema.description),
155165
content: _.map(schema.enum, (key) => ({
156-
key,
166+
key: isIntegerEnum ? key : checkAndRenameModelName(key),
157167
type,
158-
value: isIntegerEnum ? `${key}` : `"${key}"`,
168+
value: key === null ? key : isIntegerEnum ? `${key}` : `"${key}"`,
159169
})),
160170
});
161171
},

0 commit comments

Comments
 (0)