@application-kit/feature-flags 0.2.0 → 0.3.1

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,17 @@
1
1
  # @application-kit/feature-flags
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8e10f98: Peer-зависимости принимают Nest 12, `@nestjs/graphql` и `@nestjs/mercurius` 14, `@nestjs/cqrs` 12 и `nestjs-pino` 5. `PinoLoggerConfig` задаёт `forRoutes` явно: с маршрутом nestjs-pino 5 по умолчанию запросы на Fastify не логировались.
8
+
9
+ ## 0.3.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 1032c06: Вход `/nest`: `FeatureFlagsRootModule.forRoot(featureFlags)` разбирает окружение и глобально отдаёт порт `FEATURE_FLAGS`. Класс окружения и конфиг-адаптер в приложении больше не нужны; отказы на неверном `FEATURE_*` прежние. Новый необязательный peer `@nestjs/common` — только для этого входа.
14
+
3
15
  ## 0.2.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -18,18 +18,18 @@ yarn add @application-kit/feature-flags @libs-for-dev/nestjs-config-module
18
18
  ```
19
19
 
20
20
  Peer: `@libs-for-dev/nestjs-config-module` (подпуть `/parse-boolean` — разбор булевых переменных, без
21
- зависимостей); `vue` — только для входа `/vue`.
21
+ зависимостей); `vue` — только для входа `/vue`, `@nestjs/common` — только для входа `/nest`.
22
22
 
23
23
  ## Входы
24
24
 
25
25
  | Вход | Что внутри | Зависимости |
26
26
  |---|---|---|
27
27
  | `@application-kit/feature-flags` | `defineFeatureFlags`, реестр `FeatureFlagRegistryInterface`, порт `FeatureFlagsInterface`, токен `FEATURE_FLAGS`, адаптер `EnvironmentFeatureFlags`, ошибки | изоморфно, без Nest и DOM |
28
+ | `@application-kit/feature-flags/nest` | `FeatureFlagsRootModule` | `@nestjs/common` |
28
29
  | `@application-kit/feature-flags/vue` | `useFeatureFlag`, ключ `FEATURE_FLAG_STATE`, `parseFeatureFlagState`, `createFeatureFlagChannel` | `vue` |
29
30
  | `@application-kit/feature-flags/testing` | `FakeFeatureFlags` | — |
30
31
 
31
- Корень грузится и в клиентском бандле (набор нужен разбору SSR-состояния), поэтому связки с Nest в пакете нет:
32
- класс окружения и регистрацию адаптера под токеном делает приложение (пример ниже).
32
+ Корень грузится и в клиентском бандле (набор нужен разбору SSR-состояния), поэтому связка с Nest — отдельный вход.
33
33
 
34
34
  ## Набор флагов
35
35
 
@@ -75,35 +75,21 @@ export const featureFlags = defineFeatureFlags({
75
75
  проверки собирают полный список до броска, чтобы отказ назвал все проблемы разом; незнакомая переменная
76
76
  проверяется первой — опечатка даёт сразу и лишнее имя, и недостающее.
77
77
 
78
- ### Связка с Nest (в приложении)
78
+ ### Связка с Nest
79
79
 
80
- Разбор ставится в класс окружения, чтобы отказ пришёл при сборке графа конфигов, а не на первом запросе:
80
+ Корневой модуль процесса подключает порт одной строкой:
81
81
 
82
82
  ```ts
83
- import { EnvironmentFeatureFlags } from '@application-kit/feature-flags'
83
+ import { FeatureFlagsRootModule } from '@application-kit/feature-flags/nest'
84
84
 
85
- export class FeatureFlagsEnvironment {
86
- @Expose()
87
- @IsObject()
88
- public FEATURE_FLAGS: FeatureFlagState
89
-
90
- // Конфиг-модуль конструирует класс без аргументов: переменных столько, сколько флагов, и объявлять их
91
- // по одной `@Expose()` значило бы держать вторую копию набора.
92
- public constructor(source: Record<string, unknown> = process.env) {
93
- this.FEATURE_FLAGS = featureFlags.readEnvironment(source)
94
- }
95
- }
96
-
97
- export class FeatureFlagsConfig extends EnvironmentFeatureFlags {
98
- public constructor(@Inject(FeatureFlagsEnvironment) environment: FeatureFlagsEnvironment) {
99
- super(featureFlags, environment.FEATURE_FLAGS)
100
- }
101
- }
102
-
103
- // провайдер модуля
104
- { provide: FEATURE_FLAGS, useExisting: FeatureFlagsConfig }
85
+ @Module({ imports: [FeatureFlagsRootModule.forRoot(featureFlags)] })
86
+ export class CommonModule {}
105
87
  ```
106
88
 
89
+ `forRoot` разбирает `process.env` сразу, на импорте модуля-носителя: отказ приходит до сборки графа, а не на первом
90
+ запросе. Поэтому окружение обязано быть готово до импорта: правка из `beforeAll` спеки опоздает. Модуль глобальный:
91
+ `FEATURE_FLAGS` виден всему графу без своей регистрации.
92
+
107
93
  ## Чтение на сервере
108
94
 
109
95
  Через порт по токену, а не чтением `process.env`:
@@ -0,0 +1,5 @@
1
+ import type { DynamicModule } from '@nestjs/common';
2
+ import type { FeatureFlagSetInterface } from '../define-feature-flags.js';
3
+ export declare class FeatureFlagsRootModule {
4
+ static forRoot(featureFlags: FeatureFlagSetInterface): DynamicModule;
5
+ }
@@ -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
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.FeatureFlagsRootModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const constants_js_1 = require("../constants.js");
12
+ const environment_feature_flags_js_1 = require("../environment-feature-flags.js");
13
+ let FeatureFlagsRootModule = class FeatureFlagsRootModule {
14
+ static forRoot(featureFlags) {
15
+ const state = featureFlags.readEnvironment(process.env);
16
+ return {
17
+ exports: [constants_js_1.FEATURE_FLAGS],
18
+ global: true,
19
+ module: this,
20
+ providers: [{ provide: constants_js_1.FEATURE_FLAGS, useValue: new environment_feature_flags_js_1.EnvironmentFeatureFlags(featureFlags, state) }],
21
+ };
22
+ }
23
+ };
24
+ exports.FeatureFlagsRootModule = FeatureFlagsRootModule;
25
+ exports.FeatureFlagsRootModule = FeatureFlagsRootModule = __decorate([
26
+ (0, common_1.Module)({})
27
+ ], FeatureFlagsRootModule);
@@ -0,0 +1 @@
1
+ export * from './feature-flags-root.module.js';
@@ -0,0 +1,17 @@
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("./feature-flags-root.module.js"), exports);
@@ -0,0 +1,5 @@
1
+ import type { DynamicModule } from '@nestjs/common';
2
+ import type { FeatureFlagSetInterface } from '../define-feature-flags.js';
3
+ export declare class FeatureFlagsRootModule {
4
+ static forRoot(featureFlags: FeatureFlagSetInterface): DynamicModule;
5
+ }
@@ -0,0 +1,24 @@
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
+ import { Module } from '@nestjs/common';
8
+ import { FEATURE_FLAGS } from '../constants.js';
9
+ import { EnvironmentFeatureFlags } from '../environment-feature-flags.js';
10
+ let FeatureFlagsRootModule = class FeatureFlagsRootModule {
11
+ static forRoot(featureFlags) {
12
+ const state = featureFlags.readEnvironment(process.env);
13
+ return {
14
+ exports: [FEATURE_FLAGS],
15
+ global: true,
16
+ module: this,
17
+ providers: [{ provide: FEATURE_FLAGS, useValue: new EnvironmentFeatureFlags(featureFlags, state) }],
18
+ };
19
+ }
20
+ };
21
+ FeatureFlagsRootModule = __decorate([
22
+ Module({})
23
+ ], FeatureFlagsRootModule);
24
+ export { FeatureFlagsRootModule };
@@ -0,0 +1 @@
1
+ export * from './feature-flags-root.module.js';
@@ -0,0 +1 @@
1
+ export * from './feature-flags-root.module.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@application-kit/feature-flags",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Фичефлаги из окружения: набор флагов параметром, порт с адаптером окружения, SSR-состояние для Vue и фейк для спек",
5
5
  "keywords": [
6
6
  "feature-flags",
@@ -32,6 +32,16 @@
32
32
  "default": "./dist/cjs/index.js"
33
33
  }
34
34
  },
35
+ "./nest": {
36
+ "import": {
37
+ "types": "./dist/esm/nest/index.d.ts",
38
+ "default": "./dist/esm/nest/index.js"
39
+ },
40
+ "require": {
41
+ "types": "./dist/cjs/nest/index.d.ts",
42
+ "default": "./dist/cjs/nest/index.js"
43
+ }
44
+ },
35
45
  "./package.json": "./package.json",
36
46
  "./testing": {
37
47
  "import": {
@@ -61,26 +71,32 @@
61
71
  "dist"
62
72
  ],
63
73
  "scripts": {
64
- "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src --entry-only=testing,vue && tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json && node ../../scripts/barrels.mjs clean ./src && node ../../scripts/mark-cjs.mjs ./dist/cjs",
74
+ "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src --entry-only=nest,testing,vue && 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
75
  "lint:tsc": "tsc --noEmit --pretty --project .",
66
76
  "test:mutation": "stryker run",
67
77
  "test:unit": "vitest run"
68
78
  },
69
79
  "devDependencies": {
70
80
  "@libs-for-dev/nestjs-config-module": "3.0.0",
81
+ "@nestjs/common": "^12.0.0",
82
+ "@nestjs/testing": "^12.0.0",
71
83
  "@stryker-mutator/core": "^10.0.0",
72
84
  "@stryker-mutator/vitest-runner": "^10.0.0",
73
85
  "@types/node": "^26.2.0",
74
86
  "jsdom": "^30.0.1",
75
87
  "typescript": "^6.0.3",
76
- "vitest": "^4.1.11",
88
+ "vitest": "^5.0.0",
77
89
  "vue": "^3.5.41"
78
90
  },
79
91
  "peerDependencies": {
80
92
  "@libs-for-dev/nestjs-config-module": "^3.0.0",
93
+ "@nestjs/common": "^11.0.0 || ^12.0.0",
81
94
  "vue": "^3.5.0"
82
95
  },
83
96
  "peerDependenciesMeta": {
97
+ "@nestjs/common": {
98
+ "optional": true
99
+ },
84
100
  "vue": {
85
101
  "optional": true
86
102
  }