@application-kit/bootstrap 0.2.4 → 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.
Files changed (43) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +59 -3
  3. package/dist/cjs/consumer/consumer-bootstrap.d.ts +3 -0
  4. package/dist/cjs/consumer/consumer-bootstrap.js +17 -0
  5. package/dist/cjs/consumer/consumer-process.environment.d.ts +3 -0
  6. package/dist/cjs/consumer/consumer-process.environment.js +27 -0
  7. package/dist/cjs/consumer/index.d.ts +2 -0
  8. package/dist/cjs/consumer/index.js +18 -0
  9. package/dist/cjs/swagger/index.d.ts +3 -0
  10. package/dist/cjs/swagger/index.js +19 -0
  11. package/dist/cjs/swagger/setup-swagger.d.ts +3 -0
  12. package/dist/cjs/swagger/setup-swagger.js +25 -0
  13. package/dist/cjs/swagger/swagger-options.interface.d.ts +6 -0
  14. package/dist/cjs/swagger/swagger-options.interface.js +2 -0
  15. package/dist/cjs/swagger/swagger.environment.d.ts +3 -0
  16. package/dist/cjs/swagger/swagger.environment.js +25 -0
  17. package/dist/cjs/web/index.d.ts +2 -0
  18. package/dist/cjs/web/index.js +2 -0
  19. package/dist/cjs/web/web-bootstrap.d.ts +4 -0
  20. package/dist/cjs/web/web-bootstrap.js +20 -0
  21. package/dist/cjs/web/web-process.environment.d.ts +4 -0
  22. package/dist/cjs/web/web-process.environment.js +35 -0
  23. package/dist/esm/consumer/consumer-bootstrap.d.ts +3 -0
  24. package/dist/esm/consumer/consumer-bootstrap.js +10 -0
  25. package/dist/esm/consumer/consumer-process.environment.d.ts +3 -0
  26. package/dist/esm/consumer/consumer-process.environment.js +23 -0
  27. package/dist/esm/consumer/index.d.ts +2 -0
  28. package/dist/esm/consumer/index.js +2 -0
  29. package/dist/esm/swagger/index.d.ts +3 -0
  30. package/dist/esm/swagger/index.js +3 -0
  31. package/dist/esm/swagger/setup-swagger.d.ts +3 -0
  32. package/dist/esm/swagger/setup-swagger.js +18 -0
  33. package/dist/esm/swagger/swagger-options.interface.d.ts +6 -0
  34. package/dist/esm/swagger/swagger-options.interface.js +1 -0
  35. package/dist/esm/swagger/swagger.environment.d.ts +3 -0
  36. package/dist/esm/swagger/swagger.environment.js +21 -0
  37. package/dist/esm/web/index.d.ts +2 -0
  38. package/dist/esm/web/index.js +2 -0
  39. package/dist/esm/web/web-bootstrap.d.ts +4 -0
  40. package/dist/esm/web/web-bootstrap.js +13 -0
  41. package/dist/esm/web/web-process.environment.d.ts +4 -0
  42. package/dist/esm/web/web-process.environment.js +31 -0
  43. package/package.json +35 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
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
+
10
+ ## 0.3.0
11
+
12
+ ### Minor Changes
13
+
14
+ - c9f24d0: Процессы запускаются целиком из пакета, а переменные контракта чарта валидируются на старте:
15
+
16
+ - `webBootstrap(rootModule, options)` из `/web` читает `PORT` (по умолчанию 3000) и `TRUST_PROXY_HOPS` (по умолчанию 0), создаёт приложение через `createFastifyApplication`, слушает `0.0.0.0` и возвращает приложение;
17
+ - новый вход `/consumer`: `consumerBootstrap(rootModule, server)` читает `METRICS_PORT` (по умолчанию 3001), поднимает сервер `/metrics` и передаёт корневой модуль транспорту `server` (например `kafkaConsumerServer` из `@application-kit/kafka`) вместе с логгером `nestjs-pino`.
18
+
19
+ Значение, которое не является целым числом в допустимом диапазоне (`abc`, `-1`, `1.5`, порт больше 65535), роняет старт ошибкой `ClassValidationError` с именем переменной ещё до создания приложения. Раньше `Number('abc')` давал `NaN`, и доверенных прокси становилось молча ноль.
20
+
21
+ Для этих входов нужен peer `@libs-for-dev/nestjs-config-module` ^3.0.0 рядом с `class-transformer` и `class-validator`. Потребителю `createFastifyApplication` менять ничего не нужно.
22
+
3
23
  ## 0.2.4
4
24
 
5
25
  ### Patch Changes
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # @application-kit/bootstrap
2
2
 
3
- Бутстрап процессов NestJS: web на Fastify с периметром и CLI на nestjs-console. Состав модулей, Swagger, метрики, порт и
4
- число прокси перед приложением знает приложение: пакет собирает процесс из его корневого модуля и опций.
3
+ Бутстрап процессов NestJS: web на Fastify с периметром, consumer с сервером метрик и CLI на nestjs-console. Состав
4
+ модулей, контроллеры документа Swagger и хуки метрик знает приложение: пакет собирает процесс из его корневого модуля и опций. Порт, число
5
+ прокси и порт метрик — переменные окружения контракта чарта; невалидное значение роняет старт.
5
6
 
6
7
  ## Установка
7
8
 
@@ -17,13 +18,40 @@ Peer-зависимости — `@nestjs/common`, `@nestjs/core`, `nestjs-pino`;
17
18
 
18
19
  | Вход | Для чего | Тянет |
19
20
  |------|----------|-------|
20
- | `@application-kit/bootstrap/web` | `createFastifyApplication` — web-процесс на Fastify | `@nestjs/platform-fastify`, `@fastify/cookie`, `class-validator`, `class-transformer`, `@opentelemetry/api` |
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
+ | `@application-kit/bootstrap/consumer` | `consumerBootstrap` — процесс-консьюмер без HTTP-слоя | `class-validator`, `class-transformer`, `@libs-for-dev/nestjs-config-module` |
21
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` |
22
25
 
23
26
  Корневого входа нет: web-процессу `nestjs-console` не нужен, CLI — Fastify.
24
27
 
28
+ ## Окружение
29
+
30
+ | Переменная | Процесс | По умолчанию | |
31
+ |------------|---------|--------------|---|
32
+ | `PORT` | web | `3000` | порт `listen` на `0.0.0.0` |
33
+ | `TRUST_PROXY_HOPS` | web | `0` | сколько прокси перед приложением доверенные; `0` — только сокет |
34
+ | `METRICS_PORT` | consumer | `3001` | порт отдельного сервера `/metrics` |
35
+ | `SWAGGER_ENABLED` | web | `false` | публиковать ли документ `setupSwagger`; выключают `false`, `0` и пустая строка |
36
+
37
+ Значение числовых переменных — целое не меньше 0 (порт — не больше 65535). Иное (`abc`, `1.5`, `-1`) — `ClassValidationError` с именем
38
+ переменной до создания приложения: `Number('abc')` дал бы `NaN`, и доверенных прокси молча стало бы ноль.
39
+
25
40
  ## Web
26
41
 
42
+ ```ts
43
+ import { webBootstrap } from '@application-kit/bootstrap/web'
44
+
45
+ void webBootstrap(AppModule, {
46
+ configure: (app) => {
47
+ setupMetricsHooks(app)
48
+ },
49
+ })
50
+ ```
51
+
52
+ `webBootstrap` берёт порт и прокси из окружения, собирает приложение через `createFastifyApplication`, слушает и
53
+ возвращает его. `createFastifyApplication` — для своего запуска, когда порт и прокси приходят не из окружения:
54
+
27
55
  ```ts
28
56
  import { createFastifyApplication } from '@application-kit/bootstrap/web'
29
57
 
@@ -56,6 +84,34 @@ await app.listen(port, '0.0.0.0')
56
84
  | `cookie` | `{}` | опции `@fastify/cookie`; `false` — плагин не регистрируется |
57
85
  | `configure` | — | `(app) => void`, зовётся после хука request-id, до интерцептора и пайпа |
58
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
+
103
+ ## Consumer
104
+
105
+ ```ts
106
+ import { consumerBootstrap } from '@application-kit/bootstrap/consumer'
107
+ import { kafkaConsumerServer } from '@application-kit/kafka'
108
+
109
+ void consumerBootstrap(ConsumerModule, kafkaConsumerServer)
110
+ ```
111
+
112
+ Сервер `/metrics` поднимается на `METRICS_PORT` со своим реестром метрик процесса, затем корневой модуль уходит
113
+ транспорту вместе с логгером `nestjs-pino`. Транспорт передаёт приложение: от брокера пакет не зависит.
114
+
59
115
  ## CLI
60
116
 
61
117
  ```ts
@@ -0,0 +1,3 @@
1
+ import type { DynamicModule, Type } from '@nestjs/common';
2
+ export type ConsumerServerType = (rootModule: DynamicModule | Type, loggerModule: Type) => Promise<void>;
3
+ export declare const consumerBootstrap: (rootModule: Type, server: ConsumerServerType) => Promise<void>;
@@ -0,0 +1,17 @@
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.consumerBootstrap = void 0;
7
+ const metrics_1 = require("@application-kit/observability/metrics");
8
+ const nestjs_config_module_1 = require("@libs-for-dev/nestjs-config-module");
9
+ const nestjs_pino_1 = require("nestjs-pino");
10
+ const node_process_1 = __importDefault(require("node:process"));
11
+ const consumer_process_environment_js_1 = require("./consumer-process.environment.js");
12
+ const consumerBootstrap = async (rootModule, server) => {
13
+ const environment = (0, nestjs_config_module_1.exposeObjectWithValidation)(node_process_1.default.env, consumer_process_environment_js_1.ConsumerProcessEnvironment);
14
+ (0, metrics_1.startMetricsServer)({ port: environment.METRICS_PORT, registry: new metrics_1.MetricsRegistry() });
15
+ await server(rootModule, nestjs_pino_1.Logger);
16
+ };
17
+ exports.consumerBootstrap = consumerBootstrap;
@@ -0,0 +1,3 @@
1
+ export declare class ConsumerProcessEnvironment {
2
+ METRICS_PORT: number;
3
+ }
@@ -0,0 +1,27 @@
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.ConsumerProcessEnvironment = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ const MAX_PORT = 65_535;
16
+ class ConsumerProcessEnvironment {
17
+ METRICS_PORT = 3001;
18
+ }
19
+ exports.ConsumerProcessEnvironment = ConsumerProcessEnvironment;
20
+ __decorate([
21
+ (0, class_transformer_1.Expose)(),
22
+ (0, class_validator_1.IsInt)(),
23
+ (0, class_validator_1.Max)(MAX_PORT),
24
+ (0, class_validator_1.Min)(0),
25
+ (0, class_transformer_1.Type)(() => Number),
26
+ __metadata("design:type", Object)
27
+ ], ConsumerProcessEnvironment.prototype, "METRICS_PORT", void 0);
@@ -0,0 +1,2 @@
1
+ export * from './consumer-bootstrap.js';
2
+ export * from './consumer-process.environment.js';
@@ -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("./consumer-bootstrap.js"), exports);
18
+ __exportStar(require("./consumer-process.environment.js"), exports);
@@ -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);
@@ -1,2 +1,4 @@
1
1
  export * from './create-fastify-application.js';
2
2
  export * from './fastify-application-options.interface.js';
3
+ export * from './web-bootstrap.js';
4
+ export * from './web-process.environment.js';
@@ -16,3 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./create-fastify-application.js"), exports);
18
18
  __exportStar(require("./fastify-application-options.interface.js"), exports);
19
+ __exportStar(require("./web-bootstrap.js"), exports);
20
+ __exportStar(require("./web-process.environment.js"), exports);
@@ -0,0 +1,4 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import type { NestFastifyApplication } from '@nestjs/platform-fastify';
3
+ import type { FastifyApplicationOptionsInterface } from './fastify-application-options.interface.js';
4
+ export declare const webBootstrap: (rootModule: Type, options?: Omit<FastifyApplicationOptionsInterface, "trustProxyHops">) => Promise<NestFastifyApplication>;
@@ -0,0 +1,20 @@
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.webBootstrap = void 0;
7
+ const nestjs_config_module_1 = require("@libs-for-dev/nestjs-config-module");
8
+ const nestjs_pino_1 = require("nestjs-pino");
9
+ const node_process_1 = __importDefault(require("node:process"));
10
+ const create_fastify_application_js_1 = require("./create-fastify-application.js");
11
+ const web_process_environment_js_1 = require("./web-process.environment.js");
12
+ const LISTEN_HOST = '0.0.0.0';
13
+ const webBootstrap = async (rootModule, options = {}) => {
14
+ const environment = (0, nestjs_config_module_1.exposeObjectWithValidation)(node_process_1.default.env, web_process_environment_js_1.WebProcessEnvironment);
15
+ const app = await (0, create_fastify_application_js_1.createFastifyApplication)(rootModule, { ...options, trustProxyHops: environment.TRUST_PROXY_HOPS });
16
+ await app.listen(environment.PORT, LISTEN_HOST);
17
+ app.get(nestjs_pino_1.Logger).log(`Application is running on port "${environment.PORT}"`);
18
+ return app;
19
+ };
20
+ exports.webBootstrap = webBootstrap;
@@ -0,0 +1,4 @@
1
+ export declare class WebProcessEnvironment {
2
+ PORT: number;
3
+ TRUST_PROXY_HOPS: number;
4
+ }
@@ -0,0 +1,35 @@
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.WebProcessEnvironment = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ const MAX_PORT = 65_535;
16
+ class WebProcessEnvironment {
17
+ PORT = 3000;
18
+ TRUST_PROXY_HOPS = 0;
19
+ }
20
+ exports.WebProcessEnvironment = WebProcessEnvironment;
21
+ __decorate([
22
+ (0, class_transformer_1.Expose)(),
23
+ (0, class_validator_1.IsInt)(),
24
+ (0, class_validator_1.Max)(MAX_PORT),
25
+ (0, class_validator_1.Min)(0),
26
+ (0, class_transformer_1.Type)(() => Number),
27
+ __metadata("design:type", Object)
28
+ ], WebProcessEnvironment.prototype, "PORT", void 0);
29
+ __decorate([
30
+ (0, class_transformer_1.Expose)(),
31
+ (0, class_validator_1.IsInt)(),
32
+ (0, class_validator_1.Min)(0),
33
+ (0, class_transformer_1.Type)(() => Number),
34
+ __metadata("design:type", Object)
35
+ ], WebProcessEnvironment.prototype, "TRUST_PROXY_HOPS", void 0);
@@ -0,0 +1,3 @@
1
+ import type { DynamicModule, Type } from '@nestjs/common';
2
+ export type ConsumerServerType = (rootModule: DynamicModule | Type, loggerModule: Type) => Promise<void>;
3
+ export declare const consumerBootstrap: (rootModule: Type, server: ConsumerServerType) => Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { MetricsRegistry, startMetricsServer } from '@application-kit/observability/metrics';
2
+ import { exposeObjectWithValidation } from '@libs-for-dev/nestjs-config-module';
3
+ import { Logger } from 'nestjs-pino';
4
+ import process from 'node:process';
5
+ import { ConsumerProcessEnvironment } from './consumer-process.environment.js';
6
+ export const consumerBootstrap = async (rootModule, server) => {
7
+ const environment = exposeObjectWithValidation(process.env, ConsumerProcessEnvironment);
8
+ startMetricsServer({ port: environment.METRICS_PORT, registry: new MetricsRegistry() });
9
+ await server(rootModule, Logger);
10
+ };
@@ -0,0 +1,3 @@
1
+ export declare class ConsumerProcessEnvironment {
2
+ METRICS_PORT: number;
3
+ }
@@ -0,0 +1,23 @@
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 { Expose, Type } from 'class-transformer';
11
+ import { IsInt, Max, Min } from 'class-validator';
12
+ const MAX_PORT = 65_535;
13
+ export class ConsumerProcessEnvironment {
14
+ METRICS_PORT = 3001;
15
+ }
16
+ __decorate([
17
+ Expose(),
18
+ IsInt(),
19
+ Max(MAX_PORT),
20
+ Min(0),
21
+ Type(() => Number),
22
+ __metadata("design:type", Object)
23
+ ], ConsumerProcessEnvironment.prototype, "METRICS_PORT", void 0);
@@ -0,0 +1,2 @@
1
+ export * from './consumer-bootstrap.js';
2
+ export * from './consumer-process.environment.js';
@@ -0,0 +1,2 @@
1
+ export * from './consumer-bootstrap.js';
2
+ export * from './consumer-process.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
+ 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);
@@ -1,2 +1,4 @@
1
1
  export * from './create-fastify-application.js';
2
2
  export * from './fastify-application-options.interface.js';
3
+ export * from './web-bootstrap.js';
4
+ export * from './web-process.environment.js';
@@ -1,2 +1,4 @@
1
1
  export * from './create-fastify-application.js';
2
2
  export * from './fastify-application-options.interface.js';
3
+ export * from './web-bootstrap.js';
4
+ export * from './web-process.environment.js';
@@ -0,0 +1,4 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import type { NestFastifyApplication } from '@nestjs/platform-fastify';
3
+ import type { FastifyApplicationOptionsInterface } from './fastify-application-options.interface.js';
4
+ export declare const webBootstrap: (rootModule: Type, options?: Omit<FastifyApplicationOptionsInterface, "trustProxyHops">) => Promise<NestFastifyApplication>;
@@ -0,0 +1,13 @@
1
+ import { exposeObjectWithValidation } from '@libs-for-dev/nestjs-config-module';
2
+ import { Logger } from 'nestjs-pino';
3
+ import process from 'node:process';
4
+ import { createFastifyApplication } from './create-fastify-application.js';
5
+ import { WebProcessEnvironment } from './web-process.environment.js';
6
+ const LISTEN_HOST = '0.0.0.0';
7
+ export const webBootstrap = async (rootModule, options = {}) => {
8
+ const environment = exposeObjectWithValidation(process.env, WebProcessEnvironment);
9
+ const app = await createFastifyApplication(rootModule, { ...options, trustProxyHops: environment.TRUST_PROXY_HOPS });
10
+ await app.listen(environment.PORT, LISTEN_HOST);
11
+ app.get(Logger).log(`Application is running on port "${environment.PORT}"`);
12
+ return app;
13
+ };
@@ -0,0 +1,4 @@
1
+ export declare class WebProcessEnvironment {
2
+ PORT: number;
3
+ TRUST_PROXY_HOPS: number;
4
+ }
@@ -0,0 +1,31 @@
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 { Expose, Type } from 'class-transformer';
11
+ import { IsInt, Max, Min } from 'class-validator';
12
+ const MAX_PORT = 65_535;
13
+ export class WebProcessEnvironment {
14
+ PORT = 3000;
15
+ TRUST_PROXY_HOPS = 0;
16
+ }
17
+ __decorate([
18
+ Expose(),
19
+ IsInt(),
20
+ Max(MAX_PORT),
21
+ Min(0),
22
+ Type(() => Number),
23
+ __metadata("design:type", Object)
24
+ ], WebProcessEnvironment.prototype, "PORT", void 0);
25
+ __decorate([
26
+ Expose(),
27
+ IsInt(),
28
+ Min(0),
29
+ Type(() => Number),
30
+ __metadata("design:type", Object)
31
+ ], WebProcessEnvironment.prototype, "TRUST_PROXY_HOPS", void 0);
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@application-kit/bootstrap",
3
- "version": "0.2.4",
4
- "description": "Бутстрап процессов NestJS: web на Fastify с периметром (доверенные прокси по хопам, request-id в каждом ответе, cookie, ValidationPipe с плоским списком ошибок, graceful shutdown) и CLI на nestjs-console с логгером pino",
3
+ "version": "0.4.0",
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",
@@ -32,7 +33,27 @@
32
33
  "default": "./dist/cjs/cli/index.js"
33
34
  }
34
35
  },
36
+ "./consumer": {
37
+ "import": {
38
+ "types": "./dist/esm/consumer/index.d.ts",
39
+ "default": "./dist/esm/consumer/index.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/cjs/consumer/index.d.ts",
43
+ "default": "./dist/cjs/consumer/index.js"
44
+ }
45
+ },
35
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
+ },
36
57
  "./web": {
37
58
  "import": {
38
59
  "types": "./dist/esm/web/index.d.ts",
@@ -51,7 +72,7 @@
51
72
  "dist"
52
73
  ],
53
74
  "scripts": {
54
- "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src/cli && 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",
55
76
  "lint:tsc": "tsc --noEmit --pretty --project .",
56
77
  "test:mutation": "stryker run",
57
78
  "test:unit": "vitest run"
@@ -61,9 +82,11 @@
61
82
  },
62
83
  "devDependencies": {
63
84
  "@fastify/cookie": "^11.1.3",
85
+ "@libs-for-dev/nestjs-config-module": "3.0.0",
64
86
  "@nestjs/common": "^11.2.7",
65
87
  "@nestjs/core": "^11.2.7",
66
88
  "@nestjs/platform-fastify": "^11.2.7",
89
+ "@nestjs/swagger": "^11.4.8",
67
90
  "@opentelemetry/api": "^1.9.1",
68
91
  "@stryker-mutator/core": "^10.0.0",
69
92
  "@stryker-mutator/vitest-runner": "^10.0.0",
@@ -81,9 +104,11 @@
81
104
  },
82
105
  "peerDependencies": {
83
106
  "@fastify/cookie": "^11.0.0",
107
+ "@libs-for-dev/nestjs-config-module": "^3.0.0",
84
108
  "@nestjs/common": "^11.0.0",
85
109
  "@nestjs/core": "^11.0.0",
86
110
  "@nestjs/platform-fastify": "^11.0.0",
111
+ "@nestjs/swagger": "^11.0.0 || ^12.0.0",
87
112
  "@opentelemetry/api": "^1.9.0",
88
113
  "class-transformer": "^0.5.1",
89
114
  "class-validator": "^0.15.1",
@@ -94,9 +119,15 @@
94
119
  "@fastify/cookie": {
95
120
  "optional": true
96
121
  },
122
+ "@libs-for-dev/nestjs-config-module": {
123
+ "optional": true
124
+ },
97
125
  "@nestjs/platform-fastify": {
98
126
  "optional": true
99
127
  },
128
+ "@nestjs/swagger": {
129
+ "optional": true
130
+ },
100
131
  "@opentelemetry/api": {
101
132
  "optional": true
102
133
  },