Skip to content

Commit 2d7925e

Browse files
committed
bump: 11.0.0; refactor: codebase of project, data-contract-jsdoc.ejs incompatible with prev version, see CHANGELOG
1 parent 9c59409 commit 2d7925e

File tree

120 files changed

+34611
-39382
lines changed

Some content is hidden

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

120 files changed

+34611
-39382
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
* text=auto
22
*.js text eol=lf
3+
*.mjs text eol=lf
34
*.jsx text eol=lf
45
*.ts text eol=lf
56
*.tsx text eol=lf

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
tests/**/*.ts
22
tests/**/schema.js
3+
tests/**/schema.ts
34
tests/**/*.d.js
45
swagger-test-cli
56
swagger-test-cli.*

CHANGELOG.md

Lines changed: 187 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,195 @@
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).
3+
# 11.0.0
4+
5+
## Breaking changes
6+
7+
- `data-contract-jsdoc.ejs` file uses new input structure. Please update your local copy.
8+
- new codebase (class way)
9+
- ability to change everything in codegen process configuration with using NodeJS Api
10+
- ability to call `generateApi` function 2 and more times per 1 NodeJS process.
11+
12+
## [feature] Ability to modify internal codegen typescript structs
13+
Everything which creates codegen about output typescript code now contains in `Ts` field in [`src/configuration`](src/configuration.js).
614
And this thing is available for end user modifications with using NodeJS Cli option `codeGenConstructs`.
715
It contains almost all which is not contains in `.eta`\ `.ejs` templates. For example: `Record<string, any>`, `readonly typeField?: value`, etc
816

17+
Structure of `Ts` property
18+
```ts
19+
const Ts = {
20+
Keyword: {
21+
Number: "number",
22+
String: "string",
23+
Boolean: "boolean",
24+
Any: "any",
25+
Void: "void",
26+
Unknown: "unknown",
27+
Null: "null",
28+
Undefined: "undefined",
29+
Object: "object",
30+
File: "File",
31+
Date: "Date",
32+
Type: "type",
33+
Enum: "enum",
34+
Interface: "interface",
35+
Array: "Array",
36+
Record: "Record",
37+
Intersection: "&",
38+
Union: "|",
39+
},
40+
CodeGenKeyword: {
41+
UtilRequiredKeys: "UtilRequiredKeys",
42+
},
43+
/**
44+
* $A[] or Array<$A>
45+
*/
46+
ArrayType: (content) => {
47+
if (this.anotherArrayType) {
48+
return Ts.TypeWithGeneric(Ts.Keyword.Array, [content]);
49+
}
50+
51+
return `${Ts.ExpressionGroup(content)}[]`;
52+
},
53+
/**
54+
* "$A"
55+
*/
56+
StringValue: (content) => `"${content}"`,
57+
/**
58+
* $A
59+
*/
60+
BooleanValue: (content) => `${content}`,
61+
/**
62+
* $A
63+
*/
64+
NumberValue: (content) => `${content}`,
65+
/**
66+
* $A
67+
*/
68+
NullValue: (content) => content,
69+
/**
70+
* $A1 | $A2
71+
*/
72+
UnionType: (contents) => _.join(_.uniq(contents), ` ${Ts.Keyword.Union} `),
73+
/**
74+
* ($A1)
75+
*/
76+
ExpressionGroup: (content) => (content ? `(${content})` : ""),
77+
/**
78+
* $A1 & $A2
79+
*/
80+
IntersectionType: (contents) => _.join(_.uniq(contents), ` ${Ts.Keyword.Intersection} `),
81+
/**
82+
* Record<$A1, $A2>
83+
*/
84+
RecordType: (key, value) => Ts.TypeWithGeneric(Ts.Keyword.Record, [key, value]),
85+
/**
86+
* readonly $key?:$value
87+
*/
88+
TypeField: ({ readonly, key, optional, value }) =>
89+
_.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
90+
/**
91+
* [key: $A1]: $A2
92+
*/
93+
InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
94+
/**
95+
* $A1 = $A2
96+
*/
97+
EnumField: (key, value) => `${key} = ${value}`,
98+
/**
99+
* $A0.key = $A0.value,
100+
* $A1.key = $A1.value,
101+
* $AN.key = $AN.value,
102+
*/
103+
EnumFieldsWrapper: (contents) =>
104+
_.map(contents, ({ key, value }) => ` ${Ts.EnumField(key, value)}`).join(",\n"),
105+
/**
106+
* {\n $A \n}
107+
*/
108+
ObjectWrapper: (content) => `{\n${content}\n}`,
109+
/**
110+
* /** $A *\/
111+
*/
112+
MultilineComment: (contents, formatFn) =>
113+
[
114+
...(contents.length === 1
115+
? [`/** ${contents[0]} */`]
116+
: ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
117+
].map((part) => `${formatFn ? formatFn(part) : part}\n`),
118+
/**
119+
* $A1<...$A2.join(,)>
120+
*/
121+
TypeWithGeneric: (typeName, genericArgs) => {
122+
return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
123+
},
124+
}
125+
```
126+
127+
## [feature] Ability to modify swagger schema type/format to typescript construction translators
128+
Swagger schema has constructions like `{ "type": "string" | "integer" | etc, "format": "date-time" | "float" | "etc" }` where field `type` is not "readable" for TypeScript.
129+
And because of this `swagger-typescript-api` has key value group to translate swagger schema fields `type`/`format` to TypeScript constructions.
130+
See more about [swagger schema type/format data here](https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times)
131+
For example, current version of default configuration translates this schema
132+
```json
133+
{
134+
"type": "string",
135+
"format": "date-time"
136+
}
137+
```
138+
translates to
139+
```ts
140+
string
141+
```
142+
If you need to see `Date` otherwise `string` you are able to change it with using `primitiveTypeConstructs`
143+
```ts
144+
generateApiForTest({
145+
// ...
146+
primitiveTypeConstructs: (construct) => ({
147+
string: {
148+
'date-time': 'Date'
149+
}
150+
})
151+
})
152+
```
153+
154+
Structure of `primitiveTypes` property
155+
```ts
156+
const primitiveTypes = {
157+
integer: () => Ts.Keyword.Number,
158+
number: () => Ts.Keyword.Number,
159+
boolean: () => Ts.Keyword.Boolean,
160+
object: () => Ts.Keyword.Object,
161+
file: () => Ts.Keyword.File,
162+
string: {
163+
$default: () => Ts.Keyword.String,
164+
165+
/** formats */
166+
binary: () => Ts.Keyword.File,
167+
file: () => Ts.Keyword.File,
168+
"date-time": () => Ts.Keyword.String,
169+
time: () => Ts.Keyword.String,
170+
date: () => Ts.Keyword.String,
171+
duration: () => Ts.Keyword.String,
172+
email: () => Ts.Keyword.String,
173+
"idn-email": () => Ts.Keyword.String,
174+
"idn-hostname": () => Ts.Keyword.String,
175+
ipv4: () => Ts.Keyword.String,
176+
ipv6: () => Ts.Keyword.String,
177+
uuid: () => Ts.Keyword.String,
178+
uri: () => Ts.Keyword.String,
179+
"uri-reference": () => Ts.Keyword.String,
180+
"uri-template": () => Ts.Keyword.String,
181+
"json-pointer": () => Ts.Keyword.String,
182+
"relative-json-pointer": () => Ts.Keyword.String,
183+
regex: () => Ts.Keyword.String,
184+
},
185+
array: ({ items, ...schemaPart }, parser) => {
186+
const content = parser.getInlineParseContent(items);
187+
return parser.checkAndAddNull(schemaPart, Ts.ArrayType(content));
188+
},
189+
}
190+
```
191+
192+
## Other
9193
feat: `--another-array-type` cli option (#414)
10194
fix: path params with dot style (truck.id) (#413)
11195

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,15 @@ generateApi({
125125
addReadonly: false,
126126
extraTemplates: [],
127127
anotherArrayType: false,
128-
codeGenConstructs: ({ Ts, JsDoc }) => ({
129-
Ts: { ...Ts, RecordType: (key, value) => `MyRecord<key, value>` },
130-
JsDoc: { ...JsDoc },
128+
codeGenConstructs: (constructs) => ({
129+
...constructs,
130+
RecordType: (key, value) => `MyRecord<key, value>`
131+
}),
132+
primitiveTypeConstructs: (constructs) => ({
133+
...constructs,
134+
string: {
135+
'date-time': 'Date'
136+
}
131137
}),
132138
hooks: {
133139
onCreateComponent: (component) => {},

index.d.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,63 @@ interface GenerateApiParamsBase {
127127
* generate readonly properties (default: false)
128128
*/
129129
addReadonly?: boolean;
130+
131+
primitiveTypeConstructs?: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>;
132+
133+
codeGenConstructs?: (struct: CodeGenConstruct) => Partial<CodeGenConstruct>;
130134
}
131135

136+
type CodeGenConstruct = {
137+
Keyword: {
138+
Number: string;
139+
String: string;
140+
Boolean: string;
141+
Any: string;
142+
Void: string;
143+
Unknown: string;
144+
Null: string;
145+
Undefined: string;
146+
Object: string;
147+
File: string;
148+
Date: string;
149+
Type: string;
150+
Enum: string;
151+
Interface: string;
152+
Array: string;
153+
Record: string;
154+
Intersection: string;
155+
Union: string;
156+
};
157+
CodeGenKeyword: {
158+
UtilRequiredKeys: string;
159+
};
160+
ArrayType: (content: any) => string;
161+
StringValue: (content: any) => string;
162+
BooleanValue: (content: any) => string;
163+
NumberValue: (content: any) => string;
164+
NullValue: (content: any) => string;
165+
UnionType: (content: any) => string;
166+
ExpressionGroup: (content: any) => string;
167+
IntersectionType: (content: any) => string;
168+
RecordType: (content: any) => string;
169+
TypeField: (content: any) => string;
170+
InterfaceDynamicField: (content: any) => string;
171+
EnumField: (content: any) => string;
172+
EnumFieldsWrapper: (content: any) => string;
173+
ObjectWrapper: (content: any) => string;
174+
MultilineComment: (content: any) => string;
175+
TypeWithGeneric: (content: any) => string;
176+
};
177+
178+
type PrimitiveTypeStructValue =
179+
| string
180+
| ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
181+
182+
type PrimitiveTypeStruct = Record<
183+
"integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
184+
string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
185+
>;
186+
132187
interface GenerateApiParamsFromPath extends GenerateApiParamsBase {
133188
/**
134189
* path to swagger schema
@@ -324,6 +379,12 @@ export interface GenerateApiConfiguration {
324379
hasDescription: boolean;
325380
};
326381
config: {
382+
input: string;
383+
output: string;
384+
url: string;
385+
spec: any;
386+
fileName: string;
387+
authorizationToken?: string;
327388
generateResponses: boolean;
328389
defaultResponseAsSuccess: boolean;
329390
generateRouteTypes: boolean;
@@ -335,10 +396,35 @@ export interface GenerateApiConfiguration {
335396
convertedFromSwagger2: boolean;
336397
moduleNameIndex: number;
337398
moduleNameFirstTag: boolean;
399+
extraTemplates: { name: string; path: string }[];
338400
disableStrictSSL: boolean;
339401
disableProxy: boolean;
340402
extractRequestParams: boolean;
341403
unwrapResponseData: boolean;
404+
sortTypes: boolean;
405+
singleHttpClient: boolean;
406+
typePrefix: string;
407+
typeSuffix: string;
408+
patch: boolean;
409+
cleanOutput: boolean;
410+
debug: boolean;
411+
anotherArrayType: boolean;
412+
extractRequestBody: boolean;
413+
httpClientType: "axios" | "fetch";
414+
addReadonly: boolean;
415+
extractResponseBody: boolean;
416+
extractResponseError: boolean;
417+
defaultResponseType: boolean;
418+
toJS: boolean;
419+
disableThrowOnError: boolean;
420+
silent: boolean;
421+
hooks: Hooks;
422+
enumNamesAsValues: boolean;
423+
version: string;
424+
internalTemplateOptions: {
425+
addUtilRequiredKeysType: boolean;
426+
};
427+
componentTypeNameResolver: typeof import("./src/util/name-resolver").ComponentTypeNameResolver;
342428
fileNames: {
343429
dataContracts: string;
344430
routeTypes: string;
@@ -351,6 +437,11 @@ export interface GenerateApiConfiguration {
351437
httpClient: string;
352438
routeTypes: string;
353439
routeName: string;
440+
dataContractJsDoc: string;
441+
interfaceDataContract: string;
442+
typeDataContract: string;
443+
enumDataContract: string;
444+
objectFieldJsDoc: string;
354445
};
355446
routeNameDuplicatesMap: Map<string, string>;
356447
apiClassName: string;
@@ -371,7 +462,9 @@ export interface GenerateApiConfiguration {
371462
utils: {
372463
formatDescription: (description: string, inline?: boolean) => string;
373464
internalCase: (value: string) => string;
465+
/** @deprecated */
374466
classNameCase: (value: string) => string;
467+
pascalCase: (value: string) => string;
375468
getInlineParseContent: (rawTypeData: SchemaComponent["rawTypeData"], typeName?: string) => string;
376469
getParseContent: (rawTypeData: SchemaComponent["rawTypeData"], typeName?: string) => ModelType;
377470
getComponentByRef: (ref: string) => SchemaComponent;

index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ const { resolve } = require("path");
1111
const { generateApi } = require("./src");
1212
const { version, name: packageName } = require("./package.json");
1313
const { HTTP_CLIENT } = require("./src/constants");
14-
const { Ts } = require("./src/code-gen-constructs");
1514

1615
const program = new Command(packageName);
1716

@@ -62,7 +61,7 @@ const options = program
6261
.option("--disable-throw-on-error", "Do not throw an error when response.ok is not true", false)
6362
.option("--single-http-client", "Ability to send HttpClient instance to Api constructor", false)
6463
.option("--silent", "Output only errors to console", false)
65-
.option("--default-response <type>", "default type for empty response schema", Ts.Keyword.Void)
64+
.option("--default-response <type>", "default type for empty response schema", "void")
6665
.option("--type-prefix <string>", "data contract name prefix", "")
6766
.option("--type-suffix <string>", "data contract name suffix", "")
6867
.option("--clean-output", "clean output folder before generate api. WARNING: May cause data loss", false)

package-lock.json

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

0 commit comments

Comments
 (0)