@nestia/sdk 2.4.3 → 3.0.0-dev.20231209

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.
Files changed (64) hide show
  1. package/lib/analyses/ReflectAnalyzer.js +1 -1
  2. package/lib/analyses/ReflectAnalyzer.js.map +1 -1
  3. package/lib/executable/sdk.js +11 -11
  4. package/lib/generates/internal/SdkFunctionProgrammer.js +2 -2
  5. package/lib/generates/internal/SdkFunctionProgrammer.js.map +1 -1
  6. package/lib/generates/internal/SwaggerSchemaGenerator.js.map +1 -1
  7. package/lib/structures/IController.d.ts +1 -1
  8. package/lib/structures/IRoute.d.ts +1 -1
  9. package/package.json +3 -3
  10. package/src/INestiaConfig.ts +234 -234
  11. package/src/NestiaSdkApplication.ts +253 -253
  12. package/src/analyses/AccessorAnalyzer.ts +60 -60
  13. package/src/analyses/ConfigAnalyzer.ts +147 -147
  14. package/src/analyses/ControllerAnalyzer.ts +379 -379
  15. package/src/analyses/ExceptionAnalyzer.ts +115 -115
  16. package/src/analyses/GenericAnalyzer.ts +51 -51
  17. package/src/analyses/ImportAnalyzer.ts +138 -138
  18. package/src/analyses/PathAnalyzer.ts +98 -98
  19. package/src/analyses/ReflectAnalyzer.ts +1 -1
  20. package/src/analyses/SecurityAnalyzer.ts +20 -20
  21. package/src/executable/internal/CommandParser.ts +15 -15
  22. package/src/executable/internal/NestiaConfigLoader.ts +67 -67
  23. package/src/executable/internal/NestiaSdkCommand.ts +60 -60
  24. package/src/executable/sdk.ts +73 -73
  25. package/src/generates/E2eGenerator.ts +64 -64
  26. package/src/generates/SdkGenerator.ts +96 -96
  27. package/src/generates/SwaggerGenerator.ts +372 -372
  28. package/src/generates/internal/E2eFileProgrammer.ts +123 -123
  29. package/src/generates/internal/SdkDistributionComposer.ts +91 -91
  30. package/src/generates/internal/SdkDtoGenerator.ts +424 -424
  31. package/src/generates/internal/SdkFileProgrammer.ts +106 -106
  32. package/src/generates/internal/SdkFunctionProgrammer.ts +2 -2
  33. package/src/generates/internal/SdkImportWizard.ts +55 -55
  34. package/src/generates/internal/SdkRouteDirectory.ts +17 -17
  35. package/src/generates/internal/SdkSimulationProgrammer.ts +133 -133
  36. package/src/generates/internal/SdkTypeDefiner.ts +119 -119
  37. package/src/generates/internal/SwaggerSchemaGenerator.ts +22 -23
  38. package/src/generates/internal/SwaggerSchemaValidator.ts +198 -198
  39. package/src/index.ts +4 -4
  40. package/src/module.ts +2 -2
  41. package/src/structures/IController.ts +5 -1
  42. package/src/structures/IErrorReport.ts +6 -6
  43. package/src/structures/INestiaProject.ts +13 -13
  44. package/src/structures/INormalizedInput.ts +20 -20
  45. package/src/structures/IRoute.ts +2 -1
  46. package/src/structures/ISwagger.ts +91 -91
  47. package/src/structures/ISwaggerComponents.ts +29 -29
  48. package/src/structures/ISwaggerError.ts +8 -8
  49. package/src/structures/ISwaggerInfo.ts +80 -80
  50. package/src/structures/ISwaggerLazyProperty.ts +7 -7
  51. package/src/structures/ISwaggerLazySchema.ts +7 -7
  52. package/src/structures/ISwaggerRoute.ts +51 -51
  53. package/src/structures/ISwaggerSecurityScheme.ts +65 -65
  54. package/src/structures/ITypeTuple.ts +6 -6
  55. package/src/structures/MethodType.ts +5 -5
  56. package/src/structures/ParamCategory.ts +1 -1
  57. package/src/structures/TypeEntry.ts +22 -22
  58. package/src/utils/ArrayUtil.ts +26 -26
  59. package/src/utils/FileRetriever.ts +22 -22
  60. package/src/utils/ImportDictionary.ts +125 -125
  61. package/src/utils/MapUtil.ts +14 -14
  62. package/src/utils/PathUtil.ts +10 -10
  63. package/src/utils/SourceFinder.ts +66 -66
  64. package/src/utils/StripEnums.ts +5 -5
@@ -1,98 +1,98 @@
1
- import { RequestMethod } from "@nestjs/common";
2
- import path from "path";
3
- import { Token, parse } from "path-to-regexp";
4
-
5
- import { INormalizedInput } from "../structures/INormalizedInput";
6
-
7
- export namespace PathAnalyzer {
8
- export const combinate =
9
- (globalPrefix: INormalizedInput["globalPrefix"]) =>
10
- (versions: Array<string | null>) =>
11
- (props: { path: string; method: string }): string[] => {
12
- const out = (str: string) =>
13
- versions.map((v) => (v === null ? str : join(v, str)));
14
- if (!globalPrefix?.prefix.length) return out(props.path);
15
- else if (!globalPrefix.exclude?.length)
16
- return out(props.path).map((str) => join(globalPrefix.prefix, str));
17
- return globalPrefix.exclude.some((exclude) =>
18
- typeof exclude === "string"
19
- ? RegExp(exclude).test(props.path)
20
- : METHOD(exclude.method) === props.method &&
21
- RegExp(exclude.path).test(props.path),
22
- )
23
- ? out(props.path)
24
- : out(props.path).map((str) => join(globalPrefix.prefix, str));
25
- };
26
-
27
- export const join = (...args: string[]) =>
28
- "/" +
29
- _Trim(
30
- path
31
- .join(...args.filter((s) => !!s.length))
32
- .split("\\")
33
- .join("/"),
34
- );
35
-
36
- export const escape = (str: string, method: () => string) =>
37
- "/" +
38
- _Parse(str, method)
39
- .map((arg) => (arg.type === "param" ? `:${arg.value}` : arg.value))
40
- .join("/");
41
-
42
- export const parameters = (str: string, method: () => string) =>
43
- _Parse(str, method)
44
- .filter((arg) => arg.type === "param")
45
- .map((arg) => arg.value);
46
-
47
- function _Parse(str: string, method: () => string): IArgument[] {
48
- const tokens: Token[] = parse(path.join(str).split("\\").join("/"));
49
- const output: IArgument[] = [];
50
-
51
- for (const key of tokens) {
52
- if (typeof key === "string")
53
- output.push({
54
- type: "path",
55
- value: _Trim(key),
56
- });
57
- else if (typeof key.name === "number" || _Trim(key.name) === "")
58
- throw new Error(`Error on ${method}: ${ERROR_MESSAGE}.`);
59
- else
60
- output.push({
61
- type: "param",
62
- value: _Trim(key.name),
63
- });
64
- }
65
- return output;
66
- }
67
-
68
- function _Trim(str: string): string {
69
- if (str[0] === "/") str = str.substring(1);
70
- if (str[str.length - 1] === "/") str = str.substring(0, str.length - 1);
71
- return str;
72
- }
73
-
74
- interface IArgument {
75
- type: "param" | "path";
76
- value: string;
77
- }
78
- }
79
-
80
- const ERROR_MESSAGE = "nestia supports only string typed parameter on path";
81
- const METHOD = (value: RequestMethod) =>
82
- value === RequestMethod.ALL
83
- ? "all"
84
- : value === RequestMethod.DELETE
85
- ? "delete"
86
- : value === RequestMethod.GET
87
- ? "get"
88
- : value === RequestMethod.HEAD
89
- ? "head"
90
- : value === RequestMethod.OPTIONS
91
- ? "options"
92
- : value === RequestMethod.PATCH
93
- ? "patch"
94
- : value === RequestMethod.POST
95
- ? "post"
96
- : value === RequestMethod.PUT
97
- ? "put"
98
- : "unknown";
1
+ import { RequestMethod } from "@nestjs/common";
2
+ import path from "path";
3
+ import { Token, parse } from "path-to-regexp";
4
+
5
+ import { INormalizedInput } from "../structures/INormalizedInput";
6
+
7
+ export namespace PathAnalyzer {
8
+ export const combinate =
9
+ (globalPrefix: INormalizedInput["globalPrefix"]) =>
10
+ (versions: Array<string | null>) =>
11
+ (props: { path: string; method: string }): string[] => {
12
+ const out = (str: string) =>
13
+ versions.map((v) => (v === null ? str : join(v, str)));
14
+ if (!globalPrefix?.prefix.length) return out(props.path);
15
+ else if (!globalPrefix.exclude?.length)
16
+ return out(props.path).map((str) => join(globalPrefix.prefix, str));
17
+ return globalPrefix.exclude.some((exclude) =>
18
+ typeof exclude === "string"
19
+ ? RegExp(exclude).test(props.path)
20
+ : METHOD(exclude.method) === props.method &&
21
+ RegExp(exclude.path).test(props.path),
22
+ )
23
+ ? out(props.path)
24
+ : out(props.path).map((str) => join(globalPrefix.prefix, str));
25
+ };
26
+
27
+ export const join = (...args: string[]) =>
28
+ "/" +
29
+ _Trim(
30
+ path
31
+ .join(...args.filter((s) => !!s.length))
32
+ .split("\\")
33
+ .join("/"),
34
+ );
35
+
36
+ export const escape = (str: string, method: () => string) =>
37
+ "/" +
38
+ _Parse(str, method)
39
+ .map((arg) => (arg.type === "param" ? `:${arg.value}` : arg.value))
40
+ .join("/");
41
+
42
+ export const parameters = (str: string, method: () => string) =>
43
+ _Parse(str, method)
44
+ .filter((arg) => arg.type === "param")
45
+ .map((arg) => arg.value);
46
+
47
+ function _Parse(str: string, method: () => string): IArgument[] {
48
+ const tokens: Token[] = parse(path.join(str).split("\\").join("/"));
49
+ const output: IArgument[] = [];
50
+
51
+ for (const key of tokens) {
52
+ if (typeof key === "string")
53
+ output.push({
54
+ type: "path",
55
+ value: _Trim(key),
56
+ });
57
+ else if (typeof key.name === "number" || _Trim(key.name) === "")
58
+ throw new Error(`Error on ${method}: ${ERROR_MESSAGE}.`);
59
+ else
60
+ output.push({
61
+ type: "param",
62
+ value: _Trim(key.name),
63
+ });
64
+ }
65
+ return output;
66
+ }
67
+
68
+ function _Trim(str: string): string {
69
+ if (str[0] === "/") str = str.substring(1);
70
+ if (str[str.length - 1] === "/") str = str.substring(0, str.length - 1);
71
+ return str;
72
+ }
73
+
74
+ interface IArgument {
75
+ type: "param" | "path";
76
+ value: string;
77
+ }
78
+ }
79
+
80
+ const ERROR_MESSAGE = "nestia supports only string typed parameter on path";
81
+ const METHOD = (value: RequestMethod) =>
82
+ value === RequestMethod.ALL
83
+ ? "all"
84
+ : value === RequestMethod.DELETE
85
+ ? "delete"
86
+ : value === RequestMethod.GET
87
+ ? "get"
88
+ : value === RequestMethod.HEAD
89
+ ? "head"
90
+ : value === RequestMethod.OPTIONS
91
+ ? "options"
92
+ : value === RequestMethod.PATCH
93
+ ? "patch"
94
+ : value === RequestMethod.POST
95
+ ? "post"
96
+ : value === RequestMethod.PUT
97
+ ? "put"
98
+ : "unknown";
@@ -280,7 +280,7 @@ export namespace ReflectAnalyzer {
280
280
  status: Reflect.getMetadata(Constants.HTTP_CODE_METADATA, proto),
281
281
  encrypted,
282
282
  contentType: encrypted
283
- ? "text/plain"
283
+ ? "application/octet-stream"
284
284
  : query
285
285
  ? "application/x-www-form-urlencoded"
286
286
  : Reflect.getMetadata(Constants.HEADERS_METADATA, proto)?.find(
@@ -1,20 +1,20 @@
1
- import { MapUtil } from "../utils/MapUtil";
2
-
3
- export namespace SecurityAnalyzer {
4
- export const merge = (...entire: Record<string, string[]>[]) => {
5
- const dict: Map<string, Set<string>> = new Map();
6
- for (const obj of entire)
7
- for (const [key, value] of Object.entries(obj)) {
8
- const set = MapUtil.take(dict, key, () => new Set());
9
- for (const val of value) set.add(val);
10
- }
11
- const output: Record<string, string[]>[] = [];
12
- for (const [key, set] of dict) {
13
- const obj = {
14
- [key]: [...set],
15
- };
16
- output.push(obj);
17
- }
18
- return output;
19
- };
20
- }
1
+ import { MapUtil } from "../utils/MapUtil";
2
+
3
+ export namespace SecurityAnalyzer {
4
+ export const merge = (...entire: Record<string, string[]>[]) => {
5
+ const dict: Map<string, Set<string>> = new Map();
6
+ for (const obj of entire)
7
+ for (const [key, value] of Object.entries(obj)) {
8
+ const set = MapUtil.take(dict, key, () => new Set());
9
+ for (const val of value) set.add(val);
10
+ }
11
+ const output: Record<string, string[]>[] = [];
12
+ for (const [key, set] of dict) {
13
+ const obj = {
14
+ [key]: [...set],
15
+ };
16
+ output.push(obj);
17
+ }
18
+ return output;
19
+ };
20
+ }
@@ -1,15 +1,15 @@
1
- export namespace CommandParser {
2
- export function parse(argList: string[]): Record<string, string> {
3
- const output: Record<string, string> = {};
4
- argList.forEach((arg, i) => {
5
- if (arg.startsWith("--") === false) return;
6
-
7
- const key = arg.slice(2);
8
- const value: string | undefined = argList[i + 1];
9
- if (value === undefined || value.startsWith("--")) return;
10
-
11
- output[key] = value;
12
- });
13
- return output;
14
- }
15
- }
1
+ export namespace CommandParser {
2
+ export function parse(argList: string[]): Record<string, string> {
3
+ const output: Record<string, string> = {};
4
+ argList.forEach((arg, i) => {
5
+ if (arg.startsWith("--") === false) return;
6
+
7
+ const key = arg.slice(2);
8
+ const value: string | undefined = argList[i + 1];
9
+ if (value === undefined || value.startsWith("--")) return;
10
+
11
+ output[key] = value;
12
+ });
13
+ return output;
14
+ }
15
+ }
@@ -1,67 +1,67 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { register } from "ts-node";
4
- import { parseNative } from "tsconfck";
5
- import ts from "typescript";
6
- import typia from "typia";
7
-
8
- import { INestiaConfig } from "../../INestiaConfig";
9
-
10
- export namespace NestiaConfigLoader {
11
- export const compilerOptions = async (
12
- project: string,
13
- ): Promise<ts.CompilerOptions> => {
14
- const configFileName = ts.findConfigFile(
15
- process.cwd(),
16
- ts.sys.fileExists,
17
- project,
18
- );
19
- if (!configFileName) throw new Error(`unable to find "${project}" file.`);
20
-
21
- const { tsconfig } = await parseNative(configFileName);
22
- const configFileText = JSON.stringify(tsconfig);
23
- const { config } = ts.parseConfigFileTextToJson(
24
- configFileName,
25
- configFileText,
26
- );
27
- const configParseResult = ts.parseJsonConfigFileContent(
28
- config,
29
- ts.sys,
30
- path.dirname(configFileName),
31
- );
32
-
33
- const { moduleResolution, ...result } =
34
- configParseResult.raw.compilerOptions;
35
- return result;
36
- };
37
-
38
- export const config = async (
39
- file: string,
40
- options: ts.CompilerOptions,
41
- ): Promise<INestiaConfig> => {
42
- if (fs.existsSync(path.resolve(file)) === false)
43
- throw new Error(`Unable to find "${file}" file.`);
44
-
45
- register({
46
- emit: false,
47
- compilerOptions: options,
48
- require: options.baseUrl ? ["tsconfig-paths/register"] : undefined,
49
- });
50
-
51
- const loaded: INestiaConfig & { default?: INestiaConfig } = await import(
52
- path.resolve(file)
53
- );
54
- const config: INestiaConfig =
55
- typeof loaded?.default === "object" && loaded.default !== null
56
- ? loaded.default
57
- : loaded;
58
-
59
- try {
60
- return typia.assert(config);
61
- } catch (exp) {
62
- if (typia.is<typia.TypeGuardError>(exp))
63
- exp.message = `invalid "${file}" data.`;
64
- throw exp;
65
- }
66
- };
67
- }
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { register } from "ts-node";
4
+ import { parseNative } from "tsconfck";
5
+ import ts from "typescript";
6
+ import typia from "typia";
7
+
8
+ import { INestiaConfig } from "../../INestiaConfig";
9
+
10
+ export namespace NestiaConfigLoader {
11
+ export const compilerOptions = async (
12
+ project: string,
13
+ ): Promise<ts.CompilerOptions> => {
14
+ const configFileName = ts.findConfigFile(
15
+ process.cwd(),
16
+ ts.sys.fileExists,
17
+ project,
18
+ );
19
+ if (!configFileName) throw new Error(`unable to find "${project}" file.`);
20
+
21
+ const { tsconfig } = await parseNative(configFileName);
22
+ const configFileText = JSON.stringify(tsconfig);
23
+ const { config } = ts.parseConfigFileTextToJson(
24
+ configFileName,
25
+ configFileText,
26
+ );
27
+ const configParseResult = ts.parseJsonConfigFileContent(
28
+ config,
29
+ ts.sys,
30
+ path.dirname(configFileName),
31
+ );
32
+
33
+ const { moduleResolution, ...result } =
34
+ configParseResult.raw.compilerOptions;
35
+ return result;
36
+ };
37
+
38
+ export const config = async (
39
+ file: string,
40
+ options: ts.CompilerOptions,
41
+ ): Promise<INestiaConfig> => {
42
+ if (fs.existsSync(path.resolve(file)) === false)
43
+ throw new Error(`Unable to find "${file}" file.`);
44
+
45
+ register({
46
+ emit: false,
47
+ compilerOptions: options,
48
+ require: options.baseUrl ? ["tsconfig-paths/register"] : undefined,
49
+ });
50
+
51
+ const loaded: INestiaConfig & { default?: INestiaConfig } = await import(
52
+ path.resolve(file)
53
+ );
54
+ const config: INestiaConfig =
55
+ typeof loaded?.default === "object" && loaded.default !== null
56
+ ? loaded.default
57
+ : loaded;
58
+
59
+ try {
60
+ return typia.assert(config);
61
+ } catch (exp) {
62
+ if (typia.is<typia.TypeGuardError>(exp))
63
+ exp.message = `invalid "${file}" data.`;
64
+ throw exp;
65
+ }
66
+ };
67
+ }
@@ -1,60 +1,60 @@
1
- import ts from "typescript";
2
-
3
- import { INestiaConfig } from "../../INestiaConfig";
4
- import { NestiaSdkApplication } from "../../NestiaSdkApplication";
5
- import { NestiaConfigLoader } from "./NestiaConfigLoader";
6
-
7
- export namespace NestiaSdkCommand {
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 compilerOptions: ts.CompilerOptions =
21
- await NestiaConfigLoader.compilerOptions(
22
- getFileArgument({
23
- type: "project",
24
- extension: "json",
25
- }) ?? "tsconfig.json",
26
- );
27
- const config: INestiaConfig = await NestiaConfigLoader.config(
28
- getFileArgument({
29
- type: "config",
30
- extension: "ts",
31
- }) ?? "nestia.config.ts",
32
- compilerOptions,
33
- );
34
-
35
- // GENERATE
36
- const app: NestiaSdkApplication = new NestiaSdkApplication(
37
- config,
38
- compilerOptions,
39
- );
40
- await task(app);
41
- };
42
-
43
- const getFileArgument = (props: {
44
- type: string;
45
- extension: string;
46
- }): string | null => {
47
- const argv: string[] = process.argv.slice(3);
48
- if (argv.length === 0) return null;
49
-
50
- const index: number = argv.findIndex((str) => str === `--${props.type}`);
51
- if (index === -1) return null;
52
- else if (argv.length === 1)
53
- throw new Error(`${props.type} file must be provided`);
54
-
55
- const file: string = argv[index + 1];
56
- if (file.endsWith(props.extension) === false)
57
- throw new Error(`${props.type} file must be ${props.extension} file`);
58
- return file;
59
- };
60
- }
1
+ import ts from "typescript";
2
+
3
+ import { INestiaConfig } from "../../INestiaConfig";
4
+ import { NestiaSdkApplication } from "../../NestiaSdkApplication";
5
+ import { NestiaConfigLoader } from "./NestiaConfigLoader";
6
+
7
+ export namespace NestiaSdkCommand {
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 compilerOptions: ts.CompilerOptions =
21
+ await NestiaConfigLoader.compilerOptions(
22
+ getFileArgument({
23
+ type: "project",
24
+ extension: "json",
25
+ }) ?? "tsconfig.json",
26
+ );
27
+ const config: INestiaConfig = await NestiaConfigLoader.config(
28
+ getFileArgument({
29
+ type: "config",
30
+ extension: "ts",
31
+ }) ?? "nestia.config.ts",
32
+ compilerOptions,
33
+ );
34
+
35
+ // GENERATE
36
+ const app: NestiaSdkApplication = new NestiaSdkApplication(
37
+ config,
38
+ compilerOptions,
39
+ );
40
+ await task(app);
41
+ };
42
+
43
+ const getFileArgument = (props: {
44
+ type: string;
45
+ extension: string;
46
+ }): string | null => {
47
+ const argv: string[] = process.argv.slice(3);
48
+ if (argv.length === 0) return null;
49
+
50
+ const index: number = argv.findIndex((str) => str === `--${props.type}`);
51
+ if (index === -1) return null;
52
+ else if (argv.length === 1)
53
+ throw new Error(`${props.type} file must be provided`);
54
+
55
+ const file: string = argv[index + 1];
56
+ if (file.endsWith(props.extension) === false)
57
+ throw new Error(`${props.type} file must be ${props.extension} file`);
58
+ return file;
59
+ };
60
+ }