@nestarc/feature-flag 0.1.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/dist/decorators/bypass-feature-flag.decorator.d.ts +1 -0
  4. package/dist/decorators/bypass-feature-flag.decorator.js +8 -0
  5. package/dist/decorators/bypass-feature-flag.decorator.js.map +1 -0
  6. package/dist/decorators/feature-flag.decorator.d.ts +2 -0
  7. package/dist/decorators/feature-flag.decorator.js +10 -0
  8. package/dist/decorators/feature-flag.decorator.js.map +1 -0
  9. package/dist/events/feature-flag.events.d.ts +29 -0
  10. package/dist/events/feature-flag.events.js +13 -0
  11. package/dist/events/feature-flag.events.js.map +1 -0
  12. package/dist/feature-flag.constants.d.ts +5 -0
  13. package/dist/feature-flag.constants.js +9 -0
  14. package/dist/feature-flag.constants.js.map +1 -0
  15. package/dist/feature-flag.module.d.ts +14 -0
  16. package/dist/feature-flag.module.js +132 -0
  17. package/dist/feature-flag.module.js.map +1 -0
  18. package/dist/guards/feature-flag.guard.d.ts +9 -0
  19. package/dist/guards/feature-flag.guard.js +53 -0
  20. package/dist/guards/feature-flag.guard.js.map +1 -0
  21. package/dist/index.d.ts +11 -0
  22. package/dist/index.js +26 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/interfaces/evaluation-context.interface.d.ts +8 -0
  25. package/dist/interfaces/evaluation-context.interface.js +3 -0
  26. package/dist/interfaces/evaluation-context.interface.js.map +1 -0
  27. package/dist/interfaces/feature-flag-options.interface.d.ts +27 -0
  28. package/dist/interfaces/feature-flag-options.interface.js +3 -0
  29. package/dist/interfaces/feature-flag-options.interface.js.map +1 -0
  30. package/dist/interfaces/feature-flag.interface.d.ts +45 -0
  31. package/dist/interfaces/feature-flag.interface.js +3 -0
  32. package/dist/interfaces/feature-flag.interface.js.map +1 -0
  33. package/dist/middleware/flag-context.middleware.d.ts +10 -0
  34. package/dist/middleware/flag-context.middleware.js +35 -0
  35. package/dist/middleware/flag-context.middleware.js.map +1 -0
  36. package/dist/services/feature-flag.service.d.ts +29 -0
  37. package/dist/services/feature-flag.service.js +208 -0
  38. package/dist/services/feature-flag.service.js.map +1 -0
  39. package/dist/services/flag-cache.service.d.ts +13 -0
  40. package/dist/services/flag-cache.service.js +72 -0
  41. package/dist/services/flag-cache.service.js.map +1 -0
  42. package/dist/services/flag-context.d.ts +9 -0
  43. package/dist/services/flag-context.js +26 -0
  44. package/dist/services/flag-context.js.map +1 -0
  45. package/dist/services/flag-evaluator.service.d.ts +12 -0
  46. package/dist/services/flag-evaluator.service.js +63 -0
  47. package/dist/services/flag-evaluator.service.js.map +1 -0
  48. package/dist/testing/index.d.ts +1 -0
  49. package/dist/testing/index.js +6 -0
  50. package/dist/testing/index.js.map +1 -0
  51. package/dist/testing/test-feature-flag.module.d.ts +4 -0
  52. package/dist/testing/test-feature-flag.module.js +41 -0
  53. package/dist/testing/test-feature-flag.module.js.map +1 -0
  54. package/dist/utils/hash.d.ts +6 -0
  55. package/dist/utils/hash.js +28 -0
  56. package/dist/utils/hash.js.map +1 -0
  57. package/package.json +88 -0
  58. package/prisma/migrations/20260405000000_init/migration.sql +76 -0
  59. package/prisma/migrations/migration_lock.toml +3 -0
  60. package/prisma/schema.prisma +41 -0
@@ -0,0 +1,132 @@
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 FeatureFlagModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.FeatureFlagModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const core_1 = require("@nestjs/core");
13
+ const feature_flag_constants_1 = require("./feature-flag.constants");
14
+ const feature_flag_service_1 = require("./services/feature-flag.service");
15
+ const flag_cache_service_1 = require("./services/flag-cache.service");
16
+ const flag_evaluator_service_1 = require("./services/flag-evaluator.service");
17
+ const flag_context_1 = require("./services/flag-context");
18
+ const feature_flag_guard_1 = require("./guards/feature-flag.guard");
19
+ const flag_context_middleware_1 = require("./middleware/flag-context.middleware");
20
+ const FULL_OPTIONS = Symbol('FEATURE_FLAG_FULL_OPTIONS');
21
+ const coreProviders = [
22
+ flag_cache_service_1.FlagCacheService,
23
+ flag_evaluator_service_1.FlagEvaluatorService,
24
+ flag_context_1.FlagContext,
25
+ feature_flag_guard_1.FeatureFlagGuard,
26
+ feature_flag_service_1.FeatureFlagService,
27
+ ];
28
+ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
29
+ configure(consumer) {
30
+ consumer
31
+ .apply(flag_context_middleware_1.FlagContextMiddleware)
32
+ .forRoutes({ path: '(.*)', method: common_1.RequestMethod.ALL });
33
+ }
34
+ static forRoot(options) {
35
+ const { prisma, ...moduleOptions } = options;
36
+ let eventProvider = { provide: 'EVENT_EMITTER', useValue: null };
37
+ if (options.emitEvents) {
38
+ try {
39
+ const { EventEmitter2 } = require('@nestjs/event-emitter');
40
+ eventProvider = { provide: 'EVENT_EMITTER', useExisting: EventEmitter2 };
41
+ }
42
+ catch {
43
+ /* @nestjs/event-emitter not installed */
44
+ }
45
+ }
46
+ return {
47
+ module: FeatureFlagModule_1,
48
+ global: true,
49
+ providers: [
50
+ { provide: feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS, useValue: moduleOptions },
51
+ { provide: 'PRISMA_SERVICE', useValue: prisma },
52
+ eventProvider,
53
+ ...coreProviders,
54
+ ],
55
+ exports: [feature_flag_service_1.FeatureFlagService, flag_context_1.FlagContext, feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS],
56
+ };
57
+ }
58
+ static forRootAsync(options) {
59
+ const asyncProviders = this.createAsyncProviders(options);
60
+ return {
61
+ module: FeatureFlagModule_1,
62
+ global: true,
63
+ imports: options.imports ?? [],
64
+ providers: [
65
+ ...asyncProviders,
66
+ {
67
+ provide: feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS,
68
+ useFactory: ({ prisma: _, ...moduleOptions }) => moduleOptions,
69
+ inject: [FULL_OPTIONS],
70
+ },
71
+ {
72
+ provide: 'PRISMA_SERVICE',
73
+ useFactory: (full) => full.prisma,
74
+ inject: [FULL_OPTIONS],
75
+ },
76
+ {
77
+ provide: 'EVENT_EMITTER',
78
+ useFactory: (full, moduleRef) => {
79
+ if (!full.emitEvents)
80
+ return null;
81
+ try {
82
+ const { EventEmitter2 } = require('@nestjs/event-emitter');
83
+ return moduleRef.get(EventEmitter2, { strict: false });
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ },
89
+ inject: [FULL_OPTIONS, core_1.ModuleRef],
90
+ },
91
+ ...coreProviders,
92
+ ],
93
+ exports: [feature_flag_service_1.FeatureFlagService, flag_context_1.FlagContext, feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS],
94
+ };
95
+ }
96
+ static createAsyncProviders(options) {
97
+ if (options.useFactory) {
98
+ return [
99
+ {
100
+ provide: FULL_OPTIONS,
101
+ useFactory: options.useFactory,
102
+ inject: options.inject ?? [],
103
+ },
104
+ ];
105
+ }
106
+ if (options.useClass) {
107
+ return [
108
+ { provide: options.useClass, useClass: options.useClass },
109
+ {
110
+ provide: FULL_OPTIONS,
111
+ useFactory: (factory) => factory.createFeatureFlagOptions(),
112
+ inject: [options.useClass],
113
+ },
114
+ ];
115
+ }
116
+ if (options.useExisting) {
117
+ return [
118
+ {
119
+ provide: FULL_OPTIONS,
120
+ useFactory: (factory) => factory.createFeatureFlagOptions(),
121
+ inject: [options.useExisting],
122
+ },
123
+ ];
124
+ }
125
+ return [];
126
+ }
127
+ };
128
+ exports.FeatureFlagModule = FeatureFlagModule;
129
+ exports.FeatureFlagModule = FeatureFlagModule = FeatureFlagModule_1 = __decorate([
130
+ (0, common_1.Module)({})
131
+ ], FeatureFlagModule);
132
+ //# sourceMappingURL=feature-flag.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag.module.js","sourceRoot":"","sources":["../src/feature-flag.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { CanActivate, ExecutionContext } from '@nestjs/common';
2
+ import { Reflector } from '@nestjs/core';
3
+ import { FeatureFlagService } from '../services/feature-flag.service';
4
+ export declare class FeatureFlagGuard implements CanActivate {
5
+ private readonly reflector;
6
+ private readonly featureFlagService;
7
+ constructor(reflector: Reflector, featureFlagService: FeatureFlagService);
8
+ canActivate(context: ExecutionContext): Promise<boolean>;
9
+ }
@@ -0,0 +1,53 @@
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.FeatureFlagGuard = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const core_1 = require("@nestjs/core");
15
+ const feature_flag_service_1 = require("../services/feature-flag.service");
16
+ const feature_flag_constants_1 = require("../feature-flag.constants");
17
+ let FeatureFlagGuard = class FeatureFlagGuard {
18
+ constructor(reflector, featureFlagService) {
19
+ this.reflector = reflector;
20
+ this.featureFlagService = featureFlagService;
21
+ }
22
+ async canActivate(context) {
23
+ const handler = context.getHandler();
24
+ const classRef = context.getClass();
25
+ // Check bypass
26
+ const bypass = this.reflector.get(feature_flag_constants_1.BYPASS_FEATURE_FLAG_KEY, handler) ||
27
+ this.reflector.get(feature_flag_constants_1.BYPASS_FEATURE_FLAG_KEY, classRef);
28
+ if (bypass)
29
+ return true;
30
+ // Check flag key (handler-level first, then class-level)
31
+ const flagKey = this.reflector.get(feature_flag_constants_1.FEATURE_FLAG_KEY, handler) ??
32
+ this.reflector.get(feature_flag_constants_1.FEATURE_FLAG_KEY, classRef);
33
+ if (!flagKey)
34
+ return true;
35
+ const options = this.reflector.get(feature_flag_constants_1.FEATURE_FLAG_OPTIONS_KEY, handler) ??
36
+ this.reflector.get(feature_flag_constants_1.FEATURE_FLAG_OPTIONS_KEY, classRef) ??
37
+ {};
38
+ const enabled = await this.featureFlagService.isEnabled(flagKey);
39
+ if (!enabled) {
40
+ const statusCode = options.statusCode ?? 403;
41
+ const body = options.fallback ?? { message: 'Feature not available' };
42
+ throw new common_1.HttpException(body, statusCode);
43
+ }
44
+ return true;
45
+ }
46
+ };
47
+ exports.FeatureFlagGuard = FeatureFlagGuard;
48
+ exports.FeatureFlagGuard = FeatureFlagGuard = __decorate([
49
+ (0, common_1.Injectable)(),
50
+ __metadata("design:paramtypes", [core_1.Reflector,
51
+ feature_flag_service_1.FeatureFlagService])
52
+ ], FeatureFlagGuard);
53
+ //# sourceMappingURL=feature-flag.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag.guard.js","sourceRoot":"","sources":["../../src/guards/feature-flag.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA0F;AAC1F,uCAAyC;AACzC,2EAAsE;AACtE,sEAImC;AAI5B,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YACmB,SAAoB,EACpB,kBAAsC;QADtC,cAAS,GAAT,SAAS,CAAW;QACpB,uBAAkB,GAAlB,kBAAkB,CAAoB;IACtD,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QAEpC,eAAe;QACf,MAAM,MAAM,GACV,IAAI,CAAC,SAAS,CAAC,GAAG,CAAU,gDAAuB,EAAE,OAAO,CAAC;YAC7D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAU,gDAAuB,EAAE,QAAQ,CAAC,CAAC;QACjE,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC;QAExB,yDAAyD;QACzD,MAAM,OAAO,GACX,IAAI,CAAC,SAAS,CAAC,GAAG,CAAS,yCAAgB,EAAE,OAAO,CAAC;YACrD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAS,yCAAgB,EAAE,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,OAAO,GACX,IAAI,CAAC,SAAS,CAAC,GAAG,CAA0B,iDAAwB,EAAE,OAAO,CAAC;YAC9E,IAAI,CAAC,SAAS,CAAC,GAAG,CAA0B,iDAAwB,EAAE,QAAQ,CAAC;YAC/E,EAAE,CAAC;QAEL,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAEjE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC;YAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;YACtE,MAAM,IAAI,sBAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AArCY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;qCAGmB,gBAAS;QACA,yCAAkB;GAH9C,gBAAgB,CAqC5B"}
@@ -0,0 +1,11 @@
1
+ export { FeatureFlagModule, FeatureFlagModuleRootOptions, FeatureFlagModuleRootAsyncOptions } from './feature-flag.module';
2
+ export { FeatureFlagService } from './services/feature-flag.service';
3
+ export { FlagContext } from './services/flag-context';
4
+ export { FeatureFlagGuard } from './guards/feature-flag.guard';
5
+ export { FeatureFlag } from './decorators/feature-flag.decorator';
6
+ export { BypassFeatureFlag } from './decorators/bypass-feature-flag.decorator';
7
+ export { FeatureFlagModuleOptions, FeatureFlagModuleAsyncOptions, FeatureFlagModuleOptionsFactory, } from './interfaces/feature-flag-options.interface';
8
+ export { EvaluationContext } from './interfaces/evaluation-context.interface';
9
+ export { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, FeatureFlagGuardOptions, FeatureFlagWithOverrides, FlagOverride, } from './interfaces/feature-flag.interface';
10
+ export { FeatureFlagEvents, FlagEvaluatedEvent, FlagMutationEvent, FlagOverrideEvent, } from './events/feature-flag.events';
11
+ export { FEATURE_FLAG_MODULE_OPTIONS } from './feature-flag.constants';
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FEATURE_FLAG_MODULE_OPTIONS = exports.FeatureFlagEvents = exports.BypassFeatureFlag = exports.FeatureFlag = exports.FeatureFlagGuard = exports.FlagContext = exports.FeatureFlagService = exports.FeatureFlagModule = void 0;
4
+ // Module
5
+ var feature_flag_module_1 = require("./feature-flag.module");
6
+ Object.defineProperty(exports, "FeatureFlagModule", { enumerable: true, get: function () { return feature_flag_module_1.FeatureFlagModule; } });
7
+ // Services
8
+ var feature_flag_service_1 = require("./services/feature-flag.service");
9
+ Object.defineProperty(exports, "FeatureFlagService", { enumerable: true, get: function () { return feature_flag_service_1.FeatureFlagService; } });
10
+ var flag_context_1 = require("./services/flag-context");
11
+ Object.defineProperty(exports, "FlagContext", { enumerable: true, get: function () { return flag_context_1.FlagContext; } });
12
+ // Guard
13
+ var feature_flag_guard_1 = require("./guards/feature-flag.guard");
14
+ Object.defineProperty(exports, "FeatureFlagGuard", { enumerable: true, get: function () { return feature_flag_guard_1.FeatureFlagGuard; } });
15
+ // Decorators
16
+ var feature_flag_decorator_1 = require("./decorators/feature-flag.decorator");
17
+ Object.defineProperty(exports, "FeatureFlag", { enumerable: true, get: function () { return feature_flag_decorator_1.FeatureFlag; } });
18
+ var bypass_feature_flag_decorator_1 = require("./decorators/bypass-feature-flag.decorator");
19
+ Object.defineProperty(exports, "BypassFeatureFlag", { enumerable: true, get: function () { return bypass_feature_flag_decorator_1.BypassFeatureFlag; } });
20
+ // Events
21
+ var feature_flag_events_1 = require("./events/feature-flag.events");
22
+ Object.defineProperty(exports, "FeatureFlagEvents", { enumerable: true, get: function () { return feature_flag_events_1.FeatureFlagEvents; } });
23
+ // Constants
24
+ var feature_flag_constants_1 = require("./feature-flag.constants");
25
+ Object.defineProperty(exports, "FEATURE_FLAG_MODULE_OPTIONS", { enumerable: true, get: function () { return feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS; } });
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAS;AACT,6DAA2H;AAAlH,wHAAA,iBAAiB,OAAA;AAE1B,WAAW;AACX,wEAAqE;AAA5D,0HAAA,kBAAkB,OAAA;AAC3B,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AAEpB,QAAQ;AACR,kEAA+D;AAAtD,sHAAA,gBAAgB,OAAA;AAEzB,aAAa;AACb,8EAAkE;AAAzD,qHAAA,WAAW,OAAA;AACpB,4FAA+E;AAAtE,kIAAA,iBAAiB,OAAA;AAkB1B,SAAS;AACT,oEAKsC;AAJpC,wHAAA,iBAAiB,OAAA;AAMnB,YAAY;AACZ,mEAAuE;AAA9D,qIAAA,2BAA2B,OAAA"}
@@ -0,0 +1,8 @@
1
+ export interface EvaluationContext {
2
+ /** User ID — used for user overrides and percentage hash */
3
+ userId?: string | null;
4
+ /** Tenant ID — used for tenant overrides. Ignored if tenancy is not installed */
5
+ tenantId?: string | null;
6
+ /** Environment — auto-injected from module options. Can be explicitly overridden */
7
+ environment?: string;
8
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=evaluation-context.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation-context.interface.js","sourceRoot":"","sources":["../../src/interfaces/evaluation-context.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { ModuleMetadata, Type } from '@nestjs/common';
2
+ import { Request } from 'express';
3
+ export interface FeatureFlagModuleOptions {
4
+ /** Current environment (e.g., 'development', 'staging', 'production') */
5
+ environment: string;
6
+ /** Cache TTL in milliseconds. 0 disables caching. Default: 30000 */
7
+ cacheTtlMs?: number;
8
+ /** Extract user ID from request. Returns null if user is not authenticated. */
9
+ userIdExtractor?: (req: Request) => string | null;
10
+ /** Default value when evaluating a non-existent flag. Default: false */
11
+ defaultOnMissing?: boolean;
12
+ /** Emit evaluation events via @nestjs/event-emitter. Default: false */
13
+ emitEvents?: boolean;
14
+ }
15
+ export interface FeatureFlagModuleOptionsFactory {
16
+ createFeatureFlagOptions(): Promise<FeatureFlagModuleOptions & {
17
+ prisma: any;
18
+ }> | (FeatureFlagModuleOptions & {
19
+ prisma: any;
20
+ });
21
+ }
22
+ export interface FeatureFlagModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
23
+ inject?: any[];
24
+ useFactory?: (...args: any[]) => Promise<FeatureFlagModuleOptions> | FeatureFlagModuleOptions;
25
+ useClass?: Type<FeatureFlagModuleOptionsFactory>;
26
+ useExisting?: Type<FeatureFlagModuleOptionsFactory>;
27
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=feature-flag-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/feature-flag-options.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ export interface CreateFeatureFlagInput {
2
+ key: string;
3
+ description?: string;
4
+ enabled?: boolean;
5
+ percentage?: number;
6
+ metadata?: Record<string, unknown>;
7
+ }
8
+ export interface UpdateFeatureFlagInput {
9
+ description?: string;
10
+ enabled?: boolean;
11
+ percentage?: number;
12
+ metadata?: Record<string, unknown>;
13
+ }
14
+ export interface SetOverrideInput {
15
+ tenantId?: string;
16
+ userId?: string;
17
+ environment?: string;
18
+ enabled: boolean;
19
+ }
20
+ export interface FeatureFlagGuardOptions {
21
+ /** HTTP status code when flag is OFF. Default: 403 */
22
+ statusCode?: number;
23
+ /** Response body when flag is OFF */
24
+ fallback?: Record<string, unknown>;
25
+ }
26
+ export interface FeatureFlagWithOverrides {
27
+ id: string;
28
+ key: string;
29
+ description: string | null;
30
+ enabled: boolean;
31
+ percentage: number;
32
+ metadata: Record<string, unknown>;
33
+ archivedAt: Date | null;
34
+ createdAt: Date;
35
+ updatedAt: Date;
36
+ overrides: FlagOverride[];
37
+ }
38
+ export interface FlagOverride {
39
+ id: string;
40
+ flagId: string;
41
+ tenantId: string | null;
42
+ userId: string | null;
43
+ environment: string | null;
44
+ enabled: boolean;
45
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=feature-flag.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag.interface.js","sourceRoot":"","sources":["../../src/interfaces/feature-flag.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { NestMiddleware } from '@nestjs/common';
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import { FlagContext } from '../services/flag-context';
4
+ import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
5
+ export declare class FlagContextMiddleware implements NestMiddleware {
6
+ private readonly context;
7
+ private readonly options;
8
+ constructor(context: FlagContext, options: FeatureFlagModuleOptions);
9
+ use(req: Request, _res: Response, next: NextFunction): void;
10
+ }
@@ -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
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FlagContextMiddleware = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const flag_context_1 = require("../services/flag-context");
18
+ const feature_flag_constants_1 = require("../feature-flag.constants");
19
+ let FlagContextMiddleware = class FlagContextMiddleware {
20
+ constructor(context, options) {
21
+ this.context = context;
22
+ this.options = options;
23
+ }
24
+ use(req, _res, next) {
25
+ const userId = this.options.userIdExtractor?.(req) ?? null;
26
+ this.context.run({ userId }, () => next());
27
+ }
28
+ };
29
+ exports.FlagContextMiddleware = FlagContextMiddleware;
30
+ exports.FlagContextMiddleware = FlagContextMiddleware = __decorate([
31
+ (0, common_1.Injectable)(),
32
+ __param(1, (0, common_1.Inject)(feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS)),
33
+ __metadata("design:paramtypes", [flag_context_1.FlagContext, Object])
34
+ ], FlagContextMiddleware);
35
+ //# sourceMappingURL=flag-context.middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-context.middleware.js","sourceRoot":"","sources":["../../src/middleware/flag-context.middleware.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoE;AAEpE,2DAAuD;AACvD,sEAAwE;AAIjE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,YACmB,OAAoB,EACiB,OAAiC;QADtE,YAAO,GAAP,OAAO,CAAa;QACiB,YAAO,GAAP,OAAO,CAA0B;IACtF,CAAC;IAEJ,GAAG,CAAC,GAAY,EAAE,IAAc,EAAE,IAAkB;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;CACF,CAAA;AAVY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;IAIR,WAAA,IAAA,eAAM,EAAC,oDAA2B,CAAC,CAAA;qCADV,0BAAW;GAF5B,qBAAqB,CAUjC"}
@@ -0,0 +1,29 @@
1
+ import { ModuleRef } from '@nestjs/core';
2
+ import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
3
+ import { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
4
+ import { EvaluationContext } from '../interfaces/evaluation-context.interface';
5
+ import { FlagCacheService } from './flag-cache.service';
6
+ import { FlagEvaluatorService } from './flag-evaluator.service';
7
+ import { FlagContext } from './flag-context';
8
+ export declare class FeatureFlagService {
9
+ private readonly options;
10
+ private readonly prisma;
11
+ private readonly cache;
12
+ private readonly evaluator;
13
+ private readonly flagContext;
14
+ private readonly moduleRef;
15
+ private readonly eventEmitter?;
16
+ constructor(options: FeatureFlagModuleOptions, prisma: any, cache: FlagCacheService, evaluator: FlagEvaluatorService, flagContext: FlagContext, moduleRef: ModuleRef, eventEmitter?: any | undefined);
17
+ isEnabled(flagKey: string, explicitContext?: EvaluationContext): Promise<boolean>;
18
+ evaluateAll(explicitContext?: EvaluationContext): Promise<Record<string, boolean>>;
19
+ create(input: CreateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
20
+ update(key: string, input: UpdateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
21
+ archive(key: string): Promise<FeatureFlagWithOverrides>;
22
+ setOverride(key: string, input: SetOverrideInput): Promise<void>;
23
+ findAll(): Promise<FeatureFlagWithOverrides[]>;
24
+ invalidateCache(): void;
25
+ private resolveFlag;
26
+ private resolveAllFlags;
27
+ private buildContext;
28
+ private getTenantId;
29
+ }
@@ -0,0 +1,208 @@
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
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FeatureFlagService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@nestjs/core");
18
+ const feature_flag_constants_1 = require("../feature-flag.constants");
19
+ const flag_cache_service_1 = require("./flag-cache.service");
20
+ const flag_evaluator_service_1 = require("./flag-evaluator.service");
21
+ const flag_context_1 = require("./flag-context");
22
+ const feature_flag_events_1 = require("../events/feature-flag.events");
23
+ let FeatureFlagService = class FeatureFlagService {
24
+ constructor(options, prisma, cache, evaluator, flagContext, moduleRef, eventEmitter) {
25
+ this.options = options;
26
+ this.prisma = prisma;
27
+ this.cache = cache;
28
+ this.evaluator = evaluator;
29
+ this.flagContext = flagContext;
30
+ this.moduleRef = moduleRef;
31
+ this.eventEmitter = eventEmitter;
32
+ }
33
+ async isEnabled(flagKey, explicitContext) {
34
+ const flag = await this.resolveFlag(flagKey);
35
+ if (!flag) {
36
+ return this.options.defaultOnMissing ?? false;
37
+ }
38
+ const context = this.buildContext(explicitContext);
39
+ const startTime = Date.now();
40
+ const { result, source } = this.evaluator.evaluate(flag, context);
41
+ const evaluationTimeMs = Date.now() - startTime;
42
+ if (this.options.emitEvents && this.eventEmitter) {
43
+ const event = {
44
+ flagKey,
45
+ result,
46
+ context,
47
+ source,
48
+ evaluationTimeMs,
49
+ };
50
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.EVALUATED, event);
51
+ }
52
+ return result;
53
+ }
54
+ async evaluateAll(explicitContext) {
55
+ const flags = await this.resolveAllFlags();
56
+ const context = this.buildContext(explicitContext);
57
+ const result = {};
58
+ for (const flag of flags) {
59
+ result[flag.key] = this.evaluator.evaluate(flag, context).result;
60
+ }
61
+ return result;
62
+ }
63
+ async create(input) {
64
+ const flag = await this.prisma.featureFlag.create({
65
+ data: {
66
+ key: input.key,
67
+ description: input.description,
68
+ enabled: input.enabled ?? false,
69
+ percentage: input.percentage ?? 0,
70
+ metadata: input.metadata ?? {},
71
+ },
72
+ include: { overrides: true },
73
+ });
74
+ this.cache.invalidate();
75
+ if (this.options.emitEvents && this.eventEmitter) {
76
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.CREATED, { flagKey: input.key, action: 'created' });
77
+ }
78
+ return flag;
79
+ }
80
+ async update(key, input) {
81
+ const flag = await this.prisma.featureFlag.update({
82
+ where: { key },
83
+ data: {
84
+ ...(input.description !== undefined && { description: input.description }),
85
+ ...(input.enabled !== undefined && { enabled: input.enabled }),
86
+ ...(input.percentage !== undefined && { percentage: input.percentage }),
87
+ ...(input.metadata !== undefined && { metadata: input.metadata }),
88
+ },
89
+ include: { overrides: true },
90
+ });
91
+ this.cache.invalidate(key);
92
+ if (this.options.emitEvents && this.eventEmitter) {
93
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.UPDATED, { flagKey: key, action: 'updated' });
94
+ }
95
+ return flag;
96
+ }
97
+ async archive(key) {
98
+ const flag = await this.prisma.featureFlag.update({
99
+ where: { key },
100
+ data: { archivedAt: new Date() },
101
+ include: { overrides: true },
102
+ });
103
+ this.cache.invalidate(key);
104
+ if (this.options.emitEvents && this.eventEmitter) {
105
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.ARCHIVED, { flagKey: key, action: 'archived' });
106
+ }
107
+ return flag;
108
+ }
109
+ async setOverride(key, input) {
110
+ const flag = await this.prisma.featureFlag.findUnique({ where: { key } });
111
+ if (!flag) {
112
+ throw new Error(`Feature flag "${key}" not found`);
113
+ }
114
+ const where = {
115
+ flagId: flag.id,
116
+ tenantId: input.tenantId ?? null,
117
+ userId: input.userId ?? null,
118
+ environment: input.environment ?? null,
119
+ };
120
+ const existing = await this.prisma.featureFlagOverride.findFirst({ where });
121
+ if (existing) {
122
+ await this.prisma.featureFlagOverride.update({
123
+ where: { id: existing.id },
124
+ data: { enabled: input.enabled },
125
+ });
126
+ }
127
+ else {
128
+ await this.prisma.featureFlagOverride.create({
129
+ data: { ...where, enabled: input.enabled },
130
+ });
131
+ }
132
+ this.cache.invalidate(key);
133
+ if (this.options.emitEvents && this.eventEmitter) {
134
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.OVERRIDE_SET, {
135
+ flagKey: key,
136
+ ...input,
137
+ action: 'set',
138
+ });
139
+ }
140
+ }
141
+ async findAll() {
142
+ return this.prisma.featureFlag.findMany({
143
+ where: { archivedAt: null },
144
+ include: { overrides: true },
145
+ orderBy: { createdAt: 'desc' },
146
+ });
147
+ }
148
+ invalidateCache() {
149
+ this.cache.invalidate();
150
+ if (this.options.emitEvents && this.eventEmitter) {
151
+ this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.CACHE_INVALIDATED, {});
152
+ }
153
+ }
154
+ async resolveFlag(key) {
155
+ const cached = this.cache.get(key);
156
+ if (cached)
157
+ return cached;
158
+ const flag = await this.prisma.featureFlag.findUnique({
159
+ where: { key },
160
+ include: { overrides: true },
161
+ });
162
+ if (flag) {
163
+ this.cache.set(key, flag);
164
+ }
165
+ return flag;
166
+ }
167
+ async resolveAllFlags() {
168
+ const cached = this.cache.getAll();
169
+ if (cached)
170
+ return cached;
171
+ const flags = await this.prisma.featureFlag.findMany({
172
+ where: { archivedAt: null },
173
+ include: { overrides: true },
174
+ });
175
+ this.cache.setAll(flags);
176
+ return flags;
177
+ }
178
+ buildContext(explicit) {
179
+ return {
180
+ userId: explicit?.userId !== undefined ? explicit.userId : this.flagContext.getUserId(),
181
+ tenantId: explicit?.tenantId !== undefined ? explicit.tenantId : this.getTenantId(),
182
+ environment: explicit?.environment !== undefined ? explicit.environment : this.options.environment,
183
+ };
184
+ }
185
+ getTenantId() {
186
+ try {
187
+ const { TenancyService } = require('@nestarc/tenancy');
188
+ const tenancyService = this.moduleRef.get(TenancyService, { strict: false });
189
+ return tenancyService?.getCurrentTenant() ?? null;
190
+ }
191
+ catch {
192
+ return null;
193
+ }
194
+ }
195
+ };
196
+ exports.FeatureFlagService = FeatureFlagService;
197
+ exports.FeatureFlagService = FeatureFlagService = __decorate([
198
+ (0, common_1.Injectable)(),
199
+ __param(0, (0, common_1.Inject)(feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS)),
200
+ __param(1, (0, common_1.Inject)('PRISMA_SERVICE')),
201
+ __param(6, (0, common_1.Optional)()),
202
+ __param(6, (0, common_1.Inject)('EVENT_EMITTER')),
203
+ __metadata("design:paramtypes", [Object, Object, flag_cache_service_1.FlagCacheService,
204
+ flag_evaluator_service_1.FlagEvaluatorService,
205
+ flag_context_1.FlagContext,
206
+ core_1.ModuleRef, Object])
207
+ ], FeatureFlagService);
208
+ //# sourceMappingURL=feature-flag.service.js.map