@nestia/sdk 2.0.0-dev.20230903 → 2.0.0-dev.20230904-2
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 +30 -45
- package/lib/NestiaSdkApplication.d.ts +6 -5
- package/lib/NestiaSdkApplication.js +27 -84
- package/lib/NestiaSdkApplication.js.map +1 -1
- package/lib/analyses/ControllerAnalyzer.js +1 -1
- package/lib/analyses/ControllerAnalyzer.js.map +1 -1
- package/lib/executable/internal/NestiaConfigLoader.d.ts +7 -0
- package/lib/executable/internal/NestiaConfigLoader.js +574 -0
- package/lib/executable/internal/NestiaConfigLoader.js.map +1 -0
- package/lib/executable/internal/NestiaProjectGetter.d.ts +3 -0
- package/lib/executable/internal/NestiaProjectGetter.js +28 -0
- package/lib/executable/internal/NestiaProjectGetter.js.map +1 -0
- package/lib/executable/internal/NestiaSdkCommand.d.ts +3 -3
- package/lib/executable/internal/NestiaSdkCommand.js +13 -104
- package/lib/executable/internal/NestiaSdkCommand.js.map +1 -1
- package/lib/executable/internal/{nestia.config.getter.js → nestia.project.getter.js} +3 -3
- package/lib/executable/internal/nestia.project.getter.js.map +1 -0
- package/lib/executable/sdk.js +3 -3
- package/lib/executable/sdk.js.map +1 -1
- package/lib/generates/SwaggerGenerator.js +3 -2
- package/lib/generates/SwaggerGenerator.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.d.ts +1 -1
- package/lib/generates/internal/SwaggerSchemaGenerator.js +57 -69
- package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
- package/lib/generates/internal/SwaggerSchemaValidator.js +0 -4
- package/lib/generates/internal/SwaggerSchemaValidator.js.map +1 -1
- package/package.json +3 -3
- package/src/INestiaConfig.ts +32 -48
- package/src/NestiaSdkApplication.ts +36 -77
- package/src/analyses/ControllerAnalyzer.ts +1 -1
- package/src/executable/internal/NestiaConfigLoader.ts +82 -0
- package/src/executable/internal/NestiaProjectGetter.ts +11 -0
- package/src/executable/internal/NestiaSdkCommand.ts +23 -146
- package/src/executable/internal/{nestia.config.getter.ts → nestia.project.getter.ts} +2 -2
- package/src/executable/sdk.ts +3 -3
- package/src/generates/SwaggerGenerator.ts +5 -4
- package/src/generates/internal/SwaggerSchemaGenerator.ts +83 -86
- package/src/generates/internal/SwaggerSchemaValidator.ts +0 -6
- package/lib/executable/internal/NestiaConfigCompilerOptions.d.ts +0 -12
- package/lib/executable/internal/NestiaConfigCompilerOptions.js +0 -18
- package/lib/executable/internal/NestiaConfigCompilerOptions.js.map +0 -1
- package/lib/executable/internal/NestiaSdkConfig.d.ts +0 -4
- package/lib/executable/internal/NestiaSdkConfig.js +0 -1019
- package/lib/executable/internal/NestiaSdkConfig.js.map +0 -1
- package/lib/executable/internal/nestia.config.getter.js.map +0 -1
- package/src/executable/internal/NestiaConfigCompilerOptions.ts +0 -19
- package/src/executable/internal/NestiaSdkConfig.ts +0 -36
- /package/lib/executable/internal/{nestia.config.getter.d.ts → nestia.project.getter.d.ts} +0 -0
package/src/INestiaConfig.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import type ts from "typescript";
|
|
2
|
-
|
|
3
1
|
import type { ISwagger } from "./structures/ISwagger";
|
|
4
2
|
import { ISwaggerInfo } from "./structures/ISwaggerInfo";
|
|
5
3
|
import { ISwaggerSecurityScheme } from "./structures/ISwaggerSecurityScheme";
|
|
6
|
-
import type { StripEnums } from "./utils/StripEnums";
|
|
7
4
|
|
|
8
5
|
/**
|
|
9
6
|
* Definition for the `nestia.config.ts` file.
|
|
@@ -56,26 +53,43 @@ export interface INestiaConfig {
|
|
|
56
53
|
e2e?: string;
|
|
57
54
|
|
|
58
55
|
/**
|
|
59
|
-
*
|
|
56
|
+
* Whether to wrap DTO by primitive type.
|
|
57
|
+
*
|
|
58
|
+
* If you don't configure this property as `false`, all of DTOs in the
|
|
59
|
+
* SDK library would be automatically wrapped by {@link Primitive} type.
|
|
60
|
+
*
|
|
61
|
+
* For refenrece, if a DTO type be capsuled by the {@link Primitive} type,
|
|
62
|
+
* all of methods in the DTO type would be automatically erased. Also, if
|
|
63
|
+
* the DTO has a `toJSON()` method, the DTO type would be automatically
|
|
64
|
+
* converted to return type of the `toJSON()` method.
|
|
65
|
+
*
|
|
66
|
+
* @default true
|
|
67
|
+
*/
|
|
68
|
+
primitive?: boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Allow simulation mode.
|
|
60
72
|
*
|
|
61
|
-
* If you
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* with
|
|
73
|
+
* If you configure this property to be `true`, the SDK library would be contain
|
|
74
|
+
* simulation mode. In the simulation mode, the SDK library would not communicate
|
|
75
|
+
* with the real backend server, but just returns random mock-up data
|
|
76
|
+
* with requestion data validation.
|
|
65
77
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
78
|
+
* For reference, random mock-up data would be generated by `typia.random<T>()`
|
|
79
|
+
* function.
|
|
68
80
|
*
|
|
69
|
-
*
|
|
70
|
-
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
simulate?: boolean;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Location of `tsconfig.json` file.
|
|
87
|
+
*
|
|
88
|
+
* If be configured, target file will replace the `tsconfig.json` file.
|
|
71
89
|
*
|
|
72
|
-
*
|
|
73
|
-
* ...tsconfig.compilerOptions,
|
|
74
|
-
* ...(nestiaConfig.compilerOptions ?? {})
|
|
75
|
-
* }
|
|
76
|
-
* ```
|
|
90
|
+
* @default tsconfig.json
|
|
77
91
|
*/
|
|
78
|
-
|
|
92
|
+
project?: string;
|
|
79
93
|
|
|
80
94
|
/**
|
|
81
95
|
* Whether to assert parameter types or not.
|
|
@@ -105,36 +119,6 @@ export interface INestiaConfig {
|
|
|
105
119
|
* @default false
|
|
106
120
|
*/
|
|
107
121
|
json?: boolean;
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Whether to wrap DTO by primitive type.
|
|
111
|
-
*
|
|
112
|
-
* If you don't configure this property as `false`, all of DTOs in the
|
|
113
|
-
* SDK library would be automatically wrapped by {@link Primitive} type.
|
|
114
|
-
*
|
|
115
|
-
* For refenrece, if a DTO type be capsuled by the {@link Primitive} type,
|
|
116
|
-
* all of methods in the DTO type would be automatically erased. Also, if
|
|
117
|
-
* the DTO has a `toJSON()` method, the DTO type would be automatically
|
|
118
|
-
* converted to return type of the `toJSON()` method.
|
|
119
|
-
*
|
|
120
|
-
* @default true
|
|
121
|
-
*/
|
|
122
|
-
primitive?: boolean;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Allow simulation mode.
|
|
126
|
-
*
|
|
127
|
-
* If you configure this property to be `true`, the SDK library would be contain
|
|
128
|
-
* simulation mode. In the simulation mode, the SDK library would not communicate
|
|
129
|
-
* with the real backend server, but just returns random mock-up data
|
|
130
|
-
* with requestion data validation.
|
|
131
|
-
*
|
|
132
|
-
* For reference, random mock-up data would be generated by `typia.random<T>()`
|
|
133
|
-
* function.
|
|
134
|
-
*
|
|
135
|
-
* @default false
|
|
136
|
-
*/
|
|
137
|
-
simulate?: boolean;
|
|
138
122
|
}
|
|
139
123
|
export namespace INestiaConfig {
|
|
140
124
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import * as runner from "ts-node";
|
|
4
3
|
import { Pair, Singleton } from "tstl";
|
|
5
4
|
import ts from "typescript";
|
|
6
5
|
|
|
@@ -8,7 +7,6 @@ import { INestiaConfig } from "./INestiaConfig";
|
|
|
8
7
|
import { AccessorAnalyzer } from "./analyses/AccessorAnalyzer";
|
|
9
8
|
import { ControllerAnalyzer } from "./analyses/ControllerAnalyzer";
|
|
10
9
|
import { ReflectAnalyzer } from "./analyses/ReflectAnalyzer";
|
|
11
|
-
import { NestiaConfigCompilerOptions } from "./executable/internal/NestiaConfigCompilerOptions";
|
|
12
10
|
import { E2eGenerator } from "./generates/E2eGenerator";
|
|
13
11
|
import { SdkGenerator } from "./generates/SdkGenerator";
|
|
14
12
|
import { SwaggerGenerator } from "./generates/SwaggerGenerator";
|
|
@@ -19,13 +17,9 @@ import { NestiaConfigUtil } from "./utils/NestiaConfigUtil";
|
|
|
19
17
|
import { SourceFinder } from "./utils/SourceFinder";
|
|
20
18
|
|
|
21
19
|
export class NestiaSdkApplication {
|
|
22
|
-
private readonly
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
public constructor(private readonly config_: INestiaConfig) {
|
|
27
|
-
this.bundle_checker_ = new Singleton(async () => {
|
|
28
|
-
if (!this.config_.output) return () => false;
|
|
20
|
+
private readonly checker_: Singleton<Promise<(str: string) => boolean>> =
|
|
21
|
+
new Singleton(async () => {
|
|
22
|
+
if (!this.config) return () => false;
|
|
29
23
|
|
|
30
24
|
const bundles: string[] = await fs.promises.readdir(
|
|
31
25
|
SdkGenerator.BUNDLE_PATH,
|
|
@@ -34,7 +28,7 @@ export class NestiaSdkApplication {
|
|
|
34
28
|
bundles,
|
|
35
29
|
async (file) => {
|
|
36
30
|
const relative: string = path.join(
|
|
37
|
-
this.
|
|
31
|
+
this.config!.output!,
|
|
38
32
|
file,
|
|
39
33
|
);
|
|
40
34
|
const location: string = path.join(
|
|
@@ -55,14 +49,33 @@ export class NestiaSdkApplication {
|
|
|
55
49
|
return false;
|
|
56
50
|
};
|
|
57
51
|
});
|
|
52
|
+
|
|
53
|
+
public constructor(
|
|
54
|
+
private readonly config: INestiaConfig,
|
|
55
|
+
private readonly compilerOptions: ts.CompilerOptions,
|
|
56
|
+
) {}
|
|
57
|
+
|
|
58
|
+
private async is_not_excluded(file: string): Promise<boolean> {
|
|
59
|
+
if (this.config.output)
|
|
60
|
+
return (
|
|
61
|
+
file.indexOf(path.join(this.config.output, "functional")) ===
|
|
62
|
+
-1 && (await this.checker_.get())(file) === false
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const content: string = await fs.promises.readFile(file, "utf8");
|
|
66
|
+
return (
|
|
67
|
+
content.indexOf(
|
|
68
|
+
" * @nestia Generated by Nestia - https://github.com/samchon/nestia",
|
|
69
|
+
) === -1
|
|
70
|
+
);
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
public async e2e(): Promise<void> {
|
|
61
|
-
if (!this.
|
|
74
|
+
if (!this.config.output)
|
|
62
75
|
throw new Error(
|
|
63
76
|
"Error on NestiaApplication.e2e(): output path of SDK is not specified.",
|
|
64
77
|
);
|
|
65
|
-
else if (!this.
|
|
78
|
+
else if (!this.config.e2e)
|
|
66
79
|
throw new Error(
|
|
67
80
|
"Error on NestiaApplication.e2e(): output path of e2e test files is not specified.",
|
|
68
81
|
);
|
|
@@ -77,8 +90,8 @@ export class NestiaSdkApplication {
|
|
|
77
90
|
`Error on NestiaApplication.e2e(): output directory of ${title} does not exists.`,
|
|
78
91
|
);
|
|
79
92
|
};
|
|
80
|
-
await validate("sdk")(this.
|
|
81
|
-
await validate("e2e")(this.
|
|
93
|
+
await validate("sdk")(this.config.output);
|
|
94
|
+
await validate("e2e")(this.config.e2e);
|
|
82
95
|
|
|
83
96
|
title("Nestia E2E Generator");
|
|
84
97
|
await this.generate(
|
|
@@ -92,12 +105,12 @@ export class NestiaSdkApplication {
|
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
public async sdk(): Promise<void> {
|
|
95
|
-
if (!this.
|
|
108
|
+
if (!this.config.output)
|
|
96
109
|
throw new Error(
|
|
97
110
|
"Error on NestiaApplication.sdk(): output path is not specified.",
|
|
98
111
|
);
|
|
99
112
|
|
|
100
|
-
const parent: string = path.resolve(this.
|
|
113
|
+
const parent: string = path.resolve(this.config.output + "/..");
|
|
101
114
|
const stats: fs.Stats = await fs.promises.lstat(parent);
|
|
102
115
|
if (stats.isDirectory() === false)
|
|
103
116
|
throw new Error(
|
|
@@ -113,15 +126,15 @@ export class NestiaSdkApplication {
|
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
public async swagger(): Promise<void> {
|
|
116
|
-
if (!this.
|
|
129
|
+
if (!this.config.swagger?.output)
|
|
117
130
|
throw new Error(
|
|
118
131
|
`Error on NestiaApplication.swagger(): output path of the "swagger.json" is not specified.`,
|
|
119
132
|
);
|
|
120
133
|
|
|
121
|
-
const parsed: path.ParsedPath = path.parse(this.
|
|
134
|
+
const parsed: path.ParsedPath = path.parse(this.config.swagger.output);
|
|
122
135
|
const directory: string = !!parsed.ext
|
|
123
136
|
? path.resolve(parsed.dir)
|
|
124
|
-
: this.
|
|
137
|
+
: this.config.swagger.output;
|
|
125
138
|
const stats: fs.Stats = await fs.promises.lstat(directory);
|
|
126
139
|
if (stats.isDirectory() === false)
|
|
127
140
|
throw new Error(
|
|
@@ -143,12 +156,9 @@ export class NestiaSdkApplication {
|
|
|
143
156
|
checker: ts.TypeChecker,
|
|
144
157
|
) => (config: Config) => (routes: IRoute[]) => Promise<void>,
|
|
145
158
|
): Promise<void> {
|
|
146
|
-
// MOUNT TS-NODE
|
|
147
|
-
this.prepare(method);
|
|
148
|
-
|
|
149
159
|
// LOAD CONTROLLER FILES
|
|
150
160
|
const input: INestiaConfig.IInput = NestiaConfigUtil.input(
|
|
151
|
-
this.
|
|
161
|
+
this.config.input,
|
|
152
162
|
);
|
|
153
163
|
const fileList: string[] = await ArrayUtil.asyncFilter(
|
|
154
164
|
await SourceFinder.find({
|
|
@@ -197,7 +207,7 @@ export class NestiaSdkApplication {
|
|
|
197
207
|
console.log("Analyzing source codes");
|
|
198
208
|
const program: ts.Program = ts.createProgram(
|
|
199
209
|
controllers.map((c) => c.file),
|
|
200
|
-
this.
|
|
210
|
+
this.compilerOptions,
|
|
201
211
|
);
|
|
202
212
|
const checker: ts.TypeChecker = program.getTypeChecker();
|
|
203
213
|
|
|
@@ -224,59 +234,7 @@ export class NestiaSdkApplication {
|
|
|
224
234
|
|
|
225
235
|
// DO GENERATE
|
|
226
236
|
AccessorAnalyzer.analyze(routeList);
|
|
227
|
-
await archiver(checker)(config(this.
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
private prepare(method: string): void {
|
|
231
|
-
// CONSTRUCT OPTIONS
|
|
232
|
-
if (!this.config_.compilerOptions)
|
|
233
|
-
this.config_.compilerOptions =
|
|
234
|
-
NestiaConfigCompilerOptions.DEFAULT_OPTIONS as any;
|
|
235
|
-
const absoluted: boolean = !!this.config_.compilerOptions?.baseUrl;
|
|
236
|
-
|
|
237
|
-
// CHECK STRICT OPTION
|
|
238
|
-
const strict: boolean =
|
|
239
|
-
this.config_.compilerOptions?.strictNullChecks !== undefined
|
|
240
|
-
? !!this.config_.compilerOptions.strictNullChecks
|
|
241
|
-
: !!this.config_.compilerOptions?.strict;
|
|
242
|
-
if (strict === false)
|
|
243
|
-
throw new Error(
|
|
244
|
-
`Error on NestiaSdkApplication.${method}(): nestia requires \`compilerOptions.strictNullChecks\` to be true.`,
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
const ttsc: boolean =
|
|
248
|
-
ts.version < "5.0.0" &&
|
|
249
|
-
(() => {
|
|
250
|
-
try {
|
|
251
|
-
require.resolve("ttypescript");
|
|
252
|
-
return true;
|
|
253
|
-
} catch (e) {
|
|
254
|
-
return false;
|
|
255
|
-
}
|
|
256
|
-
})();
|
|
257
|
-
|
|
258
|
-
// MOUNT TS-NODE
|
|
259
|
-
runner.register({
|
|
260
|
-
emit: false,
|
|
261
|
-
compiler: ttsc ? "ttypescript" : undefined,
|
|
262
|
-
compilerOptions: this.config_.compilerOptions,
|
|
263
|
-
require: absoluted ? ["tsconfig-paths/register"] : undefined,
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
private async is_not_excluded(file: string): Promise<boolean> {
|
|
268
|
-
if (this.config_.output)
|
|
269
|
-
return (
|
|
270
|
-
file.indexOf(path.join(this.config_.output, "functional")) ===
|
|
271
|
-
-1 && (await this.bundle_checker_.get())(file) === false
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
const content: string = await fs.promises.readFile(file, "utf8");
|
|
275
|
-
return (
|
|
276
|
-
content.indexOf(
|
|
277
|
-
" * @nestia Generated by Nestia - https://github.com/samchon/nestia",
|
|
278
|
-
) === -1
|
|
279
|
-
);
|
|
237
|
+
await archiver(checker)(config(this.config))(routeList);
|
|
280
238
|
}
|
|
281
239
|
}
|
|
282
240
|
|
|
@@ -301,4 +259,5 @@ const is_implicit_return_typed = (route: IRoute): boolean => {
|
|
|
301
259
|
else if (VARIABLE.test(name[i])) return false;
|
|
302
260
|
return true;
|
|
303
261
|
};
|
|
262
|
+
|
|
304
263
|
const VARIABLE = /[a-zA-Z_$0-9]/;
|
|
@@ -192,7 +192,7 @@ export namespace ControllerAnalyzer {
|
|
|
192
192
|
})(),
|
|
193
193
|
description: CommentFactory.description(symbol),
|
|
194
194
|
operationId: tags
|
|
195
|
-
.find(({ name }) => name === "
|
|
195
|
+
.find(({ name }) => name === "operationId")
|
|
196
196
|
?.text!?.[0].text.split(" ")[0]
|
|
197
197
|
.trim(),
|
|
198
198
|
tags,
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { WorkerConnector } from "tgrid/protocols/workers/WorkerConnector";
|
|
4
|
+
import { register } from "ts-node";
|
|
5
|
+
import { parseNative } from "tsconfck";
|
|
6
|
+
import ts from "typescript";
|
|
7
|
+
|
|
8
|
+
import typia from "typia";
|
|
9
|
+
|
|
10
|
+
import { INestiaConfig } from "../../INestiaConfig";
|
|
11
|
+
import { NestiaProjectGetter } from "./NestiaProjectGetter";
|
|
12
|
+
|
|
13
|
+
export namespace NestiaConfigLoader {
|
|
14
|
+
export const compilerOptions = async (
|
|
15
|
+
project: string,
|
|
16
|
+
): Promise<ts.CompilerOptions> => {
|
|
17
|
+
const configFileName = ts.findConfigFile(
|
|
18
|
+
process.cwd(),
|
|
19
|
+
ts.sys.fileExists,
|
|
20
|
+
project,
|
|
21
|
+
);
|
|
22
|
+
if (!configFileName)
|
|
23
|
+
throw new Error(`unable to find "tsconfig.json" file.`);
|
|
24
|
+
|
|
25
|
+
const { tsconfig } = await parseNative(configFileName);
|
|
26
|
+
const configFileText = JSON.stringify(tsconfig);
|
|
27
|
+
const { config } = ts.parseConfigFileTextToJson(
|
|
28
|
+
configFileName,
|
|
29
|
+
configFileText,
|
|
30
|
+
);
|
|
31
|
+
const configParseResult = ts.parseJsonConfigFileContent(
|
|
32
|
+
config,
|
|
33
|
+
ts.sys,
|
|
34
|
+
path.dirname(configFileName),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const { moduleResolution, ...result } =
|
|
38
|
+
configParseResult.raw.compilerOptions;
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const config = async (
|
|
43
|
+
options: ts.CompilerOptions,
|
|
44
|
+
): Promise<INestiaConfig> => {
|
|
45
|
+
if (fs.existsSync(path.resolve("nestia.config.ts")) === false)
|
|
46
|
+
throw new Error(`unable to find "nestia.config.ts" file.`);
|
|
47
|
+
|
|
48
|
+
register({
|
|
49
|
+
emit: false,
|
|
50
|
+
compilerOptions: options,
|
|
51
|
+
require: options.baseUrl ? ["tsconfig-paths/register"] : undefined,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const loaded: INestiaConfig & { default?: INestiaConfig } =
|
|
55
|
+
await import(path.resolve("nestia.config.ts"));
|
|
56
|
+
const config: INestiaConfig =
|
|
57
|
+
typeof loaded?.default === "object" && loaded.default !== null
|
|
58
|
+
? loaded.default
|
|
59
|
+
: loaded;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
return typia.assert(config);
|
|
63
|
+
} catch (exp) {
|
|
64
|
+
if (typia.is<typia.TypeGuardError>(exp))
|
|
65
|
+
exp.message = `invalid "nestia.config.ts" data.`;
|
|
66
|
+
throw exp;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const project = async (): Promise<string> => {
|
|
71
|
+
const connector = new WorkerConnector(null, null, "process");
|
|
72
|
+
await connector.connect(
|
|
73
|
+
`${__dirname}/nestia.project.getter.${__filename.substr(-2)}`,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const driver = await connector.getDriver<typeof NestiaProjectGetter>();
|
|
77
|
+
const project: string = await driver.get();
|
|
78
|
+
await connector.close();
|
|
79
|
+
|
|
80
|
+
return project;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NestiaConfigLoader } from "./NestiaConfigLoader";
|
|
2
|
+
|
|
3
|
+
export namespace NestiaProjectGetter {
|
|
4
|
+
export async function get(): Promise<string> {
|
|
5
|
+
const config = await NestiaConfigLoader.config({
|
|
6
|
+
module: "CommonJS" as any,
|
|
7
|
+
noEmit: true,
|
|
8
|
+
});
|
|
9
|
+
return config.project ?? "tsconfig.json";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,157 +1,34 @@
|
|
|
1
|
-
import cli from "cli";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { WorkerConnector } from "tgrid/protocols/workers/WorkerConnector";
|
|
4
|
-
import { parseNative } from "tsconfck";
|
|
5
1
|
import ts from "typescript";
|
|
6
2
|
|
|
7
3
|
import { INestiaConfig } from "../../INestiaConfig";
|
|
8
4
|
import { NestiaSdkApplication } from "../../NestiaSdkApplication";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
interface ICommand {
|
|
12
|
-
exclude: string | null;
|
|
13
|
-
out: string | null;
|
|
14
|
-
e2e: string | null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface IProps {
|
|
18
|
-
assign: (config: INestiaConfig, output: string) => void;
|
|
19
|
-
validate: (config: INestiaConfig) => boolean;
|
|
20
|
-
location: (config: INestiaConfig) => string;
|
|
21
|
-
}
|
|
5
|
+
import { NestiaConfigLoader } from "./NestiaConfigLoader";
|
|
22
6
|
|
|
23
7
|
export namespace NestiaSdkCommand {
|
|
24
|
-
export const sdk = (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export const e2e = (argv: string[]) =>
|
|
42
|
-
main({
|
|
43
|
-
assign: (config, output) => (config.output = output),
|
|
44
|
-
validate: (config) => !!config.output,
|
|
45
|
-
location: (config) => config.output!,
|
|
46
|
-
})(argv)((app) => app.e2e());
|
|
47
|
-
|
|
48
|
-
const main =
|
|
49
|
-
(props: IProps) =>
|
|
50
|
-
(argv: string[]) =>
|
|
51
|
-
async (task: (app: NestiaSdkApplication) => Promise<void>) => {
|
|
52
|
-
const command: ICommand = cli.parse({
|
|
53
|
-
exclude: ["e", "Something to exclude", "string", null],
|
|
54
|
-
out: ["o", "Output path of the SDK files", "string", null],
|
|
55
|
-
e2e: [
|
|
56
|
-
"e",
|
|
57
|
-
"Output path of e2e test function files",
|
|
58
|
-
"string",
|
|
59
|
-
null,
|
|
60
|
-
],
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const inputs: string[] = [];
|
|
64
|
-
for (const r of argv) {
|
|
65
|
-
if (r[0] === "-") break;
|
|
66
|
-
inputs.push(r);
|
|
67
|
-
}
|
|
68
|
-
await generate(props)(command)(inputs)(task);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const generate =
|
|
72
|
-
(props: IProps) =>
|
|
73
|
-
(command: ICommand) =>
|
|
74
|
-
(include: string[]) =>
|
|
75
|
-
async (task: (app: NestiaSdkApplication) => Promise<void>) => {
|
|
76
|
-
// CONFIGURATION
|
|
77
|
-
const config: INestiaConfig =
|
|
78
|
-
(await get_nestia_config(props.validate)) ??
|
|
79
|
-
parse_cli(props)(command)(include);
|
|
80
|
-
|
|
81
|
-
const options: ts.CompilerOptions | null =
|
|
82
|
-
await get_typescript_options();
|
|
83
|
-
config.compilerOptions = {
|
|
84
|
-
...(options ?? {}),
|
|
85
|
-
...(config.compilerOptions ?? {}),
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// CALL THE APP.GENERATE()
|
|
89
|
-
const app: NestiaSdkApplication = new NestiaSdkApplication(config);
|
|
90
|
-
await task(app);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
async function get_typescript_options(): Promise<ts.CompilerOptions | null> {
|
|
94
|
-
const configFileName = ts.findConfigFile(
|
|
95
|
-
process.cwd(),
|
|
96
|
-
ts.sys.fileExists,
|
|
97
|
-
"tsconfig.json",
|
|
8
|
+
export const sdk = () => main((app) => app.sdk());
|
|
9
|
+
export const swagger = () => main((app) => app.swagger());
|
|
10
|
+
export const e2e = () => main((app) => app.e2e());
|
|
11
|
+
|
|
12
|
+
const main = async (task: (app: NestiaSdkApplication) => Promise<void>) => {
|
|
13
|
+
await generate(task);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const generate = async (
|
|
17
|
+
task: (app: NestiaSdkApplication) => Promise<void>,
|
|
18
|
+
) => {
|
|
19
|
+
// LOAD CONFIG INFO
|
|
20
|
+
const project: string = await NestiaConfigLoader.project();
|
|
21
|
+
const compilerOptions: ts.CompilerOptions =
|
|
22
|
+
await NestiaConfigLoader.compilerOptions(project);
|
|
23
|
+
const config: INestiaConfig = await NestiaConfigLoader.config(
|
|
24
|
+
compilerOptions,
|
|
98
25
|
);
|
|
99
|
-
if (!configFileName) return null;
|
|
100
26
|
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
const { config } = ts.parseConfigFileTextToJson(
|
|
104
|
-
configFileName,
|
|
105
|
-
configFileText,
|
|
106
|
-
);
|
|
107
|
-
const configParseResult = ts.parseJsonConfigFileContent(
|
|
27
|
+
// GENERATE
|
|
28
|
+
const app: NestiaSdkApplication = new NestiaSdkApplication(
|
|
108
29
|
config,
|
|
109
|
-
|
|
110
|
-
path.dirname(configFileName),
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
const { moduleResolution, ...result } =
|
|
114
|
-
configParseResult.raw.compilerOptions;
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function get_nestia_config(
|
|
119
|
-
validate: (config: INestiaConfig) => boolean,
|
|
120
|
-
): Promise<INestiaConfig | null> {
|
|
121
|
-
const connector = new WorkerConnector(null, null, "process");
|
|
122
|
-
await connector.connect(
|
|
123
|
-
`${__dirname}/nestia.config.getter.${__filename.substr(-2)}`,
|
|
30
|
+
compilerOptions,
|
|
124
31
|
);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const config: INestiaConfig | null = await driver.get();
|
|
128
|
-
await connector.close();
|
|
129
|
-
|
|
130
|
-
if (config !== null && validate(config) === false)
|
|
131
|
-
throw new Error(
|
|
132
|
-
`Error on NestiaCommand.main(): output path is not specified in the "nestia.config.ts".`,
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
return config;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const parse_cli =
|
|
139
|
-
(props: IProps) =>
|
|
140
|
-
(command: ICommand) =>
|
|
141
|
-
(include: string[]): INestiaConfig => {
|
|
142
|
-
if (command.out === null)
|
|
143
|
-
throw new Error(
|
|
144
|
-
`Error on NestiaCommand.main(): output directory is not specified. Add the "--out <output_directory>" option.`,
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
const config: INestiaConfig = {
|
|
148
|
-
input: {
|
|
149
|
-
include,
|
|
150
|
-
exclude: command.exclude ? [command.exclude] : undefined,
|
|
151
|
-
},
|
|
152
|
-
e2e: command.e2e ?? undefined,
|
|
153
|
-
};
|
|
154
|
-
props.assign(config, command.out);
|
|
155
|
-
return config;
|
|
156
|
-
};
|
|
32
|
+
await task(app);
|
|
33
|
+
};
|
|
157
34
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { WorkerServer } from "tgrid/protocols/workers/WorkerServer";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { NestiaProjectGetter } from "./NestiaProjectGetter";
|
|
4
4
|
|
|
5
5
|
async function main(): Promise<void> {
|
|
6
6
|
const worker = new WorkerServer();
|
|
7
|
-
await worker.open(
|
|
7
|
+
await worker.open(NestiaProjectGetter);
|
|
8
8
|
}
|
|
9
9
|
main().catch((exp) => {
|
|
10
10
|
console.log(exp);
|
package/src/executable/sdk.ts
CHANGED
|
@@ -59,9 +59,9 @@ async function main() {
|
|
|
59
59
|
|
|
60
60
|
if (type === "dependencies") dependencies(argv);
|
|
61
61
|
else if (type === "init") await initialize();
|
|
62
|
-
else if (type === "sdk") await execute((c) => c.sdk(
|
|
63
|
-
else if (type === "swagger") await execute((c) => c.swagger(
|
|
64
|
-
else if (type === "e2e") await execute((c) => c.e2e(
|
|
62
|
+
else if (type === "sdk") await execute((c) => c.sdk());
|
|
63
|
+
else if (type === "swagger") await execute((c) => c.swagger());
|
|
64
|
+
else if (type === "e2e") await execute((c) => c.e2e());
|
|
65
65
|
else halt(USAGE);
|
|
66
66
|
}
|
|
67
67
|
main().catch((exp) => {
|
|
@@ -111,9 +111,9 @@ export namespace SwaggerGenerator {
|
|
|
111
111
|
if (errors.length) {
|
|
112
112
|
for (const e of errors)
|
|
113
113
|
console.error(
|
|
114
|
-
`${path.relative(location, process.cwd())}:${
|
|
115
|
-
e.route.symbol
|
|
116
|
-
}:${
|
|
114
|
+
`${path.relative(e.route.location, process.cwd())}:${
|
|
115
|
+
e.route.symbol.class
|
|
116
|
+
}.${e.route.symbol.function}:${
|
|
117
117
|
e.from
|
|
118
118
|
} - error TS(@nestia/sdk): invalid type detected.\n\n` +
|
|
119
119
|
e.messages.map((m) => ` - ${m}`).join("\n"),
|
|
@@ -348,7 +348,8 @@ export namespace SwaggerGenerator {
|
|
|
348
348
|
.filter((param) => param.category !== "body")
|
|
349
349
|
.map((param) =>
|
|
350
350
|
SwaggerSchemaGenerator.parameter(props)(route)(param),
|
|
351
|
-
)
|
|
351
|
+
)
|
|
352
|
+
.flat(),
|
|
352
353
|
requestBody: body
|
|
353
354
|
? SwaggerSchemaGenerator.body(props)(route)(body)
|
|
354
355
|
: undefined,
|