@nestarc/feature-flag 0.1.0 → 0.2.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 (55) hide show
  1. package/README.md +150 -2
  2. package/dist/admin/admin-options.interface.d.ts +5 -0
  3. package/dist/admin/admin-options.interface.js +3 -0
  4. package/dist/admin/admin-options.interface.js.map +1 -0
  5. package/dist/admin/feature-flag-admin.controller.d.ts +14 -0
  6. package/dist/admin/feature-flag-admin.controller.js +100 -0
  7. package/dist/admin/feature-flag-admin.controller.js.map +1 -0
  8. package/dist/admin/feature-flag-admin.module.d.ts +5 -0
  9. package/dist/admin/feature-flag-admin.module.js +33 -0
  10. package/dist/admin/feature-flag-admin.module.js.map +1 -0
  11. package/dist/cache/memory-cache.adapter.d.ts +11 -0
  12. package/dist/{services/flag-cache.service.js → cache/memory-cache.adapter.js} +18 -31
  13. package/dist/cache/memory-cache.adapter.js.map +1 -0
  14. package/dist/cache/redis-cache.adapter.d.ts +26 -0
  15. package/dist/cache/redis-cache.adapter.js +102 -0
  16. package/dist/cache/redis-cache.adapter.js.map +1 -0
  17. package/dist/feature-flag.constants.d.ts +3 -0
  18. package/dist/feature-flag.constants.js +4 -1
  19. package/dist/feature-flag.constants.js.map +1 -1
  20. package/dist/feature-flag.module.js +49 -10
  21. package/dist/feature-flag.module.js.map +1 -1
  22. package/dist/index.d.ts +10 -2
  23. package/dist/index.js +13 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/interfaces/cache-adapter.interface.d.ts +9 -0
  26. package/dist/interfaces/cache-adapter.interface.js +3 -0
  27. package/dist/interfaces/cache-adapter.interface.js.map +1 -0
  28. package/dist/interfaces/feature-flag-options.interface.d.ts +3 -0
  29. package/dist/interfaces/feature-flag-repository.interface.d.ts +20 -0
  30. package/dist/interfaces/feature-flag-repository.interface.js +3 -0
  31. package/dist/interfaces/feature-flag-repository.interface.js.map +1 -0
  32. package/dist/interfaces/feature-flag.interface.d.ts +5 -0
  33. package/dist/interfaces/tenant-context-provider.interface.d.ts +3 -0
  34. package/dist/interfaces/tenant-context-provider.interface.js +3 -0
  35. package/dist/interfaces/tenant-context-provider.interface.js.map +1 -0
  36. package/dist/repositories/prisma-feature-flag.repository.d.ts +18 -0
  37. package/dist/repositories/prisma-feature-flag.repository.js +157 -0
  38. package/dist/repositories/prisma-feature-flag.repository.js.map +1 -0
  39. package/dist/services/default-tenant-context-provider.d.ts +7 -0
  40. package/dist/services/default-tenant-context-provider.js +35 -0
  41. package/dist/services/default-tenant-context-provider.js.map +1 -0
  42. package/dist/services/feature-flag.service.d.ts +20 -13
  43. package/dist/services/feature-flag.service.js +99 -123
  44. package/dist/services/feature-flag.service.js.map +1 -1
  45. package/dist/services/flag-context-resolver.d.ts +11 -0
  46. package/dist/services/flag-context-resolver.js +40 -0
  47. package/dist/services/flag-context-resolver.js.map +1 -0
  48. package/dist/services/flag-event-publisher.d.ts +7 -0
  49. package/dist/services/flag-event-publisher.js +37 -0
  50. package/dist/services/flag-event-publisher.js.map +1 -0
  51. package/dist/testing/test-feature-flag.module.js +26 -5
  52. package/dist/testing/test-feature-flag.module.js.map +1 -1
  53. package/package.json +15 -2
  54. package/dist/services/flag-cache.service.d.ts +0 -13
  55. package/dist/services/flag-cache.service.js.map +0 -1
@@ -12,16 +12,21 @@ const common_1 = require("@nestjs/common");
12
12
  const core_1 = require("@nestjs/core");
13
13
  const feature_flag_constants_1 = require("./feature-flag.constants");
14
14
  const feature_flag_service_1 = require("./services/feature-flag.service");
15
- const flag_cache_service_1 = require("./services/flag-cache.service");
15
+ const memory_cache_adapter_1 = require("./cache/memory-cache.adapter");
16
+ const prisma_feature_flag_repository_1 = require("./repositories/prisma-feature-flag.repository");
17
+ const default_tenant_context_provider_1 = require("./services/default-tenant-context-provider");
16
18
  const flag_evaluator_service_1 = require("./services/flag-evaluator.service");
17
19
  const flag_context_1 = require("./services/flag-context");
20
+ const flag_context_resolver_1 = require("./services/flag-context-resolver");
21
+ const flag_event_publisher_1 = require("./services/flag-event-publisher");
18
22
  const feature_flag_guard_1 = require("./guards/feature-flag.guard");
19
23
  const flag_context_middleware_1 = require("./middleware/flag-context.middleware");
20
24
  const FULL_OPTIONS = Symbol('FEATURE_FLAG_FULL_OPTIONS');
21
25
  const coreProviders = [
22
- flag_cache_service_1.FlagCacheService,
23
26
  flag_evaluator_service_1.FlagEvaluatorService,
24
27
  flag_context_1.FlagContext,
28
+ flag_context_resolver_1.FlagContextResolver,
29
+ flag_event_publisher_1.FlagEventPublisher,
25
30
  feature_flag_guard_1.FeatureFlagGuard,
26
31
  feature_flag_service_1.FeatureFlagService,
27
32
  ];
@@ -48,11 +53,29 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
48
53
  global: true,
49
54
  providers: [
50
55
  { provide: feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS, useValue: moduleOptions },
51
- { provide: 'PRISMA_SERVICE', useValue: prisma },
52
56
  eventProvider,
57
+ {
58
+ provide: feature_flag_constants_1.CACHE_ADAPTER,
59
+ useValue: options.cacheAdapter ?? new memory_cache_adapter_1.MemoryCacheAdapter(),
60
+ },
61
+ {
62
+ provide: feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
63
+ useValue: new prisma_feature_flag_repository_1.PrismaFeatureFlagRepository(prisma),
64
+ },
65
+ {
66
+ provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
67
+ useClass: default_tenant_context_provider_1.DefaultTenantContextProvider,
68
+ },
53
69
  ...coreProviders,
54
70
  ],
55
- exports: [feature_flag_service_1.FeatureFlagService, flag_context_1.FlagContext, feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS],
71
+ exports: [
72
+ feature_flag_service_1.FeatureFlagService,
73
+ flag_context_1.FlagContext,
74
+ feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS,
75
+ feature_flag_constants_1.CACHE_ADAPTER,
76
+ feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
77
+ feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
78
+ ],
56
79
  };
57
80
  }
58
81
  static forRootAsync(options) {
@@ -68,11 +91,6 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
68
91
  useFactory: ({ prisma: _, ...moduleOptions }) => moduleOptions,
69
92
  inject: [FULL_OPTIONS],
70
93
  },
71
- {
72
- provide: 'PRISMA_SERVICE',
73
- useFactory: (full) => full.prisma,
74
- inject: [FULL_OPTIONS],
75
- },
76
94
  {
77
95
  provide: 'EVENT_EMITTER',
78
96
  useFactory: (full, moduleRef) => {
@@ -88,9 +106,30 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
88
106
  },
89
107
  inject: [FULL_OPTIONS, core_1.ModuleRef],
90
108
  },
109
+ {
110
+ provide: feature_flag_constants_1.CACHE_ADAPTER,
111
+ useFactory: (full) => full.cacheAdapter ?? new memory_cache_adapter_1.MemoryCacheAdapter(),
112
+ inject: [FULL_OPTIONS],
113
+ },
114
+ {
115
+ provide: feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
116
+ useFactory: (full) => new prisma_feature_flag_repository_1.PrismaFeatureFlagRepository(full.prisma),
117
+ inject: [FULL_OPTIONS],
118
+ },
119
+ {
120
+ provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
121
+ useClass: default_tenant_context_provider_1.DefaultTenantContextProvider,
122
+ },
91
123
  ...coreProviders,
92
124
  ],
93
- exports: [feature_flag_service_1.FeatureFlagService, flag_context_1.FlagContext, feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS],
125
+ exports: [
126
+ feature_flag_service_1.FeatureFlagService,
127
+ flag_context_1.FlagContext,
128
+ feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS,
129
+ feature_flag_constants_1.CACHE_ADAPTER,
130
+ feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
131
+ feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
132
+ ],
94
133
  };
95
134
  }
96
135
  static createAsyncProviders(options) {
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flag.module.js","sourceRoot":"","sources":["../src/feature-flag.module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-flag.module.js","sourceRoot":"","sources":["../src/feature-flag.module.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,14 @@ export { FeatureFlag } from './decorators/feature-flag.decorator';
6
6
  export { BypassFeatureFlag } from './decorators/bypass-feature-flag.decorator';
7
7
  export { FeatureFlagModuleOptions, FeatureFlagModuleAsyncOptions, FeatureFlagModuleOptionsFactory, } from './interfaces/feature-flag-options.interface';
8
8
  export { EvaluationContext } from './interfaces/evaluation-context.interface';
9
- export { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, FeatureFlagGuardOptions, FeatureFlagWithOverrides, FlagOverride, } from './interfaces/feature-flag.interface';
9
+ export { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, RemoveOverrideInput, FeatureFlagGuardOptions, FeatureFlagWithOverrides, FlagOverride, } from './interfaces/feature-flag.interface';
10
10
  export { FeatureFlagEvents, FlagEvaluatedEvent, FlagMutationEvent, FlagOverrideEvent, } from './events/feature-flag.events';
11
- export { FEATURE_FLAG_MODULE_OPTIONS } from './feature-flag.constants';
11
+ export { FEATURE_FLAG_MODULE_OPTIONS, CACHE_ADAPTER, FEATURE_FLAG_REPOSITORY, TENANT_CONTEXT_PROVIDER, } from './feature-flag.constants';
12
+ export type { CacheAdapter } from './interfaces/cache-adapter.interface';
13
+ export { MemoryCacheAdapter } from './cache/memory-cache.adapter';
14
+ export { RedisCacheAdapter, type RedisCacheAdapterOptions } from './cache/redis-cache.adapter';
15
+ export type { FeatureFlagRepository, OverrideCriteria } from './interfaces/feature-flag-repository.interface';
16
+ export { PrismaFeatureFlagRepository } from './repositories/prisma-feature-flag.repository';
17
+ export type { TenantContextProvider } from './interfaces/tenant-context-provider.interface';
18
+ export { FeatureFlagAdminModule } from './admin/feature-flag-admin.module';
19
+ export type { FeatureFlagAdminOptions } from './admin/admin-options.interface';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
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;
3
+ exports.FeatureFlagAdminModule = exports.PrismaFeatureFlagRepository = exports.RedisCacheAdapter = exports.MemoryCacheAdapter = exports.TENANT_CONTEXT_PROVIDER = exports.FEATURE_FLAG_REPOSITORY = exports.CACHE_ADAPTER = exports.FEATURE_FLAG_MODULE_OPTIONS = exports.FeatureFlagEvents = exports.BypassFeatureFlag = exports.FeatureFlag = exports.FeatureFlagGuard = exports.FlagContext = exports.FeatureFlagService = exports.FeatureFlagModule = void 0;
4
4
  // Module
5
5
  var feature_flag_module_1 = require("./feature-flag.module");
6
6
  Object.defineProperty(exports, "FeatureFlagModule", { enumerable: true, get: function () { return feature_flag_module_1.FeatureFlagModule; } });
@@ -23,4 +23,16 @@ Object.defineProperty(exports, "FeatureFlagEvents", { enumerable: true, get: fun
23
23
  // Constants
24
24
  var feature_flag_constants_1 = require("./feature-flag.constants");
25
25
  Object.defineProperty(exports, "FEATURE_FLAG_MODULE_OPTIONS", { enumerable: true, get: function () { return feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS; } });
26
+ Object.defineProperty(exports, "CACHE_ADAPTER", { enumerable: true, get: function () { return feature_flag_constants_1.CACHE_ADAPTER; } });
27
+ Object.defineProperty(exports, "FEATURE_FLAG_REPOSITORY", { enumerable: true, get: function () { return feature_flag_constants_1.FEATURE_FLAG_REPOSITORY; } });
28
+ Object.defineProperty(exports, "TENANT_CONTEXT_PROVIDER", { enumerable: true, get: function () { return feature_flag_constants_1.TENANT_CONTEXT_PROVIDER; } });
29
+ var memory_cache_adapter_1 = require("./cache/memory-cache.adapter");
30
+ Object.defineProperty(exports, "MemoryCacheAdapter", { enumerable: true, get: function () { return memory_cache_adapter_1.MemoryCacheAdapter; } });
31
+ var redis_cache_adapter_1 = require("./cache/redis-cache.adapter");
32
+ Object.defineProperty(exports, "RedisCacheAdapter", { enumerable: true, get: function () { return redis_cache_adapter_1.RedisCacheAdapter; } });
33
+ var prisma_feature_flag_repository_1 = require("./repositories/prisma-feature-flag.repository");
34
+ Object.defineProperty(exports, "PrismaFeatureFlagRepository", { enumerable: true, get: function () { return prisma_feature_flag_repository_1.PrismaFeatureFlagRepository; } });
35
+ // Admin module
36
+ var feature_flag_admin_module_1 = require("./admin/feature-flag-admin.module");
37
+ Object.defineProperty(exports, "FeatureFlagAdminModule", { enumerable: true, get: function () { return feature_flag_admin_module_1.FeatureFlagAdminModule; } });
26
38
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +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"}
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;AAmB1B,SAAS;AACT,oEAKsC;AAJpC,wHAAA,iBAAiB,OAAA;AAMnB,YAAY;AACZ,mEAKkC;AAJhC,qIAAA,2BAA2B,OAAA;AAC3B,uHAAA,aAAa,OAAA;AACb,iIAAA,uBAAuB,OAAA;AACvB,iIAAA,uBAAuB,OAAA;AAKzB,qEAAkE;AAAzD,0HAAA,kBAAkB,OAAA;AAC3B,mEAA+F;AAAtF,wHAAA,iBAAiB,OAAA;AAI1B,gGAA4F;AAAnF,6IAAA,2BAA2B,OAAA;AAKpC,eAAe;AACf,+EAA2E;AAAlE,mIAAA,sBAAsB,OAAA"}
@@ -0,0 +1,9 @@
1
+ import { FeatureFlagWithOverrides } from './feature-flag.interface';
2
+ export interface CacheAdapter {
3
+ get(key: string): Promise<FeatureFlagWithOverrides | null>;
4
+ set(key: string, data: FeatureFlagWithOverrides, ttlMs: number): Promise<void>;
5
+ getAll(): Promise<FeatureFlagWithOverrides[] | null>;
6
+ setAll(data: FeatureFlagWithOverrides[], ttlMs: number): Promise<void>;
7
+ invalidate(key?: string): Promise<void>;
8
+ onModuleDestroy?(): Promise<void>;
9
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=cache-adapter.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-adapter.interface.js","sourceRoot":"","sources":["../../src/interfaces/cache-adapter.interface.ts"],"names":[],"mappings":""}
@@ -1,5 +1,6 @@
1
1
  import { ModuleMetadata, Type } from '@nestjs/common';
2
2
  import { Request } from 'express';
3
+ import { CacheAdapter } from './cache-adapter.interface';
3
4
  export interface FeatureFlagModuleOptions {
4
5
  /** Current environment (e.g., 'development', 'staging', 'production') */
5
6
  environment: string;
@@ -11,6 +12,8 @@ export interface FeatureFlagModuleOptions {
11
12
  defaultOnMissing?: boolean;
12
13
  /** Emit evaluation events via @nestjs/event-emitter. Default: false */
13
14
  emitEvents?: boolean;
15
+ /** Custom cache adapter implementation. If not provided, an in-memory cache is used. */
16
+ cacheAdapter?: CacheAdapter;
14
17
  }
15
18
  export interface FeatureFlagModuleOptionsFactory {
16
19
  createFeatureFlagOptions(): Promise<FeatureFlagModuleOptions & {
@@ -0,0 +1,20 @@
1
+ import { CreateFeatureFlagInput, UpdateFeatureFlagInput, FeatureFlagWithOverrides } from './feature-flag.interface';
2
+ export interface OverrideCriteria {
3
+ tenantId: string | null;
4
+ userId: string | null;
5
+ environment: string | null;
6
+ }
7
+ export interface FeatureFlagRepository {
8
+ createFlag(input: CreateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
9
+ updateFlag(key: string, input: UpdateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
10
+ archiveFlag(key: string): Promise<FeatureFlagWithOverrides>;
11
+ findFlagByKey(key: string): Promise<FeatureFlagWithOverrides | null>;
12
+ findFlagIdByKey(key: string): Promise<string | null>;
13
+ findAllActiveFlags(): Promise<FeatureFlagWithOverrides[]>;
14
+ findOverride(flagId: string, criteria: OverrideCriteria): Promise<{
15
+ id: string;
16
+ } | null>;
17
+ createOverride(flagId: string, criteria: OverrideCriteria, enabled: boolean): Promise<void>;
18
+ updateOverrideEnabled(id: string, enabled: boolean): Promise<void>;
19
+ deleteOverride(id: string): Promise<void>;
20
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=feature-flag-repository.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flag-repository.interface.js","sourceRoot":"","sources":["../../src/interfaces/feature-flag-repository.interface.ts"],"names":[],"mappings":""}
@@ -43,3 +43,8 @@ export interface FlagOverride {
43
43
  environment: string | null;
44
44
  enabled: boolean;
45
45
  }
46
+ export interface RemoveOverrideInput {
47
+ tenantId?: string;
48
+ userId?: string;
49
+ environment?: string;
50
+ }
@@ -0,0 +1,3 @@
1
+ export interface TenantContextProvider {
2
+ getCurrentTenantId(): string | null;
3
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=tenant-context-provider.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-context-provider.interface.js","sourceRoot":"","sources":["../../src/interfaces/tenant-context-provider.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { FeatureFlagRepository, OverrideCriteria } from '../interfaces/feature-flag-repository.interface';
2
+ import { CreateFeatureFlagInput, UpdateFeatureFlagInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
3
+ export declare class PrismaFeatureFlagRepository implements FeatureFlagRepository {
4
+ private readonly prisma;
5
+ constructor(prisma: any);
6
+ createFlag(input: CreateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
7
+ updateFlag(key: string, input: UpdateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
8
+ archiveFlag(key: string): Promise<FeatureFlagWithOverrides>;
9
+ findFlagByKey(key: string): Promise<FeatureFlagWithOverrides | null>;
10
+ findFlagIdByKey(key: string): Promise<string | null>;
11
+ findAllActiveFlags(): Promise<FeatureFlagWithOverrides[]>;
12
+ findOverride(flagId: string, criteria: OverrideCriteria): Promise<{
13
+ id: string;
14
+ } | null>;
15
+ createOverride(flagId: string, criteria: OverrideCriteria, enabled: boolean): Promise<void>;
16
+ updateOverrideEnabled(id: string, enabled: boolean): Promise<void>;
17
+ deleteOverride(id: string): Promise<void>;
18
+ }
@@ -0,0 +1,157 @@
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.PrismaFeatureFlagRepository = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ function isPrismaError(error, code) {
15
+ return (typeof error === 'object' &&
16
+ error !== null &&
17
+ 'code' in error &&
18
+ error.code === code);
19
+ }
20
+ let PrismaFeatureFlagRepository = class PrismaFeatureFlagRepository {
21
+ constructor(prisma) {
22
+ this.prisma = prisma;
23
+ }
24
+ async createFlag(input) {
25
+ const percentage = input.percentage ?? 0;
26
+ if (percentage < 0 || percentage > 100) {
27
+ throw new common_1.BadRequestException(`percentage must be between 0 and 100, got ${percentage}`);
28
+ }
29
+ try {
30
+ return await this.prisma.featureFlag.create({
31
+ data: {
32
+ key: input.key,
33
+ description: input.description,
34
+ enabled: input.enabled ?? false,
35
+ percentage,
36
+ metadata: input.metadata ?? {},
37
+ },
38
+ include: { overrides: true },
39
+ });
40
+ }
41
+ catch (error) {
42
+ if (isPrismaError(error, 'P2002')) {
43
+ throw new common_1.ConflictException(`Feature flag "${input.key}" already exists`);
44
+ }
45
+ throw error;
46
+ }
47
+ }
48
+ async updateFlag(key, input) {
49
+ if (input.percentage !== undefined && (input.percentage < 0 || input.percentage > 100)) {
50
+ throw new common_1.BadRequestException(`percentage must be between 0 and 100, got ${input.percentage}`);
51
+ }
52
+ try {
53
+ return await this.prisma.featureFlag.update({
54
+ where: { key },
55
+ data: {
56
+ ...(input.description !== undefined && { description: input.description }),
57
+ ...(input.enabled !== undefined && { enabled: input.enabled }),
58
+ ...(input.percentage !== undefined && { percentage: input.percentage }),
59
+ ...(input.metadata !== undefined && { metadata: input.metadata }),
60
+ },
61
+ include: { overrides: true },
62
+ });
63
+ }
64
+ catch (error) {
65
+ if (isPrismaError(error, 'P2025')) {
66
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
67
+ }
68
+ throw error;
69
+ }
70
+ }
71
+ async archiveFlag(key) {
72
+ try {
73
+ return await this.prisma.featureFlag.update({
74
+ where: { key },
75
+ data: { archivedAt: new Date() },
76
+ include: { overrides: true },
77
+ });
78
+ }
79
+ catch (error) {
80
+ if (isPrismaError(error, 'P2025')) {
81
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
82
+ }
83
+ throw error;
84
+ }
85
+ }
86
+ async findFlagByKey(key) {
87
+ return this.prisma.featureFlag.findUnique({
88
+ where: { key },
89
+ include: { overrides: true },
90
+ });
91
+ }
92
+ async findFlagIdByKey(key) {
93
+ const flag = await this.prisma.featureFlag.findUnique({ where: { key } });
94
+ return flag?.id ?? null;
95
+ }
96
+ async findAllActiveFlags() {
97
+ return this.prisma.featureFlag.findMany({
98
+ where: { archivedAt: null },
99
+ include: { overrides: true },
100
+ orderBy: { createdAt: 'desc' },
101
+ });
102
+ }
103
+ async findOverride(flagId, criteria) {
104
+ return this.prisma.featureFlagOverride.findFirst({
105
+ where: { flagId, ...criteria },
106
+ select: { id: true },
107
+ });
108
+ }
109
+ async createOverride(flagId, criteria, enabled) {
110
+ try {
111
+ await this.prisma.featureFlagOverride.create({
112
+ data: { flagId, ...criteria, enabled },
113
+ });
114
+ }
115
+ catch (error) {
116
+ if (isPrismaError(error, 'P2002')) {
117
+ // Concurrent insert hit the unique index — fall back to update
118
+ const existing = await this.prisma.featureFlagOverride.findFirst({
119
+ where: { flagId, ...criteria },
120
+ select: { id: true },
121
+ });
122
+ if (existing) {
123
+ await this.prisma.featureFlagOverride.update({
124
+ where: { id: existing.id },
125
+ data: { enabled },
126
+ });
127
+ return;
128
+ }
129
+ }
130
+ throw error;
131
+ }
132
+ }
133
+ async updateOverrideEnabled(id, enabled) {
134
+ await this.prisma.featureFlagOverride.update({
135
+ where: { id },
136
+ data: { enabled },
137
+ });
138
+ }
139
+ async deleteOverride(id) {
140
+ try {
141
+ await this.prisma.featureFlagOverride.delete({ where: { id } });
142
+ }
143
+ catch (error) {
144
+ if (isPrismaError(error, 'P2025')) {
145
+ // Already deleted by a concurrent request — idempotent
146
+ return;
147
+ }
148
+ throw error;
149
+ }
150
+ }
151
+ };
152
+ exports.PrismaFeatureFlagRepository = PrismaFeatureFlagRepository;
153
+ exports.PrismaFeatureFlagRepository = PrismaFeatureFlagRepository = __decorate([
154
+ (0, common_1.Injectable)(),
155
+ __metadata("design:paramtypes", [Object])
156
+ ], PrismaFeatureFlagRepository);
157
+ //# sourceMappingURL=prisma-feature-flag.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma-feature-flag.repository.js","sourceRoot":"","sources":["../../src/repositories/prisma-feature-flag.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { ModuleRef } from '@nestjs/core';
2
+ import { TenantContextProvider } from '../interfaces/tenant-context-provider.interface';
3
+ export declare class DefaultTenantContextProvider implements TenantContextProvider {
4
+ private readonly moduleRef;
5
+ constructor(moduleRef: ModuleRef);
6
+ getCurrentTenantId(): string | null;
7
+ }
@@ -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.DefaultTenantContextProvider = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const core_1 = require("@nestjs/core");
15
+ let DefaultTenantContextProvider = class DefaultTenantContextProvider {
16
+ constructor(moduleRef) {
17
+ this.moduleRef = moduleRef;
18
+ }
19
+ getCurrentTenantId() {
20
+ try {
21
+ const { TenancyService } = require('@nestarc/tenancy');
22
+ const tenancyService = this.moduleRef.get(TenancyService, { strict: false });
23
+ return tenancyService?.getCurrentTenant() ?? null;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ };
30
+ exports.DefaultTenantContextProvider = DefaultTenantContextProvider;
31
+ exports.DefaultTenantContextProvider = DefaultTenantContextProvider = __decorate([
32
+ (0, common_1.Injectable)(),
33
+ __metadata("design:paramtypes", [core_1.ModuleRef])
34
+ ], DefaultTenantContextProvider);
35
+ //# sourceMappingURL=default-tenant-context-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-tenant-context-provider.js","sourceRoot":"","sources":["../../src/services/default-tenant-context-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,uCAAyC;AAIlC,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IACvC,YAA6B,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAErD,kBAAkB;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;YACvD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7E,OAAO,cAAc,EAAE,gBAAgB,EAAE,IAAI,IAAI,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF,CAAA;AAZY,oEAA4B;uCAA5B,4BAA4B;IADxC,IAAA,mBAAU,GAAE;qCAE6B,gBAAS;GADtC,4BAA4B,CAYxC"}
@@ -1,19 +1,20 @@
1
- import { ModuleRef } from '@nestjs/core';
2
1
  import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
3
- import { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
2
+ import { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, RemoveOverrideInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
4
3
  import { EvaluationContext } from '../interfaces/evaluation-context.interface';
5
- import { FlagCacheService } from './flag-cache.service';
4
+ import { CacheAdapter } from '../interfaces/cache-adapter.interface';
5
+ import { FeatureFlagRepository } from '../interfaces/feature-flag-repository.interface';
6
6
  import { FlagEvaluatorService } from './flag-evaluator.service';
7
- import { FlagContext } from './flag-context';
7
+ import { FlagContextResolver } from './flag-context-resolver';
8
+ import { FlagEventPublisher } from './flag-event-publisher';
8
9
  export declare class FeatureFlagService {
9
10
  private readonly options;
10
- private readonly prisma;
11
- private readonly cache;
11
+ private readonly repository;
12
+ private readonly cacheAdapter;
12
13
  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);
14
+ private readonly contextResolver;
15
+ private readonly eventPublisher;
16
+ constructor(options: FeatureFlagModuleOptions, repository: FeatureFlagRepository, cacheAdapter: CacheAdapter, evaluator: FlagEvaluatorService, contextResolver: FlagContextResolver, eventPublisher: FlagEventPublisher);
17
+ private get cacheTtlMs();
17
18
  isEnabled(flagKey: string, explicitContext?: EvaluationContext): Promise<boolean>;
18
19
  evaluateAll(explicitContext?: EvaluationContext): Promise<Record<string, boolean>>;
19
20
  create(input: CreateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
@@ -21,9 +22,15 @@ export declare class FeatureFlagService {
21
22
  archive(key: string): Promise<FeatureFlagWithOverrides>;
22
23
  setOverride(key: string, input: SetOverrideInput): Promise<void>;
23
24
  findAll(): Promise<FeatureFlagWithOverrides[]>;
24
- invalidateCache(): void;
25
+ invalidateCache(): Promise<void>;
26
+ findByKey(key: string): Promise<FeatureFlagWithOverrides>;
27
+ removeOverride(key: string, input: RemoveOverrideInput): Promise<void>;
28
+ /**
29
+ * Best-effort cache invalidation for mutation paths.
30
+ * DB write already succeeded — cache failure should not fail the caller.
31
+ * Stale entries self-heal via TTL (default 30s).
32
+ */
33
+ private safeInvalidateCache;
25
34
  private resolveFlag;
26
35
  private resolveAllFlags;
27
- private buildContext;
28
- private getTenantId;
29
36
  }