Skip to content

Commit e708898

Browse files
authored
Merge pull request #5 from acacode/next
new version 1.2.5
2 parents e6d8bcc + 1d8f13b commit e708898

22 files changed

+2715
-41
lines changed

CHANGELOG.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 1.2.5
2+
Features: better naming of routes without `operationId`
3+
![route naming](./assets/changelog_assets/1.2.5_route_naming.jpg)
4+
Changes: rename `@security true` -> `@secure`, `@duplicate true` -> `@duplicate`
5+
Fixes: Support generated swagger schemes from tsoa 3.x with complex types (Omit, Pick, etc)
6+
7+
# 1.2.4
8+
Features: add .d.ts file into npm package
9+
Changes: update help block in CLI
10+
Internal: add greenkeeper, update npm keywords
11+
12+
# 1.2.3
13+
Features: @summary, @description comments at each route
14+
Fixes: parsing schema without routes
15+
Changes: update documentation
16+
Internal: add anyOf, allOf test schemas, slack notifications in CI
17+
18+
# 1.2.2
19+
Fixes: fix complex types (oneOf, anyOf), required fields of object type was not required
20+
21+
# 1.2.0
22+
Changes: rename `ApiParams` to `RequestParams`, secure module always exist in generated API module, update documentation
23+
Fixes: Query params was all required, parse yaml files, typescript minor warnings (;)
24+
Internal: test schemas + manual testing, add travis CI/CD
25+
26+
# 1.1.0
27+
Fixes: catching http errors with use API module
28+
29+
# 1.0.9
30+
Features: add description to interfaces and their fields
31+
Changes: update documentation
32+
33+
# 1.0.8
34+
Changes: update documentation
35+
36+
# 1.0.7
37+
Changes: update documentation (+ add logo), add comment about author in generated module
38+
39+
# 1.0.6
40+
Fixes: route naming, http(s) requests for getting swagger schema, integer enums
41+
Changes: include only required files into npm pacakge
42+
43+
# 1.0.5
44+
Changes: update documentation
45+
46+
# 1.0.4
47+
Changes: disable linters rules for generated API module
48+
Fixes: TS issues in template
49+
50+
# 1.0.3
51+
Fixes: NodeJS main script cannot been called on Unix* machines
52+
Changes: add LICENSE, update README
53+
54+
# 1.0.2
55+
Changes(Internal): change dependencies
56+
57+
# 1.0.1
58+
New features: query params, separating routes on submodules, common params in constructor, swagger v2 + yaml parsers
59+
Enhancements: better type extracting.
60+
Fixes: mustache escaping chars
61+
Changes: order of request params, emojis messages in console
62+
63+
# 1.0.0
64+
Initial project.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# swagger-typescript-api
22

33
[![Greenkeeper badge](https://badges.greenkeeper.io/acacode/swagger-typescript-api.svg)](https://greenkeeper.io/)
4+
[![NPM badge](https://img.shields.io/npm/v/swagger-typescript-api.svg)](https://www.npmjs.com/package/swagger-typescript-api)
45

5-
<img src="https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/swagger-typescript-api-logo1.png" align="left"
6+
<img src="https://raw.githubusercontent.com/acacode/swagger-typescript-api/master/assets/swagger-typescript-api-logo.png" align="left"
67
title="swagger-typescript-api logo by js2me" width="93" height="180">
78

89
Generate api via swagger scheme.
@@ -16,6 +17,8 @@ Any questions you can ask [**here**](https://github.com/acacode/swagger-typescri
1617

1718
<br>
1819

20+
![](./assets/components-converter-example.jpg)
21+
1922
## 👀 Examples
2023

2124
All examples you can find [**here**](https://github.com/acacode/swagger-typescript-api/tree/master/tests)
148 KB
Loading
63.8 KB
Loading
13.9 KB
Loading
-14 KB
Binary file not shown.

src/modelNames.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
const checkAndRenameModelName = name => {
3+
4+
if (!/^([A-Za-z$_]{1,})$/g.test(name)) {
5+
// specific replaces for TSOA 3.x
6+
7+
if (name.includes('.'))
8+
name = name
9+
.replace(/Exclude_keyof[A-Za-z]{1,}/g, match => 'ExcludeKeys')
10+
.replace(/%22\~AND\~%22/g, 'And')
11+
.replace(/%22\~OR\~%22/g, 'Or')
12+
.replace(/(\.?%22)|\./g, '_')
13+
.replace(/__+$/, '');
14+
}
15+
16+
return name;
17+
}
18+
19+
module.exports = {
20+
checkAndRenameModelName
21+
}

src/modelTypes.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const _ = require('lodash');
22
const { formatters } = require("./typeFormatters");
3+
const { checkAndRenameModelName } = require("./modelNames");
34

45
const CONTENT_KEYWORD = '__CONTENT__';
56

@@ -10,12 +11,13 @@ const contentWrapersByTypeIdentifier = {
1011
}
1112

1213
// { typeIdentifier, name, content, type }
13-
const getModelType = ({ typeIdentifier, name, content, type, description }) => {
14+
const getModelType = ({ typeIdentifier, name: originalName, content, type, description }) => {
1415
if (!contentWrapersByTypeIdentifier[typeIdentifier]) {
1516
throw new Error(`${typeIdentifier} - type identifier is unknown for this utility`)
1617
}
1718

1819
const resultContent = formatters[type] ? formatters[type](content) : content;
20+
const name = checkAndRenameModelName(originalName);
1921

2022
return {
2123
typeIdentifier,
@@ -26,7 +28,7 @@ const getModelType = ({ typeIdentifier, name, content, type, description }) => {
2628
}
2729
}
2830

29-
3031
module.exports = {
3132
getModelType,
32-
}
33+
checkAndRenameModelName,
34+
}

src/routes.js

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
const _ = require("lodash");
22
const { parseSchema } = require("./schema");
3+
const { checkAndRenameModelName } = require("./modelNames");
34
const { inlineExtraFormatters } = require("./typeFormatters");
45

6+
const methodAliases = {
7+
get: (pathName, hasPathInserts) => _.camelCase(`${pathName}_${hasPathInserts ? 'detail': 'list'}`),
8+
post: (pathName, hasPathInserts) => _.camelCase(`${pathName}_create`),
9+
put: (pathName, hasPathInserts) => _.camelCase(`${pathName}_update`),
10+
patch: (pathName, hasPathInserts) => _.camelCase(`${pathName}_partial_update`),
11+
delete: (pathName, hasPathInserts) => _.camelCase(`${pathName}_delete`)
12+
}
13+
514
const getTypeFromRequestInfo = (requestInfo, parsedSchemas, contentType) => {
615
// TODO: make more flexible pick schema without content type
716
const schema = _.get(requestInfo, `content["${contentType}"].schema`);
@@ -10,7 +19,8 @@ const getTypeFromRequestInfo = (requestInfo, parsedSchemas, contentType) => {
1019
const extractedSchema = _.get(schema, 'additionalProperties', schema);
1120
const { content } = parseSchema(extractedSchema, 'none', inlineExtraFormatters);
1221
const foundSchema = _.find(parsedSchemas, parsedSchema => _.isEqual(parsedSchema.content, content))
13-
return foundSchema ? foundSchema.name : content;
22+
23+
return foundSchema ? foundSchema.name : checkAndRenameModelName(content);
1424
}
1525

1626
return 'any';
@@ -20,14 +30,17 @@ const findSuccessResponse = (responses) => {
2030
return _.find(responses, (v, status) => status === 'default' || (+status >= 200 && +status < 300))
2131
}
2232

33+
const createCustomOperationId = (method, route, moduleName) => {
34+
const hasPathInserts = /\{(\w){1,}\}/g.test(route);
35+
const splitedRouteBySlash = _.replace(route, /\{(\w){1,}\}/g, '').split('/').filter(Boolean);
36+
const routeParts = (splitedRouteBySlash.length > 1 ? splitedRouteBySlash.splice(1) : splitedRouteBySlash).join('_');
37+
return routeParts.length > 3 && methodAliases[method] ? methodAliases[method](routeParts, hasPathInserts) : _.camelCase(_.lowerCase(method) + '_' + ([moduleName]).join('_')) || 'index'
38+
}
39+
2340
const getRouteName = (operationId, method, route, moduleName) => {
2441
if (operationId) return operationId;
2542
if (route === '/') return `${_.lowerCase(method)}Root`;
26-
27-
const routeParts = _.replace(route, /\{(\w){1,}\}/g, '').split('/').filter(Boolean);
28-
29-
// create route name via method and route
30-
return _.camelCase(_.lowerCase(method) + '_' + (moduleName ? routeParts.splice(1) : routeParts).join('_')) || 'index'
43+
return createCustomOperationId(method, route, moduleName);
3144
}
3245

3346
const parseRoutes = (routes, parsedSchemas) =>
@@ -159,7 +172,7 @@ const groupRoutes = routes => {
159172
`🥵 This method has been renamed to "${route.name + (duplicates[route.moduleName][route.name] + 1)}()" to solve conflict names.`
160173
)
161174
route.comments.push(`@originalName ${route.name}`)
162-
route.comments.push(`@duplicate true`)
175+
route.comments.push(`@duplicate`)
163176
route.name += ++duplicates[route.moduleName][route.name];
164177
}
165178

@@ -171,21 +184,37 @@ const groupRoutes = routes => {
171184
return modules
172185
}, {
173186
$outOfModule: []
174-
}), (shuffle, packRoutes, moduleName) => {
175-
187+
}), (acc, packRoutes, moduleName) => {
188+
189+
// if (moduleName === "$outOfModule") {
190+
// acc.outOfModule.push(...routes)
191+
// } else {
192+
// if (routes.length === 1) {
193+
// const route = routes[0]
194+
// acc.outOfModule.push({
195+
// ...route,
196+
// name: route.name === _.lowerCase(route.name) ? moduleName : route.name,
197+
// })
198+
// } else {
199+
// acc.combined.push({
200+
// moduleName,
201+
// routes: routes,
202+
// })
203+
// }
204+
// }
176205

177206
if (moduleName === "$outOfModule") {
178-
shuffle['outOfModule'] = packRoutes
207+
acc.outOfModule = packRoutes
179208
} else {
180-
if (!shuffle.combined) shuffle.combined = []
209+
if (!acc.combined) acc.combined = []
181210

182-
shuffle.combined.push({
211+
acc.combined.push({
183212
moduleName,
184213
routes: packRoutes,
185214
})
186215
}
187216

188-
return shuffle;
217+
return acc;
189218
}, {})
190219
}
191220

src/schema.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const findSchemaType = schema => {
1515
const typeAliases = {
1616
"integer": "number",
1717
}
18-
const getTypeAlias = type => typeAliases[type] || type || 'any'
18+
const getPrimitiveType = type => typeAliases[type] || type || 'any'
1919

2020
const specificObjectTypes = {
2121
'array': ({ items }) => {
@@ -25,7 +25,7 @@ const specificObjectTypes = {
2525
}
2626
const getRefType = (ref) => _.last(_.split(ref, '/'))
2727
const getType = (property) => {
28-
const func = specificObjectTypes[property.type] || (() => getTypeAlias(property.type))
28+
const func = specificObjectTypes[property.type] || (() => getPrimitiveType(property.type))
2929
return property["$ref"] ? getRefType(property["$ref"]) : func(property)
3030
}
3131
const getObjectTypeContent = (properties) => {
@@ -73,7 +73,7 @@ const getComplexType = (schema) => {
7373

7474
const schemaParsers = {
7575
'enum': (schema, typeName) => {
76-
const type = getTypeAlias(schema.type);
76+
const type = getPrimitiveType(schema.type);
7777
const isIntegerEnum = type === "number";
7878
return {
7979
type: isIntegerEnum ? "intEnum" : 'enum',
@@ -136,4 +136,5 @@ const parseSchema = (schema, typeName, formattersMap) => {
136136
module.exports = {
137137
parseSchema,
138138
getType,
139+
getPrimitiveType,
139140
}

0 commit comments

Comments
 (0)