nestia 2.1.3 → 2.1.4

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/README.md CHANGED
@@ -1,60 +1,36 @@
1
1
  # Nestia
2
- Automatic `SDK` and `Swagger` generator for the `NestJS`.
2
+ Automatic `SDK` and `Swagger` generator for the `NestJS`, evolved than ever.
3
3
 
4
4
  [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)
5
5
  [![npm version](https://badge.fury.io/js/nestia.svg)](https://www.npmjs.com/package/nestia)
6
6
  [![Downloads](https://img.shields.io/npm/dm/nestia.svg)](https://www.npmjs.com/package/nestia)
7
7
  [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
- [![Guide Documents](https://img.shields.io/badge/wiki-documentation-forestgreen)](https://github.com/samchon/nestia/wiki)
8
+ [![Guide Documents](https://img.shields.io/badge/wiki-documentation-forestgreen)](https://github.com/samchon/nestia/wiki)
9
9
 
10
10
  - Github: https://github.com/samchon/nestia
11
11
  - NPM: https://www.npmjs.com/packages/nestia
12
12
  - Guide Documents: https://github.com/samchon/nestia/wiki
13
13
 
14
- ```bash
15
- # INSTALL NESTIA
16
- npm install --save-dev nestia
17
-
18
- # BUILDING SDK LIBRARY
19
- npx nestia sdk "src/controller" --out "src/api"
20
- npx nestia sdk "src/**/*.controller.ts" --out "src/api"
21
- npx nestia sdk "src/controller" \
22
- --exclude "src/controller/test" \
23
- --out "src/api"
24
-
25
- # BUILDING SWAGGER.JSON IS ALSO POSSIBLE
26
- npx nestia swagger "src/controller" -- out "swagger.json"
27
- ```
28
-
29
- Don't write any swagger comment and DTO decorator. Just run the `nestia` up.
30
-
31
- - No swagger comment/decorator
32
- - No DTO comment/decorator
33
- - Only pure `interface`s and NestJS code are required
34
- - Suppors generic typed `interface`s and `controller`s
35
- - Support union/intersection types
36
- - Support conditional types
14
+ `nestia` is an evolved `SDK` and `Swagger` generator, which analyzes your `NestJS` server code in the compilation level. With `nestia` and compilation level analyzer, you don't need to write any swagger or class-validator decorators. All you need to do is use the `nestia` CLI as shown below.
37
15
 
38
- The `nestia` is an evolved automatic `SDK` and `Swagger` generator than ever, who does not require any type of swagger comment or DTO decorator function, by analyzing your `NestJS` developed backend server code in the compilation level (`nestia` utilizes the TypeScript Compiler API).
39
-
40
- Therefore, don't write any swagger comment and don't use any DTO related decorator function. Just use the pure interface type with the pure `NestJS` code. Reading below sections and looking at example codes of the `nestia`, feel how the `nestia` is much stronger than the legacy `@nestjs/swagger`.
16
+ Reading below contents, feel how the "compilation level" makes `nestia` stronger.
41
17
 
42
18
  Components | `nestia`::SDK | `nestia`::swagger | `@nestjs/swagger`
43
19
  -----------|---|---|---
44
- DTO with pure interface | ✔ | ✔ | ❌
45
- descriptions by comments | ✔ | ✔ | ❌
20
+ Pure DTO interface | ✔ | ✔ | ❌
21
+ Description comments | ✔ | ✔ | ❌
46
22
  Simple structure | ✔ | ✔ | ✔
47
- Generic typed structure | ✔ | ✔ | ❌
48
- Union typed structure | ✔ | ✔ | ▲
49
- Intersection typed structure | ✔ | ✔ | ▲
50
- Conditional typed structure | ✔ | ▲ | ❌
23
+ Generic type | ✔ | ✔ | ❌
24
+ Union type | ✔ | ✔ | ▲
25
+ Intersection type | ✔ | ✔ | ▲
26
+ Conditional type | ✔ | ▲ | ❌
51
27
  Auto completion | ✔ | ❌ | ❌
52
28
  Type hints | ✔ | ❌ | ❌
53
29
  2x faster `JSON.stringify()` | ✔ | ❌ | ❌
54
- Ensure type safety | | ❌ | ❌
30
+ Ensure type safety | | ❌ | ❌
55
31
 
56
32
  ```typescript
57
- // IMPORT SDK LIBRARY WHO'VE BEEN GENERATED BY THE NESTIA
33
+ // IMPORT SDK LIBRARY GENERATED BY NESTIA
58
34
  import api from "@samchon/shopping-api";
59
35
  import { IPage } from "@samchon/shopping-api/lib/structures/IPage";
60
36
  import { ISale } from "@samchon/shopping-api/lib/structures/ISale";
@@ -112,14 +88,44 @@ export async function trace_sale_question_and_comment
112
88
 
113
89
 
114
90
 
91
+ ## Setup
92
+ Just like any other package, you've got to install it before you can use it.
93
+
94
+ ```sh
95
+ npm install --save-dev nestia
96
+ ```
97
+
98
+ After the installation, you can generate the `SDK` or `Swagger`, directly.
99
+
100
+ ```sh
101
+ npx nestia sdk "src/**/*.controller" --out "src/api"
102
+ npx nestia swagger "src/**/*.controller" --out "swagger.json"
103
+ ```
104
+
105
+ > If all of your controller files are gathered into one directory:
106
+ >
107
+ > ```sh
108
+ > npx nestia sdk "src/controllers" --out "src/api"
109
+ > npx nestia swagger "src/controllers" --out "swagger.json"
110
+ > ```
111
+ >
112
+ > You can omit all of the parameters if you've configured the [nestia.config.ts](#configuration) file.
113
+ >
114
+ > ```sh
115
+ > npx nestia sdk
116
+ > npx nestia swagger
117
+ > ```
118
+
119
+
120
+
115
121
 
116
122
  ## Demonstrations
117
123
  ### Pure DTO Interface
118
- The `nestia` can utilize the pure interface type as DTO.
124
+ `nestia` can utilize pure interface type as DTO.
119
125
 
120
- Unlike the legacy `@nestjs/swagger` who requires a class with decorator functions when defining the DTO, the `nestia` can use the pure interface directly. Also, `nestia` can use the descriptive comments of the pure DTO interface, too.
126
+ Unlike `@nestjs/swagger` which requires the DTO class with decorators, `nestia` can use the pure interface type directly. Also, `nestia` can utilize the pure descriptive comments, instead of using the `description` property of the decorators. Furthermore, `nestia` can even support generic types, union/intersection types and even conditional types.
121
127
 
122
- Furthermore, as the `nestia` can use the pure interface type directly, it's possible to define a generic typed DTO interface with inheritance. Of course, using alis type or union typed DTO are also possibble, too. Besides, `@nestjs/swagger` never can construct such generic typed DTO and constructing union typed DTO is possible but extremely difficult.
128
+ Look at the code below, you may see the difference between `nestia` and `@nestjs/swagger`, and thereby catch the meaning of the pure DTO interface.
123
129
 
124
130
  - Simple [`ISaleArticleComment`](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/structures/ISaleArticleComment.ts)
125
131
  - Generic interfaces
@@ -127,15 +133,77 @@ Furthermore, as the `nestia` can use the pure interface type directly, it's poss
127
133
  - parent interface, [`ISaleInquiry<Content>`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleInquiry.ts)
128
134
  - 1st sub-type interface, [`ISaleQuestion`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleQuestion.ts)
129
135
  - 2nd sub-type interface, [`ISaleReview`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleReview.ts)
130
- - Union alias type [`ISaleEntireArticle`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleArticle.ts)
131
-
132
- Looking at the below example code, then you may understand which differences between the `nestia` and `@nestjs/swagger` and what the pure interface DTO type means. Writing the legacy DTO class of the `@nestjs/swagger` after a very long time, I felt the feeling again, "this is insane".
136
+ - Union alias type [`ISaleEntireArticle`](https://github.com/samchon/nestia/tree/master/demo/union/src/api/structures/ISaleEntireArticle.ts)
133
137
 
134
138
  > The below example code would be shown by clicking the arrow button or text.
135
139
 
136
140
  <details>
137
141
  <summary>
138
- Pure DTO interface, of the <code>nestia</code>
142
+ Traditional DTO class using <code>@nestjs/swagger</code>
143
+ </summary>
144
+
145
+ ```typescript
146
+ export class SaleArticleComment
147
+ {
148
+ @ApiProperty({
149
+ description:
150
+ `Comment wrote on a sale related article.
151
+
152
+ When an article of a sale has been enrolled, all of the participants like consumers and sellers can write a comment on that article. However, when the writer is a consumer, the consumer can hide its name through the annoymous option.
153
+
154
+ Also, writing a reply comment for a specific comment is possible and in that case, the ISaleArticleComment.parent_id property would be activated.`
155
+ })
156
+ id: number;
157
+
158
+ @ApiProperty({
159
+ type: "number",
160
+ nullable: true,
161
+ description:
162
+ `Parent comment ID.
163
+
164
+ Only When this comment has been written as a reply.`
165
+ })
166
+ parent_id: number | null;
167
+
168
+ @ApiProperty({
169
+ type: "string",
170
+ description: "Type of the writer."
171
+ })
172
+ writer_type: "seller" | "consumer";
173
+
174
+ @ApiProperty({
175
+ type: "string",
176
+ nullable: true,
177
+ description:
178
+ `Name of the writer.
179
+
180
+ When this is a type of anonymous comment, writer name would be hidden.`
181
+ })
182
+ writer_name: string | null;
183
+
184
+ @ApiProperty({
185
+ type: "array",
186
+ items: {
187
+ schema: { $ref: getSchemaPath(SaleArticleComment.Content) }
188
+ },
189
+ description:
190
+ `Contents of the comments.
191
+
192
+ When the comment writer tries to modify content, it would not modify the comment content but would be accumulated Therefore, all of the people can read how the content has been changed.`
193
+ })
194
+ contents: SaleArticleComment.Content[];
195
+
196
+ @ApiProperty({
197
+ description: "Creation time."
198
+ })
199
+ created_at: string;
200
+ }
201
+ ```
202
+ </details>
203
+
204
+ <details>
205
+ <summary>
206
+ Pure DTO interface using <code>nestia</code>
139
207
  </summary>
140
208
 
141
209
  ```typescript
@@ -235,79 +303,116 @@ export namespace ISaleArticleComment
235
303
 
236
304
  <details>
237
305
  <summary>
238
- Legacy DTO class, of the <code>@nestjs/swagger</code>
306
+ Generic typed DTO using <code>nestia</code>
239
307
  </summary>
240
308
 
241
309
  ```typescript
242
- export class SaleArticleComment
310
+ /**
311
+ * Inquiry article.
312
+ *
313
+ * Sub-type of article and super-type of question and answer.
314
+ *
315
+ * - List of the sub-types
316
+ * - {@link ISaleQuestion}
317
+ * - {@link ISaleReview}
318
+ *
319
+ * @template Content Content type
320
+ * @author Jeongho Nam - https://github.com/samchon
321
+ */
322
+ export interface ISaleInquiry<Content extends ISaleInquiry.IContent>
323
+ extends ISaleArticle<Content>
243
324
  {
244
- @ApiProperty({
245
- description:
246
- `Comment wrote on a sale related article.
247
-
248
- When an article of a sale has been enrolled, all of the participants like consumers and sellers can write a comment on that article. However, when the writer is a consumer, the consumer can hide its name through the annoymous option.
249
-
250
- Also, writing a reply comment for a specific comment is possible and in that case, the ISaleArticleComment.parent_id property would be activated.`
251
- })
325
+ /**
326
+ * Primary Key.
327
+ */
252
328
  id: number;
253
329
 
254
- @ApiProperty({
255
- type: "number",
256
- nullable: true,
257
- description:
258
- `Parent comment ID.
259
-
260
- Only When this comment has been written as a reply.`
261
- })
262
- parent_id: number | null;
330
+ /**
331
+ * Name of the writer.
332
+ */
333
+ writer: string;
263
334
 
264
- @ApiProperty({
265
- type: "string",
266
- description: "Type of the writer."
267
- })
268
- writer_type: "seller" | "consumer";
335
+ /**
336
+ * List of contents.
337
+ *
338
+ * When the article writer tries to modify content, it would not modify the article
339
+ * content but would be accumulated. Therefore, all the people can read how
340
+ * the content has been changed.
341
+ */
342
+ contents: Content[];
269
343
 
270
- @ApiProperty({
271
- type: "string",
272
- nullable: true,
273
- description:
274
- `Name of the writer.
344
+ /**
345
+ * Creation time.
346
+ */
347
+ createdAat: string;
348
+
349
+ /**
350
+ * Formal answer from the seller.
351
+ */
352
+ answer: ISaleInquiryAnswer | null;
353
+ }
354
+ export namespace ISaleInquiry
355
+ {
356
+ /**
357
+ * Content info.
358
+ */
359
+ export interface IContent
360
+ {
361
+ /**
362
+ * Primary Key
363
+ */
364
+ id: string;
275
365
 
276
- When this is a type of anonymous comment, writer name would be hidden.`
277
- })
278
- writer_name: string | null;
366
+ /**
367
+ * Title of the content.
368
+ */
369
+ title: string;
279
370
 
280
- @ApiProperty({
281
- type: "array",
282
- items: {
283
- schema: { $ref: getSchemaPath(SaleArticleComment.Content) }
284
- },
285
- description:
286
- `Contents of the comments.
371
+ /**
372
+ * Body of the content.
373
+ */
374
+ body: string;
287
375
 
288
- When the comment writer tries to modify content, it would not modify the comment content but would be accumulated Therefore, all of the people can read how the content has been changed.`
289
- })
290
- contents: SaleArticleComment.Content[];
376
+ /**
377
+ * Attached files.
378
+ */
379
+ files: IAttachmentFile[];
291
380
 
292
- @ApiProperty({
293
- description: "Creation time."
294
- })
295
- created_at: string;
381
+ /**
382
+ * Creation time.
383
+ */
384
+ createdAt: string;
385
+ }
296
386
  }
297
387
  ```
298
388
  </details>
299
389
 
390
+ <details>
391
+ <summary>
392
+ Union typed DTO using <code>nestia</code>
393
+ </summary>
394
+
395
+ ```typescript
396
+ /**
397
+ * Union type of the entire sub-type articles.
398
+ *
399
+ * @author Jeongho Nam - https://github.com/samchon
400
+ */
401
+ export type ISaleEntireArtcle = ISaleQuestion | ISaleReview;
402
+ ```
403
+ </details>
404
+
300
405
 
301
406
 
302
407
 
303
408
  ### Advanced Controller Class
304
409
  Controller also can use the generic arguments.
305
410
 
306
- In the previous [Pure DTO Interface](#pure-dto-interface) corner, we've learned that the `nestia` can use the pure interface type as the DTO. Also, we've learned that using the pure interface type as DTO means that making generic typed interface or union typed interface as the DTO are also possible, too.
411
+ In the previous [Pure DTO Interface](#pure-dto-interface) corner, we've learned that `nestia` can use the pure interface type as DTO. Also, we've learned that utilizing generic, union/intersection and even conditional typed interfaces are also possible.
307
412
 
308
- In the Controller case, it's the same with the upper interface story. In the `nestia`, as using generic typed interface as DTO was possible, defining generic typed controller class is also possible, too. By defining the generic typed controller class as the super type class, you can extremely reduce both duplicated code and duplicated description comments.
413
+ In the Controller case, it's same with the upper DTO story. With `nestia`, defining a generic typed controller class is also possible, too. By defining a generic typed controller class as a super-type class, you can reduce both duplicated code and description comments.
309
414
 
310
- Look at the below code and feel how the `nestia` is powerful. I repeat that, `@nestjs/swagger` never can construct such generic or union typed controller classes, either.
415
+ Look at the below code and feel how powerful `nestia` is. It should be stated that, `@nestjs/swagger` cannot construct such generic or union typed controller class.
311
416
 
312
417
  - Simple [`CustomerSaleArticleCommentsController`](https://github.com/samchon/nestia/blob/master/demo/simple/src/controllers/ConsumerSaleArticleCommentsController.ts)
313
418
  - Generic controllers
@@ -316,6 +421,26 @@ Look at the below code and feel how the `nestia` is powerful. I repeat that, `@n
316
421
  - 2nd sub-type controller, [`ConsumerSaleQuestionsController`](https://github.com/samchon/nestia/tree/master/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts)
317
422
  - Union controller, [`ConsumerSaleEntireArticlesController`](https://github.com/samchon/nestia/tree/master/demo/union/src/controllers/ConsumerSaleEntireArticlesController.ts)
318
423
 
424
+ > [typescript-is](https://github.com/woutervh-/typescript-is) can replace the class-validator with only one line.
425
+ >
426
+ > ```typescript
427
+ > import * as nest from "@nestjs/common";
428
+ > import { assertType } from "typescript-is";
429
+ >
430
+ > @nest.Controller("consumers/:section/sales/:saleId/questions")
431
+ > export class SaleQuestionsController
432
+ > extends SaleInquiriesController<
433
+ > ISaleQuestion,
434
+ > ISaleQuestion.IContent,
435
+ > ISaleQuestion.IStore>
436
+ > {
437
+ > public constructor()
438
+ > {
439
+ > super(input => assertType<ISaleQuestion.IStore>(input));
440
+ > }
441
+ > }
442
+ > ```
443
+
319
444
  ```typescript
320
445
  import * as express from "express";
321
446
  import * as nest from "@nestjs/common";
@@ -328,6 +453,11 @@ export abstract class SaleInquiriesController<
328
453
  Store extends ISaleInquiry.IStore,
329
454
  Json extends ISaleInquiry<Content>>
330
455
  {
456
+ /**
457
+ * Constructor with type assert function.
458
+ */
459
+ protected constructor(private readonly assert: (input: Store) => void);
460
+
331
461
  /**
332
462
  * Store a new inquiry.
333
463
  *
@@ -385,19 +515,19 @@ export abstract class SaleInquiriesController<
385
515
 
386
516
 
387
517
  ### Software Development Kit
388
- > `Swagger` is torturing the client developers.
518
+ > `Swagger` is torturing client developers.
389
519
  >
390
- > If you're a backend developer and you deliver a `Swagger` to your companion client developers, the client developers should analyze the `Swagger` and implement duplicated router functions with DTO interfaces by themselves. During those jobs, if the client developers take a mistake by mis-reading the `Swagger`, it becomes the critical runtime error directly.
520
+ > If you're a backend developer and you deliver a `Swagger` to your companion client developers, they should analyze the `Swagger` and implement duplicated router functions with DTO interfaces by themselves. During those jobs, if a client developer takes a mistake by mis-reading the `Swagger`, it becomes a critical runtime error directly.
391
521
  >
392
- > Why do you torture the client developers such like that? If you deliver an SDK (Software Development Kit) instead of the `Swagger`, the client developers don't need to read the `Swagger` file and don't need to implement the duplicated DTO interfaces and router functions, either.
522
+ > Why are you torturing the client developers such like that? If you deliver an SDK (Software Development Kit) instead of the `Swagger`, the client developers don't need to read the `Swagger` file. They never need to implement the duplicated DTO interfaces with router functions, either.
393
523
  >
394
- > Therefore, just build the SDK through this `nestia` and delivers the SDK. Your client developers would be anticipated from the long time torturing and become happy. Your solution would be much more reliable and efficient, too.
524
+ > Therefore, just build the SDK through this `nestia` and deliver the SDK. Your client developers would be anticipated from the long time torturing and become happy. Your solution would be much more reliable and efficient, too.
395
525
 
396
- Looking at the SDK library file, generated by the `nestia`, it seems perfect.
526
+ Looking at the SDK library file, generated by `nestia`, it is perfect.
397
527
 
398
- Exact route method, path and parameters are constructed and DTO structures are perfectly imported. Also, descriptive comments written on the controller class methods, DTO interfaces and their properties are exactly revied in the SDK library.
528
+ Route method, path and parameters are well-formed and DTO structures are correctly imported. Also, descriptive comments are fully revived in the SDK library, regardless of where they are written.
399
529
 
400
- Furthermore, there's not any problem even when the generic typed abstract controller classes with generic typed DTO comes. The `nestia` will specialize the generic arguments exactly, by analyzing your `NestJS` developed backend server code, in the compilation level.
530
+ Furthermore, there's not any problem even when a generic typed controller class comes. `nestia` will specialize the generic arguments exactly, by analyzing your `NestJS` server code, in the compilation level.
401
531
 
402
532
  - [simple/.../comments/index.ts](https://github.com/samchon/nestia/blob/master/demo/simple/src/api/functional/consumers/sales/articles/comments/index.ts)
403
533
  - [generic/.../questions/index.ts](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/functional/consumers/sales/questions/index.ts)
@@ -540,11 +670,9 @@ export namespace update
540
670
  ### Swagger
541
671
  Building `Swagger` is also possible and even much powerful.
542
672
 
543
- Although I think the `Swagger` is a typical tool that torturing the client developers, the `nestia` also can build the `swagger.json` file. Even `Swagger` generator of the `nestia` is much powerful and convenient than the `@nestjs/swagger`. It doesn't require any type of the swagger comment or DTO decorator function and just using the pure interface type as DTO is possible.
544
-
545
- Looking at the [simple/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fsimple%2Fswagger.json) file, generated by the `nestia`, it seems perfect. Exact route method, path and parameters are constructed and DTO structures are exactly same with the pure interace type `ISaleArticleComment`. Also, comments written on the controller class method, DTO interface `ISaleArticleComment` and its properties are exactly revied on the `description` fields in the `swagger.json`.
673
+ Looking at the [simple/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fsimple%2Fswagger.json) file, generated by `nestia`, everything is perfect. Route method, path and parameters are well-formed. Also, schema definitions are exactly matched with the pure interface type `ISaleArticleComment`. Of course, descriptive comments are perfectly resurrected in the `description` properties of the `swagger.json` file.
546
674
 
547
- Looking at the another file [generic/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fgeneric%2Fswagger.json), you can find that there isn't any problem even when the generic typed DTO interfaces or controller classes come. Furthermore, traveling the `description` properties of the [generic/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Funion%2Fswagger.json), comments written on the generic interfaces and controllers are exactly revived in each route functions and schema definitions.
675
+ Looking at the another file [generic/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fgeneric%2Fswagger.json), you can find that there isn't any problem even when a generic typed DTO and controller come. The last file [union/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Funion%2Fswagger.json), there's no problem on the union type, either.
548
676
 
549
677
  - View in the `Swagger Editor`
550
678
  - [simple/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fsimple%2Fswagger.json)
@@ -565,29 +693,34 @@ SDK Generation | ✔ | ✔ | ❌
565
693
  Type check in runtime | ✔ | ❌ | ❌
566
694
  Custom compiler options | ✔ | ❌ | ❌
567
695
 
568
- You can configure the nestia builder options by two ways: `CLI` or `configuration file`.
696
+ `nestia` can configure generator options by two ways: CLI and configuration file.
569
697
 
570
- The CLI (Command Line Interface) is easy to use, because it does not require any type of configuration file wrinting. However, it's not safe thing that repeating the same command whenever generating the SDK or `swagger.json` through the CLI, because command miswriting can be happened.
698
+ At first, the CLI (Command Line Interface) is convenient, but does not support detailed options.
571
699
 
572
- ```bash
700
+ ```sh
573
701
  # BASIC COMMAND
574
- npx nestia <nestia|swagger> <source_directories_or_patterns> \
702
+ npx nestia <sdk|swagger> <source_directories_or_patterns> \
575
703
  --exclude <exclude_directory_or_pattern> \
576
704
  --out <output_directory_or_file>
577
705
 
578
706
  # EXAMPLES
579
- npx nestia nestia "src/controllers" --out "src/api"
580
- npx nestia swagger "src/**/*.controller.ts" -- out "swagger.json"
707
+ npx nestia sdk "src/controllers" --out "src/api"
708
+ npx nestia swagger "src/**/*.controller.ts" --out "swagger.json"
581
709
  npx nestia swagger "src/main/controllers" "src/sub/controllers" \
582
710
  --exclude "src/main/test" \
583
711
  --out "composite.swagger.json"
584
712
 
585
713
  # ONLY WHEN NESTIA.CONFIG.TS EXISTS
586
- npx nestia nestia
714
+ npx nestia sdk
587
715
  npx nestia swagger
588
716
  ```
589
717
 
590
- Otherwise, configuration file `nestia.config.ts` may hard to construct and the construction would be annoying and inconvenient, such configuration would be useful within framework of the reusability. Also, the configuration file `nestia.config.ts` use much detailed options than the `CLI` and its content can be ensured its safety by TypeScript compiler through the `IConfigruation` interface type.
718
+ Besides, the configuration file `nestia.config.ts` supports much detailed options.
719
+
720
+ The detailed options are listed up to the `IConfiguration` interface. You can utilize the `IConfiguration` type like below. If you want to know more about those options, please check the [Guide Documents](https://github.com/samchon/nestia/wiki/Configuration).
721
+
722
+ <details>
723
+ <summary> Read <code>IConfiguration</code> </summary>
591
724
 
592
725
  ```typescript
593
726
  /**
@@ -595,10 +728,9 @@ Otherwise, configuration file `nestia.config.ts` may hard to construct and the c
595
728
  *
596
729
  * @author Jeongho Nam - https://github.com/samchon
597
730
  */
598
- export interface IConfiguration
599
- {
731
+ export interface IConfiguration {
600
732
  /**
601
- * List of files or directories containing the NestJS controller classes.
733
+ * List of files or directories containing the `NestJS` controller classes.
602
734
  */
603
735
  input: string | string[] | IConfiguration.IInput;
604
736
 
@@ -660,13 +792,12 @@ export interface IConfiguration
660
792
  export namespace IConfiguration
661
793
  {
662
794
  /**
663
- * List of files or directories to include or exclude to specifying the NestJS
795
+ * List of files or directories to include or exclude to specifying the `NestJS`
664
796
  * controllers.
665
797
  */
666
- export interface IInput
667
- {
798
+ export interface IInput {
668
799
  /**
669
- * List of files or directories containing the NestJS controller classes.
800
+ * List of files or directories containing the `NestJS` controller classes.
670
801
  */
671
802
  include: string[];
672
803
 
@@ -679,8 +810,7 @@ export namespace IConfiguration
679
810
  /**
680
811
  * Building `swagger.json` is also possible.
681
812
  */
682
- export interface ISwagger
683
- {
813
+ export interface ISwagger {
684
814
  /**
685
815
  * Output path of the `swagger.json`.
686
816
  *
@@ -692,8 +822,7 @@ export namespace IConfiguration
692
822
  }
693
823
  }
694
824
  ```
695
-
696
- When you've completed to reading the `IConfiguration` interface, let's make the `nestia.config.ts` file directly. At first, move to your project directory. Note that the project directory means the top level directory of your project, where configuration files like `package.json` or `tsconfig.json` are placed in. After the movement, make the new `nestia` configuration file and write some script like below:
825
+ </details>
697
826
 
698
827
  ```typescript
699
828
  import type { IConfiguration } from "nestia";
@@ -714,18 +843,7 @@ export default NESTIA_CONFIG;
714
843
 
715
844
  ## Appendix
716
845
  ### Dependencies of the SDK
717
- An SDK library generated by the `nestia` requires the [nestia-fetcher](https://github.com/samchon/nestia-fetcher) module. Also, the [typescript-is](https://github.com/woutervh-/typescript-is) and [typescript-json](https://github.com/samchon/typescript-json) modules can be required following your nestia.config.ts options.
718
-
719
- ```json
720
- {
721
- "name": "payments-server-api",
722
- "dependencies": {
723
- "nestia-fetcher": "^2.0.1",
724
- "typescript-is": "^0.19.0",
725
- "typescript-json": "^2.0.9"
726
- }
727
- }
728
- ```
846
+ An SDK library generated by `nestia` requires [nestia-fetcher](https://github.com/samchon/nestia-fetcher) module. Also, [typescript-is](https://github.com/woutervh-/typescript-is) and [typescript-json](https://github.com/samchon/typescript-json) modules can be required following your `nestia.config.ts` configuration file.
729
847
 
730
848
  The `npx nestia install` command installs those dependencies with the `package.json` configuration.
731
849
 
@@ -742,7 +860,7 @@ https://github.com/samchon/backend
742
860
 
743
861
  I support template backend project using this `nestia` library, `samchon/backend`.
744
862
 
745
- Reading the README content of the backend template repository, you can find lots of example backend projects who've been generated from the backend. Furthermore, those example projects guide how to generate SDK library from the `nestia` and how to distribute the SDK library thorugh the NPM module.
863
+ Reading the README content of the backend template repository, you can find lots of example backend projects who've been generated from the backend. Furthermore, those example projects guide how to generate SDK library from `nestia` and how to distribute the SDK library thorugh the NPM module.
746
864
 
747
865
  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 `samchon/backend` template project.
748
866
 
@@ -762,4 +880,4 @@ The Archidraw is a great IT company developing 3D interior editor and lots of so
762
880
  > - 회사소개서: [archidraw.pdf](https://github.com/archidraw/payments/files/7696710/archidraw.pdf)
763
881
  > - 기술 스택: React + TypeScript
764
882
  > - 이력서: 자유 양식
765
- > - 지원처: samchon@archisketch.com
883
+ > - 지원처: samchon@archisketch.com
@@ -1 +1 @@
1
- {"version":3,"file":"ControllerAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyses/ControllerAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAM9C,yBAAiB,kBAAkB,CACnC;IACI,SAAgB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,GAAG,MAAM,EAAE,CAc7G;CAqJJ"}
1
+ {"version":3,"file":"ControllerAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyses/ControllerAnalyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAM9C,yBAAiB,kBAAkB,CACnC;IACI,SAAgB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,GAAG,MAAM,EAAE,CAc7G;CA+JJ"}
@@ -93,8 +93,8 @@ var ControllerAnalyzer;
93
93
  var runtime = controller.functions.find(function (f) { return f.name === identifier.escapedText; });
94
94
  if (runtime === undefined)
95
95
  return "continue";
96
- var route = _Analyze_function(checker, controller, genericDict, runtime, property);
97
- ret.push(route);
96
+ var routes = _Analyze_function(checker, controller, genericDict, runtime, property);
97
+ ret.push.apply(ret, __spreadArray([], __read(routes), false));
98
98
  };
99
99
  try {
100
100
  for (var _b = __values(classType.getProperties()), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -115,6 +115,7 @@ var ControllerAnalyzer;
115
115
  FUNCTION
116
116
  --------------------------------------------------------- */
117
117
  function _Analyze_function(checker, controller, genericDict, func, symbol) {
118
+ var e_2, _a, e_3, _b;
118
119
  // PREPARE ASSETS
119
120
  var type = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
120
121
  var signature = checker.getSignaturesOfType(type, typescript_1.default.SignatureKind.Call)[0];
@@ -127,12 +128,38 @@ var ControllerAnalyzer;
127
128
  var imports = importDict
128
129
  .toJSON()
129
130
  .map(function (pair) { return [pair.first, pair.second.toJSON()]; });
130
- // CONFIGURE PATH
131
- var path = _Normalize_path(path_1.default.join(controller.path, func.path)
132
- .split("\\")
133
- .join("/"));
131
+ // CONSTRUCT COMMON DATA
132
+ var common = __assign(__assign({}, func), { parameters: parameters, output: output, imports: imports, symbol: "".concat(controller.name, ".").concat(func.name, "()"), comments: signature.getDocumentationComment(undefined), tags: signature.getJsDocTags() });
133
+ // CONFIGURE PATHS
134
+ var pathList = [];
135
+ try {
136
+ for (var _c = __values(controller.paths), _d = _c.next(); !_d.done; _d = _c.next()) {
137
+ var controllerPath = _d.value;
138
+ try {
139
+ for (var _e = (e_3 = void 0, __values(func.paths)), _f = _e.next(); !_f.done; _f = _e.next()) {
140
+ var filePath = _f.value;
141
+ var path = path_1.default.join(controllerPath, filePath).split("\\").join("/");
142
+ pathList.push(_Normalize_path(path));
143
+ }
144
+ }
145
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
146
+ finally {
147
+ try {
148
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
149
+ }
150
+ finally { if (e_3) throw e_3.error; }
151
+ }
152
+ }
153
+ }
154
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
155
+ finally {
156
+ try {
157
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
158
+ }
159
+ finally { if (e_2) throw e_2.error; }
160
+ }
134
161
  // RETURNS
135
- return __assign(__assign({}, func), { path: path, parameters: parameters, output: output, imports: imports, symbol: "".concat(controller.name, ".").concat(func.name, "()"), comments: signature.getDocumentationComment(undefined), tags: signature.getJsDocTags() });
162
+ return pathList.map(function (path) { return (__assign(__assign({}, common), { path: path })); });
136
163
  }
137
164
  function _Normalize_path(path) {
138
165
  if (path[0] !== "/")
@@ -1 +1 @@
1
- {"version":3,"file":"ReflectAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyses/ReflectAnalyzer.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAQxD,yBAAiB,eAAe,CAChC;IACI,SAAsB,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAiBxF;CAsMJ"}
1
+ {"version":3,"file":"ReflectAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyses/ReflectAnalyzer.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAQxD,yBAAiB,eAAe,CAChC;IACI,SAAsB,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAiBxF;CAqNJ"}
@@ -158,10 +158,11 @@ var ReflectAnalyzer;
158
158
  // CONSTRUCTION
159
159
  //----
160
160
  // BASIC INFO
161
+ var paths = _Get_paths(Reflect.getMetadata("path", creator));
161
162
  var meta = {
162
163
  file: file,
163
164
  name: name,
164
- path: Reflect.getMetadata("path", creator),
165
+ paths: paths,
165
166
  functions: []
166
167
  };
167
168
  try {
@@ -191,12 +192,20 @@ var ReflectAnalyzer;
191
192
  entries.push.apply(entries, __spreadArray([], __read(_Get_prototype_entries(parent)), false));
192
193
  return entries;
193
194
  }
195
+ function _Get_paths(value) {
196
+ if (typeof value === "string")
197
+ return [value];
198
+ else if (value.length === 0)
199
+ return [""];
200
+ else
201
+ return value;
202
+ }
194
203
  /* ---------------------------------------------------------
195
204
  FUNCTION
196
205
  --------------------------------------------------------- */
197
206
  function _Analyze_function(classProto, controller, name, proto) {
198
- var e_3, _a;
199
- var _b, _c;
207
+ var e_3, _a, e_4, _b, e_5, _c;
208
+ var _d, _e;
200
209
  //----
201
210
  // VALIDATIONS
202
211
  //----
@@ -213,10 +222,10 @@ var ReflectAnalyzer;
213
222
  var meta = {
214
223
  name: name,
215
224
  method: METHODS[Reflect.getMetadata("method", proto)],
216
- path: Reflect.getMetadata("path", proto),
225
+ paths: _Get_paths(Reflect.getMetadata("path", proto)),
217
226
  parameters: [],
218
227
  encrypted: Reflect.hasMetadata("__interceptors__", proto)
219
- && ((_c = (_b = Reflect.getMetadata("__interceptors__", proto)[0]) === null || _b === void 0 ? void 0 : _b.constructor) === null || _c === void 0 ? void 0 : _c.name) === "EncryptedRouteInterceptor"
228
+ && ((_e = (_d = Reflect.getMetadata("__interceptors__", proto)[0]) === null || _d === void 0 ? void 0 : _d.constructor) === null || _e === void 0 ? void 0 : _e.name) === "EncryptedRouteInterceptor"
220
229
  };
221
230
  // PARSE CHILDREN DATA
222
231
  var nestParameters = Reflect.getMetadata("__routeArguments__", classProto.constructor, name);
@@ -224,8 +233,8 @@ var ReflectAnalyzer;
224
233
  meta.parameters = [];
225
234
  else {
226
235
  try {
227
- for (var _d = __values(Object.entries(nestParameters)), _e = _d.next(); !_e.done; _e = _d.next()) {
228
- var tuple = _e.value;
236
+ for (var _f = __values(Object.entries(nestParameters)), _g = _f.next(); !_g.done; _g = _f.next()) {
237
+ var tuple = _g.value;
229
238
  var child = _Analyze_parameter.apply(void 0, __spreadArray([], __read(tuple), false));
230
239
  if (child !== null)
231
240
  meta.parameters.push(child);
@@ -234,22 +243,46 @@ var ReflectAnalyzer;
234
243
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
235
244
  finally {
236
245
  try {
237
- if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
246
+ if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
238
247
  }
239
248
  finally { if (e_3) throw e_3.error; }
240
249
  }
241
250
  meta.parameters = meta.parameters.sort(function (x, y) { return x.index - y.index; });
242
251
  }
243
- // VALIDATE PATH ARGUMENTS
244
- var funcPathArguments = StringUtil_1.StringUtil.betweens(path_1.default.join(controller.path, meta.path)
245
- .split("\\")
246
- .join("/"), ":", "/").sort();
247
- var paramPathArguments = meta.parameters
248
- .filter(function (param) { return param.category === "param"; })
249
- .map(function (param) { return param.field; })
250
- .sort();
251
- if ((0, module_1.equal)(funcPathArguments, paramPathArguments) === false)
252
- throw new Error("Error on ".concat(controller.name, ".").concat(name, "(): binded arguments in the \"path\" between function's decorator and parameters' decorators are different (function: [").concat(funcPathArguments.join(", "), "], parameters: [").concat(paramPathArguments.join(", "), "])"));
252
+ try {
253
+ // VALIDATE PATH ARGUMENTS
254
+ for (var _h = __values(controller.paths), _j = _h.next(); !_j.done; _j = _h.next()) {
255
+ var controllerPath = _j.value;
256
+ try {
257
+ for (var _k = (e_5 = void 0, __values(meta.paths)), _l = _k.next(); !_l.done; _l = _k.next()) {
258
+ var metaPath = _l.value;
259
+ var funcPathArguments = StringUtil_1.StringUtil.betweens(path_1.default.join(controllerPath, metaPath)
260
+ .split("\\")
261
+ .join("/"), ":", "/").sort();
262
+ var paramPathArguments = meta.parameters
263
+ .filter(function (param) { return param.category === "param"; })
264
+ .map(function (param) { return param.field; })
265
+ .sort();
266
+ if ((0, module_1.equal)(funcPathArguments, paramPathArguments) === false)
267
+ throw new Error("Error on ".concat(controller.name, ".").concat(name, "(): binded arguments in the \"path\" between function's decorator and parameters' decorators are different (function: [").concat(funcPathArguments.join(", "), "], parameters: [").concat(paramPathArguments.join(", "), "])"));
268
+ }
269
+ }
270
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
271
+ finally {
272
+ try {
273
+ if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
274
+ }
275
+ finally { if (e_5) throw e_5.error; }
276
+ }
277
+ }
278
+ }
279
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
280
+ finally {
281
+ try {
282
+ if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
283
+ }
284
+ finally { if (e_4) throw e_4.error; }
285
+ }
253
286
  // RETURNS
254
287
  return meta;
255
288
  }
@@ -2,14 +2,14 @@ import { ParamCategory } from "./ParamCategory";
2
2
  export interface IController {
3
3
  file: string;
4
4
  name: string;
5
- path: string;
5
+ paths: string[];
6
6
  functions: IController.IFunction[];
7
7
  }
8
8
  export declare namespace IController {
9
9
  interface IFunction {
10
10
  name: string;
11
11
  method: string;
12
- path: string;
12
+ paths: string[];
13
13
  encrypted: boolean;
14
14
  parameters: IParameter[];
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"IController.d.ts","sourceRoot":"","sources":["../../src/structures/IController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,WAAW;IAExB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC;CACtC;AAED,yBAAiB,WAAW,CAC5B;IACI,UAAiB,SAAS;QAEtB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,OAAO,CAAC;QAEnB,UAAU,EAAE,UAAU,EAAE,CAAC;KAC5B;IAED,UAAiB,UAAU;QAEvB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;QAC1B,QAAQ,EAAE,aAAa,CAAC;QACxB,SAAS,EAAE,OAAO,CAAC;KACtB;CACJ"}
1
+ {"version":3,"file":"IController.d.ts","sourceRoot":"","sources":["../../src/structures/IController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,WAAW,WAAW;IAExB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC;CACtC;AAED,yBAAiB,WAAW,CAC5B;IACI,UAAiB,SAAS;QAEtB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QAEnB,UAAU,EAAE,UAAU,EAAE,CAAC;KAC5B;IAED,UAAiB,UAAU;QAEvB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;QAC1B,QAAQ,EAAE,aAAa,CAAC;QACxB,SAAS,EAAE,OAAO,CAAC;KACtB;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestia",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "Automatic SDK and Document generator for the NestJS",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",