@nestia/sdk 11.0.0-dev.20260305 → 11.0.0-dev.20260312

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 (68) hide show
  1. package/assets/bundle/distribute/package.json +1 -1
  2. package/lib/INestiaConfig.d.ts +2 -2
  3. package/lib/NestiaSwaggerComposer.d.ts +2 -2
  4. package/lib/NestiaSwaggerComposer.js +4 -5
  5. package/lib/NestiaSwaggerComposer.js.map +1 -1
  6. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js +2 -0
  7. package/lib/analyses/ReflectHttpOperationExceptionAnalyzer.js.map +1 -1
  8. package/lib/executable/internal/NestiaConfigLoader.js +65 -10
  9. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  10. package/lib/executable/sdk.js +12 -12
  11. package/lib/generates/SwaggerGenerator.js +8 -9
  12. package/lib/generates/SwaggerGenerator.js.map +1 -1
  13. package/lib/generates/internal/SwaggerOperationParameterComposer.js +1 -1
  14. package/lib/generates/internal/SwaggerOperationParameterComposer.js.map +1 -1
  15. package/lib/transformers/SdkOperationTransformer.js +1 -1
  16. package/lib/transformers/SdkOperationTransformer.js.map +1 -1
  17. package/package.json +8 -8
  18. package/src/INestiaConfig.ts +2 -2
  19. package/src/NestiaSwaggerComposer.ts +10 -7
  20. package/src/analyses/ConfigAnalyzer.ts +155 -155
  21. package/src/analyses/ExceptionAnalyzer.ts +154 -154
  22. package/src/analyses/GenericAnalyzer.ts +49 -49
  23. package/src/analyses/PathAnalyzer.ts +69 -69
  24. package/src/analyses/ReflectControllerAnalyzer.ts +105 -105
  25. package/src/analyses/ReflectMetadataAnalyzer.ts +44 -44
  26. package/src/analyses/ReflectWebSocketOperationAnalyzer.ts +172 -172
  27. package/src/analyses/SecurityAnalyzer.ts +25 -25
  28. package/src/analyses/TypedWebSocketRouteAnalyzer.ts +33 -33
  29. package/src/decorators/OperationMetadata.ts +15 -15
  30. package/src/executable/internal/CommandParser.ts +15 -15
  31. package/src/executable/sdk.ts +75 -75
  32. package/src/generates/CloneGenerator.ts +66 -66
  33. package/src/generates/E2eGenerator.ts +32 -32
  34. package/src/generates/SdkGenerator.ts +160 -160
  35. package/src/generates/SwaggerGenerator.ts +16 -10
  36. package/src/generates/internal/SdkDistributionComposer.ts +103 -103
  37. package/src/generates/internal/SdkHttpParameterProgrammer.ts +178 -178
  38. package/src/generates/internal/SdkRouteDirectory.ts +18 -18
  39. package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +87 -87
  40. package/src/generates/internal/SwaggerDescriptionComposer.ts +64 -64
  41. package/src/generates/internal/SwaggerOperationParameterComposer.ts +1 -1
  42. package/src/index.ts +4 -4
  43. package/src/structures/INestiaProject.ts +13 -13
  44. package/src/structures/INestiaSdkInput.ts +20 -20
  45. package/src/structures/IReflectApplication.ts +8 -8
  46. package/src/structures/IReflectController.ts +15 -15
  47. package/src/structures/IReflectHttpOperation.ts +26 -26
  48. package/src/structures/IReflectImport.ts +6 -6
  49. package/src/structures/IReflectOperationError.ts +26 -26
  50. package/src/structures/IReflectType.ts +4 -4
  51. package/src/structures/IReflectWebSocketOperation.ts +17 -17
  52. package/src/structures/IReflectWebSocketOperationParameter.ts +36 -36
  53. package/src/structures/ITypedHttpRoute.ts +41 -41
  54. package/src/structures/ITypedWebSocketRoute.ts +24 -24
  55. package/src/structures/ITypedWebSocketRouteParameter.ts +3 -3
  56. package/src/structures/MethodType.ts +5 -5
  57. package/src/structures/ParamCategory.ts +1 -1
  58. package/src/structures/TypeEntry.ts +22 -22
  59. package/src/transform.ts +9 -9
  60. package/src/typings/get-function-location.d.ts +7 -7
  61. package/src/utils/ArrayUtil.ts +26 -26
  62. package/src/utils/FileRetriever.ts +22 -22
  63. package/src/utils/MapUtil.ts +14 -14
  64. package/src/utils/PathUtil.ts +10 -10
  65. package/src/utils/SourceFinder.ts +63 -63
  66. package/src/utils/StringUtil.ts +17 -17
  67. package/src/utils/StripEnums.ts +5 -5
  68. package/src/utils/VersioningStrategy.ts +28 -28
@@ -1,160 +1,160 @@
1
- import fs from "fs";
2
- import NodePath from "path";
3
- import { IPointer } from "tstl";
4
-
5
- import { INestiaConfig } from "../INestiaConfig";
6
- import { IReflectOperationError } from "../structures/IReflectOperationError";
7
- import { IReflectType } from "../structures/IReflectType";
8
- import { ITypedApplication } from "../structures/ITypedApplication";
9
- import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
10
- import { CloneGenerator } from "./CloneGenerator";
11
- import { SdkDistributionComposer } from "./internal/SdkDistributionComposer";
12
- import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
13
- import { SdkHttpParameterProgrammer } from "./internal/SdkHttpParameterProgrammer";
14
-
15
- export namespace SdkGenerator {
16
- export const generate = async (app: ITypedApplication): Promise<void> => {
17
- if (app.project.config.output === undefined)
18
- throw new Error("Output directory is not defined.");
19
-
20
- // PREPARE NEW DIRECTORIES
21
- console.log("Generating SDK Library");
22
- try {
23
- await fs.promises.mkdir(app.project.config.output);
24
- } catch {}
25
-
26
- // BUNDLING
27
- const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
28
- for (const file of bundle) {
29
- const current: string = `${BUNDLE_PATH}/${file}`;
30
- const target: string = `${app.project.config.output}/${file}`;
31
- const stats: fs.Stats = await fs.promises.stat(current);
32
-
33
- if (stats.isFile() === true) {
34
- const content: string = await fs.promises.readFile(current, "utf8");
35
- if (fs.existsSync(target) === false)
36
- await fs.promises.writeFile(target, content, "utf8");
37
- else if (BUNDLE_CHANGES[file] !== undefined) {
38
- const r: IPointer<string> = {
39
- value: await fs.promises.readFile(target, "utf8"),
40
- };
41
- for (const [before, after] of BUNDLE_CHANGES[file])
42
- r.value = r.value.replace(before, after);
43
- await fs.promises.writeFile(target, r.value, "utf8");
44
- }
45
- }
46
- }
47
-
48
- // STRUCTURES
49
- if (app.project.config.clone === true) await CloneGenerator.write(app);
50
-
51
- // FUNCTIONAL
52
- await SdkFileProgrammer.generate(app);
53
-
54
- // DISTRIBUTION
55
- if (app.project.config.distribute !== undefined)
56
- await SdkDistributionComposer.compose({
57
- config: app.project.config,
58
- websocket: app.routes.some((r) => r.protocol === "websocket"),
59
- });
60
- };
61
-
62
- export const validate = (
63
- app: ITypedApplication,
64
- ): IReflectOperationError[] => {
65
- const errors: IReflectOperationError[] = [];
66
- if (app.project.config.clone === true) return errors;
67
- for (const route of app.routes)
68
- if (route.protocol === "http")
69
- validateImplicit({
70
- config: app.project.config,
71
- errors,
72
- route,
73
- });
74
- return errors;
75
- };
76
-
77
- const validateImplicit = (props: {
78
- config: INestiaConfig;
79
- errors: IReflectOperationError[];
80
- route: ITypedHttpRoute;
81
- }): void => {
82
- for (const p of SdkHttpParameterProgrammer.getAll(props.route)) {
83
- if (isImplicitType(p.type))
84
- props.errors.push({
85
- file: props.route.controller.file,
86
- class: props.route.controller.class.name,
87
- function: props.route.name,
88
- from: `parameter ${JSON.stringify(p.name)}`,
89
- contents: [`implicit (unnamed) parameter type.`],
90
- });
91
- }
92
- if (props.config.propagate === true)
93
- for (const [key, value] of Object.entries(props.route.exceptions))
94
- if (isImplicitType(value.type))
95
- props.errors.push({
96
- file: props.route.controller.file,
97
- class: props.route.controller.class.name,
98
- function: props.route.name,
99
- from: `exception ${JSON.stringify(key)}`,
100
- contents: [`implicit (unnamed) exception type.`],
101
- });
102
- if (isImplicitType(props.route.success.type))
103
- props.errors.push({
104
- file: props.route.controller.file,
105
- class: props.route.controller.class.name,
106
- function: props.route.name,
107
- from: "success",
108
- contents: [`implicit (unnamed) return type.`],
109
- });
110
- };
111
-
112
- const isImplicitType = (type: IReflectType): boolean =>
113
- type.name === "__type" ||
114
- type.name === "__object" ||
115
- type.name.startsWith("__type.") ||
116
- type.name.startsWith("__object.") ||
117
- type.name.includes("readonly [") ||
118
- (!!type.typeArguments?.length && type.typeArguments.some(isImplicitType));
119
-
120
- export const BUNDLE_PATH = NodePath.join(
121
- __dirname,
122
- "..",
123
- "..",
124
- "assets",
125
- "bundle",
126
- "api",
127
- );
128
- }
129
-
130
- const BUNDLE_CHANGES: Record<string, [string, string][]> = {
131
- "IConnection.ts": [
132
- [
133
- `export { IConnection } from "@nestia/fetcher"`,
134
- `export type { IConnection } from "@nestia/fetcher"`,
135
- ],
136
- ],
137
- "module.ts": [
138
- [`export * from "./IConnection"`, `export type * from "./IConnection"`],
139
- ],
140
- "Primitive.ts": [
141
- [
142
- `export { Primitive } from "@nestia/fetcher"`,
143
- `export type { Primitive } from "typia"`,
144
- ],
145
- [
146
- `export type { Primitive } from "@nestia/fetcher"`,
147
- `export type { Primitive } from "typia"`,
148
- ],
149
- ],
150
- "Resolved.ts": [
151
- [
152
- `export { Resolved } from "@nestia/fetcher"`,
153
- `export type { Resolved } from "typia"`,
154
- ],
155
- [
156
- `export type { Resolved } from "@nestia/fetcher"`,
157
- `export type { Resolved } from "typia"`,
158
- ],
159
- ],
160
- };
1
+ import fs from "fs";
2
+ import NodePath from "path";
3
+ import { IPointer } from "tstl";
4
+
5
+ import { INestiaConfig } from "../INestiaConfig";
6
+ import { IReflectOperationError } from "../structures/IReflectOperationError";
7
+ import { IReflectType } from "../structures/IReflectType";
8
+ import { ITypedApplication } from "../structures/ITypedApplication";
9
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
10
+ import { CloneGenerator } from "./CloneGenerator";
11
+ import { SdkDistributionComposer } from "./internal/SdkDistributionComposer";
12
+ import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
13
+ import { SdkHttpParameterProgrammer } from "./internal/SdkHttpParameterProgrammer";
14
+
15
+ export namespace SdkGenerator {
16
+ export const generate = async (app: ITypedApplication): Promise<void> => {
17
+ if (app.project.config.output === undefined)
18
+ throw new Error("Output directory is not defined.");
19
+
20
+ // PREPARE NEW DIRECTORIES
21
+ console.log("Generating SDK Library");
22
+ try {
23
+ await fs.promises.mkdir(app.project.config.output);
24
+ } catch {}
25
+
26
+ // BUNDLING
27
+ const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
28
+ for (const file of bundle) {
29
+ const current: string = `${BUNDLE_PATH}/${file}`;
30
+ const target: string = `${app.project.config.output}/${file}`;
31
+ const stats: fs.Stats = await fs.promises.stat(current);
32
+
33
+ if (stats.isFile() === true) {
34
+ const content: string = await fs.promises.readFile(current, "utf8");
35
+ if (fs.existsSync(target) === false)
36
+ await fs.promises.writeFile(target, content, "utf8");
37
+ else if (BUNDLE_CHANGES[file] !== undefined) {
38
+ const r: IPointer<string> = {
39
+ value: await fs.promises.readFile(target, "utf8"),
40
+ };
41
+ for (const [before, after] of BUNDLE_CHANGES[file])
42
+ r.value = r.value.replace(before, after);
43
+ await fs.promises.writeFile(target, r.value, "utf8");
44
+ }
45
+ }
46
+ }
47
+
48
+ // STRUCTURES
49
+ if (app.project.config.clone === true) await CloneGenerator.write(app);
50
+
51
+ // FUNCTIONAL
52
+ await SdkFileProgrammer.generate(app);
53
+
54
+ // DISTRIBUTION
55
+ if (app.project.config.distribute !== undefined)
56
+ await SdkDistributionComposer.compose({
57
+ config: app.project.config,
58
+ websocket: app.routes.some((r) => r.protocol === "websocket"),
59
+ });
60
+ };
61
+
62
+ export const validate = (
63
+ app: ITypedApplication,
64
+ ): IReflectOperationError[] => {
65
+ const errors: IReflectOperationError[] = [];
66
+ if (app.project.config.clone === true) return errors;
67
+ for (const route of app.routes)
68
+ if (route.protocol === "http")
69
+ validateImplicit({
70
+ config: app.project.config,
71
+ errors,
72
+ route,
73
+ });
74
+ return errors;
75
+ };
76
+
77
+ const validateImplicit = (props: {
78
+ config: INestiaConfig;
79
+ errors: IReflectOperationError[];
80
+ route: ITypedHttpRoute;
81
+ }): void => {
82
+ for (const p of SdkHttpParameterProgrammer.getAll(props.route)) {
83
+ if (isImplicitType(p.type))
84
+ props.errors.push({
85
+ file: props.route.controller.file,
86
+ class: props.route.controller.class.name,
87
+ function: props.route.name,
88
+ from: `parameter ${JSON.stringify(p.name)}`,
89
+ contents: [`implicit (unnamed) parameter type.`],
90
+ });
91
+ }
92
+ if (props.config.propagate === true)
93
+ for (const [key, value] of Object.entries(props.route.exceptions))
94
+ if (isImplicitType(value.type))
95
+ props.errors.push({
96
+ file: props.route.controller.file,
97
+ class: props.route.controller.class.name,
98
+ function: props.route.name,
99
+ from: `exception ${JSON.stringify(key)}`,
100
+ contents: [`implicit (unnamed) exception type.`],
101
+ });
102
+ if (isImplicitType(props.route.success.type))
103
+ props.errors.push({
104
+ file: props.route.controller.file,
105
+ class: props.route.controller.class.name,
106
+ function: props.route.name,
107
+ from: "success",
108
+ contents: [`implicit (unnamed) return type.`],
109
+ });
110
+ };
111
+
112
+ const isImplicitType = (type: IReflectType): boolean =>
113
+ type.name === "__type" ||
114
+ type.name === "__object" ||
115
+ type.name.startsWith("__type.") ||
116
+ type.name.startsWith("__object.") ||
117
+ type.name.includes("readonly [") ||
118
+ (!!type.typeArguments?.length && type.typeArguments.some(isImplicitType));
119
+
120
+ export const BUNDLE_PATH = NodePath.join(
121
+ __dirname,
122
+ "..",
123
+ "..",
124
+ "assets",
125
+ "bundle",
126
+ "api",
127
+ );
128
+ }
129
+
130
+ const BUNDLE_CHANGES: Record<string, [string, string][]> = {
131
+ "IConnection.ts": [
132
+ [
133
+ `export { IConnection } from "@nestia/fetcher"`,
134
+ `export type { IConnection } from "@nestia/fetcher"`,
135
+ ],
136
+ ],
137
+ "module.ts": [
138
+ [`export * from "./IConnection"`, `export type * from "./IConnection"`],
139
+ ],
140
+ "Primitive.ts": [
141
+ [
142
+ `export { Primitive } from "@nestia/fetcher"`,
143
+ `export type { Primitive } from "typia"`,
144
+ ],
145
+ [
146
+ `export type { Primitive } from "@nestia/fetcher"`,
147
+ `export type { Primitive } from "typia"`,
148
+ ],
149
+ ],
150
+ "Resolved.ts": [
151
+ [
152
+ `export { Resolved } from "@nestia/fetcher"`,
153
+ `export type { Resolved } from "typia"`,
154
+ ],
155
+ [
156
+ `export type { Resolved } from "@nestia/fetcher"`,
157
+ `export type { Resolved } from "typia"`,
158
+ ],
159
+ ],
160
+ };
@@ -1,6 +1,12 @@
1
1
  import { SwaggerCustomizer } from "@nestia/core";
2
2
  import { JsonSchemasProgrammer, MetadataSchema } from "@typia/core";
3
- import { OpenApi, OpenApiV3, SwaggerV2 } from "@typia/interface";
3
+ import {
4
+ OpenApi,
5
+ OpenApiV3,
6
+ OpenApiV3_1,
7
+ OpenApiV3_2,
8
+ SwaggerV2,
9
+ } from "@typia/interface";
4
10
  import { OpenApiConverter } from "@typia/utils";
5
11
  import fs from "fs";
6
12
  import path from "path";
@@ -46,12 +52,12 @@ export namespace SwaggerGenerator {
46
52
  const specified:
47
53
  | OpenApi.IDocument
48
54
  | SwaggerV2.IDocument
49
- | OpenApiV3.IDocument =
50
- config.openapi === "2.0"
51
- ? OpenApiConverter.downgradeDocument(document, config.openapi)
52
- : config.openapi === "3.0"
53
- ? OpenApiConverter.downgradeDocument(document, config.openapi)
54
- : document;
55
+ | OpenApiV3.IDocument
56
+ | OpenApiV3_1.IDocument
57
+ | OpenApiV3_2.IDocument =
58
+ (config.openapi ?? "3.2") === "3.2"
59
+ ? document
60
+ : OpenApiConverter.downgradeDocument(document, config.openapi as "2.0");
55
61
  await fs.promises.writeFile(
56
62
  location,
57
63
  !config.beautify
@@ -86,7 +92,7 @@ export namespace SwaggerGenerator {
86
92
  .filter((m) => m.size() !== 0);
87
93
 
88
94
  // COMPOSE JSON SCHEMAS
89
- const json: IJsonSchemaCollection = JsonSchemasProgrammer.write({
95
+ const json: IJsonSchemaCollection = JsonSchemasProgrammer.writeSchemas({
90
96
  version: "3.1",
91
97
  metadatas,
92
98
  });
@@ -155,7 +161,7 @@ export namespace SwaggerGenerator {
155
161
  );
156
162
 
157
163
  return {
158
- openapi: "3.1.0",
164
+ openapi: "3.2.0",
159
165
  servers: config.servers ?? [
160
166
  {
161
167
  url: "https://github.com/samchon/nestia",
@@ -181,7 +187,7 @@ export namespace SwaggerGenerator {
181
187
  securitySchemes: config.security,
182
188
  },
183
189
  tags: config.tags ?? [],
184
- "x-samchon-emended-v4": true,
190
+ "x-typia-emended-v12": true,
185
191
  };
186
192
  };
187
193
 
@@ -1,103 +1,103 @@
1
- import cp from "child_process";
2
- import fs from "fs";
3
- import path from "path";
4
- import typia from "typia";
5
-
6
- import { INestiaConfig } from "../../INestiaConfig";
7
-
8
- export namespace SdkDistributionComposer {
9
- export const compose = async (props: {
10
- config: INestiaConfig;
11
- websocket: boolean;
12
- }) => {
13
- if (!fs.existsSync(props.config.distribute!))
14
- await fs.promises.mkdir(props.config.distribute!);
15
-
16
- const root: string = process.cwd();
17
- const output: string = path.resolve(props.config.output!);
18
- process.chdir(props.config.distribute!);
19
-
20
- const exit = () => process.chdir(root);
21
- if (await configured()) return exit();
22
-
23
- // COPY FILES
24
- console.log("Composing SDK distribution environments...");
25
- for (const file of await fs.promises.readdir(BUNDLE))
26
- await fs.promises.copyFile(`${BUNDLE}/${file}`, file);
27
-
28
- // CONFIGURE PATHS
29
- for (const file of ["package.json", "tsconfig.json"])
30
- await replace({ root, output })(file);
31
-
32
- // INSTALL PACKAGES
33
- const v: IDependencies = await dependencies();
34
- execute("npm install --save-dev rimraf");
35
- execute(`npm install --save @nestia/fetcher@${v.version}`);
36
- execute(`npm install --save typia@${v.typia}`);
37
- if (props.websocket) execute(`npm install --save tgrid@${v.tgrid}`);
38
- execute("npx typia setup --manager npm");
39
-
40
- exit();
41
- };
42
-
43
- const configured = async (): Promise<boolean> =>
44
- ["package.json", "tsconfig.json"].every(fs.existsSync) &&
45
- (await (async () => {
46
- const content = JSON.parse(
47
- await fs.promises.readFile("package.json", "utf8"),
48
- );
49
- return !!content.dependencies?.["@nestia/fetcher"];
50
- })());
51
-
52
- const execute = (command: string) => {
53
- console.log(` - ${command}`);
54
- cp.execSync(command, { stdio: "ignore" });
55
- };
56
-
57
- const replace =
58
- (props: { root: string; output: string }) =>
59
- async (file: string): Promise<void> => {
60
- const relative = (from: string) => (to: string) =>
61
- path.relative(from, to).split("\\").join("/");
62
- const root: string = relative(process.cwd())(props.root);
63
- const output: string = relative(process.cwd())(props.output);
64
- const current: string = relative(props.root)(process.cwd());
65
-
66
- const content: string = await fs.promises.readFile(file, "utf8");
67
- await fs.promises.writeFile(
68
- file,
69
- content
70
- .split("${root}")
71
- .join(root)
72
- .split("${output}")
73
- .join(output)
74
- .split("${current}")
75
- .join(current),
76
- "utf8",
77
- );
78
- };
79
-
80
- const dependencies = async (): Promise<IDependencies> => {
81
- const content: string = await fs.promises.readFile(
82
- __dirname + "/../../../package.json",
83
- "utf8",
84
- );
85
- const json: {
86
- version: string;
87
- dependencies: Record<string, string>;
88
- devDependencies: Record<string, string>;
89
- } = JSON.parse(content);
90
- return typia.assert<IDependencies>({
91
- ...json.devDependencies,
92
- ...json.dependencies,
93
- version: json.version,
94
- });
95
- };
96
- }
97
-
98
- interface IDependencies {
99
- version: string;
100
- typia: string;
101
- tgrid: string;
102
- }
103
- const BUNDLE = __dirname + "/../../../assets/bundle/distribute";
1
+ import cp from "child_process";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import typia from "typia";
5
+
6
+ import { INestiaConfig } from "../../INestiaConfig";
7
+
8
+ export namespace SdkDistributionComposer {
9
+ export const compose = async (props: {
10
+ config: INestiaConfig;
11
+ websocket: boolean;
12
+ }) => {
13
+ if (!fs.existsSync(props.config.distribute!))
14
+ await fs.promises.mkdir(props.config.distribute!);
15
+
16
+ const root: string = process.cwd();
17
+ const output: string = path.resolve(props.config.output!);
18
+ process.chdir(props.config.distribute!);
19
+
20
+ const exit = () => process.chdir(root);
21
+ if (await configured()) return exit();
22
+
23
+ // COPY FILES
24
+ console.log("Composing SDK distribution environments...");
25
+ for (const file of await fs.promises.readdir(BUNDLE))
26
+ await fs.promises.copyFile(`${BUNDLE}/${file}`, file);
27
+
28
+ // CONFIGURE PATHS
29
+ for (const file of ["package.json", "tsconfig.json"])
30
+ await replace({ root, output })(file);
31
+
32
+ // INSTALL PACKAGES
33
+ const v: IDependencies = await dependencies();
34
+ execute("npm install --save-dev rimraf");
35
+ execute(`npm install --save @nestia/fetcher@${v.version}`);
36
+ execute(`npm install --save typia@${v.typia}`);
37
+ if (props.websocket) execute(`npm install --save tgrid@${v.tgrid}`);
38
+ execute("npx typia setup --manager npm");
39
+
40
+ exit();
41
+ };
42
+
43
+ const configured = async (): Promise<boolean> =>
44
+ ["package.json", "tsconfig.json"].every(fs.existsSync) &&
45
+ (await (async () => {
46
+ const content = JSON.parse(
47
+ await fs.promises.readFile("package.json", "utf8"),
48
+ );
49
+ return !!content.dependencies?.["@nestia/fetcher"];
50
+ })());
51
+
52
+ const execute = (command: string) => {
53
+ console.log(` - ${command}`);
54
+ cp.execSync(command, { stdio: "ignore" });
55
+ };
56
+
57
+ const replace =
58
+ (props: { root: string; output: string }) =>
59
+ async (file: string): Promise<void> => {
60
+ const relative = (from: string) => (to: string) =>
61
+ path.relative(from, to).split("\\").join("/");
62
+ const root: string = relative(process.cwd())(props.root);
63
+ const output: string = relative(process.cwd())(props.output);
64
+ const current: string = relative(props.root)(process.cwd());
65
+
66
+ const content: string = await fs.promises.readFile(file, "utf8");
67
+ await fs.promises.writeFile(
68
+ file,
69
+ content
70
+ .split("${root}")
71
+ .join(root)
72
+ .split("${output}")
73
+ .join(output)
74
+ .split("${current}")
75
+ .join(current),
76
+ "utf8",
77
+ );
78
+ };
79
+
80
+ const dependencies = async (): Promise<IDependencies> => {
81
+ const content: string = await fs.promises.readFile(
82
+ __dirname + "/../../../package.json",
83
+ "utf8",
84
+ );
85
+ const json: {
86
+ version: string;
87
+ dependencies: Record<string, string>;
88
+ devDependencies: Record<string, string>;
89
+ } = JSON.parse(content);
90
+ return typia.assert<IDependencies>({
91
+ ...json.devDependencies,
92
+ ...json.dependencies,
93
+ version: json.version,
94
+ });
95
+ };
96
+ }
97
+
98
+ interface IDependencies {
99
+ version: string;
100
+ typia: string;
101
+ tgrid: string;
102
+ }
103
+ const BUNDLE = __dirname + "/../../../assets/bundle/distribute";