@nestia/sdk 2.0.0-dev.20230904-2 → 2.0.0-dev.20230906
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/lib/INestiaConfig.d.ts +8 -0
- package/lib/NestiaSdkApplication.d.ts +1 -1
- package/lib/NestiaSdkApplication.js +5 -5
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.js +4 -4
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectAnalyzer.js +9 -1
- package/lib/analyses/ReflectAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaConfigLoader.js +5 -1
- package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
- package/lib/generates/SdkGenerator.d.ts +2 -1
- package/lib/generates/SdkGenerator.js +5 -1
- package/lib/generates/SdkGenerator.js.map +1 -1
- package/lib/generates/SwaggerGenerator.js +9 -6
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.js +15 -10
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkDtoGenerator.d.ts +9 -0
- package/lib/generates/internal/SdkDtoGenerator.js +264 -0
- package/lib/generates/internal/SdkDtoGenerator.js.map +1 -0
- package/lib/generates/internal/SdkFileProgrammer.js +8 -7
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkFunctionProgrammer.js +11 -7
- package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkSimulationProgrammer.js +5 -1
- package/lib/generates/internal/SdkSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.js +2 -2
- package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
- package/lib/structures/IController.d.ts +2 -0
- package/lib/structures/IRoute.d.ts +5 -1
- package/package.json +5 -5
- package/src/INestiaConfig.ts +9 -0
- package/src/NestiaSdkApplication.ts +5 -9
- package/src/analyses/ControllerAnalyzer.ts +5 -5
- package/src/analyses/ReflectAnalyzer.ts +8 -0
- package/src/generates/SdkGenerator.ts +7 -0
- package/src/generates/SwaggerGenerator.ts +11 -7
- package/src/generates/internal/E2eFileProgrammer.ts +24 -11
- package/src/generates/internal/SdkDtoGenerator.ts +384 -0
- package/src/generates/internal/SdkFileProgrammer.ts +8 -7
- package/src/generates/internal/SdkFunctionProgrammer.ts +35 -7
- package/src/generates/internal/SdkSimulationProgrammer.ts +10 -1
- package/src/generates/internal/SwaggerSchemaGenerator.ts +2 -2
- package/src/structures/IController.ts +2 -0
- package/src/structures/IRoute.ts +7 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestia/sdk",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.20230906",
|
|
4
4
|
"description": "Nestia SDK and Swagger generator",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://nestia.io",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@nestia/fetcher": "^2.0.0-dev.
|
|
38
|
+
"@nestia/fetcher": "^2.0.0-dev.20230906",
|
|
39
39
|
"cli": "^1.0.1",
|
|
40
40
|
"glob": "^7.2.0",
|
|
41
41
|
"path-to-regexp": "^6.2.1",
|
|
@@ -44,16 +44,16 @@
|
|
|
44
44
|
"tsconfck": "^2.0.1",
|
|
45
45
|
"tsconfig-paths": "^4.1.1",
|
|
46
46
|
"tstl": "^2.5.13",
|
|
47
|
-
"typia": "^5.0.
|
|
47
|
+
"typia": "^5.0.2"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@nestia/fetcher": ">=2.0.0-dev.
|
|
50
|
+
"@nestia/fetcher": ">=2.0.0-dev.20230906",
|
|
51
51
|
"@nestjs/common": ">=7.0.1",
|
|
52
52
|
"@nestjs/core": ">=7.0.1",
|
|
53
53
|
"reflect-metadata": ">=0.1.12",
|
|
54
54
|
"ts-node": ">=10.6.0",
|
|
55
55
|
"typescript": ">=4.8.0",
|
|
56
|
-
"typia": ">=5.0.
|
|
56
|
+
"typia": ">=5.0.2 <6.0.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@nestjs/common": ">= 7.0.1",
|
package/src/INestiaConfig.ts
CHANGED
|
@@ -52,6 +52,15 @@ export interface INestiaConfig {
|
|
|
52
52
|
*/
|
|
53
53
|
e2e?: string;
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Whether to clone DTO structures or not.
|
|
57
|
+
*
|
|
58
|
+
* If being configured, all of DTOs used in the backend server would be cloned
|
|
59
|
+
* into the `structures` directory, and the SDK library would be refer to the
|
|
60
|
+
* cloned DTOs instead of the original.
|
|
61
|
+
*/
|
|
62
|
+
clone?: boolean;
|
|
63
|
+
|
|
55
64
|
/**
|
|
56
65
|
* Whether to wrap DTO by primitive type.
|
|
57
66
|
*
|
|
@@ -17,7 +17,7 @@ import { NestiaConfigUtil } from "./utils/NestiaConfigUtil";
|
|
|
17
17
|
import { SourceFinder } from "./utils/SourceFinder";
|
|
18
18
|
|
|
19
19
|
export class NestiaSdkApplication {
|
|
20
|
-
private readonly
|
|
20
|
+
private readonly bundler_: Singleton<Promise<(str: string) => boolean>> =
|
|
21
21
|
new Singleton(async () => {
|
|
22
22
|
if (!this.config) return () => false;
|
|
23
23
|
|
|
@@ -59,7 +59,7 @@ export class NestiaSdkApplication {
|
|
|
59
59
|
if (this.config.output)
|
|
60
60
|
return (
|
|
61
61
|
file.indexOf(path.join(this.config.output, "functional")) ===
|
|
62
|
-
-1 && (await this.
|
|
62
|
+
-1 && (await this.bundler_.get())(file) === false
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
const content: string = await fs.promises.readFile(file, "utf8");
|
|
@@ -97,8 +97,8 @@ export class NestiaSdkApplication {
|
|
|
97
97
|
await this.generate(
|
|
98
98
|
"e2e",
|
|
99
99
|
(config) => config,
|
|
100
|
-
() => (config) => async (routes) => {
|
|
101
|
-
await SdkGenerator.generate(config)(routes);
|
|
100
|
+
(checker) => (config) => async (routes) => {
|
|
101
|
+
await SdkGenerator.generate(checker)(config)(routes);
|
|
102
102
|
await E2eGenerator.generate(config)(routes);
|
|
103
103
|
},
|
|
104
104
|
);
|
|
@@ -118,11 +118,7 @@ export class NestiaSdkApplication {
|
|
|
118
118
|
);
|
|
119
119
|
|
|
120
120
|
title("Nestia SDK Generator");
|
|
121
|
-
await this.generate(
|
|
122
|
-
"sdk",
|
|
123
|
-
(config) => config,
|
|
124
|
-
() => SdkGenerator.generate,
|
|
125
|
-
);
|
|
121
|
+
await this.generate("sdk", (config) => config, SdkGenerator.generate);
|
|
126
122
|
}
|
|
127
123
|
|
|
128
124
|
public async swagger(): Promise<void> {
|
|
@@ -145,11 +145,11 @@ export namespace ControllerAnalyzer {
|
|
|
145
145
|
.map((pair) => [pair.first, pair.second.toJSON()]);
|
|
146
146
|
|
|
147
147
|
// PARSE COMMENT TAGS
|
|
148
|
-
const
|
|
148
|
+
const jsDocTags = signature.getJsDocTags();
|
|
149
149
|
const security: Record<string, string[]>[] = SecurityAnalyzer.merge(
|
|
150
150
|
...controller.security,
|
|
151
151
|
...func.security,
|
|
152
|
-
...
|
|
152
|
+
...jsDocTags
|
|
153
153
|
.filter((tag) => tag.name === "security")
|
|
154
154
|
.map((tag) =>
|
|
155
155
|
(tag.text ?? []).map((text) => {
|
|
@@ -191,12 +191,12 @@ export namespace ControllerAnalyzer {
|
|
|
191
191
|
}:${character + 1}`;
|
|
192
192
|
})(),
|
|
193
193
|
description: CommentFactory.description(symbol),
|
|
194
|
-
operationId:
|
|
194
|
+
operationId: jsDocTags
|
|
195
195
|
.find(({ name }) => name === "operationId")
|
|
196
196
|
?.text!?.[0].text.split(" ")[0]
|
|
197
197
|
.trim(),
|
|
198
|
-
|
|
199
|
-
setHeaders:
|
|
198
|
+
jsDocTags: jsDocTags,
|
|
199
|
+
setHeaders: jsDocTags
|
|
200
200
|
.filter(
|
|
201
201
|
(t) =>
|
|
202
202
|
t.text?.length &&
|
|
@@ -90,6 +90,8 @@ export namespace ReflectAnalyzer {
|
|
|
90
90
|
paths,
|
|
91
91
|
functions: [],
|
|
92
92
|
security: _Get_securities(creator),
|
|
93
|
+
swaggerTgas:
|
|
94
|
+
Reflect.getMetadata("swagger/apiUseTags", creator) ?? [],
|
|
93
95
|
};
|
|
94
96
|
|
|
95
97
|
// PARSE CHILDREN DATA
|
|
@@ -228,6 +230,12 @@ export namespace ReflectAnalyzer {
|
|
|
228
230
|
)?.value ?? "application/json",
|
|
229
231
|
security: _Get_securities(proto),
|
|
230
232
|
exceptions: _Get_exceptions(proto),
|
|
233
|
+
swaggerTags: [
|
|
234
|
+
...new Set([
|
|
235
|
+
...controller.swaggerTgas,
|
|
236
|
+
...(Reflect.getMetadata("swagger/apiUseTags", proto) ?? []),
|
|
237
|
+
]),
|
|
238
|
+
],
|
|
231
239
|
};
|
|
232
240
|
|
|
233
241
|
// VALIDATE PATH ARGUMENTS
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import NodePath from "path";
|
|
3
3
|
import { IPointer } from "tstl";
|
|
4
|
+
import ts from "typescript";
|
|
4
5
|
|
|
5
6
|
import { INestiaConfig } from "../INestiaConfig";
|
|
6
7
|
import { IRoute } from "../structures/IRoute";
|
|
7
8
|
import { DistributionComposer } from "./internal/DistributionComposer";
|
|
9
|
+
import { SdkDtoGenerator } from "./internal/SdkDtoGenerator";
|
|
8
10
|
import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
|
|
9
11
|
|
|
10
12
|
export namespace SdkGenerator {
|
|
11
13
|
export const generate =
|
|
14
|
+
(checker: ts.TypeChecker) =>
|
|
12
15
|
(config: INestiaConfig) =>
|
|
13
16
|
async (routes: IRoute[]): Promise<void> => {
|
|
14
17
|
console.log("Generating SDK Library");
|
|
@@ -55,6 +58,10 @@ export namespace SdkGenerator {
|
|
|
55
58
|
);
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
// STRUCTURES
|
|
62
|
+
if (config.clone)
|
|
63
|
+
await SdkDtoGenerator.generate(checker)(config)(routes);
|
|
64
|
+
|
|
58
65
|
// FUNCTIONAL
|
|
59
66
|
await SdkFileProgrammer.generate(config)(routes);
|
|
60
67
|
|
|
@@ -71,7 +71,8 @@ export namespace SwaggerGenerator {
|
|
|
71
71
|
> = new Map();
|
|
72
72
|
|
|
73
73
|
for (const route of routeList) {
|
|
74
|
-
if (route.
|
|
74
|
+
if (route.jsDocTags.find((tag) => tag.name === "internal"))
|
|
75
|
+
continue;
|
|
75
76
|
|
|
76
77
|
const path: Record<string, ISwaggerRoute> = MapUtil.take(
|
|
77
78
|
pathDict,
|
|
@@ -297,8 +298,8 @@ export namespace SwaggerGenerator {
|
|
|
297
298
|
const body = route.parameters.find(
|
|
298
299
|
(param) => param.category === "body",
|
|
299
300
|
);
|
|
300
|
-
const
|
|
301
|
-
route.
|
|
301
|
+
const getJsDocTexts = (name: string) =>
|
|
302
|
+
route.jsDocTags
|
|
302
303
|
.filter(
|
|
303
304
|
(tag) =>
|
|
304
305
|
tag.name === name &&
|
|
@@ -320,7 +321,7 @@ export namespace SwaggerGenerator {
|
|
|
320
321
|
const summary: string | undefined = (() => {
|
|
321
322
|
if (description === undefined) return undefined;
|
|
322
323
|
|
|
323
|
-
const [explicit] =
|
|
324
|
+
const [explicit] = getJsDocTexts("summary");
|
|
324
325
|
if (explicit?.length) return explicit;
|
|
325
326
|
|
|
326
327
|
const index: number = description.indexOf(".");
|
|
@@ -329,13 +330,16 @@ export namespace SwaggerGenerator {
|
|
|
329
330
|
const content: string = description.substring(0, index).trim();
|
|
330
331
|
return content.length ? content : undefined;
|
|
331
332
|
})();
|
|
332
|
-
const deprecated = route.
|
|
333
|
+
const deprecated = route.jsDocTags.find(
|
|
333
334
|
(tag) => tag.name === "deprecated",
|
|
334
335
|
);
|
|
335
336
|
|
|
336
337
|
return {
|
|
337
338
|
deprecated: deprecated ? true : undefined,
|
|
338
|
-
tags:
|
|
339
|
+
tags: [
|
|
340
|
+
...route.swaggerTags,
|
|
341
|
+
...new Set([...getJsDocTexts("tag")]),
|
|
342
|
+
],
|
|
339
343
|
operationId:
|
|
340
344
|
route.operationId ??
|
|
341
345
|
props.config.operationId?.({
|
|
@@ -363,7 +367,7 @@ export namespace SwaggerGenerator {
|
|
|
363
367
|
.filter((str) => str.length && str[0] !== ":"),
|
|
364
368
|
route.name,
|
|
365
369
|
].join("."),
|
|
366
|
-
"x-nestia-jsDocTags": route.
|
|
370
|
+
"x-nestia-jsDocTags": route.jsDocTags,
|
|
367
371
|
"x-nestia-method": route.method,
|
|
368
372
|
};
|
|
369
373
|
};
|
|
@@ -3,6 +3,7 @@ import fs from "fs";
|
|
|
3
3
|
import { INestiaConfig } from "../../INestiaConfig";
|
|
4
4
|
import { IRoute } from "../../structures/IRoute";
|
|
5
5
|
import { ImportDictionary } from "../../utils/ImportDictionary";
|
|
6
|
+
import { SdkDtoGenerator } from "./SdkDtoGenerator";
|
|
6
7
|
import { SdkImportWizard } from "./SdkImportWizard";
|
|
7
8
|
|
|
8
9
|
export namespace E2eFileProgrammer {
|
|
@@ -11,20 +12,21 @@ export namespace E2eFileProgrammer {
|
|
|
11
12
|
(props: { api: string; current: string }) =>
|
|
12
13
|
async (route: IRoute): Promise<void> => {
|
|
13
14
|
const importer: ImportDictionary = new ImportDictionary();
|
|
14
|
-
|
|
15
|
-
for (const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
if (config.clone !== true)
|
|
16
|
+
for (const tuple of route.imports)
|
|
17
|
+
for (const instance of tuple[1])
|
|
18
|
+
importer.internal({
|
|
19
|
+
file: tuple[0],
|
|
20
|
+
type: true,
|
|
21
|
+
instance,
|
|
22
|
+
});
|
|
22
23
|
importer.internal({
|
|
23
24
|
type: false,
|
|
24
25
|
file: props.api,
|
|
25
26
|
instance: null,
|
|
26
27
|
name: "api",
|
|
27
28
|
});
|
|
29
|
+
|
|
28
30
|
const body: string = arrow(config)(importer)(route);
|
|
29
31
|
const content: string = [
|
|
30
32
|
importer.toScript(props.current),
|
|
@@ -57,7 +59,9 @@ export namespace E2eFileProgrammer {
|
|
|
57
59
|
" ...(connection.headers ?? {}),",
|
|
58
60
|
` ...${SdkImportWizard.typia(
|
|
59
61
|
importer,
|
|
60
|
-
)}.random<${
|
|
62
|
+
)}.random<${getTypeName(config)(importer)(
|
|
63
|
+
headers,
|
|
64
|
+
)}>(),`,
|
|
61
65
|
" },",
|
|
62
66
|
"},",
|
|
63
67
|
]
|
|
@@ -77,7 +81,7 @@ export namespace E2eFileProgrammer {
|
|
|
77
81
|
? [` ${output}`]
|
|
78
82
|
: [
|
|
79
83
|
` const output: ${primitive(config)(importer)(
|
|
80
|
-
route.output
|
|
84
|
+
getTypeName(config)(importer)(route.output),
|
|
81
85
|
)} = `,
|
|
82
86
|
` ${output}`,
|
|
83
87
|
` ${SdkImportWizard.typia(
|
|
@@ -95,7 +99,9 @@ export namespace E2eFileProgrammer {
|
|
|
95
99
|
(param: IRoute.IParameter): string => {
|
|
96
100
|
const middle: string = `${SdkImportWizard.typia(
|
|
97
101
|
importer,
|
|
98
|
-
)}.random<${primitive(config)(importer)(
|
|
102
|
+
)}.random<${primitive(config)(importer)(
|
|
103
|
+
getTypeName(config)(importer)(param),
|
|
104
|
+
)}>()`;
|
|
99
105
|
return `${" ".repeat(4 * tab)}${middle},`;
|
|
100
106
|
};
|
|
101
107
|
|
|
@@ -113,3 +119,10 @@ export namespace E2eFileProgrammer {
|
|
|
113
119
|
? `${SdkImportWizard.Primitive(importer)}<${name}>`
|
|
114
120
|
: name;
|
|
115
121
|
}
|
|
122
|
+
const getTypeName =
|
|
123
|
+
(config: INestiaConfig) =>
|
|
124
|
+
(importer: ImportDictionary) =>
|
|
125
|
+
(p: IRoute.IParameter | IRoute.IOutput) =>
|
|
126
|
+
p.metadata
|
|
127
|
+
? SdkDtoGenerator.decode(config)(importer)(p.metadata)
|
|
128
|
+
: p.typeName;
|