@nestia/sdk 1.1.0 → 1.2.0-dev.20230504
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/assets/bundle/api/index.ts +4 -0
- package/assets/bundle/api/module.ts +5 -0
- package/assets/bundle/e2e/index.ts +41 -0
- package/lib/INestiaConfig.d.ts +6 -0
- package/lib/NestiaSdkApplication.d.ts +1 -0
- package/lib/NestiaSdkApplication.js +35 -14
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.js +1 -0
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/analyses/ReflectAnalyzer.js +14 -2
- package/lib/analyses/ReflectAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaSdkCommand.d.ts +3 -2
- package/lib/executable/internal/NestiaSdkCommand.js +53 -57
- package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
- package/lib/executable/internal/NestiaSdkConfig.js +23 -50
- package/lib/executable/internal/NestiaSdkConfig.js.map +1 -1
- package/lib/executable/sdk.js +5 -8
- package/lib/executable/sdk.js.map +1 -1
- package/lib/generates/E2eGenerator.d.ts +5 -0
- package/lib/generates/E2eGenerator.js +52 -0
- package/lib/generates/E2eGenerator.js.map +1 -0
- package/lib/generates/SdkGenerator.d.ts +1 -2
- package/lib/generates/SdkGenerator.js +20 -22
- package/lib/generates/SdkGenerator.js.map +1 -1
- package/lib/generates/SwaggerGenerator.d.ts +1 -1
- package/lib/generates/SwaggerGenerator.js +40 -43
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.d.ts +8 -0
- package/lib/generates/internal/E2eFileProgrammer.js +101 -0
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkFileProgrammer.d.ts +5 -0
- package/lib/generates/internal/SdkFileProgrammer.js +121 -0
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkFunctionProgrammer.d.ts +5 -0
- package/lib/generates/{FunctionGenerator.js → internal/SdkFunctionProgrammer.js} +58 -57
- package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -0
- package/lib/generates/internal/SdkRouteDirectory.d.ts +10 -0
- package/lib/generates/internal/SdkRouteDirectory.js +18 -0
- package/lib/generates/internal/SdkRouteDirectory.js.map +1 -0
- package/lib/structures/IController.d.ts +4 -0
- package/lib/structures/IRoute.d.ts +4 -0
- package/lib/utils/NestiaConfigUtil.d.ts +4 -0
- package/lib/utils/NestiaConfigUtil.js +24 -0
- package/lib/utils/NestiaConfigUtil.js.map +1 -0
- package/lib/utils/SourceFinder.d.ts +9 -0
- package/lib/utils/SourceFinder.js +60 -0
- package/lib/utils/SourceFinder.js.map +1 -0
- package/package.json +6 -10
- package/src/INestiaConfig.ts +7 -0
- package/src/NestiaSdkApplication.ts +54 -17
- package/src/analyses/ControllerAnalyzer.ts +1 -0
- package/src/analyses/ReflectAnalyzer.ts +14 -2
- package/src/executable/internal/NestiaSdkCommand.ts +87 -105
- package/src/executable/sdk.ts +4 -8
- package/src/generates/E2eGenerator.ts +65 -0
- package/src/generates/SdkGenerator.ts +29 -30
- package/src/generates/SwaggerGenerator.ts +66 -64
- package/src/generates/internal/E2eFileProgrammer.ts +119 -0
- package/src/generates/internal/SdkFileProgrammer.ts +144 -0
- package/src/generates/internal/SdkFunctionProgrammer.ts +371 -0
- package/src/generates/internal/SdkRouteDirectory.ts +21 -0
- package/src/structures/IController.ts +4 -0
- package/src/structures/IRoute.ts +4 -0
- package/src/utils/NestiaConfigUtil.ts +21 -0
- package/src/utils/SourceFinder.ts +60 -0
- package/lib/analyses/SourceFinder.d.ts +0 -4
- package/lib/analyses/SourceFinder.js +0 -71
- package/lib/analyses/SourceFinder.js.map +0 -1
- package/lib/generates/FileGenerator.d.ts +0 -5
- package/lib/generates/FileGenerator.js +0 -138
- package/lib/generates/FileGenerator.js.map +0 -1
- package/lib/generates/FunctionGenerator.d.ts +0 -5
- package/lib/generates/FunctionGenerator.js.map +0 -1
- package/src/analyses/SourceFinder.ts +0 -59
- package/src/generates/FileGenerator.ts +0 -156
- package/src/generates/FunctionGenerator.ts +0 -348
- /package/assets/bundle/{HttpError.ts → api/HttpError.ts} +0 -0
- /package/assets/bundle/{IConnection.ts → api/IConnection.ts} +0 -0
- /package/assets/bundle/{Primitive.ts → api/Primitive.ts} +0 -0
|
@@ -1,44 +1,42 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import NodePath from "path";
|
|
3
|
-
import ts from "typescript";
|
|
4
3
|
|
|
5
4
|
import { INestiaConfig } from "../INestiaConfig";
|
|
6
5
|
import { IRoute } from "../structures/IRoute";
|
|
7
|
-
import {
|
|
6
|
+
import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
|
|
8
7
|
|
|
9
8
|
export namespace SdkGenerator {
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
await fs.promises.mkdir(config.output!);
|
|
18
|
-
} catch {}
|
|
9
|
+
export const generate =
|
|
10
|
+
(config: INestiaConfig) =>
|
|
11
|
+
async (routes: IRoute[]): Promise<void> => {
|
|
12
|
+
// PREPARE NEW DIRECTORIES
|
|
13
|
+
try {
|
|
14
|
+
await fs.promises.mkdir(config.output!);
|
|
15
|
+
} catch {}
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
// BUNDLING
|
|
18
|
+
const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
|
|
19
|
+
for (const file of bundle) {
|
|
20
|
+
const current: string = `${BUNDLE_PATH}/${file}`;
|
|
21
|
+
const stats: fs.Stats = await fs.promises.stat(current);
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
if (stats.isFile() === true) {
|
|
24
|
+
const content: string = await fs.promises.readFile(
|
|
25
|
+
current,
|
|
26
|
+
"utf8",
|
|
27
|
+
);
|
|
28
|
+
if (fs.existsSync(`${config.output}/${file}`) === false)
|
|
29
|
+
await fs.promises.writeFile(
|
|
30
|
+
`${config.output}/${file}`,
|
|
31
|
+
content,
|
|
32
|
+
"utf8",
|
|
33
|
+
);
|
|
34
|
+
}
|
|
36
35
|
}
|
|
37
|
-
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
// FUNCTIONAL
|
|
38
|
+
await SdkFileProgrammer.generate(config)(routes);
|
|
39
|
+
};
|
|
42
40
|
|
|
43
41
|
export const BUNDLE_PATH = NodePath.join(
|
|
44
42
|
__dirname,
|
|
@@ -46,5 +44,6 @@ export namespace SdkGenerator {
|
|
|
46
44
|
"..",
|
|
47
45
|
"assets",
|
|
48
46
|
"bundle",
|
|
47
|
+
"api",
|
|
49
48
|
);
|
|
50
49
|
}
|
|
@@ -17,72 +17,74 @@ import { ISwaggerDocument } from "../structures/ISwaggerDocument";
|
|
|
17
17
|
import { MapUtil } from "../utils/MapUtil";
|
|
18
18
|
|
|
19
19
|
export namespace SwaggerGenerator {
|
|
20
|
-
export
|
|
21
|
-
checker: ts.TypeChecker
|
|
22
|
-
config: INestiaConfig.ISwaggerConfig
|
|
23
|
-
routeList: IRoute[]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
20
|
+
export const generate =
|
|
21
|
+
(checker: ts.TypeChecker) =>
|
|
22
|
+
(config: INestiaConfig.ISwaggerConfig) =>
|
|
23
|
+
async (routeList: IRoute[]): Promise<void> => {
|
|
24
|
+
// PREPARE ASSETS
|
|
25
|
+
const parsed: NodePath.ParsedPath = NodePath.parse(config.output);
|
|
26
|
+
const location: string = !!parsed.ext
|
|
27
|
+
? NodePath.resolve(config.output)
|
|
28
|
+
: NodePath.join(
|
|
29
|
+
NodePath.resolve(config.output),
|
|
30
|
+
"swagger.json",
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const collection: MetadataCollection = new MetadataCollection({
|
|
34
|
+
replace: MetadataCollection.replace,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// CONSTRUCT SWAGGER DOCUMENTS
|
|
38
|
+
const tupleList: Array<ISchemaTuple> = [];
|
|
39
|
+
const swagger: ISwaggerDocument = await initialize(location);
|
|
40
|
+
const pathDict: Map<string, ISwaggerDocument.IPath> = new Map();
|
|
41
|
+
|
|
42
|
+
for (const route of routeList) {
|
|
43
|
+
if (route.tags.find((tag) => tag.name === "internal")) continue;
|
|
44
|
+
|
|
45
|
+
const path: ISwaggerDocument.IPath = MapUtil.take(
|
|
46
|
+
pathDict,
|
|
47
|
+
get_path(route.path, route.parameters),
|
|
48
|
+
() => ({}),
|
|
49
|
+
);
|
|
50
|
+
path[route.method.toLowerCase()] = generate_route(
|
|
51
|
+
checker,
|
|
52
|
+
collection,
|
|
53
|
+
tupleList,
|
|
54
|
+
route,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
swagger.paths = {};
|
|
58
|
+
for (const [path, routes] of pathDict) {
|
|
59
|
+
swagger.paths[path] = routes;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// FILL JSON-SCHEMAS
|
|
63
|
+
const application: IJsonApplication = ApplicationProgrammer.write({
|
|
64
|
+
purpose: "swagger",
|
|
65
|
+
})(tupleList.map(({ metadata }) => metadata));
|
|
66
|
+
swagger.components = {
|
|
67
|
+
...(swagger.components ?? {}),
|
|
68
|
+
schemas: application.components.schemas,
|
|
69
|
+
};
|
|
70
|
+
tupleList.forEach(({ schema }, index) => {
|
|
71
|
+
Object.assign(schema, application.schemas[index]!);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// CONFIGURE SECURITY
|
|
75
|
+
if (config.security) fill_security(config.security, swagger);
|
|
76
|
+
|
|
77
|
+
// ERASE IJsonComponents.IObject.$id
|
|
78
|
+
for (const obj of Object.values(swagger.components.schemas))
|
|
79
|
+
if (obj.$id) delete obj.$id;
|
|
80
|
+
|
|
81
|
+
// DO GENERATE
|
|
82
|
+
await fs.promises.writeFile(
|
|
83
|
+
location,
|
|
84
|
+
JSON.stringify(swagger, null, 2),
|
|
85
|
+
"utf8",
|
|
53
86
|
);
|
|
54
|
-
}
|
|
55
|
-
swagger.paths = {};
|
|
56
|
-
for (const [path, routes] of pathDict) {
|
|
57
|
-
swagger.paths[path] = routes;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// FILL JSON-SCHEMAS
|
|
61
|
-
const application: IJsonApplication = ApplicationProgrammer.write({
|
|
62
|
-
purpose: "swagger",
|
|
63
|
-
})(tupleList.map(({ metadata }) => metadata));
|
|
64
|
-
swagger.components = {
|
|
65
|
-
...(swagger.components ?? {}),
|
|
66
|
-
schemas: application.components.schemas,
|
|
67
87
|
};
|
|
68
|
-
tupleList.forEach(({ schema }, index) => {
|
|
69
|
-
Object.assign(schema, application.schemas[index]!);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// CONFIGURE SECURITY
|
|
73
|
-
if (config.security) fill_security(config.security, swagger);
|
|
74
|
-
|
|
75
|
-
// ERASE IJsonComponents.IObject.$id
|
|
76
|
-
for (const obj of Object.values(swagger.components.schemas))
|
|
77
|
-
if (obj.$id) delete obj.$id;
|
|
78
|
-
|
|
79
|
-
// DO GENERATE
|
|
80
|
-
await fs.promises.writeFile(
|
|
81
|
-
location,
|
|
82
|
-
JSON.stringify(swagger, null, 2),
|
|
83
|
-
"utf8",
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
88
|
|
|
87
89
|
/* ---------------------------------------------------------
|
|
88
90
|
INITIALIZERS
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
import { INestiaConfig } from "../../INestiaConfig";
|
|
5
|
+
import { IRoute } from "../../structures/IRoute";
|
|
6
|
+
import { ImportDictionary } from "../../utils/ImportDictionary";
|
|
7
|
+
|
|
8
|
+
export namespace E2eFileProgrammer {
|
|
9
|
+
export const generate =
|
|
10
|
+
(config: INestiaConfig) =>
|
|
11
|
+
(props: { api: string; current: string }) =>
|
|
12
|
+
async (route: IRoute): Promise<void> => {
|
|
13
|
+
const importDict: ImportDictionary = new ImportDictionary();
|
|
14
|
+
for (const tuple of route.imports)
|
|
15
|
+
for (const instance of tuple[1])
|
|
16
|
+
importDict.emplace(tuple[0], false, instance);
|
|
17
|
+
|
|
18
|
+
const uuid: boolean = route.parameters.some(
|
|
19
|
+
(p) => p.category === "param" && p.meta?.type === "uuid",
|
|
20
|
+
);
|
|
21
|
+
const content: string = [
|
|
22
|
+
config.primitive === false
|
|
23
|
+
? `import typia from "typia";`
|
|
24
|
+
: `import typia, { Primitive } from "typia";`,
|
|
25
|
+
"",
|
|
26
|
+
`import api from "./${path
|
|
27
|
+
.relative(props.current, props.api)
|
|
28
|
+
.split("\\")
|
|
29
|
+
.join("/")}";`,
|
|
30
|
+
...(importDict.empty()
|
|
31
|
+
? []
|
|
32
|
+
: [importDict.toScript(props.current)]),
|
|
33
|
+
"",
|
|
34
|
+
arrow(config)(route),
|
|
35
|
+
...(uuid ? ["", UUID] : []),
|
|
36
|
+
].join("\n");
|
|
37
|
+
|
|
38
|
+
await fs.promises.writeFile(
|
|
39
|
+
`${props.current}/${name(route)}.ts`,
|
|
40
|
+
content,
|
|
41
|
+
"utf8",
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const arrow =
|
|
46
|
+
(config: INestiaConfig) =>
|
|
47
|
+
(route: IRoute): string => {
|
|
48
|
+
const tab: number = route.output.name === "void" ? 2 : 3;
|
|
49
|
+
const output = [
|
|
50
|
+
`await ${accessor(route)}(`,
|
|
51
|
+
`${" ".repeat(tab * 4)}connection,`,
|
|
52
|
+
...route.parameters.map(parameter(config)(tab)),
|
|
53
|
+
`${" ".repeat((tab - 1) * 4)});`,
|
|
54
|
+
].join("\n");
|
|
55
|
+
return [
|
|
56
|
+
`export const ${name(route)} = async (`,
|
|
57
|
+
` connection: api.IConnection`,
|
|
58
|
+
`): Promise<void> => {`,
|
|
59
|
+
...(route.output.name === "void"
|
|
60
|
+
? [` ${output}`]
|
|
61
|
+
: [
|
|
62
|
+
` const output: ${primitive(config)(
|
|
63
|
+
route.output.name,
|
|
64
|
+
)} = `,
|
|
65
|
+
` ${output}`,
|
|
66
|
+
` typia.assert(output);`,
|
|
67
|
+
]),
|
|
68
|
+
`};`,
|
|
69
|
+
].join("\n");
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const parameter =
|
|
73
|
+
(config: INestiaConfig) =>
|
|
74
|
+
(tab: number) =>
|
|
75
|
+
(param: IRoute.IParameter): string => {
|
|
76
|
+
const middle: string =
|
|
77
|
+
param.category === "param" && param.meta?.type === "uuid"
|
|
78
|
+
? param.meta.nullable
|
|
79
|
+
? `Math.random() < .2 ? null : uuid()`
|
|
80
|
+
: `uuid()`
|
|
81
|
+
: `typia.random<${primitive(config)(param.type.name)}>()`;
|
|
82
|
+
return `${" ".repeat(4 * tab)}${middle},`;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const name = (route: IRoute): string =>
|
|
86
|
+
[
|
|
87
|
+
"test_api",
|
|
88
|
+
...route.path
|
|
89
|
+
.split("/")
|
|
90
|
+
.filter((str) => str.length && str[0] !== ":")
|
|
91
|
+
.map(normalize),
|
|
92
|
+
route.name,
|
|
93
|
+
].join("_");
|
|
94
|
+
|
|
95
|
+
const accessor = (route: IRoute): string =>
|
|
96
|
+
[
|
|
97
|
+
"api.functional",
|
|
98
|
+
...route.path
|
|
99
|
+
.split("/")
|
|
100
|
+
.filter((str) => str.length && str[0] !== ":")
|
|
101
|
+
.map(normalize),
|
|
102
|
+
route.name,
|
|
103
|
+
].join(".");
|
|
104
|
+
|
|
105
|
+
const normalize = (str: string) =>
|
|
106
|
+
str.split("-").join("_").split(".").join("_");
|
|
107
|
+
|
|
108
|
+
const primitive =
|
|
109
|
+
(config: INestiaConfig) =>
|
|
110
|
+
(name: string): string =>
|
|
111
|
+
config.primitive !== false ? `Primitive<${name}>` : name;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const UUID = `const uuid = (): string =>
|
|
115
|
+
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
116
|
+
const r = (Math.random() * 16) | 0;
|
|
117
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
118
|
+
return v.toString(16);
|
|
119
|
+
});`;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
|
|
3
|
+
import { INestiaConfig } from "../../INestiaConfig";
|
|
4
|
+
import { IRoute } from "../../structures/IRoute";
|
|
5
|
+
import { ImportDictionary } from "../../utils/ImportDictionary";
|
|
6
|
+
import { SdkFunctionProgrammer } from "./SdkFunctionProgrammer";
|
|
7
|
+
import { SdkRouteDirectory } from "./SdkRouteDirectory";
|
|
8
|
+
|
|
9
|
+
export namespace SdkFileProgrammer {
|
|
10
|
+
/* ---------------------------------------------------------
|
|
11
|
+
CONSTRUCTOR
|
|
12
|
+
--------------------------------------------------------- */
|
|
13
|
+
export const generate =
|
|
14
|
+
(config: INestiaConfig) =>
|
|
15
|
+
async (routeList: IRoute[]): Promise<void> => {
|
|
16
|
+
// CONSTRUCT FOLDER TREE
|
|
17
|
+
const root: SdkRouteDirectory = new SdkRouteDirectory(
|
|
18
|
+
null,
|
|
19
|
+
"functional",
|
|
20
|
+
);
|
|
21
|
+
for (const route of routeList) emplace(root)(route);
|
|
22
|
+
|
|
23
|
+
// RELOCATE FOR ONLY ONE CONTROLLER METHOD IN AN URL CASE
|
|
24
|
+
relocate(root);
|
|
25
|
+
|
|
26
|
+
// ITERATE FILES
|
|
27
|
+
await iterate(config)(root)(config.output + "/functional");
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const emplace =
|
|
31
|
+
(directory: SdkRouteDirectory) =>
|
|
32
|
+
(route: IRoute): void => {
|
|
33
|
+
// SEPARATE IDENTIFIERS
|
|
34
|
+
const identifiers: string[] = route.path
|
|
35
|
+
.split("/")
|
|
36
|
+
.filter((str) => str.length && str[0] !== ":")
|
|
37
|
+
.map((str) => str.split("-").join("_").split(".").join("_"));
|
|
38
|
+
|
|
39
|
+
// OPEN DIRECTORIES
|
|
40
|
+
for (const key of identifiers) {
|
|
41
|
+
directory = directory.directories.take(
|
|
42
|
+
key,
|
|
43
|
+
() => new SdkRouteDirectory(directory, key),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ADD ROUTE
|
|
48
|
+
directory.routes.push(route);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const relocate = (directory: SdkRouteDirectory): void => {
|
|
52
|
+
if (
|
|
53
|
+
directory.parent !== null &&
|
|
54
|
+
directory.directories.empty() &&
|
|
55
|
+
directory.routes.length === 1 &&
|
|
56
|
+
directory.name === directory.routes[0].name
|
|
57
|
+
) {
|
|
58
|
+
directory.parent.routes.push(directory.routes[0]);
|
|
59
|
+
directory.parent.directories.erase(directory.name);
|
|
60
|
+
} else if (directory.directories.empty() === false)
|
|
61
|
+
for (const it of directory.directories) relocate(it.second);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/* ---------------------------------------------------------
|
|
65
|
+
FILE ITERATOR
|
|
66
|
+
--------------------------------------------------------- */
|
|
67
|
+
const iterate =
|
|
68
|
+
(config: INestiaConfig) =>
|
|
69
|
+
(directory: SdkRouteDirectory) =>
|
|
70
|
+
async (outDir: string): Promise<void> => {
|
|
71
|
+
// CREATE A NEW DIRECTORY
|
|
72
|
+
try {
|
|
73
|
+
await fs.promises.mkdir(outDir);
|
|
74
|
+
} catch {}
|
|
75
|
+
|
|
76
|
+
// ITERATE CHILDREN
|
|
77
|
+
const content: string[] = [];
|
|
78
|
+
for (const it of directory.directories) {
|
|
79
|
+
await iterate(config)(it.second)(`${outDir}/${it.first}`);
|
|
80
|
+
content.push(`export * as ${it.first} from "./${it.first}";`);
|
|
81
|
+
}
|
|
82
|
+
if (content.length && directory.routes.length) content.push("");
|
|
83
|
+
|
|
84
|
+
// ITERATE ROUTES
|
|
85
|
+
const importDict: ImportDictionary = new ImportDictionary();
|
|
86
|
+
directory.routes.forEach((route, i) => {
|
|
87
|
+
for (const tuple of route.imports)
|
|
88
|
+
for (const instance of tuple[1])
|
|
89
|
+
importDict.emplace(tuple[0], false, instance);
|
|
90
|
+
|
|
91
|
+
content.push(SdkFunctionProgrammer.generate(config)(route));
|
|
92
|
+
if (i !== directory.routes.length - 1) content.push("");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// FINALIZE THE CONTENT
|
|
96
|
+
if (directory.routes.length !== 0) {
|
|
97
|
+
const primitived: boolean =
|
|
98
|
+
config.primitive !== false &&
|
|
99
|
+
directory.routes.some(
|
|
100
|
+
(route) =>
|
|
101
|
+
route.output.name !== "void" ||
|
|
102
|
+
route.parameters.some(
|
|
103
|
+
(param) => param.category !== "param",
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
const asserted: boolean =
|
|
107
|
+
config.assert === true &&
|
|
108
|
+
directory.routes.some(
|
|
109
|
+
(route) => route.parameters.length !== 0,
|
|
110
|
+
);
|
|
111
|
+
const json: boolean =
|
|
112
|
+
config.json === true &&
|
|
113
|
+
directory.routes.some(
|
|
114
|
+
(route) =>
|
|
115
|
+
route.method === "POST" ||
|
|
116
|
+
route.method === "PUT" ||
|
|
117
|
+
route.method === "PATCH",
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const fetcher: string[] = ["Fetcher"];
|
|
121
|
+
if (primitived) fetcher.push("Primitive");
|
|
122
|
+
|
|
123
|
+
const head: string[] = [
|
|
124
|
+
`import { ${fetcher.join(", ")} } from "@nestia/fetcher";`,
|
|
125
|
+
`import type { IConnection } from "@nestia/fetcher";`,
|
|
126
|
+
];
|
|
127
|
+
if (asserted || json) head.push(`import typia from "typia";`);
|
|
128
|
+
if (!importDict.empty())
|
|
129
|
+
head.push("", importDict.toScript(outDir));
|
|
130
|
+
|
|
131
|
+
content.push(...head, "", ...content.splice(0, content.length));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const script: string =
|
|
135
|
+
"/**\n" +
|
|
136
|
+
" * @packageDocumentation\n" +
|
|
137
|
+
` * @module ${directory.module}\n` +
|
|
138
|
+
" * @nestia Generated by Nestia - https://github.com/samchon/nestia \n" +
|
|
139
|
+
" */\n" +
|
|
140
|
+
"//================================================================\n" +
|
|
141
|
+
content.join("\n");
|
|
142
|
+
await fs.promises.writeFile(`${outDir}/index.ts`, script, "utf8");
|
|
143
|
+
};
|
|
144
|
+
}
|