nestia 1.0.0 → 2.0.0

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.
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ open_collective: nestia
package/README.md CHANGED
@@ -7,8 +7,14 @@ Automatic SDK generator for the NestJS.
7
7
  [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
8
 
9
9
  ```bash
10
+ # INSTALL NESTIA
10
11
  npm install --save-dev nestia
12
+
13
+ # WHEN ALL OF THE CONTROLLRES ARE GATHERED INTO A DIRECTORY
11
14
  npx nestia sdk "src/controller" --out "src/api"
15
+
16
+ # REGULAR NESTJS PATTERN
17
+ npx nestia sdk "src/**/*.controller.ts" --out "src/api"
12
18
  ```
13
19
 
14
20
  Don't write any `swagger` comment. Just deliver the SDK.
@@ -60,13 +66,15 @@ Just type the `npm install --save-dev nestia` command in your NestJS backend pro
60
66
  ```bash
61
67
  npx nestia sdk <source_controller_directory> --out <output_sdk_directory>
62
68
 
69
+ npx nestia sdk "src/**/*.controller.ts" --out "src/api"
63
70
  npx nestia sdk "src/controllers" --out "src/api"
64
- npx nestia sdk "src/controllers/consumers" "src/controllers/sellers" --out "src/api
71
+ npx nestia sdk "src/controllers/consumers" "src/controllers/sellers" --out "src/api"
72
+ npx nestia sdk "src/controllers" --exclude "src/**/Fake*.ts" --out "src/api"
65
73
  ```
66
74
 
67
75
  To generate a SDK library through the **Nestia** is very easy.
68
76
 
69
- Just type the `nestia sdk <input> --out <output>` command in the console. If there're multiple source directories containing the NestJS controller classes, type all of them separating by a `space` word.
77
+ Just type the `nestia sdk <input> --out <output>` command in the console. When there're multiple source directories containing the NestJS controller classes, type all of them separating by a `space` word. If you want to exclude some directories or files from the SDK generation, the `--exclude` option would be useful.
70
78
 
71
79
  Also, when generating a SDK using the cli options, `compilerOptions` would follow the `tsconfig.json`, that is configured for the backend server. If no `tsconfig.json` file exists in your project, the configuration would be default option (`ES5` with `strict` mode). If you want to use different `compilerOptions` with the `tsconfig.json`, you should configure the [nestia.config.ts](#nestiaconfigts).
72
80
 
@@ -89,26 +97,38 @@ Therefore, when you publish an SDK library generated by this **Nestia**, you hav
89
97
  ## Advanced
90
98
  ### `nestia.config.ts`
91
99
  ```typescript
92
- export namespace NestiaApplication
100
+ export interface IConfiguration
93
101
  {
94
- export interface IConfiguration
95
- {
96
- /**
97
- * List of directories containing the NestJS controller classes.
98
- */
99
- input: string | string[];
102
+ /**
103
+ * List of files or directories containing the NestJS controller classes.
104
+ */
105
+ input: string | string[] | IConfiguration.IInput;
100
106
 
107
+ /**
108
+ * Output directory that SDK would be placed in.
109
+ */
110
+ output: string;
111
+
112
+ /**
113
+ * Compiler options for the TypeScript.
114
+ *
115
+ * If omitted, the configuration would follow the `tsconfig.json`.
116
+ */
117
+ compilerOptions?: tsc.CompilerOptions
118
+ }
119
+ export namespace IConfiguration
120
+ {
121
+ export interface IInput
122
+ {
101
123
  /**
102
- * Output directory that SDK would be placed in.
124
+ * List of files or directories containing the NestJS controller classes.
103
125
  */
104
- output: string;
126
+ include: string[];
105
127
 
106
128
  /**
107
- * Compiler options for the TypeScript.
108
- *
109
- * If omitted, the configuration would follow the `tsconfig.json`.
129
+ * List of files or directories to be excluded.
110
130
  */
111
- compilerOptions?: tsc.CompilerOptions
131
+ exclude: string[];
112
132
  }
113
133
  }
114
134
  ```
@@ -119,11 +139,24 @@ Write below content as the `nestia.config.ts` file and place it onto the root di
119
139
 
120
140
  ```typescript
121
141
  export = {
122
- input: "src/controllers`",
142
+ input: "src/controllers",
123
143
  output: "src/api"
124
144
  };
125
145
  ```
126
146
 
147
+ > Alternative options for the regular NestJS project:
148
+ >
149
+ > ```typescript
150
+ > export = {
151
+ > input: "src/**/*.controller.ts",
152
+ > /* input: {
153
+ > include: ["src/controllers/*.controller.ts"],
154
+ > exclude: ["src/controllers/fake_*.controller.ts"]
155
+ > },*/
156
+ > output: "src/api"
157
+ > }
158
+ > ```
159
+
127
160
 
128
161
 
129
162
  ### Recommended Structures
@@ -214,18 +247,15 @@ export function store
214
247
  connection: IConnection,
215
248
  section: string,
216
249
  saleId: number,
217
- input: store.Input
250
+ input: Primitive<store.Input>
218
251
  ): Promise<store.Output>
219
252
  {
220
253
  return Fetcher.fetch
221
254
  (
222
255
  connection,
223
- {
224
- input_encrypted: false,
225
- output_encrypted: false
226
- },
227
- "POST",
228
- `/consumers/${section}/sales/${saleId}/questions/`,
256
+ store.ENCRYPTED,
257
+ store.METHOD,
258
+ store.path(section, saleId),
229
259
  input
230
260
  );
231
261
  }
@@ -233,6 +263,18 @@ export namespace store
233
263
  {
234
264
  export type Input = Primitive<ISaleInquiry.IStore>;
235
265
  export type Output = Primitive<ISaleInquiry<ISaleArticle.IContent>>;
266
+
267
+ export const METHOD = "POST" as const;
268
+ export const PATH: string = "/consumers/:section/sales/:saleId/questions";
269
+ export const ENCRYPTED: Fetcher.IEncrypted = {
270
+ request: true,
271
+ response: true,
272
+ };
273
+
274
+ export function path(section: string, saleId: number): string
275
+ {
276
+ return `/consumers/${section}/sales/${saleId}/questions`;
277
+ }
236
278
  }
237
279
  ```
238
280
 
@@ -240,26 +282,55 @@ export namespace store
240
282
 
241
283
 
242
284
  ## Appendix
243
- ### Safe-TypeORM
244
- https://github.com/samchon/safe-typeorm
285
+ ### Template Project
286
+ https://github.com/samchon/backend
245
287
 
246
- [safe-typeorm](https://github.com/samchon/safe-typeorm) is another library that what I've developed, helping typeorm in the compilation level and optimizes DB performance automatically without any extra dedication.
288
+ I support template backend project using this **Nestia*** library, [backend](https://github.com/samchon/backend).
247
289
 
248
- Therefore, this **Nestia** makes you to be much convenient in the API interaction level and safe-typeorm helps you to be much convenient in the DB interaction level. With those **Nestia** and [safe-typeorm](https://github.com/samchon/safe-typeorm), let's implement the backend server much easily and conveniently.
290
+ Also, reading the README content of the [backend](https://github.com/samchon/backend) template repository, you can find lots of example backend projects who've been generated from the [backend](https://github.com/samchon/backend). Furthermore, the example projects guide how to generate SDK library from the **Nestia** and how to distribute the SDK library thorugh the NPM module.
291
+
292
+ Therefore, if you're planning to compose your own backend project using this **Nestia**, I recommend you to create the repository and learn from the [backend](https://github.com/samchon/backend) template project.
293
+
294
+ ### Nestia-Helper
295
+ https://github.com/samchon/nestia-helper
249
296
 
250
- ### Technial Support
251
- samchon.github@gmail.com
297
+ Helper library of the `NestJS` with **Nestia**.
252
298
 
253
- I can provide technical support about those **Nestia** and [safe-typeorm](https://github.com/samchon/safe-typeorm).
299
+ [nestia-helper](https://github.com/samchon/nestia-helper) is a type of helper library for `Nestia` by enhancing decorator functions. Also, all of the decorator functions provided by this [nestia-helper](https://github.com/samchon/nestia-helper) are all fully compatible with the **Nestia**, who can generate SDK library by analyzing NestJS controller classes in the compilation level.
254
300
 
255
- Therefore, if you have any question or need help, feel free to contact me. If you want to adapt those **Nestia** and [safe-typeorm](https://github.com/samchon/safe-typeorm) in your commercial project, I can provide you the best guidance.
301
+ Of course, this [nestia-helper](https://github.com/samchon/nestia-helper) is not essential for utilizing the `NestJS` and **Nestia**. You can generate SDK library of your NestJS developed backend server without this [nestia-helper](https://github.com/samchon/nestia-helper). However, as decorator functions of this [nestia-helper](https://github.com/samchon/nestia-helper) is enough strong, I recommend you to adapt this [nestia-helper](https://github.com/samchon/nestia-helper) when using `NestJS` and **Nestia**.
256
302
 
257
- I also can help your backend project in the entire development level. If you're suffering by DB architecture design or API structure design, just contact me and get help. I'll help you with my best effort.
303
+ - Supported decorator functions
304
+ - [EncryptedController](https://github.com/samchon/nestia-helper#encryptedcontroller), [EncryptedModule](https://github.com/samchon/nestia-helper#encryptedmodule)
305
+ - [TypedRoute](https://github.com/samchon/nestia-helper#typedroute), [EncryptedRoute](https://github.com/samchon/nestia-helper#encryptedroute)
306
+ - [TypedParam](https://github.com/samchon/nestia-helper#typedparam), [EncryptedBody](https://github.com/samchon/nestia-helper#encryptedbody), [PlainBody](https://github.com/samchon/nestia-helper#plainbody)
307
+ - [ExceptionManager](https://github.com/samchon/nestia-helper#exceptionmanager)
308
+
309
+ ### Safe-TypeORM
310
+ https://github.com/samchon/safe-typeorm
311
+
312
+ [safe-typeorm](https://github.com/samchon/safe-typeorm) is another library that what I've developed, helping `TypeORM` in the compilation level and optimizes DB performance automatically without any extra dedication.
313
+
314
+ Therefore, this **Nestia** makes you to be much convenient in the API interaction level and safe-typeorm helps you to be much convenient in the DB interaction level. With those **Nestia** and [safe-typeorm](https://github.com/samchon/safe-typeorm), let's implement the backend server much easily and conveniently.
315
+
316
+ - When writing [**SQL query**](https://github.com/samchon/safe-typeorm#safe-query-builder),
317
+ - Errors would be detected in the **compilation** level
318
+ - **Auto Completion** would be provided
319
+ - **Type Hint** would be supported
320
+ - You can implement [**App-join**](https://github.com/samchon/safe-typeorm#app-join-builder) very conveniently
321
+ - When [**SELECT**ing for **JSON** conversion](https://github.com/samchon/safe-typeorm#json-select-builder)
322
+ - [**App-Join**](https://github.com/samchon/safe-typeorm#app-join-builder) with the related entities would be automatically done
323
+ - Exact JSON **type** would be automatically **deduced**
324
+ - The **performance** would be **automatically tuned**
325
+ - When [**INSERT**](https://github.com/samchon/safe-typeorm#insert-collection)ing records
326
+ - Sequence of tables would be automatically sorted by analyzing dependencies
327
+ - The **performance** would be **automatically tuned**
328
+
329
+ ![Safe-TypeORM Demo](https://raw.githubusercontent.com/samchon/safe-typeorm/master/assets/demonstrations/safe-query-builder.gif)
258
330
 
259
331
  ### Archidraw
260
332
  https://www.archisketch.com/
261
333
 
262
334
  I have special thanks to the Archidraw, where I'm working for.
263
335
 
264
- The Archidraw is a great IT company developing 3D interior editor and lots of solutions based on the 3D assets. Also, the Archidraw is the first company who had adopted this **Nestia** on their commercial backend project, even this **Nestia** was in the alpha level.
265
-
336
+ The Archidraw is a great IT company developing 3D interior editor and lots of solutions based on the 3D assets. Also, the Archidraw is the first company who had adopted this **Nestia** on their commercial backend project, even this **Nestia** was in the alpha level.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestia",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Automatic SDK and Document generator for the NestJS",
5
5
  "main": "src/index.ts",
6
6
  "bin": {
@@ -30,16 +30,19 @@
30
30
  "homepage": "https://github.com/samchon/nestia#readme",
31
31
  "dependencies": {
32
32
  "@types/cli": "^0.11.19",
33
+ "@types/glob": "^7.2.0",
33
34
  "@types/node": "^14.14.22",
34
35
  "@types/reflect-metadata": "^0.1.0",
35
36
  "cli": "^1.0.1",
36
37
  "del": "^6.0.0",
38
+ "glob": "^7.2.0",
37
39
  "ts-node": "^9.1.1",
38
- "tstl": "^2.5.0",
39
- "typescript": "^4.3.2"
40
+ "tsconfig-paths": "^3.14.1",
41
+ "tstl": "^2.5.3",
42
+ "typescript": "^4.6.3"
40
43
  },
41
44
  "devDependencies": {
42
- "nestia-helper": "^1.0.0",
45
+ "nestia-helper": "^2.0.0",
43
46
  "rimraf": "^3.0.2"
44
47
  }
45
48
  }
@@ -0,0 +1,16 @@
1
+ import type tsc from "typescript";
2
+
3
+ export interface IConfiguration
4
+ {
5
+ input: string | string[] | IConfiguration.IInput;
6
+ output: string;
7
+ compilerOptions?: tsc.CompilerOptions;
8
+ }
9
+ export namespace IConfiguration
10
+ {
11
+ export interface IInput
12
+ {
13
+ include: string[];
14
+ exclude?: string[];
15
+ }
16
+ }
@@ -9,16 +9,17 @@ import { ReflectAnalyzer } from "./analyses/ReflectAnalyzer";
9
9
  import { SourceFinder } from "./analyses/SourceFinder";
10
10
  import { SdkGenerator } from "./generates/SdkGenerator";
11
11
 
12
+ import { IConfiguration } from "./IConfiguration";
12
13
  import { IController } from "./structures/IController";
13
14
  import { IRoute } from "./structures/IRoute";
14
15
  import { ArrayUtil } from "./utils/ArrayUtil";
15
16
 
16
17
  export class NestiaApplication
17
18
  {
18
- private readonly config_: NestiaApplication.IConfiguration;
19
+ private readonly config_: IConfiguration;
19
20
  private readonly bundle_checker_: Singleton<Promise<(str: string) => boolean>>;
20
21
 
21
- public constructor(config: NestiaApplication.IConfiguration)
22
+ public constructor(config: IConfiguration)
22
23
  {
23
24
  this.config_ = config;
24
25
  this.bundle_checker_ = new Singleton(async () =>
@@ -47,18 +48,16 @@ export class NestiaApplication
47
48
  public async generate(): Promise<void>
48
49
  {
49
50
  // LOAD CONTROLLER FILES
50
- const fileList: string[] = [];
51
- const inputList: string[] = this.config_.input instanceof Array
52
- ? this.config_.input
53
- : [this.config_.input];
54
-
55
- for (const file of inputList.map(str => path.resolve(str)))
56
- {
57
- const found: string[] = await SourceFinder.find(file);
58
- const filtered: string[] = await ArrayUtil.asyncFilter(found, file => this.is_not_excluded(file));
59
-
60
- fileList.push(...filtered);
61
- }
51
+ const input: IConfiguration.IInput = this.config_.input instanceof Array
52
+ ? { include: this.config_.input }
53
+ : typeof this.config_.input === "string"
54
+ ? { include: [ this.config_.input ] }
55
+ : this.config_.input;
56
+ const fileList: string[] = await ArrayUtil.asyncFilter
57
+ (
58
+ await SourceFinder.find(input),
59
+ file => this.is_not_excluded(file)
60
+ );
62
61
 
63
62
  // ANALYZE REFLECTS
64
63
  const unique: WeakSet<any> = new WeakSet();
@@ -94,14 +93,4 @@ export class NestiaApplication
94
93
  return file.indexOf(`${this.config_.output}${path.sep}functional`) === -1
95
94
  && (await this.bundle_checker_.get())(file) === false;
96
95
  }
97
- }
98
-
99
- export namespace NestiaApplication
100
- {
101
- export interface IConfiguration
102
- {
103
- input: string | string[];
104
- output: string;
105
- compilerOptions?: tsc.CompilerOptions;
106
- }
107
96
  }
@@ -1,33 +1,73 @@
1
- import * as fs from "fs";
2
- import * as path from "path";
1
+ import fs from "fs";
2
+ import glob from "glob";
3
+ import path from "path";
4
+
5
+ import { IConfiguration } from "../IConfiguration";
3
6
 
4
7
  export namespace SourceFinder
5
8
  {
6
- export async function find(directory: string): Promise<string[]>
9
+ export async function find(input: IConfiguration.IInput): Promise<string[]>
7
10
  {
8
- const output: string[] = [];
9
- await gather(output, directory);
11
+ const dict: Set<string> = new Set();
12
+ await decode(input.include, str => dict.add(str));
13
+ if (input.exclude)
14
+ await decode(input.exclude, str => dict.delete(str));
15
+
16
+ return [...dict];
17
+ }
10
18
 
11
- return output;
19
+ async function decode
20
+ (
21
+ input: string[],
22
+ closure: (location: string) => void,
23
+ ): Promise<void>
24
+ {
25
+ for (const pattern of input)
26
+ for (const location of await _Glob(path.resolve(pattern)))
27
+ {
28
+ const stats: fs.Stats = await fs.promises.stat(location);
29
+ if (stats.isDirectory() === true)
30
+ await iterate(closure, location);
31
+ else if (stats.isFile() && _Is_ts_file(location))
32
+ closure(location);
33
+ }
12
34
  }
13
35
 
14
- async function gather(output: string[], directory: string): Promise<void>
36
+ async function iterate
37
+ (
38
+ closure: (location: string) => void,
39
+ location: string
40
+ ): Promise<void>
15
41
  {
16
- const children: string[] = await fs.promises.readdir(directory);
17
- for (const file of children)
42
+ const directory: string[] = await fs.promises.readdir(location);
43
+ for (const file of directory)
18
44
  {
19
- const current: string = `${directory}${path.sep}${file}`;
20
- const stats: fs.Stats = await fs.promises.lstat(current);
45
+ const next: string = path.resolve(`${location}/${file}`);
46
+ const stats: fs.Stats = await fs.promises.stat(next);
21
47
 
22
48
  if (stats.isDirectory() === true)
23
- {
24
- await gather(output, current);
25
- continue;
26
- }
27
- else if (file.substr(-3) !== ".ts" || file.substr(-5) === ".d.ts")
28
- continue;
29
-
30
- output.push(current);
49
+ await iterate(closure, next);
50
+ else if (stats.isFile() && _Is_ts_file(file))
51
+ closure(next);
31
52
  }
32
53
  }
54
+
55
+ function _Glob(pattern: string): Promise<string[]>
56
+ {
57
+ return new Promise((resolve, reject) =>
58
+ {
59
+ glob(pattern, (err, matches) =>
60
+ {
61
+ if (err)
62
+ reject(err);
63
+ else
64
+ resolve(matches.map(str => path.resolve(str)));
65
+ });
66
+ });
67
+ }
68
+
69
+ function _Is_ts_file(file: string): boolean
70
+ {
71
+ return file.substr(-3) === ".ts" && file.substr(-5) !== ".d.ts";
72
+ }
33
73
  }
package/src/bin/nestia.ts CHANGED
@@ -1,84 +1,82 @@
1
- #!/usr/bin/env ts-node-script
1
+ #!/usr/bin/env ts-node
2
2
 
3
- import cli from "cli";
3
+ import cp from "child_process";
4
4
  import fs from "fs";
5
- import path from "path";
6
5
  import tsc from "typescript";
7
6
 
8
- import { NestiaApplication } from "../NestiaApplication";
9
-
10
- import { Terminal } from "../utils/Terminal";
11
7
  import { stripJsonComments } from "../utils/stripJsonComments";
12
8
 
13
- interface ICommand
9
+ function install(): void
14
10
  {
15
- out: string | null;
11
+ const command: string = "npm install --save nestia-fetcher";
12
+ cp.execSync(command, { stdio: "inherit" });
16
13
  }
17
14
 
18
- async function sdk(input: string[], command: ICommand): Promise<void>
15
+ function sdk(alias: boolean): void
19
16
  {
20
- let compilerOptions: tsc.CompilerOptions | undefined = {};
17
+ const parameters: string[] = [
18
+ alias ? "npx ts-node -r tsconfig-paths/register" : "npx ts-node",
19
+ __dirname + "/../executable/sdk",
20
+ ...process.argv.slice(3)
21
+ ];
22
+ const command: string = parameters.join(" ");
23
+ cp.execSync(command, { stdio: "inherit" });
24
+ }
21
25
 
22
- //----
23
- // NESTIA.CONFIG.TS
24
- //----
25
- if (fs.existsSync("nestia.config.ts") === true)
26
+ async function tsconfig(task: (alias: boolean) => void): Promise<void>
27
+ {
28
+ // NO TSCONFIG.JSON?
29
+ if (fs.existsSync("tsconfig.json") === false)
26
30
  {
27
- const config: NestiaApplication.IConfiguration = await import(path.resolve("nestia.config.ts"));
28
- compilerOptions = config.compilerOptions;
29
- input = config.input instanceof Array ? config.input : [config.input];
30
- command.out = config.output;
31
+ task(false);
32
+ return;
31
33
  }
32
-
33
- //----
34
- // VALIDATIONS
35
- //----
36
- // CHECK OUTPUT
37
- if (command.out === null)
38
- throw new Error(`Output directory is not specified. Add the "--out <output_directory>" option.`);
39
34
 
40
- // CHECK PARENT DIRECTORY
41
- const parentPath: string = path.resolve(command.out + "/..");
42
- const parentStats: fs.Stats = await fs.promises.stat(parentPath);
35
+ const content: string = await fs.promises.readFile("tsconfig.json", "utf8");
36
+ const json: any = JSON.parse(stripJsonComments(content));
37
+ const options: tsc.CompilerOptions = json.compilerOptions;
43
38
 
44
- if (parentStats.isDirectory() === false)
45
- throw new Error(`Unable to find parent directory of the output path: "${parentPath}".`);
46
-
47
- // CHECK INPUTS
48
- for (const path of input)
39
+ // NO ALIAS PATHS
40
+ if (!options.paths || !Object.entries(options.paths).length)
49
41
  {
50
- const inputStats: fs.Stats = await fs.promises.stat(path);
51
- if (inputStats.isDirectory() === false)
52
- throw new Error(`Target "${path}" is not a directory.`);
42
+ task(false);
43
+ return;
53
44
  }
54
45
 
55
- //----
56
- // GENERATION
57
- //----
58
- if (fs.existsSync("tsconfig.json") === true)
59
- {
60
- const content: string = await fs.promises.readFile("tsconfig.json", "utf8");
61
- const options: tsc.CompilerOptions = JSON.parse(stripJsonComments(content)).compilerOptions;
46
+ let closer: null | (() => Promise<void>) = null;
47
+ let error: Error | null = null;
62
48
 
63
- compilerOptions = compilerOptions
64
- ? { ...options, ...compilerOptions }
65
- : options;
49
+ if (!options.baseUrl)
50
+ {
51
+ options.baseUrl = "./";
52
+ await fs.promises.writeFile
53
+ (
54
+ "tsconfig.json",
55
+ JSON.stringify(json, null, 2),
56
+ "utf8"
57
+ );
58
+
59
+ closer = () => fs.promises.writeFile
60
+ (
61
+ "tsconfig.json",
62
+ content,
63
+ "utf8"
64
+ );
66
65
  }
67
66
 
68
- // CHECK NESTIA.CONFIG.TS
69
-
70
- // CALL THE APP.GENERATE()
71
- const app: NestiaApplication = new NestiaApplication({
72
- output: command.out,
73
- input,
74
- compilerOptions,
75
- });
76
- await app.generate();
77
- }
67
+ try
68
+ {
69
+ task(true);
70
+ }
71
+ catch (exp)
72
+ {
73
+ error = exp as Error;
74
+ }
78
75
 
79
- async function install(): Promise<void>
80
- {
81
- await Terminal.execute("npm install --save nestia-fetcher");
76
+ if (closer)
77
+ await closer();
78
+ if (error)
79
+ throw error;
82
80
  }
83
81
 
84
82
  async function main(): Promise<void>
@@ -86,32 +84,12 @@ async function main(): Promise<void>
86
84
  if (process.argv[2] === "install")
87
85
  await install();
88
86
  else if (process.argv[2] === "sdk")
89
- {
90
- const command: ICommand = cli.parse({
91
- out: ["o", "Output path of the SDK files", "string", null],
92
- });
93
-
94
- try
95
- {
96
- const inputs: string[] = [];
97
- for (const arg of process.argv.slice(3))
98
- {
99
- if (arg[0] === "-")
100
- break;
101
- inputs.push(arg);
102
- }
103
- await sdk(inputs, command);
104
- }
105
- catch (exp)
106
- {
107
- console.log(exp);
108
- process.exit(-1);
109
- }
110
- }
87
+ await tsconfig(sdk);
111
88
  else
112
- {
113
- console.log(`nestia supports only two commands; install and sdk, however you typed ${process.argv[2]}`);
114
- process.exit(-1);
115
- }
89
+ throw new Error(`nestia supports only two commands; install and sdk, however you typed ${process.argv[2]}`);
116
90
  }
117
- main();
91
+ main().catch(exp =>
92
+ {
93
+ console.log(exp.message);
94
+ process.exit(-1);
95
+ });
@@ -0,0 +1,89 @@
1
+ import cli from "cli";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import tsc from "typescript";
5
+ import { Primitive } from "nestia-fetcher";
6
+
7
+ import { IConfiguration } from "../IConfiguration";
8
+ import { NestiaApplication } from "../NestiaApplication";
9
+ import { stripJsonComments } from "../utils/stripJsonComments";
10
+
11
+ interface ICommand
12
+ {
13
+ exclude: string | null;
14
+ out: string | null;
15
+ }
16
+
17
+ async function sdk(include: string[], command: ICommand): Promise<void>
18
+ {
19
+ // CONFIGURATION
20
+ let config: IConfiguration;
21
+ if (fs.existsSync("nestia.config.ts") === true)
22
+ config = Primitive.clone
23
+ (
24
+ await import(path.resolve("nestia.config.ts"))
25
+ );
26
+ else
27
+ {
28
+ if (command.out === null)
29
+ throw new Error(`Output directory is not specified. Add the "--out <output_directory>" option.`);
30
+ config = {
31
+ input: {
32
+ include,
33
+ exclude: command.exclude
34
+ ? [command.exclude]
35
+ : undefined
36
+ },
37
+ output: command.out
38
+ };
39
+ }
40
+
41
+ // VALIDATE OUTPUT DIRECTORY
42
+ const parentPath: string = path.resolve(config.output + "/..");
43
+ const parentStats: fs.Stats = await fs.promises.stat(parentPath);
44
+
45
+ if (parentStats.isDirectory() === false)
46
+ throw new Error(`Unable to find parent directory of the output path: "${parentPath}".`);
47
+
48
+ // GENERATION
49
+ if (fs.existsSync("tsconfig.json") === true)
50
+ {
51
+ const content: string = await fs.promises.readFile("tsconfig.json", "utf8");
52
+ const options: tsc.CompilerOptions = JSON.parse(stripJsonComments(content)).compilerOptions;
53
+
54
+ config.compilerOptions = {
55
+ ...options,
56
+ ...(config.compilerOptions || {})
57
+ };
58
+ }
59
+
60
+ // CALL THE APP.GENERATE()
61
+ const app: NestiaApplication = new NestiaApplication(config);
62
+ await app.generate();
63
+ }
64
+
65
+ async function main(): Promise<void>
66
+ {
67
+ const command: ICommand = cli.parse({
68
+ exclude: ["e", "Something to exclude", "string", null],
69
+ out: ["o", "Output path of the SDK files", "string", null],
70
+ });
71
+
72
+ try
73
+ {
74
+ const inputs: string[] = [];
75
+ for (const arg of process.argv.slice(2))
76
+ {
77
+ if (arg[0] === "-")
78
+ break;
79
+ inputs.push(arg);
80
+ }
81
+ await sdk(inputs, command);
82
+ }
83
+ catch (exp)
84
+ {
85
+ console.log(exp);
86
+ process.exit(-1);
87
+ }
88
+ }
89
+ main();
package/tsconfig.json CHANGED
@@ -74,10 +74,5 @@
74
74
  "skipLibCheck": true, /* Skip type checking of declaration files. */
75
75
  "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
76
76
  },
77
- "include": [
78
- "src",
79
- "test/default/src",
80
- "test/nestia.config.ts/src",
81
- // "test/tsconfig.json/src"
82
- ]
77
+ "include": ["src"]
83
78
  }
@@ -1,19 +0,0 @@
1
- import * as cp from "child_process";
2
- import { Pair } from "tstl/utility/Pair";
3
-
4
- export namespace Terminal
5
- {
6
- export function execute(...commands: string[]): Promise<Pair<string, string>>
7
- {
8
- return new Promise((resolve, reject) =>
9
- {
10
- cp.exec(commands.join(" && "), (error: Error | null, stdout: string, stderr: string) =>
11
- {
12
- if (error)
13
- reject(error);
14
- else
15
- resolve(new Pair(stdout, stderr));
16
- });
17
- });
18
- }
19
- }