nestia 2.1.2 → 2.1.5

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,373 +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
- - [Guide Documents (Wiki)](https://github.com/samchon/nestia/wiki), if you want to know more
29
-
30
- 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.
31
-
32
- 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.
33
-
34
- > 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 | | |
35
31
 
36
32
  ```typescript
37
- import api from "@samchon/bbs-api";
38
- import { IBbsArticle } from "@samchon/bbs-api/lib/structures/bbs/IBbsArticle";
39
- import { IPage } from "@samchon/bbs-api/lib/structures/common/IPage";
40
-
41
- 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>
42
42
  {
43
- // LIST UP ARTICLE SUMMARIES
44
- 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
45
45
  (
46
46
  connection,
47
- "free",
47
+ "general",
48
48
  { limit: 100, page: 1 }
49
49
  );
50
50
 
51
- // READ AN ARTICLE DETAILY
52
- const article: IBbsArticle = await api.functional.bbs.articles.at
51
+ // PICK A SALE
52
+ const sale: ISale = await api.functional.shoppings.sales.at
53
53
  (
54
- connection,
55
- "free",
54
+ connection,
56
55
  index.data[0].id
57
56
  );
58
- 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);
59
86
  }
60
87
  ```
61
88
 
62
89
 
63
90
 
91
+ ## Setup
92
+ Just like any other package, you've got to install it before you can use it.
64
93
 
65
- ## Usage
66
- ### Installation
67
- ```bash
94
+ ```sh
68
95
  npm install --save-dev nestia
69
96
  ```
70
97
 
71
- Installing the [nestia](https://github.com/samchon/nestia) is very easy.
98
+ After the installation, you can generate the `SDK` or `Swagger`, directly.
72
99
 
73
- 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
+ ```
74
104
 
75
- ### SDK generation
76
- ```bash
77
- 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
+ > ```
78
118
 
79
- npx nestia sdk "src/**/*.controller.ts" --out "src/api"
80
- npx nestia sdk "src/controllers" --out "src/api"
81
- npx nestia sdk "src/controllers/consumers" "src/controllers/sellers" --out "src/api"
82
- npx nestia sdk "src/controllers" --exclude "src/**/Fake*.ts" --out "src/api"
83
- ```
84
119
 
85
- To generate a SDK library through the [nestia](https://github.com/samchon/nestia) is very easy.
86
120
 
87
- 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.
88
121
 
89
- 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.
90
125
 
91
- ### Swagger generation
92
- ```bash
93
- 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.
94
127
 
95
- npx nestia swagger "src/**/*.controller.ts" --out "./"
96
- npx nestia swagger "src/controllers" --out "./swagger.json"
97
- npx nestia swagger "src/consumers" "src/sellers" --out "actors.json"
98
- npx nestia swagger "src/controllers" --exclude "src/**/Fake*.ts" -out "./"
99
- ```
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.
100
129
 
101
- 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)
102
137
 
103
- 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.
104
139
 
105
- 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>
106
144
 
107
- ### Dependencies
108
- ```bash
109
- npx nestia install
110
- ```
145
+ ```typescript
146
+ export class SaleArticleComment
147
+ {
148
+ @ApiProperty({
149
+ description:
150
+ `Comment wrote on a sale related article.
111
151
 
112
- 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.
113
153
 
114
- 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;
115
157
 
116
- ```json
117
- {
118
- "name": "payments-server-api",
119
- "dependencies": {
120
- "nestia-fetcher": "^2.0.1",
121
- "typescript-is": "^0.19.0",
122
- "typescript-json": "^2.0.9"
123
- }
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;
124
200
  }
125
201
  ```
202
+ </details>
126
203
 
204
+ <details>
205
+ <summary>
206
+ Pure DTO interface using <code>nestia</code>
207
+ </summary>
127
208
 
128
-
129
- ## Advanced
130
- ### `nestia.config.ts`
131
209
  ```typescript
132
210
  /**
133
- * 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.
134
219
  *
135
220
  * @author Jeongho Nam - https://github.com/samchon
136
221
  */
137
- export interface IConfiguration
222
+ export interface ISaleArticleComment
138
223
  {
139
224
  /**
140
- * List of files or directories containing the NestJS controller classes.
225
+ * Primary Key.
141
226
  */
142
- input: string | string[] | IConfiguration.IInput;
227
+ id: number;
143
228
 
144
229
  /**
145
- * Output directory that SDK would be placed in.
230
+ * Parent comment ID.
231
+ *
232
+ * Only When this comment has been written as a reply.
146
233
  */
147
- output?: string;
234
+ parent_id: number | null;
148
235
 
149
236
  /**
150
- * Compiler options for the TypeScript.
151
- *
152
- * If omitted, the configuration would follow the `tsconfig.json`.
237
+ * Type of the writer.
153
238
  */
154
- compilerOptions?: ts.CompilerOptions;
239
+ writer_type: "seller" | "consumer";
155
240
 
156
241
  /**
157
- * Whether to assert parameter types or not.
242
+ * Name of the writer.
158
243
  *
159
- * If you configure this option to be `true`, all of the function parameters would be
160
- * 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.
161
245
  */
162
- assert?: boolean;
246
+ writer_name: string | null;
163
247
 
164
248
  /**
165
- * Whether to optimize JSON string conversion 2x faster or not.
249
+ * Contents of the comments.
166
250
  *
167
- * If you configure this option to be `true`, the SDK library would utilize the
168
- * [typescript-json](https://github.com/samchon/typescript-json) and the JSON string
169
- * 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.
170
254
  */
171
- json?: boolean;
255
+ contents: ISaleArticleComment.IContent[];
172
256
 
173
257
  /**
174
- * Building `swagger.json` is also possible.
258
+ * Creation time.
175
259
  */
176
- swagger?: IConfiguration.ISwagger;
260
+ created_at: string;
177
261
  }
178
- export namespace IConfiguration
262
+ export namespace ISaleArticleComment
179
263
  {
180
264
  /**
181
- * List of files or directories to include or exclude to specifying the NestJS
182
- * controllers.
265
+ * Store info.
183
266
  */
184
- export interface IInput
267
+ export interface IStore
185
268
  {
186
269
  /**
187
- * List of files or directories containing the NestJS controller classes.
270
+ * Body of the content.
188
271
  */
189
- include: string[];
272
+ body: string;
190
273
 
191
274
  /**
192
- * List of files or directories to be excluded.
275
+ * Whether to hide the writer name or not.
193
276
  */
194
- exclude?: string[];
277
+ annonymous: boolean;
195
278
  }
196
279
 
197
280
  /**
198
- * Building `swagger.json` is also possible.
281
+ * Content info.
199
282
  */
200
- export interface ISwagger
283
+ export interface IContent
201
284
  {
202
285
  /**
203
- * Output path of the `swagger.json`.
204
- *
205
- * If you've configure only directory, the file name would be `swagger.json`.
206
- * Otherwise you configure file name and extension, the `swagger.json` file would
207
- * be renamed to what you've configured.
286
+ * Primary Key.
208
287
  */
209
- output: string;
210
- }
211
- }
212
- ```
213
-
214
- 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`.
215
-
216
- 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;
217
289
 
218
- ```typescript
219
- import type nestia from "nestia";
290
+ /**
291
+ * Body of the content.
292
+ */
293
+ body: string;
220
294
 
221
- const config: nestia.IConfiguration = {
222
- input: "src/controllers",
223
- output: "src/api",
224
- assert: false
225
- };
226
- export default config;
295
+ /**
296
+ * Creation time.
297
+ */
298
+ created_at: string;
299
+ }
300
+ }
227
301
  ```
302
+ </details>
228
303
 
229
- > Alternative options for the regular NestJS project:
230
- >
231
- > ```typescript
232
- > export = {
233
- > input: "src/**/*.controller.ts",
234
- > /* input: {
235
- > include: ["src/controllers/**\/*.controller.ts"],
236
- > exclude: ["src/controllers/**\/fake_*.controller.ts"]
237
- > },*/
238
- > output: "src/api",
239
- > assert: true
240
- > }
241
- > ```
242
-
243
-
244
-
245
- ### Recommended Structures
246
- 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.
247
-
248
- 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).
249
-
250
- - src
251
- - api
252
- - **functional**: automatically generated SDK functions
253
- - **structures**: DTO structures
254
- - controllers
255
- - providers
256
- - models
257
- - **test**: Test automation program using SDK functions
258
- - package.json
259
- - tsconfig.json
260
- - nestia.config.ts
261
-
262
- 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.
263
-
264
- - https://github.com/samchon/backend
265
-
266
-
267
-
268
-
269
- ## Demonstration
270
- To demonstrate which SDK codes would be generated by this [nestia](https://github.com/samchon/nestia):
271
-
272
- - Representative files
273
- - [DTO interface used in the RestAPI](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/structures/ISaleArticleComment.ts)
274
- - [Controllers of the NestJS](https://github.com/samchon/nestia/tree/master/demo/simple/src/controllers/ConsumerSaleArticleCommentsController.ts)
275
- - [SDK generated by this **nestia**](https://github.com/samchon/nestia/tree/master/demo/simple/src/api/functional/consumers/sales/articles/comments/index.ts)
276
- - [`swagger.json` generated by this **nestia**](https://github.com/samchon/nestia/tree/master/demo/simple/swagger.json)
277
- - Demonstration Projects
278
- - [encrypt](https://github.com/samchon/nestia/tree/master/demo/encrypt): Request and response body are fully encrypted
279
- - [generic](https://github.com/samchon/nestia/tree/master/demo/generic): Generic typed controller classes
280
- - [recursive](https://github.com/samchon/nestia/tree/master/demo/recursive): Recursive DTO interface, [swagger editor](https://editor.swagger.io) can't expresss it
281
- - [simple](https://github.com/samchon/nestia/tree/master/demo/simple): Simple DTO interface and controller class
282
- - [union](https://github.com/samchon/nestia/tree/master/demo/union): Only [nestia](https://github.com/samchon/nestia) can handle the union typed DTO interface
283
-
284
- ### DTO
285
- Using pure interface type as DTO is possible.
286
-
287
- 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.
288
-
289
- 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>
290
308
 
291
309
  ```typescript
292
310
  /**
293
- * Comment wrote on a sale related article.
311
+ * Inquiry article.
294
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
295
320
  * @author Jeongho Nam - https://github.com/samchon
296
321
  */
297
- export interface ISaleComment
322
+ export interface ISaleInquiry<Content extends ISaleInquiry.IContent>
323
+ extends ISaleArticle<Content>
298
324
  {
299
325
  /**
300
326
  * Primary Key.
301
327
  */
302
328
  id: number;
303
329
 
304
- /**
305
- * Type of the writer.
306
- */
307
- writer_type: "seller" | "consumer";
308
-
309
330
  /**
310
331
  * Name of the writer.
311
332
  */
312
- writer_name: string;
333
+ writer: string;
313
334
 
314
335
  /**
315
- * Contents of the comments.
336
+ * List of contents.
316
337
  *
317
- * When the comment writer tries to modify content, it would not modify the comment
318
- * 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
319
340
  * the content has been changed.
320
341
  */
321
- contents: ISaleComment.IContent[];
342
+ contents: Content[];
322
343
 
323
344
  /**
324
345
  * Creation time.
325
346
  */
326
- created_at: string;
347
+ createdAat: string;
348
+
349
+ /**
350
+ * Formal answer from the seller.
351
+ */
352
+ answer: ISaleInquiryAnswer | null;
327
353
  }
328
-
329
- export namespace ISaleComment
354
+ export namespace ISaleInquiry
330
355
  {
331
356
  /**
332
- * Store info.
357
+ * Content info.
333
358
  */
334
- export interface IStore
359
+ export interface IContent
335
360
  {
361
+ /**
362
+ * Primary Key
363
+ */
364
+ id: string;
365
+
366
+ /**
367
+ * Title of the content.
368
+ */
369
+ title: string;
370
+
336
371
  /**
337
372
  * Body of the content.
338
373
  */
339
374
  body: string;
340
- }
341
375
 
342
- /**
343
- * Content info.
344
- */
345
- export interface IContent extends IStore
346
- {
376
+ /**
377
+ * Attached files.
378
+ */
379
+ files: IAttachmentFile[];
380
+
347
381
  /**
348
382
  * Creation time.
349
383
  */
350
- created_at: string;
384
+ createdAt: string;
351
385
  }
352
386
  }
353
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>
354
404
 
355
- ### Controller
356
- 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
+ > ```
357
443
 
358
444
  ```typescript
359
- @nest.Controller("consumers/:section/sales/:saleId/questions")
360
- 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>>
361
455
  {
362
456
  /**
363
- * 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.
364
465
  *
365
466
  * @param request Instance of the Express.Request
366
467
  * @param section Code of the target section
367
468
  * @param saleId ID of the target sale
368
469
  * @param input Content to archive
470
+ * @return Newly archived inquiry
369
471
  *
370
- * @return Newly archived question
371
472
  * @throw 400 bad request error when type of the input data is not valid
372
473
  * @throw 401 unauthorized error when you've not logged in yet
373
474
  */
@@ -375,40 +476,101 @@ export class ConsumerSaleQuestionsController
375
476
  public store
376
477
  (
377
478
  @nest.Request() request: express.Request,
378
- @nest.Param("section") section: string,
379
- @nest.Param("saleId") saleId: number,
380
- @nest.Body() input: ISaleQuestion.IStore
381
- ): 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>;
382
511
  }
383
512
  ```
384
513
 
385
- ### SDK
386
- 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.
387
514
 
388
- 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)
389
536
 
390
537
  ```typescript
391
538
  /**
392
- * 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.
393
555
  *
394
556
  * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password)
395
557
  * @param request Instance of the Express.Request
396
558
  * @param section Code of the target section
397
559
  * @param saleId ID of the target sale
398
560
  * @param input Content to archive
399
- * @return Newly archived question
561
+ * @return Newly archived inquiry
400
562
  * @throw 400 bad request error when type of the input data is not valid
401
563
  * @throw 401 unauthorized error when you've not logged in yet
402
564
  *
565
+ * @controller ConsumerSaleReviewsController.store()
566
+ * @path POST /consumers/:section/sales/:saleId/reviews
403
567
  * @nestia Generated by Nestia - https://github.com/samchon/nestia
404
- * @controller ConsumerSaleQuestionsController.store()
405
- * @path POST /consumers/:section/sales/:saleId/questions/
406
568
  */
407
569
  export function store
408
570
  (
409
571
  connection: IConnection,
410
572
  section: string,
411
- saleId: number,
573
+ saleId: string,
412
574
  input: Primitive<store.Input>
413
575
  ): Promise<store.Output>
414
576
  {
@@ -418,249 +580,304 @@ export function store
418
580
  store.ENCRYPTED,
419
581
  store.METHOD,
420
582
  store.path(section, saleId),
421
- input
583
+ input,
584
+ store.stringify
422
585
  );
423
586
  }
424
587
  export namespace store
425
588
  {
426
- export type Input = Primitive<ISaleInquiry.IStore>;
427
- export type Output = Primitive<ISaleInquiry<ISaleArticle.IContent>>;
589
+ export type Input = Primitive<ISaleReview.IStore>;
590
+ export type Output = Primitive<ISaleInquiry<ISaleReview.IContent>>;
428
591
 
429
592
  export const METHOD = "POST" as const;
430
- export const PATH: string = "/consumers/:section/sales/:saleId/questions";
593
+ export const PATH: string = "/consumers/:section/sales/:saleId/reviews";
431
594
  export const ENCRYPTED: Fetcher.IEncrypted = {
432
- request: true,
433
- response: true,
595
+ request: false,
596
+ response: false,
434
597
  };
435
598
 
436
- export function path(section: string, saleId: number): string
599
+ export function path(section: string, saleId: string): string
437
600
  {
438
- return `/consumers/${section}/sales/${saleId}/questions`;
601
+ return `/consumers/${section}/sales/${saleId}/reviews`;
439
602
  }
603
+ export const stringify = createStringifier<Input>();
440
604
  }
441
- ```
442
605
 
443
- ### `swagger.json`
444
- 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>>;
445
651
 
446
- 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
+ };
447
658
 
448
- ```json
449
- {
450
- "paths": {
451
- "/consumers/{section}/sales/{saleId}/comments/{articleId}": {
452
- "post": {
453
- "tags": [],
454
- "parameters": [
455
- {
456
- "name": "section",
457
- "in": "path",
458
- "description": "Code of the target section",
459
- "schema": {
460
- "type": "string",
461
- "nullable": false
462
- },
463
- "required": true
464
- },
465
- {
466
- "name": "saleId",
467
- "in": "path",
468
- "description": "ID of the target sale",
469
- "schema": {
470
- "type": "number",
471
- "nullable": false
472
- },
473
- "required": true
474
- },
475
- {
476
- "name": "articleId",
477
- "in": "path",
478
- "description": "ID of the target article",
479
- "schema": {
480
- "type": "number",
481
- "nullable": false
482
- },
483
- "required": true
484
- }
485
- ],
486
- "requestBody": {
487
- "description": "Content to write",
488
- "content": {
489
- "application/json": {
490
- "schema": {
491
- "$ref": "#/components/schemas/ISaleComment.IStore"
492
- }
493
- }
494
- },
495
- "required": true
496
- },
497
- "responses": {
498
- "201": {
499
- "description": "Newly archived comment",
500
- "content": {
501
- "application/json": {
502
- "schema": {
503
- "$ref": "#/components/schemas/ISaleComment"
504
- }
505
- }
506
- }
507
- },
508
- "400": {
509
- "description": "bad request error when type of the input data is not valid"
510
- },
511
- "401": {
512
- "description": "unauthorized error when you've not logged in yet"
513
- },
514
- "403": {
515
- "description": "forbidden error when you're a seller and the sale is not yours"
516
- },
517
- "404": {
518
- "description": "not found error when unable to find the matched record"
519
- }
520
- },
521
- "description": "Store a new comment."
522
- }
523
- }
524
- },
525
- "components": {
526
- "schemas": {
527
- "ISaleComment": {
528
- "type": "object",
529
- "properties": {
530
- "id": {
531
- "description": "Primary Key.",
532
- "type": "number",
533
- "nullable": false
534
- },
535
- "writer_type": {
536
- "description": "Type of the writer.",
537
- "type": "string",
538
- "nullable": false
539
- },
540
- "writer_name": {
541
- "description": "Name of the writer.",
542
- "type": "string",
543
- "nullable": false
544
- },
545
- "contents": {
546
- "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.",
547
- "type": "array",
548
- "items": {
549
- "$ref": "#/components/schemas/ISaleComment.IContent"
550
- },
551
- "nullable": false
552
- },
553
- "created_at": {
554
- "description": "Creation time.",
555
- "type": "string",
556
- "nullable": false
557
- }
558
- },
559
- "nullable": false,
560
- "required": [
561
- "id",
562
- "writer_type",
563
- "writer_name",
564
- "contents",
565
- "created_at"
566
- ],
567
- "description": "Comment wrote on an article."
568
- },
569
- "ISaleComment.IContent": {
570
- "type": "object",
571
- "properties": {
572
- "created_at": {
573
- "description": "Creation time.",
574
- "type": "string",
575
- "nullable": false
576
- },
577
- "body": {
578
- "description": "Body of the content.",
579
- "type": "string",
580
- "nullable": false
581
- }
582
- },
583
- "nullable": false,
584
- "required": [
585
- "created_at",
586
- "body"
587
- ],
588
- "description": "Content info."
589
- },
590
- "ISaleComment.IStore": {
591
- "type": "object",
592
- "properties": {
593
- "body": {
594
- "description": "Body of the content.",
595
- "type": "string",
596
- "nullable": false
597
- }
598
- },
599
- "nullable": false,
600
- "required": [
601
- "body"
602
- ],
603
- "description": "Store info."
604
- }
659
+ export function path(section: string, saleId: string, id: number): string
660
+ {
661
+ return `/consumers/${section}/sales/${saleId}/reviews/${id}`;
605
662
  }
606
- }
663
+ export const stringify = createStringifier<Input>();
607
664
  }
608
665
  ```
609
666
 
610
667
 
611
668
 
612
669
 
670
+ ### Swagger
671
+ Building `Swagger` is also possible and even much powerful.
613
672
 
614
- ## Appendix
615
- ### Template Project
616
- 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.
617
674
 
618
- 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.
619
676
 
620
- 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)
621
681
 
622
- 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)
623
683
 
624
- ### Nestia-Helper
625
- https://github.com/samchon/nestia-helper
626
684
 
627
- Helper library of the `NestJS` with [nestia](https://github.com/samchon/nestia).
628
685
 
629
- [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.
630
686
 
631
- 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 | ✔ | ❌ | ❌
632
695
 
633
- - Supported decorator functions
634
- - [EncryptedController](https://github.com/samchon/nestia-helper#encryptedcontroller), [EncryptedModule](https://github.com/samchon/nestia-helper#encryptedmodule)
635
- - [TypedRoute](https://github.com/samchon/nestia-helper#typedroute), [EncryptedRoute](https://github.com/samchon/nestia-helper#encryptedroute)
636
- - [TypedParam](https://github.com/samchon/nestia-helper#typedparam), [EncryptedBody](https://github.com/samchon/nestia-helper#encryptedbody), [PlainBody](https://github.com/samchon/nestia-helper#plainbody)
637
- - [ExceptionManager](https://github.com/samchon/nestia-helper#exceptionmanager)
696
+ `nestia` can configure generator options by two ways: CLI and configuration file.
638
697
 
639
- ### Safe-TypeORM
640
- https://github.com/samchon/safe-typeorm
698
+ At first, the CLI (Command Line Interface) is convenient, but does not support detailed options.
641
699
 
642
- [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
643
860
 
644
- 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`.
645
862
 
646
- - When writing [**SQL query**](https://github.com/samchon/safe-typeorm#safe-query-builder),
647
- - Errors would be detected in the **compilation** level
648
- - **Auto Completion** would be provided
649
- - **Type Hint** would be supported
650
- - You can implement [**App-join**](https://github.com/samchon/safe-typeorm#app-join-builder) very conveniently
651
- - When [**SELECT**ing for **JSON** conversion](https://github.com/samchon/safe-typeorm#json-select-builder)
652
- - [**App-Join**](https://github.com/samchon/safe-typeorm#app-join-builder) with the related entities would be automatically done
653
- - Exact JSON **type** would be automatically **deduced**
654
- - The **performance** would be **automatically tuned**
655
- - When [**INSERT**](https://github.com/samchon/safe-typeorm#insert-collection)ing records
656
- - Sequence of tables would be automatically sorted by analyzing dependencies
657
- - 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.
658
864
 
659
- ![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.
660
866
 
661
867
  ### Archidraw
662
868
  https://www.archisketch.com/
663
869
 
664
870
  I have special thanks to the Archidraw, where I'm working for.
665
871
 
666
- 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