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.
- package/.github/FUNDING.yml +3 -0
- package/README.md +105 -34
- package/package.json +7 -4
- package/src/IConfiguration.ts +16 -0
- package/src/NestiaApplication.ts +13 -24
- package/src/analyses/SourceFinder.ts +59 -19
- package/src/bin/nestia.ts +64 -86
- package/src/executable/sdk.ts +89 -0
- package/tsconfig.json +1 -6
- package/src/utils/Terminal.ts +0 -19
package/README.md
CHANGED
|
@@ -7,8 +7,14 @@ Automatic SDK generator for the NestJS.
|
|
|
7
7
|
[](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.
|
|
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
|
|
100
|
+
export interface IConfiguration
|
|
93
101
|
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
*
|
|
124
|
+
* List of files or directories containing the NestJS controller classes.
|
|
103
125
|
*/
|
|
104
|
-
|
|
126
|
+
include: string[];
|
|
105
127
|
|
|
106
128
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* If omitted, the configuration would follow the `tsconfig.json`.
|
|
129
|
+
* List of files or directories to be excluded.
|
|
110
130
|
*/
|
|
111
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
-
###
|
|
244
|
-
https://github.com/samchon/
|
|
285
|
+
### Template Project
|
|
286
|
+
https://github.com/samchon/backend
|
|
245
287
|
|
|
246
|
-
[
|
|
288
|
+
I support template backend project using this **Nestia*** library, [backend](https://github.com/samchon/backend).
|
|
247
289
|
|
|
248
|
-
|
|
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
|
-
|
|
251
|
-
samchon.github@gmail.com
|
|
297
|
+
Helper library of the `NestJS` with **Nestia**.
|
|
252
298
|
|
|
253
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+

|
|
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": "
|
|
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
|
-
"
|
|
39
|
-
"
|
|
40
|
+
"tsconfig-paths": "^3.14.1",
|
|
41
|
+
"tstl": "^2.5.3",
|
|
42
|
+
"typescript": "^4.6.3"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
42
|
-
"nestia-helper": "^
|
|
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
|
+
}
|
package/src/NestiaApplication.ts
CHANGED
|
@@ -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_:
|
|
19
|
+
private readonly config_: IConfiguration;
|
|
19
20
|
private readonly bundle_checker_: Singleton<Promise<(str: string) => boolean>>;
|
|
20
21
|
|
|
21
|
-
public constructor(config:
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
2
|
-
import
|
|
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(
|
|
9
|
+
export async function find(input: IConfiguration.IInput): Promise<string[]>
|
|
7
10
|
{
|
|
8
|
-
const
|
|
9
|
-
await
|
|
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
|
-
|
|
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
|
|
36
|
+
async function iterate
|
|
37
|
+
(
|
|
38
|
+
closure: (location: string) => void,
|
|
39
|
+
location: string
|
|
40
|
+
): Promise<void>
|
|
15
41
|
{
|
|
16
|
-
const
|
|
17
|
-
for (const file of
|
|
42
|
+
const directory: string[] = await fs.promises.readdir(location);
|
|
43
|
+
for (const file of directory)
|
|
18
44
|
{
|
|
19
|
-
const
|
|
20
|
-
const stats: fs.Stats = await fs.promises.
|
|
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
|
-
|
|
25
|
-
|
|
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
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
2
|
|
|
3
|
-
import
|
|
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
|
-
|
|
9
|
+
function install(): void
|
|
14
10
|
{
|
|
15
|
-
|
|
11
|
+
const command: string = "npm install --save nestia-fetcher";
|
|
12
|
+
cp.execSync(command, { stdio: "inherit" });
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
function sdk(alias: boolean): void
|
|
19
16
|
{
|
|
20
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
if (fs.existsSync("
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
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
|
-
|
|
45
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
throw new Error(`Target "${path}" is not a directory.`);
|
|
42
|
+
task(false);
|
|
43
|
+
return;
|
|
53
44
|
}
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
}
|
package/src/utils/Terminal.ts
DELETED
|
@@ -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
|
-
}
|