@grandlinex/swagger-mate 1.3.1 → 1.3.3
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/dist/cjs/Swagger/Meta/SwaggerTypes.d.ts +3 -2
- package/dist/cjs/Swagger/Path/ESchemaEditor.d.ts +51 -0
- package/dist/cjs/Swagger/Path/ESchemaEditor.js +151 -0
- package/dist/cjs/Swagger/Path/SPathUtil.d.ts +107 -5
- package/dist/cjs/Swagger/Path/SPathUtil.js +136 -52
- package/dist/cjs/Swagger/SwaggerUtil.d.ts +18 -2
- package/dist/cjs/Swagger/SwaggerUtil.js +32 -5
- package/dist/cjs/Swagger/annotation/index.d.ts +8 -3
- package/dist/cjs/Swagger/debug/BaseCon.d.ts +115 -11
- package/dist/cjs/Swagger/debug/BaseCon.js +142 -38
- package/dist/cjs/cli.js +5 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/mjs/Swagger/Meta/SwaggerTypes.d.ts +3 -2
- package/dist/mjs/Swagger/Path/ESchemaEditor.d.ts +51 -0
- package/dist/mjs/Swagger/Path/ESchemaEditor.js +147 -0
- package/dist/mjs/Swagger/Path/SPathUtil.d.ts +107 -5
- package/dist/mjs/Swagger/Path/SPathUtil.js +137 -53
- package/dist/mjs/Swagger/SwaggerUtil.d.ts +18 -2
- package/dist/mjs/Swagger/SwaggerUtil.js +33 -6
- package/dist/mjs/Swagger/annotation/index.d.ts +8 -3
- package/dist/mjs/Swagger/debug/BaseCon.d.ts +115 -11
- package/dist/mjs/Swagger/debug/BaseCon.js +142 -38
- package/dist/mjs/cli.js +5 -1
- package/dist/mjs/index.d.ts +1 -0
- package/dist/mjs/index.js +1 -0
- package/package.json +2 -2
- package/res/html/rapi-doc/index.html +28 -0
- package/res/html/rapi-doc/rapidoc-min.js +3915 -0
- package/res/html/{index.html → swagger-ui/index.html} +11 -3
- package/res/html/swagger-ui/swagger-ui-bundle.js +2 -0
- package/res/html/swagger-ui/swagger-ui-standalone-preset.js +2 -0
- package/res/html/swagger-ui/swagger-ui.css +3 -0
- package/res/templates/class/BaseCon.ts +160 -61
- package/res/html/swagger-ui-bundle.js +0 -2
- package/res/html/swagger-ui-standalone-preset.js +0 -2
- package/res/html/swagger-ui.css +0 -3
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { getColumnMeta, getEntityMeta, } from '@grandlinex/core';
|
|
2
|
+
function resolveDBType(dType) {
|
|
3
|
+
switch (dType) {
|
|
4
|
+
case 'int':
|
|
5
|
+
case 'long':
|
|
6
|
+
return 'integer';
|
|
7
|
+
case 'double':
|
|
8
|
+
case 'float':
|
|
9
|
+
return 'number';
|
|
10
|
+
case 'blob':
|
|
11
|
+
return 'string';
|
|
12
|
+
case 'string':
|
|
13
|
+
case 'text':
|
|
14
|
+
case 'uuid':
|
|
15
|
+
return 'string';
|
|
16
|
+
case 'boolean':
|
|
17
|
+
return 'boolean';
|
|
18
|
+
case 'date':
|
|
19
|
+
return 'string';
|
|
20
|
+
case 'json':
|
|
21
|
+
return 'object';
|
|
22
|
+
default:
|
|
23
|
+
throw Error('TypeNotSupported');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class ESchemaEditor {
|
|
27
|
+
constructor(entity, name) {
|
|
28
|
+
this.data = ESchemaEditor.schemaFromEntity(entity);
|
|
29
|
+
this.name = name;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Removes the specified keys from the schema's properties and updates the required list.
|
|
33
|
+
*
|
|
34
|
+
* @param {...(keyof T)} keys - The keys of the properties to remove.
|
|
35
|
+
* @returns {ESchemaEditor<T>} The editor instance for method chaining.
|
|
36
|
+
*/
|
|
37
|
+
remove(...keys) {
|
|
38
|
+
if (this.data.properties) {
|
|
39
|
+
for (const key of keys) {
|
|
40
|
+
this.data.properties = Object.fromEntries(Object.entries(this.data.properties).filter(([e]) => key !== e));
|
|
41
|
+
this.data.required = (this.data.required || []).filter((e) => key !== e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Adds properties to the schema based on the provided options.
|
|
48
|
+
*
|
|
49
|
+
* @param {...ESchemaAddOption} options The options describing the properties to add. Each option may specify a
|
|
50
|
+
* `key`, a `schema` or an `entity`, and optionally whether the property is a `list`, `nullable`, or `required`.
|
|
51
|
+
* @returns {ESchemaEditor<T>} The editor instance for chaining.
|
|
52
|
+
*/
|
|
53
|
+
add(...options) {
|
|
54
|
+
if (!this.data.properties) {
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
for (const option of options) {
|
|
58
|
+
if (option.schema) {
|
|
59
|
+
if (option.list) {
|
|
60
|
+
this.data.properties[option.key] = {
|
|
61
|
+
type: 'array',
|
|
62
|
+
items: option.schema,
|
|
63
|
+
nullable: option.nullable,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.data.properties[option.key] = option.schema;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (option.entity) {
|
|
71
|
+
const scheme = ESchemaEditor.fromEntity(option.entity).getSchema();
|
|
72
|
+
if (option.nullable) {
|
|
73
|
+
scheme.nullable = true;
|
|
74
|
+
}
|
|
75
|
+
if (option.list) {
|
|
76
|
+
this.data.properties[option.key] = {
|
|
77
|
+
type: 'array',
|
|
78
|
+
items: scheme,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.data.properties[option.key] = scheme;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (option.required) {
|
|
86
|
+
this.data.required = [...(this.data.required || []), option.key];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
getSchema() {
|
|
92
|
+
return this.data;
|
|
93
|
+
}
|
|
94
|
+
getSKeySchema() {
|
|
95
|
+
return {
|
|
96
|
+
[this.name]: this.data,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
static fromEntity(e) {
|
|
100
|
+
const meta = getEntityMeta(e);
|
|
101
|
+
if (meta) {
|
|
102
|
+
return new ESchemaEditor(e, meta.name);
|
|
103
|
+
}
|
|
104
|
+
throw new Error('Entity metadata not found');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generates a JSON schema representation from a CoreEntity instance.
|
|
108
|
+
*
|
|
109
|
+
* This method inspects the entity's metadata to construct a schema object
|
|
110
|
+
* describing the entity's shape. The resulting schema contains:
|
|
111
|
+
* - `type`: always `"object"`.
|
|
112
|
+
* - `description`: a string indicating the entity name.
|
|
113
|
+
* - `required`: an array of property names that are defined on the entity.
|
|
114
|
+
* - `properties`: an object mapping each property name to an object that
|
|
115
|
+
* includes the resolved database type and its nullability.
|
|
116
|
+
*
|
|
117
|
+
* If no metadata is found for the provided entity, the method returns `undefined`.
|
|
118
|
+
*
|
|
119
|
+
* @param {T} entity - The entity instance for which to create a schema.
|
|
120
|
+
* @returns {SSchemaElObj | undefined} The generated schema object, or `undefined`
|
|
121
|
+
* if the entity's metadata could not be retrieved.
|
|
122
|
+
*/
|
|
123
|
+
static schemaFromEntity(entity) {
|
|
124
|
+
const schema = {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: {},
|
|
127
|
+
};
|
|
128
|
+
const meta = getEntityMeta(entity);
|
|
129
|
+
if (!meta) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
schema.description = `Entity: ${meta.name}`;
|
|
133
|
+
schema.required = [];
|
|
134
|
+
const keys = Object.keys(entity);
|
|
135
|
+
keys.forEach((k) => {
|
|
136
|
+
const cMeta = getColumnMeta(entity, k);
|
|
137
|
+
if (cMeta && schema.properties) {
|
|
138
|
+
schema.required.push(k);
|
|
139
|
+
schema.properties[k] = {
|
|
140
|
+
type: resolveDBType(cMeta.dataType),
|
|
141
|
+
nullable: cMeta.canBeNull,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return schema;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -1,16 +1,107 @@
|
|
|
1
1
|
import { CoreEntity } from '@grandlinex/core';
|
|
2
2
|
import { HttpStatusTypes } from '../Meta/SwaggerTypesStatic.js';
|
|
3
|
-
import { SKey, SSchemaEl, SwaggerContent, SwaggerRPathConfResponse, SwaggerRPathReqBody } from '../Meta/SwaggerTypes.js';
|
|
3
|
+
import { SKey, SSchemaEl, SSchemaElObj, SwaggerContent, SwaggerRPathConfResponse, SwaggerRPathReqBody } from '../Meta/SwaggerTypes.js';
|
|
4
|
+
import { ESchemaEditor } from './ESchemaEditor.js';
|
|
4
5
|
export default class SPathUtil {
|
|
6
|
+
/**
|
|
7
|
+
* Generates a default response mapping for the specified HTTP status types.
|
|
8
|
+
*
|
|
9
|
+
* @param {HttpStatusTypes[]} types - The HTTP status types for which default responses should be created.
|
|
10
|
+
* @return {SwaggerRPathConfResponse} An object mapping each provided status type to its default response definition. */
|
|
5
11
|
static defaultResponse(...types: HttpStatusTypes[]): SwaggerRPathConfResponse;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a request body definition for JSON content type using the provided schema.
|
|
14
|
+
*
|
|
15
|
+
* @param {SSchemaEl} schema - The JSON schema used for validating the request body.
|
|
16
|
+
* @return {SwaggerRPathReqBody} A Swagger path request body object specifying application/json content type with the provided schema.
|
|
17
|
+
*/
|
|
6
18
|
static jsonBody(schema: SSchemaEl): SwaggerRPathReqBody;
|
|
19
|
+
/**
|
|
20
|
+
* Builds a Swagger request body for `multipart/form-data` requests.
|
|
21
|
+
*
|
|
22
|
+
* @param {SSchemaEl} [schema] Optional schema describing the form data.
|
|
23
|
+
* If omitted, a default schema with a single binary `file` field is provided.
|
|
24
|
+
* @return {SwaggerRPathReqBody} Swagger request body definition with
|
|
25
|
+
* `multipart/form-data` content and the supplied or default schema. */
|
|
7
26
|
static formBody(schema?: SSchemaEl): SwaggerRPathReqBody;
|
|
27
|
+
/**
|
|
28
|
+
* Generates a Swagger content definition for the provided entity.
|
|
29
|
+
*
|
|
30
|
+
* @param {T} entity - The entity instance to derive the Swagger schema from.
|
|
31
|
+
* @param {boolean} [list] - When true, the schema will be wrapped in an array type, representing a list of entities.
|
|
32
|
+
*
|
|
33
|
+
* @returns {SwaggerContent|undefined} The Swagger content object for the entity, or `undefined` if the entity does not have a schema.
|
|
34
|
+
*/
|
|
8
35
|
static entityContent<T extends CoreEntity>(entity: T, list?: boolean): SwaggerContent | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* @template T extends CoreEntity
|
|
38
|
+
* @param {T} entity - The entity instance for which to build the response configuration.
|
|
39
|
+
* @param {boolean} [list] - Indicates whether the response should represent a list of entities.
|
|
40
|
+
* @param {boolean} [create] - Indicates whether the response corresponds to a creation operation (status code 201); otherwise 200.
|
|
41
|
+
* @returns {SwaggerRPathConfResponse} The Swagger response configuration object containing the appropriate status code and content.
|
|
42
|
+
*/
|
|
9
43
|
static entityResponse<T extends CoreEntity>(entity: T, list?: boolean, create?: boolean): SwaggerRPathConfResponse;
|
|
44
|
+
/**
|
|
45
|
+
* Builds a JSON schema reference path for the given component name.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} inp - The name of the schema component.
|
|
48
|
+
* @return {string} The JSON reference path formatted as `#/components/schemas/<inp>`.
|
|
49
|
+
*/
|
|
10
50
|
static schemaPath(inp: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a Swagger request body definition that references a schema.
|
|
53
|
+
*
|
|
54
|
+
* @param {string | CoreEntity} $ref
|
|
55
|
+
* Either the string reference to a schema or a `CoreEntity` instance whose
|
|
56
|
+
* class name will be used to build the reference path.
|
|
57
|
+
* @param {boolean} list
|
|
58
|
+
* If true, the referenced schema is wrapped in an array; otherwise the
|
|
59
|
+
* schema is used directly.
|
|
60
|
+
* @returns {SwaggerRPathReqBody}
|
|
61
|
+
* The request body object containing the appropriate content and schema
|
|
62
|
+
* configuration.
|
|
63
|
+
*/
|
|
64
|
+
static refRequest($ref: string | CoreEntity, list: boolean): SwaggerRPathReqBody;
|
|
65
|
+
/**
|
|
66
|
+
* Creates a Swagger response configuration for a given HTTP status code.
|
|
67
|
+
*
|
|
68
|
+
* @param {HttpStatusTypes} code - The primary HTTP status code for */
|
|
11
69
|
static refResponse(code: HttpStatusTypes, $ref: string | CoreEntity, list: boolean, ...addCodes: HttpStatusTypes[]): SwaggerRPathConfResponse;
|
|
70
|
+
/**
|
|
71
|
+
* Builds a Swagger response configuration object for a given HTTP status code and schema.
|
|
72
|
+
*
|
|
73
|
+
* @param {HttpStatusTypes} code - The primary HTTP status code for the response.
|
|
74
|
+
* @param {SSchemaEl} schema - The JSON schema definition for the response body.
|
|
75
|
+
* @param {boolean} list - If true, the schema is wrapped in an array for list responses.
|
|
76
|
+
* @param {...HttpStatusTypes} addCodes - Additional HTTP status codes for default responses.
|
|
77
|
+
* @return {SwaggerRPathConfResponse} The constructed response configuration object.
|
|
78
|
+
*/
|
|
12
79
|
static jsonResponse(code: HttpStatusTypes, schema: SSchemaEl, list: boolean, ...addCodes: HttpStatusTypes[]): SwaggerRPathConfResponse;
|
|
13
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Generates a JSON schema representation from a CoreEntity instance.
|
|
82
|
+
*
|
|
83
|
+
* This method inspects the entity's metadata to construct a schema object
|
|
84
|
+
* describing the entity's shape. The resulting schema contains:
|
|
85
|
+
* - `type`: always `"object"`.
|
|
86
|
+
* - `description`: a string indicating the entity name.
|
|
87
|
+
* - `required`: an array of property names that are defined on the entity.
|
|
88
|
+
* - `properties`: an object mapping each property name to an object that
|
|
89
|
+
* includes the resolved database type and its nullability.
|
|
90
|
+
*
|
|
91
|
+
* If no metadata is found for the provided entity, the method returns `undefined`.
|
|
92
|
+
*
|
|
93
|
+
* @param {T} entity - The entity instance for which to create a schema.
|
|
94
|
+
* @returns {SSchemaElObj | undefined} The generated schema object, or `undefined`
|
|
95
|
+
* if the entity's metadata could not be retrieved.
|
|
96
|
+
* @deprecated Use {@link ESchemaEditor.schemaFromEntity} instead.
|
|
97
|
+
*/
|
|
98
|
+
static schemaFromEntity<T extends CoreEntity>(entity: T): SSchemaElObj | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Generates a content schema object for the given entity. The schema contains a description derived from the entity metadata and a JSON content schema based on the entity's structure.
|
|
101
|
+
*
|
|
102
|
+
* @param {T} entity - The entity instance for which to generate the content schema. The generic type `T` must extend {@link CoreEntity}.
|
|
103
|
+
* @returns {{ description: string; content: { 'application/json': { schema: SSchemaEl } }; } | undefined} An object containing the content schema, or `undefined` if no metadata is available for the entity.
|
|
104
|
+
*/
|
|
14
105
|
static contentSchemaFromEntity<T extends CoreEntity>(entity: T): {
|
|
15
106
|
description: string;
|
|
16
107
|
content: {
|
|
@@ -20,9 +111,20 @@ export default class SPathUtil {
|
|
|
20
111
|
};
|
|
21
112
|
} | undefined;
|
|
22
113
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
114
|
+
* Generates a mapping from entity names to their corresponding schema objects.
|
|
115
|
+
*
|
|
116
|
+
* @param {CoreEntity[]} e The entities for which schema entries should be generated.
|
|
117
|
+
* @return {SKey<SSchemaEl>} An object whose keys are entity names and values are the schemas derived from those entities.
|
|
118
|
+
*/
|
|
119
|
+
static schemaEntryGen(...e: CoreEntity[]): SKey<SSchemaElObj>;
|
|
120
|
+
/**
|
|
121
|
+
* Builds a JSON schema representation for an entity view that includes both the
|
|
122
|
+
* entity data and its related entity map.
|
|
123
|
+
*
|
|
124
|
+
* @param entity The primary entity used to construct the `dat` portion of the schema.
|
|
125
|
+
* @param entityMap The related entity map used to construct the `join_map` portion of the schema.
|
|
126
|
+
* @returns A {@link SSchemaEl} object schema with properties `i`, `dat`, and `join_map`.
|
|
25
127
|
*/
|
|
26
|
-
static schemaEntryGen(...e: CoreEntity[]): SKey<SSchemaEl>;
|
|
27
128
|
static schemaFromEntityView<A extends CoreEntity, B extends CoreEntity>(entity: A, entityMap: B): SSchemaEl;
|
|
129
|
+
static editor<J extends CoreEntity>(e: J): ESchemaEditor<J>;
|
|
28
130
|
}
|
|
@@ -1,30 +1,12 @@
|
|
|
1
|
-
import { getEntityMeta, XUtil
|
|
1
|
+
import { getEntityMeta, XUtil } from '@grandlinex/core';
|
|
2
2
|
import map from './SUtilMap.js';
|
|
3
|
-
|
|
4
|
-
switch (dType) {
|
|
5
|
-
case 'int':
|
|
6
|
-
case 'long':
|
|
7
|
-
return 'integer';
|
|
8
|
-
case 'double':
|
|
9
|
-
case 'float':
|
|
10
|
-
return 'number';
|
|
11
|
-
case 'blob':
|
|
12
|
-
return 'string';
|
|
13
|
-
case 'string':
|
|
14
|
-
case 'text':
|
|
15
|
-
case 'uuid':
|
|
16
|
-
return 'string';
|
|
17
|
-
case 'boolean':
|
|
18
|
-
return 'boolean';
|
|
19
|
-
case 'date':
|
|
20
|
-
return 'string';
|
|
21
|
-
case 'json':
|
|
22
|
-
return 'object';
|
|
23
|
-
default:
|
|
24
|
-
throw Error('TypeNotSupported');
|
|
25
|
-
}
|
|
26
|
-
}
|
|
3
|
+
import { ESchemaEditor } from './ESchemaEditor.js';
|
|
27
4
|
export default class SPathUtil {
|
|
5
|
+
/**
|
|
6
|
+
* Generates a default response mapping for the specified HTTP status types.
|
|
7
|
+
*
|
|
8
|
+
* @param {HttpStatusTypes[]} types - The HTTP status types for which default responses should be created.
|
|
9
|
+
* @return {SwaggerRPathConfResponse} An object mapping each provided status type to its default response definition. */
|
|
28
10
|
static defaultResponse(...types) {
|
|
29
11
|
const res = {};
|
|
30
12
|
types.forEach((el) => {
|
|
@@ -32,6 +14,12 @@ export default class SPathUtil {
|
|
|
32
14
|
});
|
|
33
15
|
return res;
|
|
34
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a request body definition for JSON content type using the provided schema.
|
|
19
|
+
*
|
|
20
|
+
* @param {SSchemaEl} schema - The JSON schema used for validating the request body.
|
|
21
|
+
* @return {SwaggerRPathReqBody} A Swagger path request body object specifying application/json content type with the provided schema.
|
|
22
|
+
*/
|
|
35
23
|
static jsonBody(schema) {
|
|
36
24
|
return {
|
|
37
25
|
content: {
|
|
@@ -41,6 +29,13 @@ export default class SPathUtil {
|
|
|
41
29
|
},
|
|
42
30
|
};
|
|
43
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Builds a Swagger request body for `multipart/form-data` requests.
|
|
34
|
+
*
|
|
35
|
+
* @param {SSchemaEl} [schema] Optional schema describing the form data.
|
|
36
|
+
* If omitted, a default schema with a single binary `file` field is provided.
|
|
37
|
+
* @return {SwaggerRPathReqBody} Swagger request body definition with
|
|
38
|
+
* `multipart/form-data` content and the supplied or default schema. */
|
|
44
39
|
static formBody(schema) {
|
|
45
40
|
return {
|
|
46
41
|
content: {
|
|
@@ -59,6 +54,14 @@ export default class SPathUtil {
|
|
|
59
54
|
},
|
|
60
55
|
};
|
|
61
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Generates a Swagger content definition for the provided entity.
|
|
59
|
+
*
|
|
60
|
+
* @param {T} entity - The entity instance to derive the Swagger schema from.
|
|
61
|
+
* @param {boolean} [list] - When true, the schema will be wrapped in an array type, representing a list of entities.
|
|
62
|
+
*
|
|
63
|
+
* @returns {SwaggerContent|undefined} The Swagger content object for the entity, or `undefined` if the entity does not have a schema.
|
|
64
|
+
*/
|
|
62
65
|
static entityContent(entity, list) {
|
|
63
66
|
const schema = this.schemaFromEntity(entity);
|
|
64
67
|
if (!schema) {
|
|
@@ -80,6 +83,13 @@ export default class SPathUtil {
|
|
|
80
83
|
},
|
|
81
84
|
};
|
|
82
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* @template T extends CoreEntity
|
|
88
|
+
* @param {T} entity - The entity instance for which to build the response configuration.
|
|
89
|
+
* @param {boolean} [list] - Indicates whether the response should represent a list of entities.
|
|
90
|
+
* @param {boolean} [create] - Indicates whether the response corresponds to a creation operation (status code 201); otherwise 200.
|
|
91
|
+
* @returns {SwaggerRPathConfResponse} The Swagger response configuration object containing the appropriate status code and content.
|
|
92
|
+
*/
|
|
83
93
|
static entityResponse(entity, list, create) {
|
|
84
94
|
const code = create ? '201' : '200';
|
|
85
95
|
const an = {};
|
|
@@ -89,9 +99,58 @@ export default class SPathUtil {
|
|
|
89
99
|
};
|
|
90
100
|
return an;
|
|
91
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Builds a JSON schema reference path for the given component name.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} inp - The name of the schema component.
|
|
106
|
+
* @return {string} The JSON reference path formatted as `#/components/schemas/<inp>`.
|
|
107
|
+
*/
|
|
92
108
|
static schemaPath(inp) {
|
|
93
109
|
return `#/components/schemas/${inp}`;
|
|
94
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates a Swagger request body definition that references a schema.
|
|
113
|
+
*
|
|
114
|
+
* @param {string | CoreEntity} $ref
|
|
115
|
+
* Either the string reference to a schema or a `CoreEntity` instance whose
|
|
116
|
+
* class name will be used to build the reference path.
|
|
117
|
+
* @param {boolean} list
|
|
118
|
+
* If true, the referenced schema is wrapped in an array; otherwise the
|
|
119
|
+
* schema is used directly.
|
|
120
|
+
* @returns {SwaggerRPathReqBody}
|
|
121
|
+
* The request body object containing the appropriate content and schema
|
|
122
|
+
* configuration.
|
|
123
|
+
*/
|
|
124
|
+
static refRequest($ref, list) {
|
|
125
|
+
const t = typeof $ref === 'string'
|
|
126
|
+
? { $ref }
|
|
127
|
+
: {
|
|
128
|
+
$ref: this.schemaPath(XUtil.getEntityNames($ref).className),
|
|
129
|
+
};
|
|
130
|
+
if (list) {
|
|
131
|
+
return {
|
|
132
|
+
content: {
|
|
133
|
+
'application/json': {
|
|
134
|
+
schema: {
|
|
135
|
+
type: 'array',
|
|
136
|
+
items: t,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
content: {
|
|
144
|
+
'application/json': {
|
|
145
|
+
schema: t,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Creates a Swagger response configuration for a given HTTP status code.
|
|
152
|
+
*
|
|
153
|
+
* @param {HttpStatusTypes} code - The primary HTTP status code for */
|
|
95
154
|
static refResponse(code, $ref, list, ...addCodes) {
|
|
96
155
|
const an = {
|
|
97
156
|
...this.defaultResponse(...addCodes),
|
|
@@ -126,6 +185,15 @@ export default class SPathUtil {
|
|
|
126
185
|
}
|
|
127
186
|
return an;
|
|
128
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Builds a Swagger response configuration object for a given HTTP status code and schema.
|
|
190
|
+
*
|
|
191
|
+
* @param {HttpStatusTypes} code - The primary HTTP status code for the response.
|
|
192
|
+
* @param {SSchemaEl} schema - The JSON schema definition for the response body.
|
|
193
|
+
* @param {boolean} list - If true, the schema is wrapped in an array for list responses.
|
|
194
|
+
* @param {...HttpStatusTypes} addCodes - Additional HTTP status codes for default responses.
|
|
195
|
+
* @return {SwaggerRPathConfResponse} The constructed response configuration object.
|
|
196
|
+
*/
|
|
129
197
|
static jsonResponse(code, schema, list, ...addCodes) {
|
|
130
198
|
const an = {
|
|
131
199
|
...this.defaultResponse(...addCodes),
|
|
@@ -155,30 +223,33 @@ export default class SPathUtil {
|
|
|
155
223
|
}
|
|
156
224
|
return an;
|
|
157
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Generates a JSON schema representation from a CoreEntity instance.
|
|
228
|
+
*
|
|
229
|
+
* This method inspects the entity's metadata to construct a schema object
|
|
230
|
+
* describing the entity's shape. The resulting schema contains:
|
|
231
|
+
* - `type`: always `"object"`.
|
|
232
|
+
* - `description`: a string indicating the entity name.
|
|
233
|
+
* - `required`: an array of property names that are defined on the entity.
|
|
234
|
+
* - `properties`: an object mapping each property name to an object that
|
|
235
|
+
* includes the resolved database type and its nullability.
|
|
236
|
+
*
|
|
237
|
+
* If no metadata is found for the provided entity, the method returns `undefined`.
|
|
238
|
+
*
|
|
239
|
+
* @param {T} entity - The entity instance for which to create a schema.
|
|
240
|
+
* @returns {SSchemaElObj | undefined} The generated schema object, or `undefined`
|
|
241
|
+
* if the entity's metadata could not be retrieved.
|
|
242
|
+
* @deprecated Use {@link ESchemaEditor.schemaFromEntity} instead.
|
|
243
|
+
*/
|
|
158
244
|
static schemaFromEntity(entity) {
|
|
159
|
-
|
|
160
|
-
type: 'object',
|
|
161
|
-
properties: {},
|
|
162
|
-
};
|
|
163
|
-
const meta = getEntityMeta(entity);
|
|
164
|
-
if (!meta) {
|
|
165
|
-
return undefined;
|
|
166
|
-
}
|
|
167
|
-
schema.description = `Entity: ${meta.name}`;
|
|
168
|
-
schema.required = [];
|
|
169
|
-
const keys = Object.keys(entity);
|
|
170
|
-
keys.forEach((k) => {
|
|
171
|
-
const cMeta = getColumnMeta(entity, k);
|
|
172
|
-
if (cMeta && schema.properties) {
|
|
173
|
-
schema.required.push(k);
|
|
174
|
-
schema.properties[k] = {
|
|
175
|
-
type: resolveDBType(cMeta.dataType),
|
|
176
|
-
nullable: cMeta.canBeNull,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
return schema;
|
|
245
|
+
return ESchemaEditor.schemaFromEntity(entity);
|
|
181
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Generates a content schema object for the given entity. The schema contains a description derived from the entity metadata and a JSON content schema based on the entity's structure.
|
|
249
|
+
*
|
|
250
|
+
* @param {T} entity - The entity instance for which to generate the content schema. The generic type `T` must extend {@link CoreEntity}.
|
|
251
|
+
* @returns {{ description: string; content: { 'application/json': { schema: SSchemaEl } }; } | undefined} An object containing the content schema, or `undefined` if no metadata is available for the entity.
|
|
252
|
+
*/
|
|
182
253
|
static contentSchemaFromEntity(entity) {
|
|
183
254
|
const meta = getEntityMeta(entity);
|
|
184
255
|
if (!meta) {
|
|
@@ -188,25 +259,35 @@ export default class SPathUtil {
|
|
|
188
259
|
description: `Entity: ${meta.name}`,
|
|
189
260
|
content: {
|
|
190
261
|
'application/json': {
|
|
191
|
-
schema:
|
|
262
|
+
schema: ESchemaEditor.schemaFromEntity(entity),
|
|
192
263
|
},
|
|
193
264
|
},
|
|
194
265
|
};
|
|
195
266
|
}
|
|
196
267
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
268
|
+
* Generates a mapping from entity names to their corresponding schema objects.
|
|
269
|
+
*
|
|
270
|
+
* @param {CoreEntity[]} e The entities for which schema entries should be generated.
|
|
271
|
+
* @return {SKey<SSchemaEl>} An object whose keys are entity names and values are the schemas derived from those entities.
|
|
199
272
|
*/
|
|
200
273
|
static schemaEntryGen(...e) {
|
|
201
274
|
const out = {};
|
|
202
275
|
e.forEach((el) => {
|
|
203
276
|
const meta = getEntityMeta(el);
|
|
204
277
|
if (meta) {
|
|
205
|
-
out[meta.name] =
|
|
278
|
+
out[meta.name] = ESchemaEditor.schemaFromEntity(el);
|
|
206
279
|
}
|
|
207
280
|
});
|
|
208
281
|
return out;
|
|
209
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Builds a JSON schema representation for an entity view that includes both the
|
|
285
|
+
* entity data and its related entity map.
|
|
286
|
+
*
|
|
287
|
+
* @param entity The primary entity used to construct the `dat` portion of the schema.
|
|
288
|
+
* @param entityMap The related entity map used to construct the `join_map` portion of the schema.
|
|
289
|
+
* @returns A {@link SSchemaEl} object schema with properties `i`, `dat`, and `join_map`.
|
|
290
|
+
*/
|
|
210
291
|
static schemaFromEntityView(entity, entityMap) {
|
|
211
292
|
return {
|
|
212
293
|
type: 'object',
|
|
@@ -214,9 +295,12 @@ export default class SPathUtil {
|
|
|
214
295
|
i: {
|
|
215
296
|
type: 'integer',
|
|
216
297
|
},
|
|
217
|
-
dat:
|
|
218
|
-
join_map:
|
|
298
|
+
dat: ESchemaEditor.schemaFromEntity(entity),
|
|
299
|
+
join_map: ESchemaEditor.schemaFromEntity(entityMap),
|
|
219
300
|
},
|
|
220
301
|
};
|
|
221
302
|
}
|
|
303
|
+
static editor(e) {
|
|
304
|
+
return ESchemaEditor.fromEntity(e);
|
|
305
|
+
}
|
|
222
306
|
}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
-
import { ObjectLike } from '@grandlinex/core';
|
|
1
|
+
import { CoreLogChannel, ObjectLike } from '@grandlinex/core';
|
|
2
2
|
import { Server } from 'net';
|
|
3
3
|
import { MergeInputType, SwaggerConfig, SwaggerRPath } from './Meta/SwaggerTypes.js';
|
|
4
4
|
import { RouteData } from './annotation/index.js';
|
|
5
5
|
export default class SwaggerUtil {
|
|
6
|
+
static logger: CoreLogChannel | null;
|
|
7
|
+
static getLogger(): CoreLogChannel;
|
|
6
8
|
static writeMeta(conf: SwaggerConfig, kind: 'JSON' | 'YAML', path?: string): void;
|
|
7
9
|
static readMeta(path: string): any;
|
|
8
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Serves a meta page for Swagger UI or rapi-doc.
|
|
12
|
+
*
|
|
13
|
+
* @param {SwaggerConfig} conf The swagger configuration to expose via `/spec`.
|
|
14
|
+
* @param {Object} [option] Options for serving the meta page.
|
|
15
|
+
* @param {'swagger-ui'|'rapi-doc'} [option.type='swagger-ui'] The type of UI to serve.
|
|
16
|
+
* @param {number} [option.port] The port to listen on. Defaults to 9000.
|
|
17
|
+
* @param {string} [option.auth] Optional authentication key appended to the URL.
|
|
18
|
+
* @returns {Promise<Server|null>} A promise that resolves with the created server instance or null.
|
|
19
|
+
*/
|
|
20
|
+
static serveMeta(conf: SwaggerConfig, option?: {
|
|
21
|
+
type?: 'swagger-ui' | 'rapi-doc';
|
|
22
|
+
port?: number;
|
|
23
|
+
auth?: string;
|
|
24
|
+
}): Promise<Server | null>;
|
|
9
25
|
static metaExtractor(root: ObjectLike, npmPackageVersion: boolean, ...path: ObjectLike[]): SwaggerConfig | undefined;
|
|
10
26
|
static routeToSwaggerPath(route: RouteData): SwaggerRPath;
|
|
11
27
|
static merge(root: SwaggerConfig, data: MergeInputType[]): SwaggerConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import jsyaml from 'js-yaml';
|
|
4
|
-
import { CMap, instanceOfEntity } from '@grandlinex/core';
|
|
4
|
+
import { CMap, CoreLogChannel, DefaultLogger, instanceOfEntity, } from '@grandlinex/core';
|
|
5
5
|
import express from 'express';
|
|
6
6
|
import * as process from 'process';
|
|
7
7
|
import { getSComponent, getSPath, getSwaggerMeta } from './Meta/Swagger.js';
|
|
@@ -9,6 +9,13 @@ import PathHelp, { getBaseFolder } from '../PathHelp.js';
|
|
|
9
9
|
import { getRouteMeta } from './annotation/index.js';
|
|
10
10
|
import { SPathUtil } from '../index.js';
|
|
11
11
|
export default class SwaggerUtil {
|
|
12
|
+
static getLogger() {
|
|
13
|
+
if (!this.logger) {
|
|
14
|
+
const logger = new DefaultLogger();
|
|
15
|
+
this.logger = new CoreLogChannel('SwaggerUtil', logger);
|
|
16
|
+
}
|
|
17
|
+
return this.logger;
|
|
18
|
+
}
|
|
12
19
|
static writeMeta(conf, kind, path) {
|
|
13
20
|
if (kind === 'JSON') {
|
|
14
21
|
const p = Path.join(path || process.cwd(), 'openapi.json');
|
|
@@ -25,11 +32,25 @@ export default class SwaggerUtil {
|
|
|
25
32
|
return JSON.parse(file);
|
|
26
33
|
}
|
|
27
34
|
catch (e) {
|
|
35
|
+
this.getLogger().error(e);
|
|
28
36
|
return null;
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Serves a meta page for Swagger UI or rapi-doc.
|
|
41
|
+
*
|
|
42
|
+
* @param {SwaggerConfig} conf The swagger configuration to expose via `/spec`.
|
|
43
|
+
* @param {Object} [option] Options for serving the meta page.
|
|
44
|
+
* @param {'swagger-ui'|'rapi-doc'} [option.type='swagger-ui'] The type of UI to serve.
|
|
45
|
+
* @param {number} [option.port] The port to listen on. Defaults to 9000.
|
|
46
|
+
* @param {string} [option.auth] Optional authentication key appended to the URL.
|
|
47
|
+
* @returns {Promise<Server|null>} A promise that resolves with the created server instance or null.
|
|
48
|
+
*/
|
|
49
|
+
static async serveMeta(conf, option) {
|
|
50
|
+
const type = option?.type ?? 'swagger-ui';
|
|
51
|
+
const port = option?.port || 9000;
|
|
52
|
+
const auth = option?.auth;
|
|
53
|
+
const resFiles = PathHelp(getBaseFolder(), '..', 'res', 'html', type);
|
|
33
54
|
const key = auth ? `?auth=${auth}` : '';
|
|
34
55
|
const app = express();
|
|
35
56
|
app.use('/', express.static(resFiles));
|
|
@@ -37,8 +58,8 @@ export default class SwaggerUtil {
|
|
|
37
58
|
res.status(200).send(conf);
|
|
38
59
|
});
|
|
39
60
|
return new Promise((resolve) => {
|
|
40
|
-
const s = app.listen(port
|
|
41
|
-
|
|
61
|
+
const s = app.listen(port, () => {
|
|
62
|
+
this.getLogger().log(`${type} listen on http://localhost:${port}${key}#`);
|
|
42
63
|
resolve(s);
|
|
43
64
|
});
|
|
44
65
|
});
|
|
@@ -83,7 +104,13 @@ export default class SwaggerUtil {
|
|
|
83
104
|
// Handle requestBody
|
|
84
105
|
if (!conf.requestBody) {
|
|
85
106
|
if (route.meta.requestSchema) {
|
|
86
|
-
|
|
107
|
+
if (typeof route.meta.requestSchema === 'string' ||
|
|
108
|
+
instanceOfEntity(route.meta.requestSchema)) {
|
|
109
|
+
conf.requestBody = SPathUtil.refRequest(route.meta.requestSchema, route.meta.responseType === 'LIST');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
conf.requestBody = SPathUtil.jsonBody(route.meta.requestSchema);
|
|
113
|
+
}
|
|
87
114
|
}
|
|
88
115
|
}
|
|
89
116
|
// Handle responses
|