Skip to content

Commit 9c59409

Browse files
committed
feat: ability to modify code gen constructs;
feat: --another-array-type cli option (Array<Type>); docs: update CHANGELOG, README
1 parent b26029c commit 9c59409

16 files changed

+369
-129
lines changed

CHANGELOG.md

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

3+
# 10.1.0
4+
**feature**
5+
everything which generate code gen about output typescript code now contains in [`src/code-gen-constructs`](src/code-gen-constructs.js).
6+
And this thing is available for end user modifications with using NodeJS Cli option `codeGenConstructs`.
7+
It contains almost all which is not contains in `.eta`\ `.ejs` templates. For example: `Record<string, any>`, `readonly typeField?: value`, etc
8+
9+
feat: `--another-array-type` cli option (#414)
10+
fix: path params with dot style (truck.id) (#413)
11+
12+
13+
314
# 10.0.3
415
fix: CRLF -> LF (#423)
516
docs: add docs for addReadonly nodeJS api flag (#425)

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Options:
7171
--clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
7272
--api-class-name <string> name of the api class
7373
--patch fix up small errors in the swagger source definition (default: false)
74+
--debug additional information about processes inside this tool (default: false)
75+
--another-array-type generate array types as Array<Type> (by default Type[]) (default: false)
7476
-h, --help display help for command
7577
```
7678

@@ -122,6 +124,11 @@ generateApi({
122124
generateUnionEnums: false,
123125
addReadonly: false,
124126
extraTemplates: [],
127+
anotherArrayType: false,
128+
codeGenConstructs: ({ Ts, JsDoc }) => ({
129+
Ts: { ...Ts, RecordType: (key, value) => `MyRecord<key, value>` },
130+
JsDoc: { ...JsDoc },
131+
}),
125132
hooks: {
126133
onCreateComponent: (component) => {},
127134
onCreateRequestParams: (rawType) => {},

index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const { Command } = require("commander");
1010
const { resolve } = require("path");
1111
const { generateApi } = require("./src");
1212
const { version, name: packageName } = require("./package.json");
13-
const { TS_KEYWORDS, HTTP_CLIENT } = require("./src/constants");
13+
const { HTTP_CLIENT } = require("./src/constants");
14+
const { Ts } = require("./src/code-gen-constructs");
1415

1516
const program = new Command(packageName);
1617

@@ -61,13 +62,14 @@ const options = program
6162
.option("--disable-throw-on-error", "Do not throw an error when response.ok is not true", false)
6263
.option("--single-http-client", "Ability to send HttpClient instance to Api constructor", false)
6364
.option("--silent", "Output only errors to console", false)
64-
.option("--default-response <type>", "default type for empty response schema", TS_KEYWORDS.VOID)
65+
.option("--default-response <type>", "default type for empty response schema", Ts.Keyword.Void)
6566
.option("--type-prefix <string>", "data contract name prefix", "")
6667
.option("--type-suffix <string>", "data contract name suffix", "")
6768
.option("--clean-output", "clean output folder before generate api. WARNING: May cause data loss", false)
6869
.option("--api-class-name <string>", "name of the api class")
6970
.option("--patch", "fix up small errors in the swagger source definition", false)
7071
.option("--debug", "additional information about processes inside this tool", false)
72+
.option("--another-array-type", "generate array types as Array<Type> (by default Type[])", false)
7173
.parse(process.argv)
7274
.opts();
7375

@@ -107,6 +109,7 @@ generateApi({
107109
patch: !!options.patch,
108110
apiClassName: options.apiClassName,
109111
debug: options.debug,
112+
anotherArrayType: options.anotherArrayType,
110113
}).catch((err) => {
111114
// NOTE collect all errors on top level and shows to users in any case
112115
console.error(err);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"test:--js": "node tests/spec/js/test.js",
4242
"test:--js--axios": "node tests/spec/jsAxios/test.js",
4343
"test:--axios": "node tests/spec/axios/test.js",
44+
"test:--another-array-type": "node tests/spec/another-array-type/test.js",
4445
"test:--object-types": "node tests/spec/object-types/test.js",
4546
"test:--axios--single-http-client": "node tests/spec/axiosSingleHttpClient/test.js",
4647
"test:--type-suffix--type-prefix": "node tests/spec/typeSuffixPrefix/test.js",

src/code-gen-constructs.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
const _ = require("lodash");
2+
3+
const Keyword = {
4+
Number: "number",
5+
String: "string",
6+
Boolean: "boolean",
7+
Any: "any",
8+
Void: "void",
9+
Unknown: "unknown",
10+
Null: "null",
11+
Undefined: "undefined",
12+
Object: "object",
13+
File: "File",
14+
Date: "Date",
15+
Type: "type",
16+
Enum: "enum",
17+
Interface: "interface",
18+
Array: "Array",
19+
Record: "Record",
20+
Intersection: "&",
21+
Union: "|",
22+
};
23+
24+
const CodeGenKeyword = {
25+
UtilRequiredKeys: "UtilRequiredKeys",
26+
};
27+
28+
const Ts = {
29+
Keyword,
30+
CodeGenKeyword,
31+
/**
32+
* $A[] or Array<$A>
33+
*/
34+
ArrayType: (content) => {
35+
const { config } = require("./config");
36+
37+
if (config.anotherArrayType) {
38+
return Ts.TypeWithGeneric(Ts.Keyword.Array, [content]);
39+
}
40+
41+
return `${Ts.ExpressionGroup(content)}[]`;
42+
},
43+
/**
44+
* "$A"
45+
*/
46+
StringValue: (content) => `"${content}"`,
47+
/**
48+
* $A
49+
*/
50+
BooleanValue: (content) => `${content}`,
51+
/**
52+
* $A
53+
*/
54+
NumberValue: (content) => `${content}`,
55+
/**
56+
* $A
57+
*/
58+
NullValue: (content) => content,
59+
/**
60+
* $A1 | $A2
61+
*/
62+
UnionType: (contents) => _.join(_.uniq(contents), ` ${Ts.Keyword.Union} `),
63+
/**
64+
* ($A1)
65+
*/
66+
ExpressionGroup: (content) => (content ? `(${content})` : ""),
67+
/**
68+
* $A1 & $A2
69+
*/
70+
IntersectionType: (contents) => _.join(_.uniq(contents), ` ${Ts.Keyword.Intersection} `),
71+
/**
72+
* Record<$A1, $A2>
73+
*/
74+
RecordType: (key, value) => Ts.TypeWithGeneric(Ts.Keyword.Record, [key, value]),
75+
/**
76+
* readonly $key?:$value
77+
*/
78+
TypeField: ({ readonly, key, optional, value }) =>
79+
_.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
80+
/**
81+
* [key: $A1]: $A2
82+
*/
83+
InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
84+
/**
85+
* $A1 = $A2
86+
*/
87+
EnumField: (key, value) => `${key} = ${value}`,
88+
/**
89+
* $A0.key = $A0.value,
90+
* $A1.key = $A1.value,
91+
* $AN.key = $AN.value,
92+
*/
93+
EnumFieldsWrapper: (contents) => _.map(contents, ({ key, value }) => ` ${Ts.EnumField(key, value)}`).join(",\n"),
94+
/**
95+
* {\n $A \n}
96+
*/
97+
ObjectWrapper: (content) => `{\n${content}\n}`,
98+
/**
99+
* /** $A *\/
100+
*/
101+
MultilineComment: (contents, formatFn) =>
102+
[
103+
...(contents.length === 1
104+
? [`/** ${contents[0]} */`]
105+
: ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
106+
].map((part) => `${formatFn ? formatFn(part) : part}\n`),
107+
/**
108+
* $A1<...$A2.join(,)>
109+
*/
110+
TypeWithGeneric: (typeName, genericArgs) => {
111+
return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
112+
},
113+
};
114+
115+
const JsDoc = {
116+
Deprecated: "@deprecated",
117+
Format: "@format",
118+
Min: "@min",
119+
Max: "@max",
120+
Pattern: "@pattern",
121+
Example: "@example",
122+
Description: "",
123+
Title: "",
124+
TextLine: (key, text) => _.compact([key, `${text === undefined ? "" : text}`]).join(" "),
125+
ObjectFieldDescription: ({ title, description, deprecated, format, minimum, maximum, pattern, example }) => {
126+
return _.compact([
127+
JsDoc.TextLine(JsDoc.Title, title),
128+
JsDoc.TextLine(JsDoc.Description, description),
129+
!_.isUndefined(deprecated) && JsDoc.Deprecated,
130+
!_.isUndefined(format) && JsDoc.TextLine(JsDoc.Format, format),
131+
!_.isUndefined(minimum) && JsDoc.TextLine(JsDoc.Min, minimum),
132+
!_.isUndefined(maximum) && JsDoc.TextLine(JsDoc.Max, maximum),
133+
!_.isUndefined(pattern) && JsDoc.TextLine(JsDoc.Pattern, pattern),
134+
!_.isUndefined(example) && JsDoc.TextLine(JsDoc.Example, _.isObject(example) ? JSON.stringify(example) : example),
135+
]).join("\n");
136+
},
137+
};
138+
139+
module.exports = {
140+
Ts,
141+
JsDoc,
142+
};

src/config.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
const { HTTP_CLIENT, TS_KEYWORDS, PRETTIER_OPTIONS } = require("./constants");
1+
const { HTTP_CLIENT, PRETTIER_OPTIONS } = require("./constants");
22
const { NameResolver } = require("./utils/resolveName");
33
const packageJson = require("../package.json");
4+
const { Ts } = require("./code-gen-constructs");
45

56
const config = {
67
version: packageJson.version,
@@ -61,7 +62,7 @@ const config = {
6162
onFormatTypeName: (typeName, rawTypeName) => {},
6263
onFormatRouteName: (routeInfo, templateRouteName) => {},
6364
},
64-
defaultResponseType: TS_KEYWORDS.VOID,
65+
defaultResponseType: Ts.Keyword.Void,
6566
singleHttpClient: false,
6667
httpClientType: HTTP_CLIENT.FETCH,
6768
unwrapResponseData: false,
@@ -96,6 +97,7 @@ const config = {
9697
/** name of the main exported class */
9798
apiClassName: "Api",
9899
debug: false,
100+
anotherArrayType: false,
99101
internalTemplateOptions: {
100102
addUtilRequiredKeysType: false,
101103
},

src/constants.js

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,7 @@
1-
const TS_KEYWORDS = {
2-
NUMBER: "number",
3-
STRING: "string",
4-
BOOLEAN: "boolean",
5-
ANY: "any",
6-
VOID: "void",
7-
UNKNOWN: "unknown",
8-
NULL: "null",
9-
UNDEFINED: "undefined",
10-
OBJECT: "object",
11-
FILE: "File",
12-
DATE: "Date",
13-
TYPE: "type",
14-
ENUM: "enum",
15-
INTERFACE: "interface",
16-
TYPE_AND_OPERATOR: " & ",
17-
TYPE_OR_OPERATOR: " | ",
18-
};
19-
20-
const TS_EXTERNAL = {
21-
RECORD: "Record<string, any>",
22-
};
1+
const { Ts } = require("./code-gen-constructs");
232

24-
const JS_PRIMITIVE_TYPES = [TS_KEYWORDS.NUMBER, TS_KEYWORDS.STRING, TS_KEYWORDS.BOOLEAN];
25-
const JS_EMPTY_TYPES = [TS_KEYWORDS.NULL, TS_KEYWORDS.UNDEFINED];
3+
const JS_PRIMITIVE_TYPES = [Ts.Keyword.Number, Ts.Keyword.String, Ts.Keyword.Boolean];
4+
const JS_EMPTY_TYPES = [Ts.Keyword.Null, Ts.Keyword.Undefined];
265

276
const RESERVED_QUERY_ARG_NAMES = ["query", "queryParams", "queryArg"];
287
const RESERVED_BODY_ARG_NAMES = ["data", "body", "reqBody"];
@@ -51,11 +30,9 @@ const HTTP_CLIENT = {
5130

5231
module.exports = {
5332
DEFAULT_BODY_ARG_NAME: "data",
54-
SUCCESS_RESPONSE_STATUS_RANGE: [200, 300],
33+
SUCCESS_RESPONSE_STATUS_RANGE: [200, 299],
5534
JS_PRIMITIVE_TYPES,
5635
JS_EMPTY_TYPES,
57-
TS_KEYWORDS,
58-
TS_EXTERNAL,
5936
SCHEMA_TYPES,
6037
HTTP_CLIENT,
6138
RESERVED_QUERY_ARG_NAMES,

src/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const formatFileContent = require("./formatFileContent");
2222
const { logger } = require("./logger");
2323
const { ComponentTypeNameResolver } = require("./utils/resolveName");
2424
const { getPrettierOptions } = require("./prettierOptions");
25+
const CodeGenConstructs = require("./code-gen-constructs");
2526

2627
module.exports = {
2728
constants: constants,
@@ -66,8 +67,18 @@ module.exports = {
6667
authorizationToken,
6768
apiClassName = config.apiClassName,
6869
debug = config.debug,
70+
anotherArrayType = config.anotherArrayType,
71+
codeGenConstructs,
6972
}) =>
7073
new Promise((resolve, reject) => {
74+
const patchedCodeGenConstructs = codeGenConstructs ? codeGenConstructs(CodeGenConstructs) : CodeGenConstructs;
75+
if (patchedCodeGenConstructs.Ts) {
76+
Object.assign(CodeGenConstructs.Ts, patchedCodeGenConstructs.Ts);
77+
}
78+
if (patchedCodeGenConstructs.JsDoc) {
79+
Object.assign(CodeGenConstructs.JsDoc, patchedCodeGenConstructs.JsDoc);
80+
}
81+
7182
addToConfig({
7283
defaultResponseAsSuccess,
7384
generateRouteTypes,
@@ -103,6 +114,7 @@ module.exports = {
103114
patch,
104115
apiClassName,
105116
debug,
117+
anotherArrayType,
106118
});
107119
(spec
108120
? convertSwaggerObject(spec, { patch })

src/render/utils/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ const {
1010
} = require("../../schema");
1111
const { formatters, inlineExtraFormatters } = require("../../typeFormatters");
1212
const { NameResolver } = require("../../utils/resolveName");
13+
const { Ts, JsDoc } = require("../../code-gen-constructs");
1314

1415
module.exports = {
16+
Ts,
17+
JsDoc,
1518
formatDescription,
1619
internalCase,
1720
classNameCase,

0 commit comments

Comments
 (0)