@rsdk/cli.cmd.autodoc 6.0.0-next.4 → 6.0.0-next.41
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/CHANGELOG.md +382 -0
- package/TODO.MD +24 -0
- package/dist/commands/autodoc.cmd.js +8 -10
- package/dist/commands/autodoc.cmd.js.map +1 -1
- package/dist/commands/openapi.variation.js +1 -2
- package/dist/commands/openapi.variation.js.map +1 -1
- package/dist/generators/file-generator.interface.d.ts +1 -1
- package/dist/generators/openapi-json/config.schema.d.ts +21 -38
- package/dist/generators/openapi-json/config.schema.js +18 -134
- package/dist/generators/openapi-json/config.schema.js.map +1 -1
- package/dist/generators/openapi-json/openapi-json.generator.d.ts +4 -5
- package/dist/generators/openapi-json/openapi-json.generator.js +12 -107
- package/dist/generators/openapi-json/openapi-json.generator.js.map +1 -1
- package/dist/generators/openapi-json/schemas/config.schema.d.ts +55 -0
- package/dist/generators/openapi-json/schemas/config.schema.js +36 -0
- package/dist/generators/openapi-json/schemas/config.schema.js.map +1 -0
- package/dist/generators/openapi-json/schemas/index.d.ts +1 -0
- package/dist/generators/openapi-json/schemas/index.js +18 -0
- package/dist/generators/openapi-json/schemas/index.js.map +1 -0
- package/eslint.config.cjs +3 -0
- package/jest.config.e2e.js +1 -0
- package/jest.config.js +1 -0
- package/jest.config.unit.js +1 -0
- package/package.json +22 -29
- package/src/base/app.loader.ts +39 -0
- package/src/base/document.file.ts +33 -0
- package/src/base/index.ts +2 -0
- package/src/commands/autodoc.cmd.ts +93 -0
- package/src/commands/openapi.variation.ts +172 -0
- package/src/generators/autodoc-md/autodoc-md.generator.ts +56 -0
- package/src/generators/autodoc-md/formatters.ts +9 -0
- package/src/generators/autodoc-md/fragments/document-fragment.abstract.ts +6 -0
- package/src/generators/autodoc-md/fragments/extractor/document.extractor.ts +73 -0
- package/src/generators/autodoc-md/fragments/implementations/additional-sources.fragment.ts +41 -0
- package/src/generators/autodoc-md/fragments/implementations/app-metadata.fragment.ts +18 -0
- package/src/generators/autodoc-md/fragments/implementations/autodoc.fragment.ts +30 -0
- package/src/generators/autodoc-md/fragments/implementations/config-section.fragment.ts +148 -0
- package/src/generators/autodoc-md/fragments/implementations/header.fragment.ts +18 -0
- package/src/generators/autodoc-md/fragments/implementations/plugin.fragment.ts +21 -0
- package/src/generators/autodoc-md/fragments/implementations/transports.fragment.ts +36 -0
- package/src/generators/autodoc-md/fragments/index.ts +9 -0
- package/src/generators/autodoc-md/index.ts +1 -0
- package/src/generators/file-generator.interface.ts +22 -0
- package/src/generators/index.ts +4 -0
- package/src/generators/openapi-json/config.schema.spec.ts +265 -0
- package/src/generators/openapi-json/config.schema.ts +37 -0
- package/src/generators/openapi-json/index.ts +2 -0
- package/src/generators/openapi-json/openapi-json.generator.ts +53 -0
- package/src/generators/openapi-json/schemas/config.schema.spec.ts +265 -0
- package/src/generators/openapi-json/schemas/config.schema.ts +37 -0
- package/src/generators/openapi-json/schemas/index.ts +1 -0
- package/src/generators/rsdk-json/index.ts +1 -0
- package/src/generators/rsdk-json/rsdk-json.generator.ts +24 -0
- package/src/index.ts +1 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +7 -0
|
@@ -1,117 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OpenApiConfigSchema = void 0;
|
|
4
|
+
const http_openapi_1 = require("@rsdk/http.openapi");
|
|
4
5
|
const typebox_1 = require("@sinclair/typebox");
|
|
5
|
-
/**
|
|
6
|
-
* Base schema for all security schemes.
|
|
7
|
-
* Contains common fields that are present in all security scheme types.
|
|
8
|
-
*/
|
|
9
|
-
const SecuritySchemeBase = typebox_1.Type.Object({
|
|
10
|
-
type: typebox_1.Type.Union([
|
|
11
|
-
typebox_1.Type.Literal('http'),
|
|
12
|
-
typebox_1.Type.Literal('apiKey'),
|
|
13
|
-
typebox_1.Type.Literal('oauth2'),
|
|
14
|
-
typebox_1.Type.Literal('mutualTLS'),
|
|
15
|
-
]),
|
|
16
|
-
description: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
17
|
-
name: typebox_1.Type.String(),
|
|
18
|
-
}, { additionalProperties: false });
|
|
19
|
-
/**
|
|
20
|
-
* HTTP Authentication scheme (Basic or Bearer).
|
|
21
|
-
* @example
|
|
22
|
-
* {
|
|
23
|
-
* "type": "http",
|
|
24
|
-
* "scheme": "bearer",
|
|
25
|
-
* "bearerFormat": "JWT",
|
|
26
|
-
* "name": "JWT Auth"
|
|
27
|
-
* }
|
|
28
|
-
*/
|
|
29
|
-
const HttpSecurityScheme = typebox_1.Type.Intersect([
|
|
30
|
-
SecuritySchemeBase,
|
|
31
|
-
typebox_1.Type.Object({
|
|
32
|
-
type: typebox_1.Type.Literal('http'),
|
|
33
|
-
scheme: typebox_1.Type.Union([typebox_1.Type.Literal('basic'), typebox_1.Type.Literal('bearer')]),
|
|
34
|
-
bearerFormat: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
35
|
-
}, { additionalProperties: false }),
|
|
36
|
-
]);
|
|
37
|
-
/**
|
|
38
|
-
* API Key Authentication scheme.
|
|
39
|
-
* The API key can be passed in a header, query parameter, or cookie.
|
|
40
|
-
* @example
|
|
41
|
-
* {
|
|
42
|
-
* "type": "apiKey",
|
|
43
|
-
* "name": "api_key",
|
|
44
|
-
* "in": "header",
|
|
45
|
-
* "description": "API Key Authentication"
|
|
46
|
-
* }
|
|
47
|
-
*/
|
|
48
|
-
const ApiKeySecurityScheme = typebox_1.Type.Intersect([
|
|
49
|
-
SecuritySchemeBase,
|
|
50
|
-
typebox_1.Type.Object({
|
|
51
|
-
type: typebox_1.Type.Literal('apiKey'),
|
|
52
|
-
in: typebox_1.Type.Union([
|
|
53
|
-
typebox_1.Type.Literal('query'),
|
|
54
|
-
typebox_1.Type.Literal('header'),
|
|
55
|
-
typebox_1.Type.Literal('cookie'),
|
|
56
|
-
]),
|
|
57
|
-
}, { additionalProperties: false }),
|
|
58
|
-
]);
|
|
59
|
-
/**
|
|
60
|
-
* OAuth2 Authentication scheme.
|
|
61
|
-
* Supports multiple OAuth2 flows (implicit, password, clientCredentials, authorizationCode).
|
|
62
|
-
* @example
|
|
63
|
-
* {
|
|
64
|
-
* "type": "oauth2",
|
|
65
|
-
* "name": "OAuth2",
|
|
66
|
-
* "flows": {
|
|
67
|
-
* "implicit": {
|
|
68
|
-
* "authorizationUrl": "https://example.com/oauth/authorize",
|
|
69
|
-
* "scopes": {
|
|
70
|
-
* "read": "Read access",
|
|
71
|
-
* "write": "Write access"
|
|
72
|
-
* }
|
|
73
|
-
* }
|
|
74
|
-
* }
|
|
75
|
-
* }
|
|
76
|
-
*/
|
|
77
|
-
const OAuth2SecurityScheme = typebox_1.Type.Intersect([
|
|
78
|
-
SecuritySchemeBase,
|
|
79
|
-
typebox_1.Type.Object({
|
|
80
|
-
type: typebox_1.Type.Literal('oauth2'),
|
|
81
|
-
flows: typebox_1.Type.Record(typebox_1.Type.String(), typebox_1.Type.Object({
|
|
82
|
-
authorizationUrl: typebox_1.Type.Optional(typebox_1.Type.String({ format: 'uri' })),
|
|
83
|
-
tokenUrl: typebox_1.Type.Optional(typebox_1.Type.String({ format: 'uri' })),
|
|
84
|
-
refreshUrl: typebox_1.Type.Optional(typebox_1.Type.String({ format: 'uri' })),
|
|
85
|
-
scopes: typebox_1.Type.Record(typebox_1.Type.String(), typebox_1.Type.String()),
|
|
86
|
-
}, { additionalProperties: false })),
|
|
87
|
-
}, { additionalProperties: false }),
|
|
88
|
-
]);
|
|
89
|
-
/**
|
|
90
|
-
* Mutual TLS Authentication scheme.
|
|
91
|
-
* Used when clients must present valid certificates to access the API.
|
|
92
|
-
* @example
|
|
93
|
-
* {
|
|
94
|
-
* "type": "mutualTLS",
|
|
95
|
-
* "name": "mtls",
|
|
96
|
-
* "description": "Client certificate required"
|
|
97
|
-
* }
|
|
98
|
-
*/
|
|
99
|
-
const MutualTLSSecurityScheme = typebox_1.Type.Intersect([
|
|
100
|
-
SecuritySchemeBase,
|
|
101
|
-
typebox_1.Type.Object({
|
|
102
|
-
type: typebox_1.Type.Literal('mutualTLS'),
|
|
103
|
-
}, { additionalProperties: false }),
|
|
104
|
-
]);
|
|
105
|
-
/**
|
|
106
|
-
* Union of all supported security schemes.
|
|
107
|
-
* Can be one of: HTTP (Basic/Bearer), API Key, OAuth2, or Mutual TLS.
|
|
108
|
-
*/
|
|
109
|
-
const SecurityScheme = typebox_1.Type.Union([
|
|
110
|
-
HttpSecurityScheme,
|
|
111
|
-
ApiKeySecurityScheme,
|
|
112
|
-
OAuth2SecurityScheme,
|
|
113
|
-
MutualTLSSecurityScheme,
|
|
114
|
-
]);
|
|
115
6
|
/**
|
|
116
7
|
* Configuration schema for OpenAPI document generation.
|
|
117
8
|
* @example
|
|
@@ -123,30 +14,23 @@ const SecurityScheme = typebox_1.Type.Union([
|
|
|
123
14
|
* "description": "API Description",
|
|
124
15
|
* "includeZones": ["public"],
|
|
125
16
|
* "excludeZones": ["internal"],
|
|
126
|
-
* "security":
|
|
127
|
-
* "
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
17
|
+
* "security": {
|
|
18
|
+
* "jwt": {
|
|
19
|
+
* "type": "http",
|
|
20
|
+
* "scheme": "bearer",
|
|
21
|
+
* "bearerFormat": "JWT",
|
|
22
|
+
* "name": "JWT Auth"
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
132
25
|
* }
|
|
133
26
|
*/
|
|
134
|
-
exports.OpenApiConfigSchema = typebox_1.Type.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
/** API description */
|
|
144
|
-
description: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
145
|
-
/** List of zones to include in the documentation */
|
|
146
|
-
includeZones: typebox_1.Type.Optional(typebox_1.Type.Array(typebox_1.Type.String())),
|
|
147
|
-
/** List of zones to exclude from the documentation */
|
|
148
|
-
excludeZones: typebox_1.Type.Optional(typebox_1.Type.Array(typebox_1.Type.String())),
|
|
149
|
-
/** Security schemes configuration */
|
|
150
|
-
security: typebox_1.Type.Optional(typebox_1.Type.Array(SecurityScheme)),
|
|
151
|
-
}, { additionalProperties: false });
|
|
27
|
+
exports.OpenApiConfigSchema = typebox_1.Type.Intersect([
|
|
28
|
+
typebox_1.Type.Partial(http_openapi_1.OpenApiOptions),
|
|
29
|
+
typebox_1.Type.Object({
|
|
30
|
+
/** Output file path for the generated OpenAPI document */
|
|
31
|
+
out: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
32
|
+
/** Path to the application file (usually `dist/app.js`) */
|
|
33
|
+
app: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
152
36
|
//# sourceMappingURL=config.schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.schema.js","sourceRoot":"","sources":["../../../src/generators/openapi-json/config.schema.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"config.schema.js","sourceRoot":"","sources":["../../../src/generators/openapi-json/config.schema.ts"],"names":[],"mappings":";;;AAAA,qDAAoD;AAEpD,+CAAyC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACU,QAAA,mBAAmB,GAAG,cAAI,CAAC,SAAS,CAAC;IAChD,cAAI,CAAC,OAAO,CAAC,6BAAc,CAAC;IAC5B,cAAI,CAAC,MAAM,CAAC;QACV,0DAA0D;QAC1D,GAAG,EAAE,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,MAAM,EAAE,CAAC;QAEjC,2DAA2D;QAC3D,GAAG,EAAE,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,MAAM,EAAE,CAAC;KAClC,CAAC;CACH,CAAC,CAAC"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { PlatformApp } from '@rsdk/core';
|
|
1
|
+
import type { PlatformApp } from '@rsdk/core';
|
|
2
2
|
import { FileGenerator } from '../file-generator.interface';
|
|
3
|
-
import { OpenApiConfigSchema } from './config.schema';
|
|
3
|
+
import type { OpenApiConfigSchema } from './config.schema';
|
|
4
4
|
/**
|
|
5
5
|
* Here we don't need `out` and `app`,
|
|
6
6
|
* but `title`, `version` and `description` are required.
|
|
7
7
|
*/
|
|
8
8
|
export type OpenApiGeneratorOptions = Omit<OpenApiConfigSchema, 'out' | 'app'> & Required<Pick<OpenApiConfigSchema, 'title' | 'version' | 'description'>>;
|
|
9
|
-
export declare class
|
|
10
|
-
private readonly
|
|
9
|
+
export declare class OpenApiFileGenerator extends FileGenerator {
|
|
10
|
+
private readonly context;
|
|
11
11
|
private readonly options;
|
|
12
12
|
constructor(app: PlatformApp, options?: Partial<OpenApiGeneratorOptions>);
|
|
13
13
|
protected getContent(): Promise<string>;
|
|
14
|
-
private clearController;
|
|
15
14
|
private resolveOptions;
|
|
16
15
|
}
|
|
@@ -1,122 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
10
|
-
const
|
|
11
|
-
const core_1 = require("@nestjs/core");
|
|
12
|
-
const swagger_1 = require("@nestjs/swagger");
|
|
13
|
-
const core_2 = require("@rsdk/core");
|
|
3
|
+
exports.OpenApiFileGenerator = void 0;
|
|
4
|
+
const http_openapi_1 = require("@rsdk/http.openapi");
|
|
14
5
|
const logging_1 = require("@rsdk/logging");
|
|
15
|
-
const nest_tools_1 = require("@rsdk/nest-tools");
|
|
16
|
-
const zones_1 = require("@rsdk/zones");
|
|
17
6
|
const file_generator_interface_1 = require("../file-generator.interface");
|
|
18
|
-
class
|
|
19
|
-
|
|
7
|
+
class OpenApiFileGenerator extends file_generator_interface_1.FileGenerator {
|
|
8
|
+
context;
|
|
20
9
|
options;
|
|
21
10
|
constructor(app, options = {}) {
|
|
22
|
-
super(logging_1.LoggerFactory.create(
|
|
23
|
-
this.
|
|
11
|
+
super(logging_1.LoggerFactory.create(OpenApiFileGenerator));
|
|
12
|
+
this.context = app.context;
|
|
24
13
|
this.options = options;
|
|
25
14
|
}
|
|
26
15
|
async getContent() {
|
|
27
|
-
const transports = this.app.context.options.transports;
|
|
28
|
-
if (!transports?.length) {
|
|
29
|
-
throw new Error('transports not found');
|
|
30
|
-
}
|
|
31
|
-
const httpTransport = transports?.find?.(core_2.isHttpTransport);
|
|
32
|
-
if (!httpTransport) {
|
|
33
|
-
throw new Error('http transport not found');
|
|
34
|
-
}
|
|
35
16
|
this.logger.info('Generate openapi starting');
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const controllers = [];
|
|
40
|
-
const { includeZones, excludeZones } = options;
|
|
41
|
-
/**
|
|
42
|
-
* TODO: А может надо на основании чего-то другого, кроме тегов ещё?
|
|
43
|
-
* Просто теги могут быть с пробелами и с другими приколами... как вариант
|
|
44
|
-
* можно на основании имён контроллеров?
|
|
45
|
-
*/
|
|
46
|
-
this.logger.info(`includeZones: ${includeZones}`);
|
|
47
|
-
this.logger.info(`excludeZones: ${excludeZones}`);
|
|
48
|
-
for await (const controller of iterator) {
|
|
49
|
-
const zone = zones_1.Zone.getForController(controller);
|
|
50
|
-
this.logger.info(`${controller.name} zone: ${zone || 'none'}`);
|
|
51
|
-
/**
|
|
52
|
-
* Исключаем контроллеры, c зоной из excludeZones
|
|
53
|
-
*/
|
|
54
|
-
if (excludeZones && excludeZones.includes(zone)) {
|
|
55
|
-
this.logger.info(`${controller.name} excluded`);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Включаем только те контроллеры, которые имеют хотя бы один из тегов из includeTags
|
|
60
|
-
*/
|
|
61
|
-
if (includeZones && !includeZones.includes(zone)) {
|
|
62
|
-
this.logger.info(`${controller.name} skipped`);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
this.logger.info(`${controller.name} included`);
|
|
66
|
-
controllers.push(this.clearController(controller));
|
|
67
|
-
}
|
|
68
|
-
let OpenApiModule = class OpenApiModule {
|
|
69
|
-
};
|
|
70
|
-
OpenApiModule = __decorate([
|
|
71
|
-
(0, common_1.Module)({ controllers })
|
|
72
|
-
], OpenApiModule);
|
|
73
|
-
const createOptions = await this.app.context.getNestFactoryCreateOptions();
|
|
74
|
-
const app = await core_1.NestFactory.create(OpenApiModule, ...createOptions);
|
|
75
|
-
const { title, version, description, security } = options;
|
|
76
|
-
const builder = new swagger_1.DocumentBuilder()
|
|
77
|
-
.setTitle(title)
|
|
78
|
-
.setVersion(version)
|
|
79
|
-
.setDescription(description);
|
|
80
|
-
for (const scheme of security || []) {
|
|
81
|
-
switch (scheme.type) {
|
|
82
|
-
case 'http':
|
|
83
|
-
if (scheme.scheme === 'bearer') {
|
|
84
|
-
builder.addBearerAuth(scheme, scheme.name);
|
|
85
|
-
}
|
|
86
|
-
else if (scheme.scheme === 'basic') {
|
|
87
|
-
builder.addBasicAuth(scheme, scheme.name);
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
case 'oauth2':
|
|
91
|
-
builder.addOAuth2(scheme, scheme.name);
|
|
92
|
-
break;
|
|
93
|
-
case 'apiKey':
|
|
94
|
-
builder.addApiKey(scheme, scheme.name);
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const openApiConfig = builder.build();
|
|
99
|
-
const document = swagger_1.SwaggerModule.createDocument(app, openApiConfig);
|
|
17
|
+
const options = await this.resolveOptions(this.context, this.options);
|
|
18
|
+
const generator = new http_openapi_1.OpenApiGenerator(this.context, options);
|
|
19
|
+
const document = await generator.generate();
|
|
100
20
|
this.logger.info('Generate openapi finished');
|
|
101
|
-
await app.close();
|
|
102
21
|
return JSON.stringify(document, null, 2);
|
|
103
22
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
const keysForRedefine = ['design:paramtypes', 'self:paramtypes'];
|
|
108
|
-
for (const forRedefineMetadataKey of keysForRedefine) {
|
|
109
|
-
Reflect.defineMetadata(forRedefineMetadataKey, [], ClearedController);
|
|
110
|
-
}
|
|
111
|
-
// Влияет на `operationId` в генерации
|
|
112
|
-
Object.defineProperty(ClearedController, 'name', {
|
|
113
|
-
value: controller.name,
|
|
114
|
-
writable: false,
|
|
115
|
-
});
|
|
116
|
-
return ClearedController;
|
|
117
|
-
}
|
|
118
|
-
async resolveOptions(app, passed) {
|
|
119
|
-
const appMetadata = await app.context.getMetadata();
|
|
23
|
+
async resolveOptions(context, passed) {
|
|
24
|
+
const appMetadata = await context.getMetadata();
|
|
120
25
|
const defaults = {
|
|
121
26
|
title: appMetadata.name,
|
|
122
27
|
version: appMetadata.version,
|
|
@@ -125,5 +30,5 @@ class OpenapiGenerator extends file_generator_interface_1.FileGenerator {
|
|
|
125
30
|
return { ...defaults, ...passed };
|
|
126
31
|
}
|
|
127
32
|
}
|
|
128
|
-
exports.
|
|
33
|
+
exports.OpenApiFileGenerator = OpenApiFileGenerator;
|
|
129
34
|
//# sourceMappingURL=openapi-json.generator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi-json.generator.js","sourceRoot":"","sources":["../../../src/generators/openapi-json/openapi-json.generator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openapi-json.generator.js","sourceRoot":"","sources":["../../../src/generators/openapi-json/openapi-json.generator.ts"],"names":[],"mappings":";;;AACA,qDAAsD;AACtD,2CAA8C;AAE9C,0EAA4D;AAW5D,MAAa,oBAAqB,SAAQ,wCAAa;IACpC,OAAO,CAAkB;IACzB,OAAO,CAAmC;IAE3D,YACE,GAAgB,EAChB,UAA4C,EAAE;QAE9C,KAAK,CAAC,uBAAa,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAES,KAAK,CAAC,UAAU;QACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAE9C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACtE,MAAM,SAAS,GAAG,IAAI,+BAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;QAE5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,OAAwB,EACxB,MAAwC;QAExC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,QAAQ,GAA4B;YACxC,KAAK,EAAE,WAAW,CAAC,IAAI;YACvB,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,WAAW,EAAE,WAAW,CAAC,WAAW;SACrC,CAAC;QAEF,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;IACpC,CAAC;CACF;AArCD,oDAqCC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Static } from '@sinclair/typebox';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration schema for OpenAPI document generation.
|
|
4
|
+
* @example
|
|
5
|
+
* {
|
|
6
|
+
* "out": "openapi.json",
|
|
7
|
+
* "app": "./dist/app.js",
|
|
8
|
+
* "title": "My API",
|
|
9
|
+
* "version": "1.0.0",
|
|
10
|
+
* "description": "API Description",
|
|
11
|
+
* "includeZones": ["public"],
|
|
12
|
+
* "excludeZones": ["internal"],
|
|
13
|
+
* "security": {
|
|
14
|
+
* "jwt": {
|
|
15
|
+
* "type": "http",
|
|
16
|
+
* "scheme": "bearer",
|
|
17
|
+
* "bearerFormat": "JWT",
|
|
18
|
+
* "name": "JWT Auth"
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
export declare const OpenApiConfigSchema: import("@sinclair/typebox").TIntersect<[import("@sinclair/typebox").TObject<{
|
|
24
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
25
|
+
version: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
26
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
27
|
+
includeZones: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
28
|
+
excludeZones: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
29
|
+
security: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
|
|
30
|
+
type: import("@sinclair/typebox").TLiteral<"http">;
|
|
31
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
32
|
+
scheme: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"basic">, import("@sinclair/typebox").TLiteral<"bearer">]>;
|
|
33
|
+
bearerFormat: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
34
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
35
|
+
type: import("@sinclair/typebox").TLiteral<"apiKey">;
|
|
36
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
37
|
+
name: import("@sinclair/typebox").TString;
|
|
38
|
+
in: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"query">, import("@sinclair/typebox").TLiteral<"header">, import("@sinclair/typebox").TLiteral<"cookie">]>;
|
|
39
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
40
|
+
type: import("@sinclair/typebox").TLiteral<"oauth2">;
|
|
41
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
42
|
+
flows: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
|
|
43
|
+
scopes: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TString>;
|
|
44
|
+
authorizationUrl: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
45
|
+
tokenUrl: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
46
|
+
refreshUrl: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
47
|
+
}>>;
|
|
48
|
+
}>]>>>;
|
|
49
|
+
}>, import("@sinclair/typebox").TObject<{
|
|
50
|
+
/** Output file path for the generated OpenAPI document */
|
|
51
|
+
out: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
52
|
+
/** Path to the application file (usually `dist/app.js`) */
|
|
53
|
+
app: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
54
|
+
}>]>;
|
|
55
|
+
export type OpenApiConfigSchema = Static<typeof OpenApiConfigSchema>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenApiConfigSchema = void 0;
|
|
4
|
+
const http_openapi_1 = require("@rsdk/http.openapi");
|
|
5
|
+
const typebox_1 = require("@sinclair/typebox");
|
|
6
|
+
/**
|
|
7
|
+
* Configuration schema for OpenAPI document generation.
|
|
8
|
+
* @example
|
|
9
|
+
* {
|
|
10
|
+
* "out": "openapi.json",
|
|
11
|
+
* "app": "./dist/app.js",
|
|
12
|
+
* "title": "My API",
|
|
13
|
+
* "version": "1.0.0",
|
|
14
|
+
* "description": "API Description",
|
|
15
|
+
* "includeZones": ["public"],
|
|
16
|
+
* "excludeZones": ["internal"],
|
|
17
|
+
* "security": {
|
|
18
|
+
* "jwt": {
|
|
19
|
+
* "type": "http",
|
|
20
|
+
* "scheme": "bearer",
|
|
21
|
+
* "bearerFormat": "JWT",
|
|
22
|
+
* "name": "JWT Auth"
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
exports.OpenApiConfigSchema = typebox_1.Type.Intersect([
|
|
28
|
+
typebox_1.Type.Partial(http_openapi_1.OpenApiOptions),
|
|
29
|
+
typebox_1.Type.Object({
|
|
30
|
+
/** Output file path for the generated OpenAPI document */
|
|
31
|
+
out: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
32
|
+
/** Path to the application file (usually `dist/app.js`) */
|
|
33
|
+
app: typebox_1.Type.Optional(typebox_1.Type.String()),
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
36
|
+
//# sourceMappingURL=config.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.schema.js","sourceRoot":"","sources":["../../../../src/generators/openapi-json/schemas/config.schema.ts"],"names":[],"mappings":";;;AAAA,qDAAoD;AAEpD,+CAAyC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACU,QAAA,mBAAmB,GAAG,cAAI,CAAC,SAAS,CAAC;IAChD,cAAI,CAAC,OAAO,CAAC,6BAAc,CAAC;IAC5B,cAAI,CAAC,MAAM,CAAC;QACV,0DAA0D;QAC1D,GAAG,EAAE,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,MAAM,EAAE,CAAC;QAEjC,2DAA2D;QAC3D,GAAG,EAAE,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,MAAM,EAAE,CAAC;KAClC,CAAC;CACH,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './config.schema';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./config.schema"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/generators/openapi-json/schemas/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config.e2e');
|
package/jest.config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('@rsdk/jest/jest.config.unit');
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsdk/cli.cmd.autodoc",
|
|
3
|
-
"
|
|
3
|
+
"role": "library",
|
|
4
|
+
"version": "6.0.0-next.41",
|
|
4
5
|
"description": "autodoc your app!",
|
|
5
6
|
"homepage": "https://github.com/R-Vision/rsdk",
|
|
6
7
|
"license": "Apache License 2.0",
|
|
@@ -8,37 +9,29 @@
|
|
|
8
9
|
"access": "public"
|
|
9
10
|
},
|
|
10
11
|
"main": "dist/index.js",
|
|
11
|
-
"
|
|
12
|
-
"dist"
|
|
13
|
-
],
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "https://github.com/R-Vision/rsdk"
|
|
17
|
-
},
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
18
13
|
"dependencies": {
|
|
19
|
-
"@
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
14
|
+
"@rsdk/autodoc.protocol": "6.0.0-next.41",
|
|
15
|
+
"@rsdk/cli.common": "6.0.0-next.41",
|
|
16
|
+
"@rsdk/common": "6.0.0-next.41",
|
|
17
|
+
"@rsdk/common.node": "6.0.0-next.41",
|
|
18
|
+
"@rsdk/core": "6.0.0-next.41",
|
|
19
|
+
"@rsdk/http.openapi": "6.0.0-next.41",
|
|
20
|
+
"@rsdk/logging": "6.0.0-next.41",
|
|
21
|
+
"@rsdk/metadata": "6.0.0-next.41",
|
|
22
|
+
"@rsdk/nest-tools": "6.0.0-next.41",
|
|
23
|
+
"@rsdk/zones": "6.0.0-next.41"
|
|
26
24
|
},
|
|
27
25
|
"peerDependencies": {
|
|
28
|
-
"@nestjs/common": "
|
|
29
|
-
"@nestjs/core": "
|
|
26
|
+
"@nestjs/common": "<=10.4.8",
|
|
27
|
+
"@nestjs/core": "<=10.4.8",
|
|
28
|
+
"@nestjs/microservices": "<=10.4.8",
|
|
30
29
|
"@nestjs/swagger": "^7.0.0 || ^8.0.0",
|
|
31
|
-
"@
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"@rsdk/core": "*",
|
|
37
|
-
"@rsdk/logging": "*",
|
|
38
|
-
"@rsdk/metadata": "*",
|
|
39
|
-
"@rsdk/nest-tools": "*",
|
|
40
|
-
"@rsdk/zones": "*",
|
|
41
|
-
"reflect-metadata": "^0.1.12 || ^0.2.0"
|
|
30
|
+
"@sinclair/typebox": "^0.34.9",
|
|
31
|
+
"lodash": "^4.17.21",
|
|
32
|
+
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
|
33
|
+
"rxjs": "^7.8.1",
|
|
34
|
+
"type-fest": "^4.29.0"
|
|
42
35
|
},
|
|
43
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "e6e580cf9f7b89e7b236530d767db5d6429c9c6f"
|
|
44
37
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Assert } from '@rsdk/common';
|
|
2
|
+
import { Path } from '@rsdk/common.node';
|
|
3
|
+
import { PlatformApp } from '@rsdk/core';
|
|
4
|
+
import type { ILogger } from '@rsdk/logging';
|
|
5
|
+
|
|
6
|
+
export class AppLoader {
|
|
7
|
+
constructor(private readonly logger: ILogger) {}
|
|
8
|
+
|
|
9
|
+
async loadApp(
|
|
10
|
+
fullpath: string,
|
|
11
|
+
required: boolean,
|
|
12
|
+
): Promise<PlatformApp | undefined> {
|
|
13
|
+
let app: PlatformApp | undefined;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const [absolute] = Path.absolutize(fullpath);
|
|
17
|
+
const loaded = await import(absolute);
|
|
18
|
+
|
|
19
|
+
app = loaded.app as PlatformApp;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
Assert.isError(error);
|
|
22
|
+
this.logger.warn(`module by path ${fullpath} not found`);
|
|
23
|
+
|
|
24
|
+
if (!required) {
|
|
25
|
+
this.logger.info(`found --if-present, finished with exit code 0`);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.logger.error(`Error on import ${fullpath}`, error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (app instanceof PlatformApp) {
|
|
34
|
+
return app;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
throw new Error('app is not instance of PlatformApp');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ILogger } from '@rsdk/logging';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* TODO: Может быть удобная абстракция для работы с файлами.
|
|
8
|
+
* Ещё в старых загашниках надо NetworkFile поискать
|
|
9
|
+
*/
|
|
10
|
+
export type DocumentFile = {
|
|
11
|
+
name: string;
|
|
12
|
+
content: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class DocumentWriter {
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly logger: ILogger,
|
|
18
|
+
private readonly basepath: string,
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
async write(file: DocumentFile): Promise<string> {
|
|
22
|
+
const exists = existsSync(this.basepath);
|
|
23
|
+
if (!exists) {
|
|
24
|
+
await mkdir(this.basepath, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
const fullpath = path.join(this.basepath, file.name);
|
|
27
|
+
|
|
28
|
+
this.logger.info(`writing file ${file.name}...`);
|
|
29
|
+
await writeFile(fullpath, file.content);
|
|
30
|
+
this.logger.info(`file ${file.name} created!`);
|
|
31
|
+
return fullpath;
|
|
32
|
+
}
|
|
33
|
+
}
|