@application-kit/bootstrap 0.3.0 → 0.4.0

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @application-kit/bootstrap
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9ee9bfa: Вход `@application-kit/bootstrap/swagger`: `setupSwagger(app, { include, path?, version? })` публикует документ OpenAPI,
8
+ только если `SWAGGER_ENABLED` включён явно. `@nestjs/swagger` — optional peer, его тянет только этот вход.
9
+
3
10
  ## 0.3.0
4
11
 
5
12
  ### Minor Changes
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @application-kit/bootstrap
2
2
 
3
3
  Бутстрап процессов NestJS: web на Fastify с периметром, consumer с сервером метрик и CLI на nestjs-console. Состав
4
- модулей, Swagger и хуки метрик знает приложение: пакет собирает процесс из его корневого модуля и опций. Порт, число
4
+ модулей, контроллеры документа Swagger и хуки метрик знает приложение: пакет собирает процесс из его корневого модуля и опций. Порт, число
5
5
  прокси и порт метрик — переменные окружения контракта чарта; невалидное значение роняет старт.
6
6
 
7
7
  ## Установка
@@ -21,6 +21,7 @@ Peer-зависимости — `@nestjs/common`, `@nestjs/core`, `nestjs-pino`;
21
21
  | `@application-kit/bootstrap/web` | `webBootstrap`, `createFastifyApplication` — web-процесс на Fastify | `@nestjs/platform-fastify`, `@fastify/cookie`, `class-validator`, `class-transformer`, `@opentelemetry/api`, `@libs-for-dev/nestjs-config-module` |
22
22
  | `@application-kit/bootstrap/consumer` | `consumerBootstrap` — процесс-консьюмер без HTTP-слоя | `class-validator`, `class-transformer`, `@libs-for-dev/nestjs-config-module` |
23
23
  | `@application-kit/bootstrap/cli` | `cliBootstrap` — CLI-процесс | `nestjs-console` |
24
+ | `@application-kit/bootstrap/swagger` | `setupSwagger` — документ OpenAPI web-процесса по выключателю | `@nestjs/swagger`, `class-validator`, `class-transformer`, `@libs-for-dev/nestjs-config-module` |
24
25
 
25
26
  Корневого входа нет: web-процессу `nestjs-console` не нужен, CLI — Fastify.
26
27
 
@@ -31,8 +32,9 @@ Peer-зависимости — `@nestjs/common`, `@nestjs/core`, `nestjs-pino`;
31
32
  | `PORT` | web | `3000` | порт `listen` на `0.0.0.0` |
32
33
  | `TRUST_PROXY_HOPS` | web | `0` | сколько прокси перед приложением доверенные; `0` — только сокет |
33
34
  | `METRICS_PORT` | consumer | `3001` | порт отдельного сервера `/metrics` |
35
+ | `SWAGGER_ENABLED` | web | `false` | публиковать ли документ `setupSwagger`; выключают `false`, `0` и пустая строка |
34
36
 
35
- Значение — целое не меньше 0 (порт — не больше 65535). Иное (`abc`, `1.5`, `-1`) — `ClassValidationError` с именем
37
+ Значение числовых переменных — целое не меньше 0 (порт — не больше 65535). Иное (`abc`, `1.5`, `-1`) — `ClassValidationError` с именем
36
38
  переменной до создания приложения: `Number('abc')` дал бы `NaN`, и доверенных прокси молча стало бы ноль.
37
39
 
38
40
  ## Web
@@ -82,6 +84,22 @@ await app.listen(port, '0.0.0.0')
82
84
  | `cookie` | `{}` | опции `@fastify/cookie`; `false` — плагин не регистрируется |
83
85
  | `configure` | — | `(app) => void`, зовётся после хука request-id, до интерцептора и пайпа |
84
86
 
87
+ ## Swagger
88
+
89
+ ```ts
90
+ import { setupSwagger } from '@application-kit/bootstrap/swagger'
91
+
92
+ const options = {
93
+ configure: (app) => {
94
+ setupSwagger(app, { include: [HealthHttpModule, MetricsHttpModule] })
95
+ },
96
+ } satisfies FastifyApplicationOptionsInterface
97
+ ```
98
+
99
+ Документ описывает всю серверную поверхность и аутентификации не требует, поэтому без `SWAGGER_ENABLED` он не
100
+ публикуется. В документ попадают контроллеры модулей из `include`, `operationId` — имя метода. UI отдаётся по `path`
101
+ (по умолчанию `swagger`), JSON — по `<path>-json`, версия в `info` — `version` (по умолчанию `1.0`).
102
+
85
103
  ## Consumer
86
104
 
87
105
  ```ts
@@ -0,0 +1,3 @@
1
+ export * from './setup-swagger.js';
2
+ export * from './swagger-options.interface.js';
3
+ export * from './swagger.environment.js';
@@ -0,0 +1,19 @@
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("./setup-swagger.js"), exports);
18
+ __exportStar(require("./swagger-options.interface.js"), exports);
19
+ __exportStar(require("./swagger.environment.js"), exports);
@@ -0,0 +1,3 @@
1
+ import type { INestApplication } from '@nestjs/common';
2
+ import type { SwaggerOptionsInterface } from './swagger-options.interface.js';
3
+ export declare const setupSwagger: (app: INestApplication, options: SwaggerOptionsInterface) => void;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupSwagger = void 0;
7
+ const nestjs_config_module_1 = require("@libs-for-dev/nestjs-config-module");
8
+ const swagger_1 = require("@nestjs/swagger");
9
+ const node_process_1 = __importDefault(require("node:process"));
10
+ const swagger_environment_js_1 = require("./swagger.environment.js");
11
+ const DEFAULT_PATH = 'swagger';
12
+ const DEFAULT_VERSION = '1.0';
13
+ const setupSwagger = (app, options) => {
14
+ const environment = (0, nestjs_config_module_1.exposeObjectWithValidation)(node_process_1.default.env, swagger_environment_js_1.SwaggerEnvironment);
15
+ if (!environment.SWAGGER_ENABLED) {
16
+ return;
17
+ }
18
+ const document = swagger_1.SwaggerModule.createDocument(app, new swagger_1.DocumentBuilder().setVersion(options.version ?? DEFAULT_VERSION)
19
+ .build(), {
20
+ include: options.include,
21
+ operationIdFactory: (_controllerKey, methodKey) => methodKey,
22
+ });
23
+ swagger_1.SwaggerModule.setup(options.path ?? DEFAULT_PATH, app, document);
24
+ };
25
+ exports.setupSwagger = setupSwagger;
@@ -0,0 +1,6 @@
1
+ import type { Type } from '@nestjs/common';
2
+ export interface SwaggerOptionsInterface {
3
+ include: Type[];
4
+ path?: string;
5
+ version?: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export declare class SwaggerEnvironment {
2
+ SWAGGER_ENABLED: boolean;
3
+ }
@@ -0,0 +1,25 @@
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
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SwaggerEnvironment = void 0;
13
+ const nestjs_config_module_1 = require("@libs-for-dev/nestjs-config-module");
14
+ const class_transformer_1 = require("class-transformer");
15
+ const class_validator_1 = require("class-validator");
16
+ class SwaggerEnvironment {
17
+ SWAGGER_ENABLED = false;
18
+ }
19
+ exports.SwaggerEnvironment = SwaggerEnvironment;
20
+ __decorate([
21
+ (0, class_transformer_1.Expose)(),
22
+ (0, class_validator_1.IsBoolean)(),
23
+ (0, nestjs_config_module_1.ParseBoolean)(),
24
+ __metadata("design:type", Object)
25
+ ], SwaggerEnvironment.prototype, "SWAGGER_ENABLED", void 0);
@@ -0,0 +1,3 @@
1
+ export * from './setup-swagger.js';
2
+ export * from './swagger-options.interface.js';
3
+ export * from './swagger.environment.js';
@@ -0,0 +1,3 @@
1
+ export * from './setup-swagger.js';
2
+ export * from './swagger-options.interface.js';
3
+ export * from './swagger.environment.js';
@@ -0,0 +1,3 @@
1
+ import type { INestApplication } from '@nestjs/common';
2
+ import type { SwaggerOptionsInterface } from './swagger-options.interface.js';
3
+ export declare const setupSwagger: (app: INestApplication, options: SwaggerOptionsInterface) => void;
@@ -0,0 +1,18 @@
1
+ import { exposeObjectWithValidation } from '@libs-for-dev/nestjs-config-module';
2
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
3
+ import process from 'node:process';
4
+ import { SwaggerEnvironment } from './swagger.environment.js';
5
+ const DEFAULT_PATH = 'swagger';
6
+ const DEFAULT_VERSION = '1.0';
7
+ export const setupSwagger = (app, options) => {
8
+ const environment = exposeObjectWithValidation(process.env, SwaggerEnvironment);
9
+ if (!environment.SWAGGER_ENABLED) {
10
+ return;
11
+ }
12
+ const document = SwaggerModule.createDocument(app, new DocumentBuilder().setVersion(options.version ?? DEFAULT_VERSION)
13
+ .build(), {
14
+ include: options.include,
15
+ operationIdFactory: (_controllerKey, methodKey) => methodKey,
16
+ });
17
+ SwaggerModule.setup(options.path ?? DEFAULT_PATH, app, document);
18
+ };
@@ -0,0 +1,6 @@
1
+ import type { Type } from '@nestjs/common';
2
+ export interface SwaggerOptionsInterface {
3
+ include: Type[];
4
+ path?: string;
5
+ version?: string;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare class SwaggerEnvironment {
2
+ SWAGGER_ENABLED: boolean;
3
+ }
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { ParseBoolean } from '@libs-for-dev/nestjs-config-module';
11
+ import { Expose } from 'class-transformer';
12
+ import { IsBoolean } from 'class-validator';
13
+ export class SwaggerEnvironment {
14
+ SWAGGER_ENABLED = false;
15
+ }
16
+ __decorate([
17
+ Expose(),
18
+ IsBoolean(),
19
+ ParseBoolean(),
20
+ __metadata("design:type", Object)
21
+ ], SwaggerEnvironment.prototype, "SWAGGER_ENABLED", void 0);
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@application-kit/bootstrap",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Бутстрап процессов NestJS: web на Fastify с периметром (доверенные прокси по хопам, request-id в каждом ответе, cookie, ValidationPipe с плоским списком ошибок, graceful shutdown), consumer с сервером метрик, CLI на nestjs-console с логгером pino; порты и прокси — из валидированного окружения",
5
5
  "keywords": [
6
6
  "bootstrap",
7
7
  "fastify",
8
8
  "nestjs",
9
- "nestjs-console"
9
+ "nestjs-console",
10
+ "swagger"
10
11
  ],
11
12
  "homepage": "https://gitlab.com/application-kit/application-kit/-/tree/main/packages/bootstrap",
12
13
  "bugs": "https://gitlab.com/application-kit/application-kit/-/issues",
@@ -43,6 +44,16 @@
43
44
  }
44
45
  },
45
46
  "./package.json": "./package.json",
47
+ "./swagger": {
48
+ "import": {
49
+ "types": "./dist/esm/swagger/index.d.ts",
50
+ "default": "./dist/esm/swagger/index.js"
51
+ },
52
+ "require": {
53
+ "types": "./dist/cjs/swagger/index.d.ts",
54
+ "default": "./dist/cjs/swagger/index.js"
55
+ }
56
+ },
46
57
  "./web": {
47
58
  "import": {
48
59
  "types": "./dist/esm/web/index.d.ts",
@@ -61,7 +72,7 @@
61
72
  "dist"
62
73
  ],
63
74
  "scripts": {
64
- "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src/cli && node ../../scripts/barrels.mjs create ./src/consumer && node ../../scripts/barrels.mjs create ./src/web && tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json && node ../../scripts/barrels.mjs clean ./src && node ../../scripts/mark-cjs.mjs ./dist/cjs",
75
+ "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src/cli && node ../../scripts/barrels.mjs create ./src/consumer && node ../../scripts/barrels.mjs create ./src/swagger && node ../../scripts/barrels.mjs create ./src/web && tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json && node ../../scripts/barrels.mjs clean ./src && node ../../scripts/mark-cjs.mjs ./dist/cjs",
65
76
  "lint:tsc": "tsc --noEmit --pretty --project .",
66
77
  "test:mutation": "stryker run",
67
78
  "test:unit": "vitest run"
@@ -75,6 +86,7 @@
75
86
  "@nestjs/common": "^11.2.7",
76
87
  "@nestjs/core": "^11.2.7",
77
88
  "@nestjs/platform-fastify": "^11.2.7",
89
+ "@nestjs/swagger": "^11.4.8",
78
90
  "@opentelemetry/api": "^1.9.1",
79
91
  "@stryker-mutator/core": "^10.0.0",
80
92
  "@stryker-mutator/vitest-runner": "^10.0.0",
@@ -96,6 +108,7 @@
96
108
  "@nestjs/common": "^11.0.0",
97
109
  "@nestjs/core": "^11.0.0",
98
110
  "@nestjs/platform-fastify": "^11.0.0",
111
+ "@nestjs/swagger": "^11.0.0 || ^12.0.0",
99
112
  "@opentelemetry/api": "^1.9.0",
100
113
  "class-transformer": "^0.5.1",
101
114
  "class-validator": "^0.15.1",
@@ -112,6 +125,9 @@
112
125
  "@nestjs/platform-fastify": {
113
126
  "optional": true
114
127
  },
128
+ "@nestjs/swagger": {
129
+ "optional": true
130
+ },
115
131
  "@opentelemetry/api": {
116
132
  "optional": true
117
133
  },