nestia 2.1.2-dev.20220509 → 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,372 +1,474 @@
1
1
  # Nestia
2
- Automatic `SDK` and `swagger.json` generator for the NestJS.
3
-
4
- [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)
5
- [![npm version](https://badge.fury.io/js/nestia.svg)](https://www.npmjs.com/package/nestia)
6
- [![Downloads](https://img.shields.io/npm/dm/nestia.svg)](https://www.npmjs.com/package/nestia)
7
- [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
-
9
- ```bash
10
- # INSTALL NESTIA
11
- npm install --save-dev nestia
12
-
13
- # WHEN ALL OF THE CONTROLLRES ARE GATHERED INTO A DIRECTORY
14
- npx nestia sdk "src/controller" --out "src/api"
15
-
16
- # REGULAR NESTJS PATTERN
17
- npx nestia sdk "src/**/*.controller.ts" --out "src/api"
18
-
19
- # BUILDING SWAGGER.JSON IS ALSO POSSIBLE
20
- npx nestia swagger "src/controller" -- out "swagger.json"
21
- ```
22
-
23
- Don't write any `swagger` comment and DTO decorator. Just run the [nestia](https://github.com/samchon/nestia) up.
24
-
25
- - No swagger comment/decorator
26
- - No DTO comment/decorator
27
- - Only pure NestJS code is required
28
-
29
- When you're developing a backend server using the `NestJS`, you don't need any extra dedication, for delivering the Rest API to the client developers, like writing the `swagger` comments or DTO decorators.
30
-
31
- You just run this [nestia](https://github.com/samchon/nestia) up, then [nestia](https://github.com/samchon/nestia) would generate the SDK automatically, by analyzing your controller classes in the compliation and runtime level. With the automatically generated SDK through this [nestia](https://github.com/samchon/nestia), client developer also does not need any extra work, like reading `swagger` and writing the duplicated interaction code. Client developer only needs to import the SDK and calls matched function with the `await` symbol.
32
-
33
- > Even generating the `swagger.json` without any swagger comment and DTO decorator is also possible. When generating the `swagger.json`, no DTO comment and decorator is required, either. Use only the pure interface definitions.
2
+ Automatic `SDK` and `Swagger` generator for the `NestJS`, evolved than ever.
3
+
4
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)
5
+ [![npm version](https://badge.fury.io/js/nestia.svg)](https://www.npmjs.com/package/nestia)
6
+ [![Downloads](https://img.shields.io/npm/dm/nestia.svg)](https://www.npmjs.com/package/nestia)
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)
9
+
10
+ - Github: https://github.com/samchon/nestia
11
+ - NPM: https://www.npmjs.com/packages/nestia
12
+ - Guide Documents: https://github.com/samchon/nestia/wiki
13
+
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.
15
+
16
+ Reading below contents, feel how the "compilation level" makes `nestia` stronger.
17
+
18
+ Components | `nestia`::SDK | `nestia`::swagger | `@nestjs/swagger`
19
+ -----------|---|---|---
20
+ Pure DTO interface | | ✔ | ❌
21
+ Description comments | ✔ | ✔ | ❌
22
+ Simple structure | ✔ | ✔ | ✔
23
+ Generic type | | |
24
+ Union type | ✔ | ✔ | ▲
25
+ Intersection type | ✔ | ✔ | ▲
26
+ Conditional type | ✔ | ▲ | ❌
27
+ Auto completion | | | ❌
28
+ Type hints | ✔ | ❌ | ❌
29
+ 2x faster `JSON.stringify()` | | |
30
+ Ensure type safety | ✅ | ❌ | ❌
34
31
 
35
32
  ```typescript
36
- import api from "@samchon/bbs-api";
37
- import { IBbsArticle } from "@samchon/bbs-api/lib/structures/bbs/IBbsArticle";
38
- import { IPage } from "@samchon/bbs-api/lib/structures/common/IPage";
39
-
40
- export async function test_article_read(connection: api.IConnection): Promise<void>
33
+ // IMPORT SDK LIBRARY GENERATED BY NESTIA
34
+ import api from "@samchon/shopping-api";
35
+ import { IPage } from "@samchon/shopping-api/lib/structures/IPage";
36
+ import { ISale } from "@samchon/shopping-api/lib/structures/ISale";
37
+ import { ISaleArticleComment } from "@samchon/shopping-api/lib/structures/ISaleArticleComment";
38
+ import { ISaleQuestion } from "@samchon/shopping-api/lib/structures/ISaleQuestion";
39
+
40
+ export async function trace_sale_question_and_comment
41
+ (connection: api.IConnection): Promise<void>
41
42
  {
42
- // LIST UP ARTICLE SUMMARIES
43
- const index: IPage<IBbsArticle.ISummary> = await api.functional.bbs.articles.index
43
+ // LIST UP SALE SUMMARIES
44
+ const index: IPage<ISale.ISummary> = await api.functional.shoppings.sales.index
44
45
  (
45
46
  connection,
46
- "free",
47
+ "general",
47
48
  { limit: 100, page: 1 }
48
49
  );
49
50
 
50
- // READ AN ARTICLE DETAILY
51
- const article: IBbsArticle = await api.functional.bbs.articles.at
51
+ // PICK A SALE
52
+ const sale: ISale = await api.functional.shoppings.sales.at
52
53
  (
53
- connection,
54
- "free",
54
+ connection,
55
55
  index.data[0].id
56
56
  );
57
- console.log(article.title, aritlce.body, article.files);
57
+ console.log("sale", sale);
58
+
59
+ // WRITE A QUESTION
60
+ const question: ISaleQuestion = await api.functional.shoppings.sales.questions.store
61
+ (
62
+ connection,
63
+ "general",
64
+ sale.id,
65
+ {
66
+ title: "How to use this product?",
67
+ body: "The description is not fully enough. Can you introduce me more?",
68
+ files: []
69
+ }
70
+ );
71
+ console.log("question", question);
72
+
73
+ // WRITE A COMMENT
74
+ const comment: ISaleArticleComment = await api.functional.shoppings.sales.comments.store
75
+ (
76
+ connection,
77
+ "general",
78
+ sale.id,
79
+ question.id,
80
+ {
81
+ body: "p.s) Can you send me a detailed catalogue?",
82
+ anonymous: false
83
+ }
84
+ );
85
+ console.log("comment", comment);
58
86
  }
59
87
  ```
60
88
 
61
89
 
62
90
 
91
+ ## Setup
92
+ Just like any other package, you've got to install it before you can use it.
63
93
 
64
- ## Usage
65
- ### Installation
66
- ```bash
94
+ ```sh
67
95
  npm install --save-dev nestia
68
96
  ```
69
97
 
70
- Installing the [nestia](https://github.com/samchon/nestia) is very easy.
98
+ After the installation, you can generate the `SDK` or `Swagger`, directly.
71
99
 
72
- Just type the `npm install --save-dev nestia` command in your NestJS backend project.
100
+ ```sh
101
+ npx nestia sdk "src/**/*.controller" --out "src/api"
102
+ npx nestia swagger "src/**/*.controller" --out "swagger.json"
103
+ ```
73
104
 
74
- ### SDK generation
75
- ```bash
76
- npx nestia sdk <source_controller_directory> --out <output_sdk_directory>
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
+ > ```
77
118
 
78
- npx nestia sdk "src/**/*.controller.ts" --out "src/api"
79
- npx nestia sdk "src/controllers" --out "src/api"
80
- npx nestia sdk "src/controllers/consumers" "src/controllers/sellers" --out "src/api"
81
- npx nestia sdk "src/controllers" --exclude "src/**/Fake*.ts" --out "src/api"
82
- ```
83
119
 
84
- To generate a SDK library through the [nestia](https://github.com/samchon/nestia) is very easy.
85
120
 
86
- 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.
87
121
 
88
- 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).
122
+ ## Demonstrations
123
+ ### Pure DTO Interface
124
+ `nestia` can utilize pure interface type as DTO.
89
125
 
90
- ### Swagger generation
91
- ```bash
92
- npx nestia <source_controller_of_directory> --out <output_path>
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.
93
127
 
94
- npx nestia swagger "src/**/*.controller.ts" --out "./"
95
- npx nestia swagger "src/controllers" --out "./swagger.json"
96
- npx nestia swagger "src/consumers" "src/sellers" --out "actors.json"
97
- npx nestia swagger "src/controllers" --exclude "src/**/Fake*.ts" -out "./"
98
- ```
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.
99
129
 
100
- The [nestia](https://github.com/samchon/nestia) even supports the `swagger.json` generation and it's also extermely easy.
130
+ - Simple [`ISaleArticleComment`](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/structures/ISaleArticleComment.ts)
131
+ - Generic interfaces
132
+ - grandparent interface, [`ISaleArticle<Content>`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleArticle.ts)
133
+ - parent interface, [`ISaleInquiry<Content>`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleInquiry.ts)
134
+ - 1st sub-type interface, [`ISaleQuestion`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleQuestion.ts)
135
+ - 2nd sub-type interface, [`ISaleReview`](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/structures/ISaleReview.ts)
136
+ - Union alias type [`ISaleEntireArticle`](https://github.com/samchon/nestia/tree/master/demo/union/src/api/structures/ISaleEntireArticle.ts)
101
137
 
102
- Jsut type the `nestia swagger <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 `swagger.json` generation, the `--exclude` option would be useful.
138
+ > The below example code would be shown by clicking the arrow button or text.
103
139
 
104
- 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).
140
+ <details>
141
+ <summary>
142
+ Traditional DTO class using <code>@nestjs/swagger</code>
143
+ </summary>
105
144
 
106
- ### Dependencies
107
- ```bash
108
- npx nestia install
109
- ```
145
+ ```typescript
146
+ export class SaleArticleComment
147
+ {
148
+ @ApiProperty({
149
+ description:
150
+ `Comment wrote on a sale related article.
110
151
 
111
- SDK library generated by the [nestia](https://github.com/samchon/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](#nestiaconfigts) options.
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.
112
153
 
113
- The `npx nestia install` command installs those dependencies with `package.json` configuration.
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;
114
157
 
115
- ```json
116
- {
117
- "name": "payments-server-api",
118
- "dependencies": {
119
- "nestia-fetcher": "^2.0.1",
120
- "typescript-is": "^0.19.0",
121
- "typescript-json": "^2.0.9"
122
- }
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;
123
200
  }
124
201
  ```
202
+ </details>
125
203
 
204
+ <details>
205
+ <summary>
206
+ Pure DTO interface using <code>nestia</code>
207
+ </summary>
126
208
 
127
-
128
- ## Advanced
129
- ### `nestia.config.ts`
130
209
  ```typescript
131
210
  /**
132
- * Definition for the `nestia.config.ts` file.
211
+ * Comment wrote on a sale related article.
212
+ *
213
+ * When an article of a sale has been enrolled, all of the participants like consumers and
214
+ * sellers can write a comment on that article. However, when the writer is a consumer, the
215
+ * consumer can hide its name through the annoymous option.
216
+ *
217
+ * Also, writing a reply comment for a specific comment is possible and in that case, the
218
+ * {@link ISaleArticleComment.parent_id} property would be activated.
133
219
  *
134
220
  * @author Jeongho Nam - https://github.com/samchon
135
221
  */
136
- export interface IConfiguration
222
+ export interface ISaleArticleComment
137
223
  {
138
224
  /**
139
- * List of files or directories containing the NestJS controller classes.
225
+ * Primary Key.
140
226
  */
141
- input: string | string[] | IConfiguration.IInput;
227
+ id: number;
142
228
 
143
229
  /**
144
- * Output directory that SDK would be placed in.
230
+ * Parent comment ID.
231
+ *
232
+ * Only When this comment has been written as a reply.
145
233
  */
146
- output?: string;
234
+ parent_id: number | null;
147
235
 
148
236
  /**
149
- * Compiler options for the TypeScript.
150
- *
151
- * If omitted, the configuration would follow the `tsconfig.json`.
237
+ * Type of the writer.
152
238
  */
153
- compilerOptions?: ts.CompilerOptions;
239
+ writer_type: "seller" | "consumer";
154
240
 
155
241
  /**
156
- * Whether to assert parameter types or not.
242
+ * Name of the writer.
157
243
  *
158
- * If you configure this option to be `true`, all of the function parameters would be
159
- * checked through the [typescript-is](https://github.com/woutervh-/typescript-is).
244
+ * When this is a type of anonymous comment, writer name would be hidden.
160
245
  */
161
- assert?: boolean;
246
+ writer_name: string | null;
162
247
 
163
248
  /**
164
- * Whether to optimize JSON string conversion 2x faster or not.
249
+ * Contents of the comments.
165
250
  *
166
- * If you configure this option to be `true`, the SDK library would utilize the
167
- * [typescript-json](https://github.com/samchon/typescript-json) and the JSON string
168
- * conversion speed really be 2x faster.
251
+ * When the comment writer tries to modify content, it would not modify the comment
252
+ * content but would be accumulated. Therefore, all of the people can read how
253
+ * the content has been changed.
169
254
  */
170
- json?: boolean;
255
+ contents: ISaleArticleComment.IContent[];
171
256
 
172
257
  /**
173
- * Building `swagger.json` is also possible.
258
+ * Creation time.
174
259
  */
175
- swagger?: IConfiguration.ISwagger;
260
+ created_at: string;
176
261
  }
177
- export namespace IConfiguration
262
+ export namespace ISaleArticleComment
178
263
  {
179
264
  /**
180
- * List of files or directories to include or exclude to specifying the NestJS
181
- * controllers.
265
+ * Store info.
182
266
  */
183
- export interface IInput
267
+ export interface IStore
184
268
  {
185
269
  /**
186
- * List of files or directories containing the NestJS controller classes.
270
+ * Body of the content.
187
271
  */
188
- include: string[];
272
+ body: string;
189
273
 
190
274
  /**
191
- * List of files or directories to be excluded.
275
+ * Whether to hide the writer name or not.
192
276
  */
193
- exclude?: string[];
277
+ annonymous: boolean;
194
278
  }
195
279
 
196
280
  /**
197
- * Building `swagger.json` is also possible.
281
+ * Content info.
198
282
  */
199
- export interface ISwagger
283
+ export interface IContent
200
284
  {
201
285
  /**
202
- * Output path of the `swagger.json`.
203
- *
204
- * If you've configure only directory, the file name would be `swagger.json`.
205
- * Otherwise you configure file name and extension, the `swagger.json` file would
206
- * be renamed to what you've configured.
286
+ * Primary Key.
207
287
  */
208
- output: string;
209
- }
210
- }
211
- ```
212
-
213
- Instead of specifying `input` and `output` directories using the cli options, you can specify those directories as an independent configuration file. It's the `nestia.config.ts` and with the `nestia.config.ts` file, you also configure independent TypeScript compiler option from the `tsconfig.json`.
214
-
215
- Write below content as the `nestia.config.ts` file and place it onto the root directory of your backend project. After the configuration, you can generate the SDK only with the `npx nestia sdk` command, without any directory specification.
288
+ id: string;
216
289
 
217
- ```typescript
218
- import type nestia from "nestia";
290
+ /**
291
+ * Body of the content.
292
+ */
293
+ body: string;
219
294
 
220
- const config: nestia.IConfiguration = {
221
- input: "src/controllers",
222
- output: "src/api",
223
- assert: false
224
- };
225
- export default config;
295
+ /**
296
+ * Creation time.
297
+ */
298
+ created_at: string;
299
+ }
300
+ }
226
301
  ```
302
+ </details>
227
303
 
228
- > Alternative options for the regular NestJS project:
229
- >
230
- > ```typescript
231
- > export = {
232
- > input: "src/**/*.controller.ts",
233
- > /* input: {
234
- > include: ["src/controllers/**\/*.controller.ts"],
235
- > exclude: ["src/controllers/**\/fake_*.controller.ts"]
236
- > },*/
237
- > output: "src/api",
238
- > assert: true
239
- > }
240
- > ```
241
-
242
-
243
-
244
- ### Recommended Structures
245
- When developing a NestJS backend server with this [nestia](https://github.com/samchon/nestia), I recommend you to follow below directory structure. The key princinple of below structure is to gathering all of the DTO interface structures into the `src/api/structures` directory and gather all of the controller classes into the `src/controllers` directory.
246
-
247
- If you place the SDK onto the `src/api` directory and gather all of the DTO interface structures into the `src/api/structures` directory, you can publish the SDK library very easily without any special configuration. Also when you're develop the test automation program, you can implement the API testing features very convenienty through the automatically generated SDK through this [nestia](https://github.com/samchon/nestia).
248
-
249
- - src
250
- - api
251
- - **functional**: automatically generated SDK functions
252
- - **structures**: DTO structures
253
- - controllers
254
- - providers
255
- - models
256
- - **test**: Test automation program using SDK functions
257
- - package.json
258
- - tsconfig.json
259
- - nestia.config.ts
260
-
261
- For your deep understanding about this directory structure with this [nestia](https://github.com/samchon/nestia), I've prepared an example backend project. Looking around the example repository and reading the [README.md](https://github.com/samchon/backend#13-directories) of it, you can feel that such directory structure is how convenient for SDK publishing and test automation program implementation.
262
-
263
- - https://github.com/samchon/backend
264
-
265
-
266
-
267
-
268
- ## Demonstration
269
- To demonstrate which SDK codes would be generated by this [nestia](https://github.com/samchon/nestia):
270
-
271
- - Representative files
272
- - [DTO interface used in the RestAPI](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/structures/ISaleArticleComment.ts)
273
- - [Controllers of the NestJS](https://github.com/samchon/nestia/tree/master/demo/simple/src/controllers/ConsumerSaleArticleCommentsController.ts)
274
- - [SDK generated by this [nestia](https://github.com/samchon/nestia)](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/functional/consumers/sales/articles/comments/index.ts)
275
- - [`swagger.json` generated by this [nestia](https://github.com/samchon/nestia)](https://github.com/samchon/nestia/tree/master/demo/simple/swagger.json)
276
- - Demonstration Projects
277
- - [encrypt](https://github.com/samchon/nestia/tree/master/demo/encrypt): Request and response body are fully encrypted
278
- - [generic](https://github.com/samchon/nestia/tree/master/demo/generic): Generic typed controller classes
279
- - [recursive](https://github.com/samchon/nestia/tree/master/demo/recursive): Recursive DTO interface, [swagger editor](https://editor.swagger.io) can't expresss it
280
- - [simple](https://github.com/samchon/nestia/tree/master/demo/simple): Simple DTO interface and controller class
281
- - [union](https://github.com/samchon/nestia/tree/master/demo/union): Only [nestia](https://github.com/samchon/nestia) can handle the union typed DTO interface
282
-
283
- ### DTO
284
- Using pure interface type as DTO is possible.
285
-
286
- You dont' need to define any extra comment or decorator function to make the DTO (Data Transfer Object). Just define the DTO as a pure interface structure, then [nestia](https://github.com/samchon/nestia) will do everything instead of you.
287
-
288
- If you're afraiding because your type is union or intersection, I can say that it does not matter. Even when generic or conditional type comes, it does not matter. Just enjoy the pure TypeScript type.
304
+ <details>
305
+ <summary>
306
+ Generic typed DTO using <code>nestia</code>
307
+ </summary>
289
308
 
290
309
  ```typescript
291
310
  /**
292
- * Comment wrote on a sale related article.
311
+ * Inquiry article.
293
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
294
320
  * @author Jeongho Nam - https://github.com/samchon
295
321
  */
296
- export interface ISaleComment
322
+ export interface ISaleInquiry<Content extends ISaleInquiry.IContent>
323
+ extends ISaleArticle<Content>
297
324
  {
298
325
  /**
299
326
  * Primary Key.
300
327
  */
301
328
  id: number;
302
329
 
303
- /**
304
- * Type of the writer.
305
- */
306
- writer_type: "seller" | "consumer";
307
-
308
330
  /**
309
331
  * Name of the writer.
310
332
  */
311
- writer_name: string;
333
+ writer: string;
312
334
 
313
335
  /**
314
- * Contents of the comments.
336
+ * List of contents.
315
337
  *
316
- * When the comment writer tries to modify content, it would not modify the comment
317
- * content but would be accumulated. Therefore, all of the people can read how
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
318
340
  * the content has been changed.
319
341
  */
320
- contents: ISaleComment.IContent[];
342
+ contents: Content[];
321
343
 
322
344
  /**
323
345
  * Creation time.
324
346
  */
325
- created_at: string;
347
+ createdAat: string;
348
+
349
+ /**
350
+ * Formal answer from the seller.
351
+ */
352
+ answer: ISaleInquiryAnswer | null;
326
353
  }
327
-
328
- export namespace ISaleComment
354
+ export namespace ISaleInquiry
329
355
  {
330
356
  /**
331
- * Store info.
357
+ * Content info.
332
358
  */
333
- export interface IStore
359
+ export interface IContent
334
360
  {
361
+ /**
362
+ * Primary Key
363
+ */
364
+ id: string;
365
+
366
+ /**
367
+ * Title of the content.
368
+ */
369
+ title: string;
370
+
335
371
  /**
336
372
  * Body of the content.
337
373
  */
338
374
  body: string;
339
- }
340
375
 
341
- /**
342
- * Content info.
343
- */
344
- export interface IContent extends IStore
345
- {
376
+ /**
377
+ * Attached files.
378
+ */
379
+ files: IAttachmentFile[];
380
+
346
381
  /**
347
382
  * Creation time.
348
383
  */
349
- created_at: string;
384
+ createdAt: string;
350
385
  }
351
386
  }
352
387
  ```
388
+ </details>
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>
353
404
 
354
- ### Controller
355
- If you've decided to adapt this [nestia](https://github.com/samchon/nestia) and you want to generate the SDK directly, you don't need any extra work. Just keep you controller class down and do noting. The only one exceptional case that you need an extra dedication is, when you want to explain about the API function to the client developers through the comments.
405
+
406
+
407
+
408
+ ### Advanced Controller Class
409
+ Controller also can use the generic arguments.
410
+
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.
412
+
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.
414
+
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.
416
+
417
+ - Simple [`CustomerSaleArticleCommentsController`](https://github.com/samchon/nestia/blob/master/demo/simple/src/controllers/ConsumerSaleArticleCommentsController.ts)
418
+ - Generic controllers
419
+ - abstract controller, [`SaleInquiriesController<Content, Store, Json>`](https://github.com/samchon/nestia/tree/master/demo/generic/src/controllers/SaleInquiriesController.ts)
420
+ - 1st sub-type controller, [`ConsumerSaleQuestionsController`](https://github.com/samchon/nestia/tree/master/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts)
421
+ - 2nd sub-type controller, [`ConsumerSaleQuestionsController`](https://github.com/samchon/nestia/tree/master/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts)
422
+ - Union controller, [`ConsumerSaleEntireArticlesController`](https://github.com/samchon/nestia/tree/master/demo/union/src/controllers/ConsumerSaleEntireArticlesController.ts)
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
+ > ```
356
443
 
357
444
  ```typescript
358
- @nest.Controller("consumers/:section/sales/:saleId/questions")
359
- export class ConsumerSaleQuestionsController
445
+ import * as express from "express";
446
+ import * as nest from "@nestjs/common";
447
+ import helper from "nestia-helper";
448
+
449
+ import { ISaleInquiry } from "@api/structures/ISaleInquiry";
450
+
451
+ export abstract class SaleInquiriesController<
452
+ Content extends ISaleInquiry.IContent,
453
+ Store extends ISaleInquiry.IStore,
454
+ Json extends ISaleInquiry<Content>>
360
455
  {
361
456
  /**
362
- * Store a new question.
457
+ * Constructor with type assert function.
458
+ */
459
+ protected constructor(private readonly assert: (input: Store) => void);
460
+
461
+ /**
462
+ * Store a new inquiry.
463
+ *
464
+ * Write a new article inquirying about a sale.
363
465
  *
364
466
  * @param request Instance of the Express.Request
365
467
  * @param section Code of the target section
366
468
  * @param saleId ID of the target sale
367
469
  * @param input Content to archive
470
+ * @return Newly archived inquiry
368
471
  *
369
- * @return Newly archived question
370
472
  * @throw 400 bad request error when type of the input data is not valid
371
473
  * @throw 401 unauthorized error when you've not logged in yet
372
474
  */
@@ -374,40 +476,101 @@ export class ConsumerSaleQuestionsController
374
476
  public store
375
477
  (
376
478
  @nest.Request() request: express.Request,
377
- @nest.Param("section") section: string,
378
- @nest.Param("saleId") saleId: number,
379
- @nest.Body() input: ISaleQuestion.IStore
380
- ): Promise<ISaleQuestion>;
479
+ @helper.TypedParam("section", "string") section: string,
480
+ @helper.TypedParam("saleId", "string") saleId: string,
481
+ @nest.Body() input: Store
482
+ ): Promise<Json>;
483
+
484
+ /**
485
+ * Update an inquiry.
486
+ *
487
+ * Update ordinary inquiry article. However, it would not modify the content reocrd
488
+ * {@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}.
489
+ * Therefore, all of the poeple can read how the content has been changed.
490
+ *
491
+ * @param request Instance of the Express.Request
492
+ * @param section Code of the target section
493
+ * @param saleId ID of the target sale
494
+ * @param id ID of the target article to be updated
495
+ * @param input New content to be overwritten
496
+ * @return The newly created content record
497
+ *
498
+ * @throw 400 bad request error when type of the input data is not valid
499
+ * @throw 401 unauthorized error when you've not logged in yet
500
+ * @throw 403 forbidden error when the article is not yours
501
+ */
502
+ @nest.Put(":id")
503
+ public update
504
+ (
505
+ @nest.Request() request: express.Request,
506
+ @helper.TypedParam("section", "string") section: string,
507
+ @helper.TypedParam("saleId", "string") saleId: string,
508
+ @helper.TypedParam("id", "number") id: number,
509
+ @nest.Body() input: Store
510
+ ): Promise<Json>;
381
511
  }
382
512
  ```
383
513
 
384
- ### SDK
385
- When you run the [nestia](https://github.com/samchon/nestia) up using the upper controller class `ConsumerSaleQuestionsController`, the [nestia](https://github.com/samchon/nestia) would generate below function for the client developers, by analyzing the `ConsumerSaleQuestionsController` class in the compilation and runtime level.
386
514
 
387
- As you can see, the comments from the `ConsumerSaleQuestionsController.store()` are fully copied to the SDK function. Therefore, if you want to deliver detailed description about the API function, writing the detailed comment would be tne best choice.
515
+
516
+
517
+ ### Software Development Kit
518
+ > `Swagger` is torturing client developers.
519
+ >
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.
521
+ >
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.
523
+ >
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.
525
+
526
+ Looking at the SDK library file, generated by `nestia`, it is perfect.
527
+
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.
529
+
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.
531
+
532
+ - [simple/.../comments/index.ts](https://github.com/samchon/nestia/blob/master/demo/simple/src/api/functional/consumers/sales/articles/comments/index.ts)
533
+ - [generic/.../questions/index.ts](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/functional/consumers/sales/questions/index.ts)
534
+ - [generic/.../reviews/index.ts](https://github.com/samchon/nestia/tree/master/demo/generic/src/api/functional/consumers/sales/reviews/index.ts)
535
+ - [union/.../entire_articles/index.ts](https://github.com/samchon/nestia/tree/master/demo/union/src/api/functional/consumers/sales/entire_articles/index.ts)
388
536
 
389
537
  ```typescript
390
538
  /**
391
- * Store a new question.
539
+ * @packageDocumentation
540
+ * @module api.functional.consumers.sales.reviews
541
+ * @nestia Generated by Nestia - https://github.com/samchon/nestia
542
+ */
543
+ //================================================================
544
+ import { Fetcher, Primitive } from "nestia-fetcher";
545
+ import type { IConnection } from "nestia-fetcher";
546
+ import { createStringifier } from "typescript-json";
547
+
548
+ import type { ISaleReview } from "./../../../../structures/ISaleReview";
549
+ import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry";
550
+
551
+ /**
552
+ * Store a new inquiry.
553
+ *
554
+ * Write a new article inquirying about a sale.
392
555
  *
393
556
  * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password)
394
557
  * @param request Instance of the Express.Request
395
558
  * @param section Code of the target section
396
559
  * @param saleId ID of the target sale
397
560
  * @param input Content to archive
398
- * @return Newly archived question
561
+ * @return Newly archived inquiry
399
562
  * @throw 400 bad request error when type of the input data is not valid
400
563
  * @throw 401 unauthorized error when you've not logged in yet
401
564
  *
565
+ * @controller ConsumerSaleReviewsController.store()
566
+ * @path POST /consumers/:section/sales/:saleId/reviews
402
567
  * @nestia Generated by Nestia - https://github.com/samchon/nestia
403
- * @controller ConsumerSaleQuestionsController.store()
404
- * @path POST /consumers/:section/sales/:saleId/questions/
405
568
  */
406
569
  export function store
407
570
  (
408
571
  connection: IConnection,
409
572
  section: string,
410
- saleId: number,
573
+ saleId: string,
411
574
  input: Primitive<store.Input>
412
575
  ): Promise<store.Output>
413
576
  {
@@ -417,249 +580,304 @@ export function store
417
580
  store.ENCRYPTED,
418
581
  store.METHOD,
419
582
  store.path(section, saleId),
420
- input
583
+ input,
584
+ store.stringify
421
585
  );
422
586
  }
423
587
  export namespace store
424
588
  {
425
- export type Input = Primitive<ISaleInquiry.IStore>;
426
- export type Output = Primitive<ISaleInquiry<ISaleArticle.IContent>>;
589
+ export type Input = Primitive<ISaleReview.IStore>;
590
+ export type Output = Primitive<ISaleInquiry<ISaleReview.IContent>>;
427
591
 
428
592
  export const METHOD = "POST" as const;
429
- export const PATH: string = "/consumers/:section/sales/:saleId/questions";
593
+ export const PATH: string = "/consumers/:section/sales/:saleId/reviews";
430
594
  export const ENCRYPTED: Fetcher.IEncrypted = {
431
- request: true,
432
- response: true,
595
+ request: false,
596
+ response: false,
433
597
  };
434
598
 
435
- export function path(section: string, saleId: number): string
599
+ export function path(section: string, saleId: string): string
436
600
  {
437
- return `/consumers/${section}/sales/${saleId}/questions`;
601
+ return `/consumers/${section}/sales/${saleId}/reviews`;
438
602
  }
603
+ export const stringify = createStringifier<Input>();
439
604
  }
440
- ```
441
605
 
442
- ### `swagger.json`
443
- Even the `swagger.json` generation does not require any swagger comment and DTO decorator.
606
+ /**
607
+ * Update an inquiry.
608
+ *
609
+ * Update ordinary inquiry article. However, it would not modify the content reocrd
610
+ * {@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}.
611
+ * Therefore, all of the poeple can read how the content has been changed.
612
+ *
613
+ * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password)
614
+ * @param request Instance of the Express.Request
615
+ * @param section Code of the target section
616
+ * @param saleId ID of the target sale
617
+ * @param id ID of the target article to be updated
618
+ * @param input New content to be overwritten
619
+ * @return The newly created content record
620
+ * @throw 400 bad request error when type of the input data is not valid
621
+ * @throw 401 unauthorized error when you've not logged in yet
622
+ * @throw 403 forbidden error when the article is not yours
623
+ *
624
+ * @controller ConsumerSaleReviewsController.update()
625
+ * @path PUT /consumers/:section/sales/:saleId/reviews/:id
626
+ * @nestia Generated by Nestia - https://github.com/samchon/nestia
627
+ */
628
+ export function update
629
+ (
630
+ connection: IConnection,
631
+ section: string,
632
+ saleId: string,
633
+ id: number,
634
+ input: Primitive<update.Input>
635
+ ): Promise<update.Output>
636
+ {
637
+ return Fetcher.fetch
638
+ (
639
+ connection,
640
+ update.ENCRYPTED,
641
+ update.METHOD,
642
+ update.path(section, saleId, id),
643
+ input,
644
+ update.stringify
645
+ );
646
+ }
647
+ export namespace update
648
+ {
649
+ export type Input = Primitive<ISaleReview.IStore>;
650
+ export type Output = Primitive<ISaleInquiry<ISaleReview.IContent>>;
444
651
 
445
- The [nestia](https://github.com/samchon/nestia) will generate the perfect `swagger.json` automatically, by analyzing your source code (DTO interface and controller class) in the compilation and runtime level. Furthermore, your descriptive comments would be automatically assigned into the adequate `description` property in the `swagger.json`.
652
+ export const METHOD = "PUT" as const;
653
+ export const PATH: string = "/consumers/:section/sales/:saleId/reviews/:id";
654
+ export const ENCRYPTED: Fetcher.IEncrypted = {
655
+ request: false,
656
+ response: false,
657
+ };
446
658
 
447
- ```json
448
- {
449
- "paths": {
450
- "/consumers/{section}/sales/{saleId}/comments/{articleId}": {
451
- "post": {
452
- "tags": [],
453
- "parameters": [
454
- {
455
- "name": "section",
456
- "in": "path",
457
- "description": "Code of the target section",
458
- "schema": {
459
- "type": "string",
460
- "nullable": false
461
- },
462
- "required": true
463
- },
464
- {
465
- "name": "saleId",
466
- "in": "path",
467
- "description": "ID of the target sale",
468
- "schema": {
469
- "type": "number",
470
- "nullable": false
471
- },
472
- "required": true
473
- },
474
- {
475
- "name": "articleId",
476
- "in": "path",
477
- "description": "ID of the target article",
478
- "schema": {
479
- "type": "number",
480
- "nullable": false
481
- },
482
- "required": true
483
- }
484
- ],
485
- "requestBody": {
486
- "description": "Content to write",
487
- "content": {
488
- "application/json": {
489
- "schema": {
490
- "$ref": "#/components/schemas/ISaleComment.IStore"
491
- }
492
- }
493
- },
494
- "required": true
495
- },
496
- "responses": {
497
- "201": {
498
- "description": "Newly archived comment",
499
- "content": {
500
- "application/json": {
501
- "schema": {
502
- "$ref": "#/components/schemas/ISaleComment"
503
- }
504
- }
505
- }
506
- },
507
- "400": {
508
- "description": "bad request error when type of the input data is not valid"
509
- },
510
- "401": {
511
- "description": "unauthorized error when you've not logged in yet"
512
- },
513
- "403": {
514
- "description": "forbidden error when you're a seller and the sale is not yours"
515
- },
516
- "404": {
517
- "description": "not found error when unable to find the matched record"
518
- }
519
- },
520
- "description": "Store a new comment."
521
- }
522
- }
523
- },
524
- "components": {
525
- "schemas": {
526
- "ISaleComment": {
527
- "type": "object",
528
- "properties": {
529
- "id": {
530
- "description": "Primary Key.",
531
- "type": "number",
532
- "nullable": false
533
- },
534
- "writer_type": {
535
- "description": "Type of the writer.",
536
- "type": "string",
537
- "nullable": false
538
- },
539
- "writer_name": {
540
- "description": "Name of the writer.",
541
- "type": "string",
542
- "nullable": false
543
- },
544
- "contents": {
545
- "description": "Contents of the comments.\n\nWhen the comment writer tries to modify content, it would not modify the comment\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.",
546
- "type": "array",
547
- "items": {
548
- "$ref": "#/components/schemas/ISaleComment.IContent"
549
- },
550
- "nullable": false
551
- },
552
- "created_at": {
553
- "description": "Creation time.",
554
- "type": "string",
555
- "nullable": false
556
- }
557
- },
558
- "nullable": false,
559
- "required": [
560
- "id",
561
- "writer_type",
562
- "writer_name",
563
- "contents",
564
- "created_at"
565
- ],
566
- "description": "Comment wrote on an article."
567
- },
568
- "ISaleComment.IContent": {
569
- "type": "object",
570
- "properties": {
571
- "created_at": {
572
- "description": "Creation time.",
573
- "type": "string",
574
- "nullable": false
575
- },
576
- "body": {
577
- "description": "Body of the content.",
578
- "type": "string",
579
- "nullable": false
580
- }
581
- },
582
- "nullable": false,
583
- "required": [
584
- "created_at",
585
- "body"
586
- ],
587
- "description": "Content info."
588
- },
589
- "ISaleComment.IStore": {
590
- "type": "object",
591
- "properties": {
592
- "body": {
593
- "description": "Body of the content.",
594
- "type": "string",
595
- "nullable": false
596
- }
597
- },
598
- "nullable": false,
599
- "required": [
600
- "body"
601
- ],
602
- "description": "Store info."
603
- }
659
+ export function path(section: string, saleId: string, id: number): string
660
+ {
661
+ return `/consumers/${section}/sales/${saleId}/reviews/${id}`;
604
662
  }
605
- }
663
+ export const stringify = createStringifier<Input>();
606
664
  }
607
665
  ```
608
666
 
609
667
 
610
668
 
611
669
 
670
+ ### Swagger
671
+ Building `Swagger` is also possible and even much powerful.
612
672
 
613
- ## Appendix
614
- ### Template Project
615
- https://github.com/samchon/backend
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.
616
674
 
617
- I support template backend project using this [nestia](https://github.com/samchon/nestia)* library, [backend](https://github.com/samchon/backend).
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.
618
676
 
619
- 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, those example projects guide how to generate SDK library from the [nestia](https://github.com/samchon/nestia) and how to distribute the SDK library thorugh the NPM module.
677
+ - View in the `Swagger Editor`
678
+ - [simple/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fsimple%2Fswagger.json)
679
+ - [generic/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Fgeneric%2Fswagger.json)
680
+ - [union/swagger.json](https://editor.swagger.io/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsamchon%2Fnestia%2Fmaster%2Fdemo%2Funion%2Fswagger.json)
620
681
 
621
- Therefore, if you're planning to compose your own backend project using this [nestia](https://github.com/samchon/nestia), I recommend you to create the repository and learn from the [backend](https://github.com/samchon/backend) template project.
682
+ ![Swagger Editor](https://github.com/samchon/nestia/wiki/images/swagger-editor-comment.png)
622
683
 
623
- ### Nestia-Helper
624
- https://github.com/samchon/nestia-helper
625
684
 
626
- Helper library of the `NestJS` with [nestia](https://github.com/samchon/nestia).
627
685
 
628
- [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](https://github.com/samchon/nestia), who can generate SDK library by analyzing NestJS controller classes in the compilation level.
629
686
 
630
- Of course, this [nestia-helper](https://github.com/samchon/nestia-helper) is not essential for utilizing the `NestJS` and [nestia](https://github.com/samchon/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](https://github.com/samchon/nestia).
687
+ ## Configuration
688
+ Components | `nestia.config.ts` | `CLI` | `@nestjs/swagger`
689
+ -----------------------------|--------------------|-------|------------------
690
+ Swagger Generation | ✔ | ✔ | ✔
691
+ SDK Generation | ✔ | ✔ | ❌
692
+ 2x faster `JSON.stringify()` | ✔ | ❌ | ❌
693
+ Type check in runtime | ✔ | ❌ | ❌
694
+ Custom compiler options | ✔ | ❌ | ❌
631
695
 
632
- - Supported decorator functions
633
- - [EncryptedController](https://github.com/samchon/nestia-helper#encryptedcontroller), [EncryptedModule](https://github.com/samchon/nestia-helper#encryptedmodule)
634
- - [TypedRoute](https://github.com/samchon/nestia-helper#typedroute), [EncryptedRoute](https://github.com/samchon/nestia-helper#encryptedroute)
635
- - [TypedParam](https://github.com/samchon/nestia-helper#typedparam), [EncryptedBody](https://github.com/samchon/nestia-helper#encryptedbody), [PlainBody](https://github.com/samchon/nestia-helper#plainbody)
636
- - [ExceptionManager](https://github.com/samchon/nestia-helper#exceptionmanager)
696
+ `nestia` can configure generator options by two ways: CLI and configuration file.
637
697
 
638
- ### Safe-TypeORM
639
- https://github.com/samchon/safe-typeorm
698
+ At first, the CLI (Command Line Interface) is convenient, but does not support detailed options.
640
699
 
641
- [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.
700
+ ```sh
701
+ # BASIC COMMAND
702
+ npx nestia <sdk|swagger> <source_directories_or_patterns> \
703
+ --exclude <exclude_directory_or_pattern> \
704
+ --out <output_directory_or_file>
705
+
706
+ # EXAMPLES
707
+ npx nestia sdk "src/controllers" --out "src/api"
708
+ npx nestia swagger "src/**/*.controller.ts" --out "swagger.json"
709
+ npx nestia swagger "src/main/controllers" "src/sub/controllers" \
710
+ --exclude "src/main/test" \
711
+ --out "composite.swagger.json"
712
+
713
+ # ONLY WHEN NESTIA.CONFIG.TS EXISTS
714
+ npx nestia sdk
715
+ npx nestia swagger
716
+ ```
717
+
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>
724
+
725
+ ```typescript
726
+ /**
727
+ * Definition for the `nestia.config.ts` file.
728
+ *
729
+ * @author Jeongho Nam - https://github.com/samchon
730
+ */
731
+ export interface IConfiguration {
732
+ /**
733
+ * List of files or directories containing the `NestJS` controller classes.
734
+ */
735
+ input: string | string[] | IConfiguration.IInput;
736
+
737
+ /**
738
+ * Output directory that SDK would be placed in.
739
+ *
740
+ * If not configured, you can't build the SDK library.
741
+ */
742
+ output?: string;
743
+
744
+ /**
745
+ * Compiler options for the TypeScript.
746
+ *
747
+ * If you've omitted this property or the assigned property cannot fully cover the
748
+ * `tsconfig.json`, the properties from the `tsconfig.json` would be assigned to here.
749
+ * Otherwise, this property has been configured and it's detailed values are different
750
+ * with the `tsconfig.json`, this property values would be overwritten.
751
+ *
752
+ * ```typescript
753
+ * import ts from "typescript";
754
+ *
755
+ * const tsconfig: ts.TsConfig;
756
+ * const nestiaConfig: IConfiguration;
757
+ *
758
+ * const compilerOptions: ts.CompilerOptions = {
759
+ * ...tsconfig.compilerOptions,
760
+ * ...(nestiaConfig.compilerOptions || {})
761
+ * }
762
+ * ```
763
+ */
764
+ compilerOptions?: ts.CompilerOptions;
765
+
766
+ /**
767
+ * Whether to assert parameter types or not.
768
+ *
769
+ * If you configure this property to be `true`, all of the function parameters would be
770
+ * checked through the [typescript-is](https://github.com/woutervh-/typescript-is). This
771
+ * option would make your SDK library slower, but would be much safer in the type level
772
+ * even in the runtime environment.
773
+ */
774
+ assert?: boolean;
775
+
776
+ /**
777
+ * Whether to optimize JSON string conversion 2x faster or not.
778
+ *
779
+ * If you configure this property to be `true`, the SDK library would utilize the
780
+ * [typescript-json](https://github.com/samchon/typescript-json) and the JSON string
781
+ * conversion speed really be 2x faster.
782
+ */
783
+ json?: boolean;
784
+
785
+ /**
786
+ * Building `swagger.json` is also possible.
787
+ *
788
+ * If not specified, you can't build the `swagger.json`.
789
+ */
790
+ swagger?: IConfiguration.ISwagger;
791
+ }
792
+ export namespace IConfiguration
793
+ {
794
+ /**
795
+ * List of files or directories to include or exclude to specifying the `NestJS`
796
+ * controllers.
797
+ */
798
+ export interface IInput {
799
+ /**
800
+ * List of files or directories containing the `NestJS` controller classes.
801
+ */
802
+ include: string[];
803
+
804
+ /**
805
+ * List of files or directories to be excluded.
806
+ */
807
+ exclude?: string[];
808
+ }
809
+
810
+ /**
811
+ * Building `swagger.json` is also possible.
812
+ */
813
+ export interface ISwagger {
814
+ /**
815
+ * Output path of the `swagger.json`.
816
+ *
817
+ * If you've configured only directory, the file name would be the `swagger.json`.
818
+ * Otherwise you've configured the full path with file name and extension, the
819
+ * `swagger.json` file would be renamed to it.
820
+ */
821
+ output: string;
822
+ }
823
+ }
824
+ ```
825
+ </details>
826
+
827
+ ```typescript
828
+ import type { IConfiguration } from "nestia";
829
+
830
+ export const NESTIA_CONFIG: IConfiguration = {
831
+ input: "./src/controllers",
832
+ output: "./src/api",
833
+ json: true,
834
+ swagger: {
835
+ output: "./public/swagger.json"
836
+ }
837
+ };
838
+ export default NESTIA_CONFIG;
839
+ ```
840
+
841
+
842
+
843
+
844
+ ## Appendix
845
+ ### Dependencies of the SDK
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.
847
+
848
+ The `npx nestia install` command installs those dependencies with the `package.json` configuration.
849
+
850
+ ```bash
851
+ # MOVE TO THE DISTRIBUTION DIRECTORY
852
+ cd packages/api
853
+
854
+ # INSTALL DEPENDENCIES OF THE SDK
855
+ npx nestia install
856
+ ```
857
+
858
+ ### Template Repository
859
+ https://github.com/samchon/backend
642
860
 
643
- Therefore, this [nestia](https://github.com/samchon/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](https://github.com/samchon/nestia) and [safe-typeorm](https://github.com/samchon/safe-typeorm), let's implement the backend server much easily and conveniently.
861
+ I support template backend project using this `nestia` library, `samchon/backend`.
644
862
 
645
- - When writing [**SQL query**](https://github.com/samchon/safe-typeorm#safe-query-builder),
646
- - Errors would be detected in the **compilation** level
647
- - **Auto Completion** would be provided
648
- - **Type Hint** would be supported
649
- - You can implement [**App-join**](https://github.com/samchon/safe-typeorm#app-join-builder) very conveniently
650
- - When [**SELECT**ing for **JSON** conversion](https://github.com/samchon/safe-typeorm#json-select-builder)
651
- - [**App-Join**](https://github.com/samchon/safe-typeorm#app-join-builder) with the related entities would be automatically done
652
- - Exact JSON **type** would be automatically **deduced**
653
- - The **performance** would be **automatically tuned**
654
- - When [**INSERT**](https://github.com/samchon/safe-typeorm#insert-collection)ing records
655
- - Sequence of tables would be automatically sorted by analyzing dependencies
656
- - The **performance** would be **automatically tuned**
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.
657
864
 
658
- ![Safe-TypeORM Demo](https://raw.githubusercontent.com/samchon/safe-typeorm/master/assets/demo/safe-query-builder.gif)
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.
659
866
 
660
867
  ### Archidraw
661
868
  https://www.archisketch.com/
662
869
 
663
870
  I have special thanks to the Archidraw, where I'm working for.
664
871
 
665
- 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](https://github.com/samchon/nestia) on their commercial backend project, even this [nestia](https://github.com/samchon/nestia) was in the alpha level.
872
+ 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.
873
+
874
+ > 저희 회사 "아키드로우" 에서, 삼촌과 함께 일할 프론트 개발자 분들을, 최고의 대우로 모십니다.
875
+ >
876
+ > "아키드로우" 는 3D (인테리어) 에디터 및 이에 관한 파생 솔루션들을 만드는 회사입니다. 다만 저희 회사의 주력 제품이 3D 에디터라 하여, 반드시 3D 내지 랜더링에 능숙해야 하는 것은 아니니, 일반적인 프론트 개발자 분들도 망설임없이 지원해주십시오.
877
+ >
878
+ > 그리고 저희 회사는 분위기가 다들 친하고 즐겁게 지내는 분위기입니다. 더하여 위 `nestia` 나 [typescript-json](https://github.com/samchon/typescript-json) 및 [payments](https://github.com/archidraw/payments) 등, 제법 합리적(?)이고 재미난 프로젝트들을 다양하게 체험해보실 수 있습니다.
879
+ >
880
+ > - 회사소개서: [archidraw.pdf](https://github.com/archidraw/payments/files/7696710/archidraw.pdf)
881
+ > - 기술 스택: React + TypeScript
882
+ > - 이력서: 자유 양식
883
+ > - 지원처: samchon@archisketch.com