@nestia/sdk 1.0.1 → 1.0.2

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.
@@ -12,13 +12,13 @@ import { ApplicationProgrammer } from "typia/lib/programmers/ApplicationProgramm
12
12
 
13
13
  import { INestiaConfig } from "../INestiaConfig";
14
14
  import { IRoute } from "../structures/IRoute";
15
- import { ISwagger } from "../structures/ISwagger";
15
+ import { ISwaggerDocument } from "../structures/ISwaggerDocument";
16
16
  import { MapUtil } from "../utils/MapUtil";
17
17
 
18
18
  export namespace SwaggerGenerator {
19
19
  export async function generate(
20
20
  checker: ts.TypeChecker,
21
- config: INestiaConfig.ISwagger,
21
+ config: INestiaConfig.ISwaggerConfig,
22
22
  routeList: IRoute[],
23
23
  ): Promise<void> {
24
24
  // PREPARE ASSETS
@@ -33,11 +33,11 @@ export namespace SwaggerGenerator {
33
33
 
34
34
  // CONSTRUCT SWAGGER DOCUMENTS
35
35
  const tupleList: Array<ISchemaTuple> = [];
36
- const swagger: ISwagger = await initialize(location);
37
- const pathDict: Map<string, ISwagger.IPath> = new Map();
36
+ const swagger: ISwaggerDocument = await initialize(location);
37
+ const pathDict: Map<string, ISwaggerDocument.IPath> = new Map();
38
38
 
39
39
  for (const route of routeList) {
40
- const path: ISwagger.IPath = MapUtil.take(
40
+ const path: ISwaggerDocument.IPath = MapUtil.take(
41
41
  pathDict,
42
42
  get_path(route.path, route.parameters),
43
43
  () => ({}),
@@ -62,13 +62,16 @@ export namespace SwaggerGenerator {
62
62
  },
63
63
  );
64
64
  swagger.components = {
65
- ...(swagger.components || {}),
65
+ ...(swagger.components ?? {}),
66
66
  schemas: application.components.schemas,
67
67
  };
68
68
  tupleList.forEach(({ schema }, index) => {
69
69
  Object.assign(schema, application.schemas[index]!);
70
70
  });
71
71
 
72
+ // CONFIGURE SECURITY
73
+ if (config.security) fill_security(config.security, swagger);
74
+
72
75
  // ERASE IJsonComponents.IObject.$id
73
76
  for (const obj of Object.values(swagger.components.schemas))
74
77
  if (obj.$id) delete obj.$id;
@@ -84,9 +87,9 @@ export namespace SwaggerGenerator {
84
87
  /* ---------------------------------------------------------
85
88
  INITIALIZERS
86
89
  --------------------------------------------------------- */
87
- async function initialize(path: string): Promise<ISwagger> {
90
+ async function initialize(path: string): Promise<ISwaggerDocument> {
88
91
  // LOAD OR CREATE NEW SWAGGER DATA
89
- const swagger: ISwagger = fs.existsSync(path)
92
+ const swagger: ISwaggerDocument = fs.existsSync(path)
90
93
  ? JSON.parse(await fs.promises.readFile(path, "utf8"))
91
94
  : {
92
95
  openapi: "3.0.1",
@@ -122,7 +125,7 @@ export namespace SwaggerGenerator {
122
125
  collection: MetadataCollection,
123
126
  tupleList: Array<ISchemaTuple>,
124
127
  route: IRoute,
125
- ): ISwagger.IRoute {
128
+ ): ISwaggerDocument.IRoute {
126
129
  const bodyParam = route.parameters.find(
127
130
  (param) => param.category === "body",
128
131
  );
@@ -170,9 +173,35 @@ export namespace SwaggerGenerator {
170
173
  route,
171
174
  ),
172
175
  description: CommentFactory.generate(route.comments),
176
+ "x-nestia-jsDocTags": route.tags,
173
177
  };
174
178
  }
175
179
 
180
+ function fill_security(
181
+ security: Required<INestiaConfig.ISwaggerConfig>["security"],
182
+ swagger: ISwaggerDocument,
183
+ ): void {
184
+ swagger.security ??= [];
185
+ swagger.components.securitySchemes = {};
186
+
187
+ for (const [key, value] of Object.entries(security)) {
188
+ swagger.security.push(key);
189
+ swagger.components.securitySchemes[key] = emend_security(value);
190
+ }
191
+ }
192
+
193
+ function emend_security(
194
+ input: INestiaConfig.ISwaggerConfig.ISecurityScheme,
195
+ ): ISwaggerDocument.ISecurityScheme {
196
+ if (input.type === "apiKey")
197
+ return {
198
+ ...input,
199
+ in: input.in ?? "header",
200
+ name: input.name ?? "Authorization",
201
+ };
202
+ return input;
203
+ }
204
+
176
205
  /* ---------------------------------------------------------
177
206
  REQUEST & RESPONSE
178
207
  --------------------------------------------------------- */
@@ -182,7 +211,7 @@ export namespace SwaggerGenerator {
182
211
  tupleList: Array<ISchemaTuple>,
183
212
  route: IRoute,
184
213
  parameter: IRoute.IParameter,
185
- ): ISwagger.IParameter {
214
+ ): ISwaggerDocument.IParameter {
186
215
  const schema: IJsonSchema | null = generate_schema(
187
216
  checker,
188
217
  collection,
@@ -195,7 +224,7 @@ export namespace SwaggerGenerator {
195
224
  );
196
225
 
197
226
  return {
198
- name: parameter.field || parameter.name,
227
+ name: parameter.field ?? parameter.name,
199
228
  in: parameter.category === "param" ? "path" : parameter.category,
200
229
  description:
201
230
  get_parametric_description(route, "param", parameter.name) ||
@@ -211,7 +240,7 @@ export namespace SwaggerGenerator {
211
240
  tupleList: Array<ISchemaTuple>,
212
241
  route: IRoute,
213
242
  parameter: IRoute.IParameter,
214
- ): ISwagger.IRequestBody {
243
+ ): ISwaggerDocument.IRequestBody {
215
244
  const schema: IJsonSchema | null = generate_schema(
216
245
  checker,
217
246
  collection,
@@ -226,7 +255,7 @@ export namespace SwaggerGenerator {
226
255
  return {
227
256
  description:
228
257
  warning.get(parameter.encrypted).get("request") +
229
- (get_parametric_description(route, "param", parameter.name) ||
258
+ (get_parametric_description(route, "param", parameter.name) ??
230
259
  ""),
231
260
  content: {
232
261
  "application/json": {
@@ -242,7 +271,7 @@ export namespace SwaggerGenerator {
242
271
  collection: MetadataCollection,
243
272
  tupleList: Array<ISchemaTuple>,
244
273
  route: IRoute,
245
- ): ISwagger.IResponseBody {
274
+ ): ISwaggerDocument.IResponseBody {
246
275
  // OUTPUT WITH SUCCESS STATUS
247
276
  const status: string =
248
277
  route.method === "GET" || route.method === "DELETE" ? "200" : "201";
@@ -252,12 +281,12 @@ export namespace SwaggerGenerator {
252
281
  tupleList,
253
282
  route.output.type,
254
283
  );
255
- const success: ISwagger.IResponseBody = {
284
+ const success: ISwaggerDocument.IResponseBody = {
256
285
  [status]: {
257
286
  description:
258
287
  warning.get(route.encrypted).get("response", route.method) +
259
- (get_parametric_description(route, "return") ||
260
- get_parametric_description(route, "returns") ||
288
+ (get_parametric_description(route, "return") ??
289
+ get_parametric_description(route, "returns") ??
261
290
  ""),
262
291
  content:
263
292
  schema === null || route.output.name === "void"
@@ -271,7 +300,7 @@ export namespace SwaggerGenerator {
271
300
  };
272
301
 
273
302
  // EXCEPTION STATUSES
274
- const exceptions: ISwagger.IResponseBody = Object.fromEntries(
303
+ const exceptions: ISwaggerDocument.IResponseBody = Object.fromEntries(
275
304
  route.tags
276
305
  .filter(
277
306
  (tag) =>
@@ -16,6 +16,10 @@ export interface IRoute {
16
16
  symbol: string;
17
17
  comments: ts.SymbolDisplayPart[];
18
18
  tags: ts.JSDocTagInfo[];
19
+ setHeaders: Array<
20
+ | { type: "setter"; source: string; target?: string }
21
+ | { type: "assigner"; source: string }
22
+ >;
19
23
  }
20
24
 
21
25
  export namespace IRoute {
@@ -0,0 +1,117 @@
1
+ import { IJsonComponents, IJsonSchema } from "typia";
2
+ import { IJsDocTagInfo } from "typia/lib/metadata/IJsDocTagInfo";
3
+
4
+ export interface ISwaggerDocument {
5
+ openapi: "3.0";
6
+ servers: ISwaggerDocument.IServer[];
7
+ info: ISwaggerDocument.IInfo;
8
+ components: ISwaggerDocument.IComponents;
9
+ security?: string[];
10
+ paths: Record<string, ISwaggerDocument.IPath>;
11
+ }
12
+ export namespace ISwaggerDocument {
13
+ export interface IServer {
14
+ url: string;
15
+ description?: string;
16
+ }
17
+
18
+ export interface IInfo {
19
+ version: string;
20
+ title: string;
21
+ }
22
+
23
+ export interface IComponents extends IJsonComponents {
24
+ securitySchemes?: Record<string, ISecurityScheme>;
25
+ }
26
+
27
+ /* ---------------------------------------------------------
28
+ SECURITY SCHEMES
29
+ --------------------------------------------------------- */
30
+ export type ISecurityScheme =
31
+ | ISecurityScheme.IHttpBasic
32
+ | ISecurityScheme.IHttpBearer
33
+ | ISecurityScheme.IApiKey
34
+ | ISecurityScheme.IOpenId
35
+ | ISecurityScheme.IOAuth2;
36
+ export namespace ISecurityScheme {
37
+ export interface IHttpBasic {
38
+ type: "http";
39
+ schema: "basic";
40
+ }
41
+ export interface IHttpBearer {
42
+ type: "http";
43
+ scheme: "bearer";
44
+ bearerFormat?: string;
45
+ }
46
+ export interface IApiKey {
47
+ type: "apiKey";
48
+ in: "header" | "query" | "cookie";
49
+ name: string;
50
+ }
51
+
52
+ export interface IOpenId {
53
+ type: "openIdConnect";
54
+ openIdConnectUrl: string;
55
+ }
56
+
57
+ export interface IOAuth2 {
58
+ type: "oauth2";
59
+ flows: IOAuth2.IFlowSet;
60
+ description?: string;
61
+ }
62
+ export namespace IOAuth2 {
63
+ export interface IFlowSet {
64
+ authorizationCode?: IFlow;
65
+ implicit?: Omit<IFlow, "tokenUrl">;
66
+ password?: Omit<IFlow, "authorizationUrl">;
67
+ clientCredentials?: Omit<IFlow, "authorizationUrl">;
68
+ }
69
+ export interface IFlow {
70
+ authorizationUrl: string;
71
+ tokenUrl: string;
72
+ refreshUrl: string;
73
+ scopes?: Record<string, string>;
74
+ }
75
+ }
76
+ }
77
+
78
+ /* ---------------------------------------------------------
79
+ ROUTE FUNCTIONS
80
+ --------------------------------------------------------- */
81
+ export type IPath = Record<string, IRoute>;
82
+ export interface IRoute {
83
+ tags: string[];
84
+ parameters: IParameter[];
85
+ requestBody?: IRequestBody;
86
+ responses: IResponseBody;
87
+ summary?: string;
88
+ description: string;
89
+ security?: string[];
90
+ "x-nestia-jsDocTags": IJsDocTagInfo[];
91
+ }
92
+
93
+ export interface IParameter {
94
+ name: string;
95
+ in: string;
96
+ schema: IJsonSchema;
97
+ required: true;
98
+ description: string;
99
+ }
100
+ export interface IRequestBody {
101
+ description: string;
102
+ content: IJsonContent;
103
+ required: true;
104
+ }
105
+ export type IResponseBody = Record<
106
+ string,
107
+ {
108
+ description: string;
109
+ content?: IJsonContent;
110
+ }
111
+ >;
112
+ export interface IJsonContent {
113
+ "application/json": {
114
+ schema: IJsonSchema;
115
+ };
116
+ }
117
+ }
@@ -1,48 +0,0 @@
1
- import { IJsonComponents, IJsonSchema } from "typia";
2
- export interface ISwagger {
3
- openapi: "3.0";
4
- servers: ISwagger.IServer[];
5
- info: ISwagger.IInfo;
6
- paths: Record<string, ISwagger.IPath>;
7
- components: IJsonComponents;
8
- }
9
- export declare namespace ISwagger {
10
- type IPath = Record<string, IRoute>;
11
- interface IRoute {
12
- description: string;
13
- tags: string[];
14
- parameters: IParameter[];
15
- responses: IResponseBody;
16
- requestBody?: IRequestBody;
17
- summary?: string;
18
- }
19
- interface IInfo {
20
- version: string;
21
- title: string;
22
- }
23
- interface IParameter {
24
- name: string;
25
- in: string;
26
- schema: IJsonSchema;
27
- required: true;
28
- description: string;
29
- }
30
- interface IRequestBody {
31
- description: string;
32
- content: IJsonContent;
33
- required: true;
34
- }
35
- type IResponseBody = Record<string, {
36
- description: string;
37
- content?: IJsonContent;
38
- }>;
39
- interface IServer {
40
- url: string;
41
- description?: string;
42
- }
43
- interface IJsonContent {
44
- "application/json": {
45
- schema: IJsonSchema;
46
- };
47
- }
48
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ISwagger.js","sourceRoot":"","sources":["../../src/structures/ISwagger.ts"],"names":[],"mappings":""}
@@ -1,55 +0,0 @@
1
- import { IJsonComponents, IJsonSchema } from "typia";
2
-
3
- export interface ISwagger {
4
- openapi: "3.0";
5
- servers: ISwagger.IServer[];
6
- info: ISwagger.IInfo;
7
- paths: Record<string, ISwagger.IPath>;
8
- components: IJsonComponents;
9
- }
10
- export namespace ISwagger {
11
- export type IPath = Record<string, IRoute>;
12
- export interface IRoute {
13
- description: string;
14
- tags: string[];
15
- parameters: IParameter[];
16
- responses: IResponseBody;
17
- requestBody?: IRequestBody;
18
- summary?: string;
19
- }
20
-
21
- export interface IInfo {
22
- version: string;
23
- title: string;
24
- }
25
- export interface IParameter {
26
- name: string;
27
- in: string;
28
- schema: IJsonSchema;
29
- required: true;
30
- description: string;
31
- }
32
- export interface IRequestBody {
33
- description: string;
34
- content: IJsonContent;
35
- required: true;
36
- }
37
- export type IResponseBody = Record<
38
- string,
39
- {
40
- description: string;
41
- content?: IJsonContent;
42
- }
43
- >;
44
-
45
- export interface IServer {
46
- url: string;
47
- description?: string;
48
- }
49
-
50
- export interface IJsonContent {
51
- "application/json": {
52
- schema: IJsonSchema;
53
- };
54
- }
55
- }