@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
@@ -14,46 +14,45 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.FeatureFlagService = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
- const core_1 = require("@nestjs/core");
18
17
  const feature_flag_constants_1 = require("../feature-flag.constants");
19
- const flag_cache_service_1 = require("./flag-cache.service");
20
18
  const flag_evaluator_service_1 = require("./flag-evaluator.service");
21
- const flag_context_1 = require("./flag-context");
19
+ const flag_context_resolver_1 = require("./flag-context-resolver");
20
+ const flag_event_publisher_1 = require("./flag-event-publisher");
22
21
  const feature_flag_events_1 = require("../events/feature-flag.events");
22
+ const CACHE_INVALIDATION_FAILED = 'feature-flag.cache.invalidation-failed';
23
23
  let FeatureFlagService = class FeatureFlagService {
24
- constructor(options, prisma, cache, evaluator, flagContext, moduleRef, eventEmitter) {
24
+ constructor(options, repository, cacheAdapter, evaluator, contextResolver, eventPublisher) {
25
25
  this.options = options;
26
- this.prisma = prisma;
27
- this.cache = cache;
26
+ this.repository = repository;
27
+ this.cacheAdapter = cacheAdapter;
28
28
  this.evaluator = evaluator;
29
- this.flagContext = flagContext;
30
- this.moduleRef = moduleRef;
31
- this.eventEmitter = eventEmitter;
29
+ this.contextResolver = contextResolver;
30
+ this.eventPublisher = eventPublisher;
31
+ }
32
+ get cacheTtlMs() {
33
+ return this.options.cacheTtlMs ?? 30_000;
32
34
  }
33
35
  async isEnabled(flagKey, explicitContext) {
34
36
  const flag = await this.resolveFlag(flagKey);
35
37
  if (!flag) {
36
38
  return this.options.defaultOnMissing ?? false;
37
39
  }
38
- const context = this.buildContext(explicitContext);
40
+ const context = this.contextResolver.resolve(explicitContext);
39
41
  const startTime = Date.now();
40
42
  const { result, source } = this.evaluator.evaluate(flag, context);
41
43
  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
- }
44
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.EVALUATED, {
45
+ flagKey,
46
+ result,
47
+ context,
48
+ source,
49
+ evaluationTimeMs,
50
+ });
52
51
  return result;
53
52
  }
54
53
  async evaluateAll(explicitContext) {
55
54
  const flags = await this.resolveAllFlags();
56
- const context = this.buildContext(explicitContext);
55
+ const context = this.contextResolver.resolve(explicitContext);
57
56
  const result = {};
58
57
  for (const flag of flags) {
59
58
  result[flag.key] = this.evaluator.evaluate(flag, context).result;
@@ -61,148 +60,125 @@ let FeatureFlagService = class FeatureFlagService {
61
60
  return result;
62
61
  }
63
62
  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
- }
63
+ const flag = await this.repository.createFlag(input);
64
+ await this.safeInvalidateCache();
65
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.CREATED, { flagKey: input.key, action: 'created' });
78
66
  return flag;
79
67
  }
80
68
  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
- }
69
+ const flag = await this.repository.updateFlag(key, input);
70
+ await this.safeInvalidateCache(key);
71
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.UPDATED, { flagKey: key, action: 'updated' });
95
72
  return flag;
96
73
  }
97
74
  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
- }
75
+ const flag = await this.repository.archiveFlag(key);
76
+ await this.safeInvalidateCache(key);
77
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.ARCHIVED, { flagKey: key, action: 'archived' });
107
78
  return flag;
108
79
  }
109
80
  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`);
81
+ const flagId = await this.repository.findFlagIdByKey(key);
82
+ if (!flagId) {
83
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
113
84
  }
114
- const where = {
115
- flagId: flag.id,
85
+ const criteria = {
116
86
  tenantId: input.tenantId ?? null,
117
87
  userId: input.userId ?? null,
118
88
  environment: input.environment ?? null,
119
89
  };
120
- const existing = await this.prisma.featureFlagOverride.findFirst({ where });
90
+ const existing = await this.repository.findOverride(flagId, criteria);
121
91
  if (existing) {
122
- await this.prisma.featureFlagOverride.update({
123
- where: { id: existing.id },
124
- data: { enabled: input.enabled },
125
- });
92
+ await this.repository.updateOverrideEnabled(existing.id, input.enabled);
126
93
  }
127
94
  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
- });
95
+ await this.repository.createOverride(flagId, criteria, input.enabled);
139
96
  }
97
+ await this.safeInvalidateCache(key);
98
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.OVERRIDE_SET, {
99
+ flagKey: key,
100
+ ...input,
101
+ action: 'set',
102
+ });
140
103
  }
141
104
  async findAll() {
142
- return this.prisma.featureFlag.findMany({
143
- where: { archivedAt: null },
144
- include: { overrides: true },
145
- orderBy: { createdAt: 'desc' },
105
+ return this.repository.findAllActiveFlags();
106
+ }
107
+ async invalidateCache() {
108
+ await this.cacheAdapter.invalidate();
109
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.CACHE_INVALIDATED, {});
110
+ }
111
+ async findByKey(key) {
112
+ const flag = await this.repository.findFlagByKey(key);
113
+ if (!flag) {
114
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
115
+ }
116
+ return flag;
117
+ }
118
+ async removeOverride(key, input) {
119
+ const flagId = await this.repository.findFlagIdByKey(key);
120
+ if (!flagId) {
121
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
122
+ }
123
+ const criteria = {
124
+ tenantId: input.tenantId ?? null,
125
+ userId: input.userId ?? null,
126
+ environment: input.environment ?? null,
127
+ };
128
+ const existing = await this.repository.findOverride(flagId, criteria);
129
+ if (existing) {
130
+ await this.repository.deleteOverride(existing.id);
131
+ }
132
+ await this.safeInvalidateCache(key);
133
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.OVERRIDE_REMOVED, {
134
+ flagKey: key,
135
+ ...input,
136
+ action: 'removed',
146
137
  });
147
138
  }
148
- invalidateCache() {
149
- this.cache.invalidate();
150
- if (this.options.emitEvents && this.eventEmitter) {
151
- this.eventEmitter.emit(feature_flag_events_1.FeatureFlagEvents.CACHE_INVALIDATED, {});
139
+ /**
140
+ * Best-effort cache invalidation for mutation paths.
141
+ * DB write already succeeded — cache failure should not fail the caller.
142
+ * Stale entries self-heal via TTL (default 30s).
143
+ */
144
+ async safeInvalidateCache(key) {
145
+ try {
146
+ await this.cacheAdapter.invalidate(key);
147
+ }
148
+ catch (error) {
149
+ this.eventPublisher.emit(CACHE_INVALIDATION_FAILED, {
150
+ key: key ?? '__all__',
151
+ error: String(error),
152
+ });
152
153
  }
153
154
  }
154
155
  async resolveFlag(key) {
155
- const cached = this.cache.get(key);
156
+ const cached = await this.cacheAdapter.get(key);
156
157
  if (cached)
157
158
  return cached;
158
- const flag = await this.prisma.featureFlag.findUnique({
159
- where: { key },
160
- include: { overrides: true },
161
- });
159
+ const flag = await this.repository.findFlagByKey(key);
162
160
  if (flag) {
163
- this.cache.set(key, flag);
161
+ await this.cacheAdapter.set(key, flag, this.cacheTtlMs);
164
162
  }
165
163
  return flag;
166
164
  }
167
165
  async resolveAllFlags() {
168
- const cached = this.cache.getAll();
166
+ const cached = await this.cacheAdapter.getAll();
169
167
  if (cached)
170
168
  return cached;
171
- const flags = await this.prisma.featureFlag.findMany({
172
- where: { archivedAt: null },
173
- include: { overrides: true },
174
- });
175
- this.cache.setAll(flags);
169
+ const flags = await this.repository.findAllActiveFlags();
170
+ await this.cacheAdapter.setAll(flags, this.cacheTtlMs);
176
171
  return flags;
177
172
  }
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
173
  };
196
174
  exports.FeatureFlagService = FeatureFlagService;
197
175
  exports.FeatureFlagService = FeatureFlagService = __decorate([
198
176
  (0, common_1.Injectable)(),
199
177
  __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])
178
+ __param(1, (0, common_1.Inject)(feature_flag_constants_1.FEATURE_FLAG_REPOSITORY)),
179
+ __param(2, (0, common_1.Inject)(feature_flag_constants_1.CACHE_ADAPTER)),
180
+ __metadata("design:paramtypes", [Object, Object, Object, flag_evaluator_service_1.FlagEvaluatorService,
181
+ flag_context_resolver_1.FlagContextResolver,
182
+ flag_event_publisher_1.FlagEventPublisher])
207
183
  ], FeatureFlagService);
208
184
  //# sourceMappingURL=feature-flag.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-flag.service.js","sourceRoot":"","sources":["../../src/services/feature-flag.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-flag.service.js","sourceRoot":"","sources":["../../src/services/feature-flag.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
2
+ import { EvaluationContext } from '../interfaces/evaluation-context.interface';
3
+ import { TenantContextProvider } from '../interfaces/tenant-context-provider.interface';
4
+ import { FlagContext } from './flag-context';
5
+ export declare class FlagContextResolver {
6
+ private readonly options;
7
+ private readonly flagContext;
8
+ private readonly tenantProvider;
9
+ constructor(options: FeatureFlagModuleOptions, flagContext: FlagContext, tenantProvider: TenantContextProvider);
10
+ resolve(explicit?: EvaluationContext): EvaluationContext;
11
+ }
@@ -0,0 +1,40 @@
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.FlagContextResolver = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const feature_flag_constants_1 = require("../feature-flag.constants");
18
+ const flag_context_1 = require("./flag-context");
19
+ let FlagContextResolver = class FlagContextResolver {
20
+ constructor(options, flagContext, tenantProvider) {
21
+ this.options = options;
22
+ this.flagContext = flagContext;
23
+ this.tenantProvider = tenantProvider;
24
+ }
25
+ resolve(explicit) {
26
+ return {
27
+ userId: explicit?.userId !== undefined ? explicit.userId : this.flagContext.getUserId(),
28
+ tenantId: explicit?.tenantId !== undefined ? explicit.tenantId : this.tenantProvider.getCurrentTenantId(),
29
+ environment: explicit?.environment !== undefined ? explicit.environment : this.options.environment,
30
+ };
31
+ }
32
+ };
33
+ exports.FlagContextResolver = FlagContextResolver;
34
+ exports.FlagContextResolver = FlagContextResolver = __decorate([
35
+ (0, common_1.Injectable)(),
36
+ __param(0, (0, common_1.Inject)(feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS)),
37
+ __param(2, (0, common_1.Inject)(feature_flag_constants_1.TENANT_CONTEXT_PROVIDER)),
38
+ __metadata("design:paramtypes", [Object, flag_context_1.FlagContext, Object])
39
+ ], FlagContextResolver);
40
+ //# sourceMappingURL=flag-context-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-context-resolver.js","sourceRoot":"","sources":["../../src/services/flag-context-resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,sEAAiG;AAIjG,iDAA6C;AAGtC,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YACwD,OAAiC,EACtE,WAAwB,EACS,cAAqC;QAFjC,YAAO,GAAP,OAAO,CAA0B;QACtE,gBAAW,GAAX,WAAW,CAAa;QACS,mBAAc,GAAd,cAAc,CAAuB;IACtF,CAAC;IAEJ,OAAO,CAAC,QAA4B;QAClC,OAAO;YACL,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE;YACvF,QAAQ,EAAE,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE;YACzG,WAAW,EAAE,QAAQ,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW;SACnG,CAAC;IACJ,CAAC;CACF,CAAA;AAdY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,oDAA2B,CAAC,CAAA;IAEnC,WAAA,IAAA,eAAM,EAAC,gDAAuB,CAAC,CAAA;6CADF,0BAAW;GAHhC,mBAAmB,CAc/B"}
@@ -0,0 +1,7 @@
1
+ import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
2
+ export declare class FlagEventPublisher {
3
+ private readonly options;
4
+ private readonly eventEmitter?;
5
+ constructor(options: FeatureFlagModuleOptions, eventEmitter?: any | undefined);
6
+ emit(event: string, payload: Record<string, unknown>): void;
7
+ }
@@ -0,0 +1,37 @@
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.FlagEventPublisher = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const feature_flag_constants_1 = require("../feature-flag.constants");
18
+ let FlagEventPublisher = class FlagEventPublisher {
19
+ constructor(options, eventEmitter) {
20
+ this.options = options;
21
+ this.eventEmitter = eventEmitter;
22
+ }
23
+ emit(event, payload) {
24
+ if (this.options.emitEvents && this.eventEmitter) {
25
+ this.eventEmitter.emit(event, payload);
26
+ }
27
+ }
28
+ };
29
+ exports.FlagEventPublisher = FlagEventPublisher;
30
+ exports.FlagEventPublisher = FlagEventPublisher = __decorate([
31
+ (0, common_1.Injectable)(),
32
+ __param(0, (0, common_1.Inject)(feature_flag_constants_1.FEATURE_FLAG_MODULE_OPTIONS)),
33
+ __param(1, (0, common_1.Optional)()),
34
+ __param(1, (0, common_1.Inject)('EVENT_EMITTER')),
35
+ __metadata("design:paramtypes", [Object, Object])
36
+ ], FlagEventPublisher);
37
+ //# sourceMappingURL=flag-event-publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-event-publisher.js","sourceRoot":"","sources":["../../src/services/flag-event-publisher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA8D;AAC9D,sEAAwE;AAIjE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YACwD,OAAiC,EACjC,YAAkB;QADlB,YAAO,GAAP,OAAO,CAA0B;QACjC,iBAAY,GAAZ,YAAY,CAAM;IACvE,CAAC;IAEJ,IAAI,CAAC,KAAa,EAAE,OAAgC;QAClD,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACjD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;CACF,CAAA;AAXY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,oDAA2B,CAAC,CAAA;IACnC,WAAA,IAAA,iBAAQ,GAAE,CAAA;IAAE,WAAA,IAAA,eAAM,EAAC,eAAe,CAAC,CAAA;;GAH3B,kBAAkB,CAW9B"}
@@ -10,6 +10,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.TestFeatureFlagModule = void 0;
11
11
  const common_1 = require("@nestjs/common");
12
12
  const feature_flag_service_1 = require("../services/feature-flag.service");
13
+ function makeStubFlag(partial = {}) {
14
+ return {
15
+ id: partial.id ?? 'stub-id',
16
+ key: partial.key ?? 'STUB',
17
+ description: partial.description ?? null,
18
+ enabled: partial.enabled ?? false,
19
+ percentage: partial.percentage ?? 0,
20
+ metadata: partial.metadata ?? {},
21
+ archivedAt: partial.archivedAt ?? null,
22
+ createdAt: partial.createdAt ?? new Date('2026-01-01'),
23
+ updatedAt: partial.updatedAt ?? new Date('2026-01-01'),
24
+ overrides: partial.overrides ?? [],
25
+ };
26
+ }
13
27
  let TestFeatureFlagModule = TestFeatureFlagModule_1 = class TestFeatureFlagModule {
14
28
  static register(flags) {
15
29
  return {
@@ -21,12 +35,19 @@ let TestFeatureFlagModule = TestFeatureFlagModule_1 = class TestFeatureFlagModul
21
35
  useValue: {
22
36
  isEnabled: async (key) => flags?.[key] ?? false,
23
37
  evaluateAll: async () => flags ?? {},
24
- create: async () => ({}),
25
- update: async () => ({}),
26
- archive: async () => ({}),
38
+ create: async (input) => makeStubFlag({ key: input.key, enabled: input.enabled ?? false }),
39
+ update: async (key, input) => makeStubFlag({ key, ...input }),
40
+ archive: async (key) => makeStubFlag({ key, archivedAt: new Date() }),
27
41
  setOverride: async () => { },
28
- findAll: async () => [],
29
- invalidateCache: () => { },
42
+ removeOverride: async () => { },
43
+ findAll: async () => Object.entries(flags ?? {}).map(([key, enabled]) => makeStubFlag({ key, enabled })),
44
+ findByKey: async (key) => {
45
+ if (flags && key in flags) {
46
+ return makeStubFlag({ key, enabled: flags[key] });
47
+ }
48
+ throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
49
+ },
50
+ invalidateCache: async () => { },
30
51
  },
31
52
  },
32
53
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"test-feature-flag.module.js","sourceRoot":"","sources":["../../src/testing/test-feature-flag.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2EAAsE;AAG/D,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAChC,MAAM,CAAC,QAAQ,CAAC,KAA+B;QAC7C,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,yCAAkB;oBAC3B,QAAQ,EAAE;wBACR,SAAS,EAAE,KAAK,EAAE,GAAW,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK;wBACvD,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE;wBACpC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;wBACxB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;wBACxB,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;wBACzB,WAAW,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;wBAC3B,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;wBACvB,eAAe,EAAE,GAAG,EAAE,GAAE,CAAC;qBAC1B;iBACF;aACF;YACD,OAAO,EAAE,CAAC,yCAAkB,CAAC;SAC9B,CAAC;IACJ,CAAC;CACF,CAAA;AAvBY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,qBAAqB,CAuBjC"}
1
+ {"version":3,"file":"test-feature-flag.module.js","sourceRoot":"","sources":["../../src/testing/test-feature-flag.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA0E;AAC1E,2EAAsE;AAMtE,SAAS,YAAY,CACnB,UAA6C,EAAE;IAE/C,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;QAC3B,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,MAAM;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;QACjC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,CAAC;QACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;QAChC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;QACtC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC;QACtD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC;QACtD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;KACnC,CAAC;AACJ,CAAC;AAGM,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAChC,MAAM,CAAC,QAAQ,CAAC,KAA+B;QAC7C,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,yCAAkB;oBAC3B,QAAQ,EAAE;wBACR,SAAS,EAAE,KAAK,EAAE,GAAW,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK;wBACvD,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE;wBACpC,MAAM,EAAE,KAAK,EAAE,KAA6B,EAAE,EAAE,CAC9C,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;wBACnE,MAAM,EAAE,KAAK,EAAE,GAAW,EAAE,KAAwC,EAAE,EAAE,CACtE,YAAY,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;wBACjC,OAAO,EAAE,KAAK,EAAE,GAAW,EAAE,EAAE,CAC7B,YAAY,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;wBAC/C,WAAW,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;wBAC3B,cAAc,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;wBAC9B,OAAO,EAAE,KAAK,IAAI,EAAE,CAClB,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,CACjD,YAAY,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAC/B;wBACH,SAAS,EAAE,KAAK,EAAE,GAAW,EAAE,EAAE;4BAC/B,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;gCAC1B,OAAO,YAAY,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;4BACpD,CAAC;4BACD,MAAM,IAAI,0BAAiB,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAAC;wBACjE,CAAC;wBACD,eAAe,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;qBAChC;iBACF;aACF;YACD,OAAO,EAAE,CAAC,yCAAkB,CAAC;SAC9B,CAAC;IACJ,CAAC;CACF,CAAA;AApCY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,qBAAqB,CAoCjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestarc/feature-flag",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "DB-backed feature flags for NestJS + Prisma + PostgreSQL with tenant-aware overrides",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,6 +22,7 @@
22
22
  "build": "tsc -p tsconfig.build.json",
23
23
  "test": "jest",
24
24
  "test:cov": "jest --coverage",
25
+ "bench": "dotenv -e .env.test -- npx ts-node benchmarks/evaluation-overhead.ts",
25
26
  "lint": "eslint 'src/**/*.ts' 'test/**/*.ts'",
26
27
  "format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
27
28
  "prisma:generate": "prisma generate",
@@ -39,10 +40,15 @@
39
40
  "keywords": [
40
41
  "nestjs",
41
42
  "feature-flag",
43
+ "feature-flags",
42
44
  "feature-toggle",
45
+ "rollout",
46
+ "percentage-rollout",
43
47
  "prisma",
44
48
  "postgresql",
45
- "multi-tenant"
49
+ "multi-tenant",
50
+ "nestjs-module",
51
+ "saas"
46
52
  ],
47
53
  "author": "nestarc",
48
54
  "license": "MIT",
@@ -50,6 +56,7 @@
50
56
  "@nestjs/common": "^10.0.0 || ^11.0.0",
51
57
  "@nestjs/core": "^10.0.0 || ^11.0.0",
52
58
  "@prisma/client": "^5.0.0 || ^6.0.0",
59
+ "ioredis": "^5.0.0",
53
60
  "reflect-metadata": "^0.1.13 || ^0.2.0",
54
61
  "rxjs": "^7.0.0"
55
62
  },
@@ -59,6 +66,9 @@
59
66
  },
60
67
  "@nestjs/event-emitter": {
61
68
  "optional": true
69
+ },
70
+ "ioredis": {
71
+ "optional": true
62
72
  }
63
73
  },
64
74
  "devDependencies": {
@@ -70,10 +80,13 @@
70
80
  "@nestjs/testing": "^11.0.0",
71
81
  "@prisma/client": "^6.0.0",
72
82
  "@types/express": "^5.0.0",
83
+ "@types/ioredis-mock": "^8.2.7",
73
84
  "@types/jest": "^29.5.0",
74
85
  "@types/supertest": "^7.2.0",
75
86
  "dotenv-cli": "^11.0.0",
76
87
  "eslint": "^9.0.0",
88
+ "ioredis": "^5.10.1",
89
+ "ioredis-mock": "^8.13.1",
77
90
  "jest": "^29.7.0",
78
91
  "prettier": "^3.0.0",
79
92
  "prisma": "^6.0.0",
@@ -1,13 +0,0 @@
1
- import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
2
- import { FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
3
- export declare class FlagCacheService {
4
- private readonly options;
5
- private cache;
6
- private allFlagsCache;
7
- constructor(options: FeatureFlagModuleOptions);
8
- get(key: string): FeatureFlagWithOverrides | null;
9
- set(key: string, data: FeatureFlagWithOverrides): void;
10
- getAll(): FeatureFlagWithOverrides[] | null;
11
- setAll(data: FeatureFlagWithOverrides[]): void;
12
- invalidate(key?: string): void;
13
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"flag-cache.service.js","sourceRoot":"","sources":["../../src/services/flag-cache.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,sEAAwE;AAUjE,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAI3B,YACuC,OAAkD;QAAjC,YAAO,GAAP,OAAO,CAA0B;QAJjF,UAAK,GAAG,IAAI,GAAG,EAAgD,CAAC;QAChE,kBAAa,GAAkD,IAAI,CAAC;IAIzE,CAAC;IAEJ,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,IAA8B;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;QAC9C,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO;QACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,CAAC;YAC9C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,IAAgC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC;QAC9C,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO;QACtB,IAAI,CAAC,aAAa,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC7D,CAAC;IAED,UAAU,CAAC,GAAY;QACrB,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;CACF,CAAA;AAhDY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;IAMR,WAAA,IAAA,eAAM,EAAC,oDAA2B,CAAC,CAAA;;GAL3B,gBAAgB,CAgD5B"}