@nestarc/feature-flag 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +114 -6
  2. package/dist/admin/feature-flag-admin.controller.d.ts +3 -1
  3. package/dist/admin/feature-flag-admin.controller.js +12 -0
  4. package/dist/admin/feature-flag-admin.controller.js.map +1 -1
  5. package/dist/admin/feature-flag-admin.dto.d.ts +8 -0
  6. package/dist/admin/feature-flag-admin.dto.js +24 -1
  7. package/dist/admin/feature-flag-admin.dto.js.map +1 -1
  8. package/dist/events/feature-flag.events.d.ts +35 -2
  9. package/dist/events/feature-flag.events.js +1 -0
  10. package/dist/events/feature-flag.events.js.map +1 -1
  11. package/dist/flag-registry.d.ts +24 -0
  12. package/dist/flag-registry.js +62 -0
  13. package/dist/flag-registry.js.map +1 -0
  14. package/dist/guards/feature-flag.guard.js +5 -1
  15. package/dist/guards/feature-flag.guard.js.map +1 -1
  16. package/dist/index.d.ts +5 -2
  17. package/dist/index.js +7 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/interfaces/evaluation-context.interface.d.ts +2 -0
  20. package/dist/interfaces/evaluation-details.interface.d.ts +29 -0
  21. package/dist/interfaces/evaluation-details.interface.js +3 -0
  22. package/dist/interfaces/evaluation-details.interface.js.map +1 -0
  23. package/dist/interfaces/feature-flag-options.interface.d.ts +3 -0
  24. package/dist/interfaces/feature-flag.interface.d.ts +9 -0
  25. package/dist/interfaces/flag-registry.interface.d.ts +17 -0
  26. package/dist/interfaces/flag-registry.interface.js +3 -0
  27. package/dist/interfaces/flag-registry.interface.js.map +1 -0
  28. package/dist/openfeature.d.ts +26 -0
  29. package/dist/openfeature.js +96 -0
  30. package/dist/openfeature.js.map +1 -0
  31. package/dist/services/feature-flag.service.d.ts +14 -7
  32. package/dist/services/feature-flag.service.js +103 -24
  33. package/dist/services/feature-flag.service.js.map +1 -1
  34. package/dist/services/flag-evaluator.service.d.ts +7 -8
  35. package/dist/services/flag-evaluator.service.js +62 -10
  36. package/dist/services/flag-evaluator.service.js.map +1 -1
  37. package/dist/testing/index.d.ts +1 -1
  38. package/dist/testing/index.js +2 -1
  39. package/dist/testing/index.js.map +1 -1
  40. package/dist/testing/test-feature-flag.module.d.ts +21 -0
  41. package/dist/testing/test-feature-flag.module.js +78 -19
  42. package/dist/testing/test-feature-flag.module.js.map +1 -1
  43. package/package.json +13 -1
@@ -23,6 +23,8 @@ export interface FeatureFlagGuardOptions {
23
23
  statusCode?: number;
24
24
  /** Response body when flag is OFF */
25
25
  fallback?: Record<string, unknown>;
26
+ /** Invocation-level default when the guard cannot find or evaluate the flag. Default: false */
27
+ defaultValue?: boolean;
26
28
  }
27
29
  export interface FeatureFlagWithOverrides {
28
30
  id: string;
@@ -48,3 +50,10 @@ export interface FlagOverride {
48
50
  export interface RemoveOverrideInput {
49
51
  attributes: TargetingAttributes;
50
52
  }
53
+ export interface FlagMutationMetadata {
54
+ actorId?: string;
55
+ actorType?: string;
56
+ reason?: string;
57
+ requestId?: string;
58
+ correlationId?: string;
59
+ }
@@ -0,0 +1,17 @@
1
+ import { BucketBy } from './evaluation-details.interface';
2
+ export type FeatureFlagType = 'release' | 'experiment' | 'ops' | 'permission';
3
+ export interface FeatureFlagLifecycleMetadata {
4
+ type?: FeatureFlagType;
5
+ owner?: string;
6
+ tags?: readonly string[];
7
+ expiresAt?: string | Date;
8
+ staleAt?: string | Date;
9
+ }
10
+ export interface FlagDefinition extends FeatureFlagLifecycleMetadata {
11
+ defaultValue: boolean;
12
+ description?: string;
13
+ bucketBy?: BucketBy;
14
+ trackExposure?: boolean;
15
+ }
16
+ export type FlagRegistry = Record<string, FlagDefinition>;
17
+ export type FlagKey<TFlags extends FlagRegistry> = Extract<keyof TFlags, string>;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=flag-registry.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flag-registry.interface.js","sourceRoot":"","sources":["../../src/interfaces/flag-registry.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { FeatureFlagService } from './services/feature-flag.service';
2
+ export interface OpenFeatureBooleanProviderOptions {
3
+ name?: string;
4
+ }
5
+ export interface OpenFeatureEvaluationContext {
6
+ targetingKey?: unknown;
7
+ userId?: unknown;
8
+ tenantId?: unknown;
9
+ environment?: unknown;
10
+ [key: string]: unknown;
11
+ }
12
+ export interface OpenFeatureBooleanResolutionDetails {
13
+ value: boolean;
14
+ reason: string;
15
+ variant?: string;
16
+ errorCode?: string;
17
+ errorMessage?: string;
18
+ flagMetadata: Record<string, unknown>;
19
+ }
20
+ export interface OpenFeatureBooleanProvider {
21
+ metadata: {
22
+ name: string;
23
+ };
24
+ resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: OpenFeatureEvaluationContext): Promise<OpenFeatureBooleanResolutionDetails>;
25
+ }
26
+ export declare function createOpenFeatureBooleanProvider(service: FeatureFlagService, options?: OpenFeatureBooleanProviderOptions): OpenFeatureBooleanProvider;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOpenFeatureBooleanProvider = createOpenFeatureBooleanProvider;
4
+ const targeting_attributes_1 = require("./utils/targeting-attributes");
5
+ function createOpenFeatureBooleanProvider(service, options = {}) {
6
+ return {
7
+ metadata: {
8
+ name: options.name ?? '@nestarc/feature-flag',
9
+ },
10
+ resolveBooleanEvaluation: async (flagKey, defaultValue, context) => {
11
+ try {
12
+ const details = await service.evaluateBoolean(flagKey, toEvaluationContext(context), { defaultValue });
13
+ return toOpenFeatureResolution(details);
14
+ }
15
+ catch (error) {
16
+ return {
17
+ value: defaultValue,
18
+ reason: 'ERROR',
19
+ errorCode: error instanceof Error ? error.constructor.name : 'Error',
20
+ errorMessage: error instanceof Error ? error.message : String(error),
21
+ flagMetadata: {
22
+ source: 'default',
23
+ localReason: 'ERROR',
24
+ defaultUsed: true,
25
+ },
26
+ };
27
+ }
28
+ },
29
+ };
30
+ }
31
+ function toEvaluationContext(context) {
32
+ const attributes = {};
33
+ for (const [key, value] of Object.entries(context)) {
34
+ if (isKnownContextKey(key)) {
35
+ continue;
36
+ }
37
+ if ((0, targeting_attributes_1.isTargetingAttributeValue)(value)) {
38
+ attributes[key] = value;
39
+ }
40
+ }
41
+ return {
42
+ targetingKey: readString(context.targetingKey),
43
+ userId: readString(context.userId),
44
+ tenantId: readString(context.tenantId),
45
+ environment: readString(context.environment) ?? undefined,
46
+ attributes,
47
+ };
48
+ }
49
+ function toOpenFeatureResolution(details) {
50
+ return {
51
+ value: details.value,
52
+ reason: mapOpenFeatureReason(details.reason),
53
+ errorCode: details.errorCode,
54
+ errorMessage: details.errorMessage,
55
+ flagMetadata: {
56
+ source: details.source,
57
+ localReason: details.reason,
58
+ defaultUsed: details.defaultUsed,
59
+ matchedOverrideId: details.matchedOverrideId,
60
+ bucket: details.bucket,
61
+ targetingKey: details.targetingKey,
62
+ evaluationTimeMs: details.evaluationTimeMs,
63
+ },
64
+ };
65
+ }
66
+ function mapOpenFeatureReason(reason) {
67
+ switch (reason) {
68
+ case 'OVERRIDE_MATCH':
69
+ return 'TARGETING_MATCH';
70
+ case 'PERCENTAGE_MATCH':
71
+ case 'PERCENTAGE_MISS':
72
+ return 'SPLIT';
73
+ case 'FLAG_NOT_FOUND':
74
+ case 'PERCENTAGE_NO_TARGETING_KEY':
75
+ return 'DEFAULT';
76
+ case 'ERROR':
77
+ return 'ERROR';
78
+ case 'ARCHIVED':
79
+ return 'DISABLED';
80
+ case 'GLOBAL':
81
+ return 'STATIC';
82
+ }
83
+ }
84
+ function isKnownContextKey(key) {
85
+ return (key === 'targetingKey' ||
86
+ key === 'userId' ||
87
+ key === 'tenantId' ||
88
+ key === 'environment');
89
+ }
90
+ function readString(value) {
91
+ if (value === null) {
92
+ return null;
93
+ }
94
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
95
+ }
96
+ //# sourceMappingURL=openfeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openfeature.js","sourceRoot":"","sources":["../src/openfeature.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  import { FeatureFlagModuleOptions } from '../interfaces/feature-flag-options.interface';
2
- import { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, RemoveOverrideInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
2
+ import { CreateFeatureFlagInput, UpdateFeatureFlagInput, SetOverrideInput, RemoveOverrideInput, FeatureFlagWithOverrides, FlagMutationMetadata } from '../interfaces/feature-flag.interface';
3
3
  import { EvaluationContext } from '../interfaces/evaluation-context.interface';
4
4
  import { CacheAdapter } from '../interfaces/cache-adapter.interface';
5
5
  import { FeatureFlagRepository } from '../interfaces/feature-flag-repository.interface';
6
6
  import { FlagEvaluatorService } from './flag-evaluator.service';
7
7
  import { FlagContextResolver } from './flag-context-resolver';
8
8
  import { FlagEventPublisher } from './flag-event-publisher';
9
+ import { BooleanEvaluationDetails, EvaluateBooleanOptions } from '../interfaces/evaluation-details.interface';
9
10
  export declare class FeatureFlagService {
10
11
  private readonly options;
11
12
  private readonly repository;
@@ -15,16 +16,17 @@ export declare class FeatureFlagService {
15
16
  private readonly eventPublisher;
16
17
  constructor(options: FeatureFlagModuleOptions, repository: FeatureFlagRepository, cacheAdapter: CacheAdapter, evaluator: FlagEvaluatorService, contextResolver: FlagContextResolver, eventPublisher: FlagEventPublisher);
17
18
  private get cacheTtlMs();
18
- isEnabled(flagKey: string, explicitContext?: EvaluationContext): Promise<boolean>;
19
+ isEnabled(flagKey: string, explicitContext?: EvaluationContext, evaluationOptions?: EvaluateBooleanOptions): Promise<boolean>;
20
+ evaluateBoolean(flagKey: string, explicitContext?: EvaluationContext, evaluationOptions?: EvaluateBooleanOptions): Promise<BooleanEvaluationDetails>;
19
21
  evaluateAll(explicitContext?: EvaluationContext): Promise<Record<string, boolean>>;
20
- create(input: CreateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
21
- update(key: string, input: UpdateFeatureFlagInput): Promise<FeatureFlagWithOverrides>;
22
- archive(key: string): Promise<FeatureFlagWithOverrides>;
23
- setOverride(key: string, input: SetOverrideInput): Promise<void>;
22
+ create(input: CreateFeatureFlagInput, metadata?: FlagMutationMetadata): Promise<FeatureFlagWithOverrides>;
23
+ update(key: string, input: UpdateFeatureFlagInput, metadata?: FlagMutationMetadata): Promise<FeatureFlagWithOverrides>;
24
+ archive(key: string, metadata?: FlagMutationMetadata): Promise<FeatureFlagWithOverrides>;
25
+ setOverride(key: string, input: SetOverrideInput, metadata?: FlagMutationMetadata): Promise<void>;
24
26
  findAll(): Promise<FeatureFlagWithOverrides[]>;
25
27
  invalidateCache(): Promise<void>;
26
28
  findByKey(key: string): Promise<FeatureFlagWithOverrides>;
27
- removeOverride(key: string, input: RemoveOverrideInput): Promise<void>;
29
+ removeOverride(key: string, input: RemoveOverrideInput, metadata?: FlagMutationMetadata): Promise<void>;
28
30
  private normalizeOverrideAttributes;
29
31
  /**
30
32
  * Best-effort cache invalidation for mutation paths.
@@ -34,4 +36,9 @@ export declare class FeatureFlagService {
34
36
  private safeInvalidateCache;
35
37
  private resolveFlag;
36
38
  private resolveAllFlags;
39
+ private defaultDetails;
40
+ private resolveDefaultValue;
41
+ private shouldTrackExposure;
42
+ private emitEvaluation;
43
+ private emitExposure;
37
44
  }
@@ -33,23 +33,38 @@ let FeatureFlagService = class FeatureFlagService {
33
33
  get cacheTtlMs() {
34
34
  return this.options.cacheTtlMs ?? 30_000;
35
35
  }
36
- async isEnabled(flagKey, explicitContext) {
37
- const flag = await this.resolveFlag(flagKey);
38
- if (!flag) {
39
- return this.options.defaultOnMissing ?? false;
40
- }
41
- const context = this.contextResolver.resolve(explicitContext);
36
+ async isEnabled(flagKey, explicitContext, evaluationOptions = {}) {
37
+ return (await this.evaluateBoolean(flagKey, explicitContext, evaluationOptions)).value;
38
+ }
39
+ async evaluateBoolean(flagKey, explicitContext, evaluationOptions = {}) {
42
40
  const startTime = Date.now();
43
- const { result, source } = this.evaluator.evaluate(flag, context);
44
- const evaluationTimeMs = Date.now() - startTime;
45
- this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.EVALUATED, {
46
- flagKey,
47
- result,
48
- context,
49
- source,
50
- evaluationTimeMs,
51
- });
52
- return result;
41
+ let context = {};
42
+ try {
43
+ context = this.contextResolver.resolve(explicitContext);
44
+ const flag = await this.resolveFlag(flagKey);
45
+ const registryDefinition = this.options.flags?.[flagKey];
46
+ const details = flag
47
+ ? {
48
+ ...this.evaluator.evaluate(flag, context, {
49
+ bucketBy: registryDefinition?.bucketBy,
50
+ }),
51
+ evaluationTimeMs: Date.now() - startTime,
52
+ }
53
+ : this.defaultDetails(flagKey, 'FLAG_NOT_FOUND', startTime, evaluationOptions);
54
+ this.emitEvaluation(details, context, evaluationOptions);
55
+ if (this.shouldTrackExposure(flagKey, flag, evaluationOptions)) {
56
+ this.emitExposure(details, context, evaluationOptions);
57
+ }
58
+ return details;
59
+ }
60
+ catch (error) {
61
+ const details = this.defaultDetails(flagKey, 'ERROR', startTime, evaluationOptions, error);
62
+ this.emitEvaluation(details, context, evaluationOptions);
63
+ if (this.shouldTrackExposure(flagKey, null, evaluationOptions)) {
64
+ this.emitExposure(details, context, evaluationOptions);
65
+ }
66
+ return details;
67
+ }
53
68
  }
54
69
  async evaluateAll(explicitContext) {
55
70
  const flags = await this.resolveAllFlags();
@@ -60,25 +75,37 @@ let FeatureFlagService = class FeatureFlagService {
60
75
  }
61
76
  return result;
62
77
  }
63
- async create(input) {
78
+ async create(input, metadata = {}) {
64
79
  const flag = await this.repository.createFlag(input);
65
80
  await this.safeInvalidateCache();
66
- this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.CREATED, { flagKey: input.key, action: 'created' });
81
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.CREATED, {
82
+ flagKey: input.key,
83
+ action: 'created',
84
+ ...metadata,
85
+ });
67
86
  return flag;
68
87
  }
69
- async update(key, input) {
88
+ async update(key, input, metadata = {}) {
70
89
  const flag = await this.repository.updateFlag(key, input);
71
90
  await this.safeInvalidateCache(key);
72
- this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.UPDATED, { flagKey: key, action: 'updated' });
91
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.UPDATED, {
92
+ flagKey: key,
93
+ action: 'updated',
94
+ ...metadata,
95
+ });
73
96
  return flag;
74
97
  }
75
- async archive(key) {
98
+ async archive(key, metadata = {}) {
76
99
  const flag = await this.repository.archiveFlag(key);
77
100
  await this.safeInvalidateCache(key);
78
- this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.ARCHIVED, { flagKey: key, action: 'archived' });
101
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.ARCHIVED, {
102
+ flagKey: key,
103
+ action: 'archived',
104
+ ...metadata,
105
+ });
79
106
  return flag;
80
107
  }
81
- async setOverride(key, input) {
108
+ async setOverride(key, input, metadata = {}) {
82
109
  const attributes = this.normalizeOverrideAttributes(input.attributes);
83
110
  const priority = input.priority ?? 0;
84
111
  const flagId = await this.repository.findFlagIdByKey(key);
@@ -103,6 +130,7 @@ let FeatureFlagService = class FeatureFlagService {
103
130
  enabled: input.enabled,
104
131
  priority,
105
132
  action: 'set',
133
+ ...metadata,
106
134
  });
107
135
  }
108
136
  async findAll() {
@@ -119,7 +147,7 @@ let FeatureFlagService = class FeatureFlagService {
119
147
  }
120
148
  return flag;
121
149
  }
122
- async removeOverride(key, input) {
150
+ async removeOverride(key, input, metadata = {}) {
123
151
  const attributes = this.normalizeOverrideAttributes(input.attributes);
124
152
  const flagId = await this.repository.findFlagIdByKey(key);
125
153
  if (!flagId) {
@@ -135,6 +163,7 @@ let FeatureFlagService = class FeatureFlagService {
135
163
  flagKey: key,
136
164
  attributes,
137
165
  action: 'removed',
166
+ ...metadata,
138
167
  });
139
168
  }
140
169
  normalizeOverrideAttributes(input) {
@@ -179,6 +208,52 @@ let FeatureFlagService = class FeatureFlagService {
179
208
  await this.cacheAdapter.setAll(flags, this.cacheTtlMs);
180
209
  return flags;
181
210
  }
211
+ defaultDetails(flagKey, reason, startTime, evaluationOptions, error) {
212
+ const defaultValue = this.resolveDefaultValue(flagKey, evaluationOptions);
213
+ const details = {
214
+ flagKey,
215
+ value: defaultValue,
216
+ result: defaultValue,
217
+ source: 'default',
218
+ reason,
219
+ defaultUsed: true,
220
+ evaluationTimeMs: Date.now() - startTime,
221
+ };
222
+ if (error) {
223
+ details.errorCode = error instanceof Error ? error.constructor.name : 'Error';
224
+ details.errorMessage = error instanceof Error ? error.message : String(error);
225
+ }
226
+ return details;
227
+ }
228
+ resolveDefaultValue(flagKey, evaluationOptions) {
229
+ return (evaluationOptions.defaultValue ??
230
+ this.options.flags?.[flagKey]?.defaultValue ??
231
+ this.options.defaultOnMissing ??
232
+ false);
233
+ }
234
+ shouldTrackExposure(flagKey, flag, evaluationOptions) {
235
+ return (evaluationOptions.trackExposure ??
236
+ this.options.flags?.[flagKey]?.trackExposure ??
237
+ readBooleanMetadata(flag?.metadata, 'trackExposure') ??
238
+ false);
239
+ }
240
+ emitEvaluation(details, context, evaluationOptions) {
241
+ const event = {
242
+ ...details,
243
+ evaluationTimeMs: details.evaluationTimeMs ?? 0,
244
+ };
245
+ if (evaluationOptions.includeContextInEvent ?? true) {
246
+ event.context = context;
247
+ }
248
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.EVALUATED, event);
249
+ }
250
+ emitExposure(details, context, evaluationOptions) {
251
+ const event = { ...details };
252
+ if (evaluationOptions.includeContextInEvent === true) {
253
+ event.context = context;
254
+ }
255
+ this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.EXPOSED, event);
256
+ }
182
257
  };
183
258
  exports.FeatureFlagService = FeatureFlagService;
184
259
  exports.FeatureFlagService = FeatureFlagService = __decorate([
@@ -190,4 +265,8 @@ exports.FeatureFlagService = FeatureFlagService = __decorate([
190
265
  flag_context_resolver_1.FlagContextResolver,
191
266
  flag_event_publisher_1.FlagEventPublisher])
192
267
  ], FeatureFlagService);
268
+ function readBooleanMetadata(metadata, key) {
269
+ const value = metadata?.[key];
270
+ return typeof value === 'boolean' ? value : undefined;
271
+ }
193
272
  //# 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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"}
@@ -1,13 +1,12 @@
1
1
  import { FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
2
2
  import { EvaluationContext } from '../interfaces/evaluation-context.interface';
3
- import { FlagEvaluatedEvent } from '../events/feature-flag.events';
4
- type EvaluationSource = FlagEvaluatedEvent['source'];
5
- export interface EvaluationResult {
6
- result: boolean;
7
- source: EvaluationSource;
8
- }
3
+ import { BooleanEvaluationDetails, FlagEvaluatorOptions } from '../interfaces/evaluation-details.interface';
4
+ export type EvaluationResult = BooleanEvaluationDetails;
9
5
  export declare class FlagEvaluatorService {
10
- evaluate(flag: FeatureFlagWithOverrides, context: EvaluationContext): EvaluationResult;
6
+ evaluate(flag: FeatureFlagWithOverrides, context: EvaluationContext, options?: FlagEvaluatorOptions): EvaluationResult;
11
7
  private findMatchingOverride;
8
+ private resolveTargetingKey;
9
+ private getMetadataBucketBy;
10
+ private readBucketValue;
11
+ private result;
12
12
  }
13
- export {};
@@ -11,26 +11,29 @@ const common_1 = require("@nestjs/common");
11
11
  const hash_1 = require("../utils/hash");
12
12
  const targeting_attributes_1 = require("../utils/targeting-attributes");
13
13
  let FlagEvaluatorService = class FlagEvaluatorService {
14
- evaluate(flag, context) {
14
+ evaluate(flag, context, options = {}) {
15
15
  if (flag.archivedAt) {
16
- return { result: false, source: 'global' };
16
+ return this.result(flag.key, false, 'global', 'ARCHIVED');
17
17
  }
18
18
  const override = this.findMatchingOverride(flag.overrides, context);
19
19
  if (override) {
20
- return { result: override.enabled, source: 'override' };
20
+ return this.result(flag.key, override.enabled, 'override', 'OVERRIDE_MATCH', {
21
+ matchedOverrideId: override.id,
22
+ });
21
23
  }
22
24
  if (flag.percentage > 0) {
23
25
  if (flag.percentage === 100) {
24
- return { result: true, source: 'percentage' };
26
+ return this.result(flag.key, true, 'percentage', 'PERCENTAGE_MATCH');
25
27
  }
26
- const hashKey = context.userId ?? context.tenantId ?? '';
27
- if (!hashKey) {
28
- return { result: flag.enabled, source: 'global' };
28
+ const targetingKey = this.resolveTargetingKey(flag, context, options.bucketBy);
29
+ if (!targetingKey) {
30
+ return this.result(flag.key, flag.enabled, 'global', 'PERCENTAGE_NO_TARGETING_KEY');
29
31
  }
30
- const bucket = (0, hash_1.murmurhash3)(flag.key + hashKey) % 100;
31
- return { result: bucket < flag.percentage, source: 'percentage' };
32
+ const bucket = (0, hash_1.murmurhash3)(flag.key + targetingKey) % 100;
33
+ const enabled = bucket < flag.percentage;
34
+ return this.result(flag.key, enabled, 'percentage', enabled ? 'PERCENTAGE_MATCH' : 'PERCENTAGE_MISS', { bucket, targetingKey });
32
35
  }
33
- return { result: flag.enabled, source: 'global' };
36
+ return this.result(flag.key, flag.enabled, 'global', 'GLOBAL');
34
37
  }
35
38
  findMatchingOverride(overrides, context) {
36
39
  const contextAttributes = context.attributes ?? {};
@@ -38,11 +41,60 @@ let FlagEvaluatorService = class FlagEvaluatorService {
38
41
  .filter((override) => (0, targeting_attributes_1.matchesTargetingAttributes)(override.attributes, contextAttributes))
39
42
  .sort(compareOverrides)[0] ?? null);
40
43
  }
44
+ resolveTargetingKey(flag, context, bucketBy) {
45
+ if (context.targetingKey) {
46
+ return context.targetingKey;
47
+ }
48
+ const configuredBucketBy = bucketBy ?? this.getMetadataBucketBy(flag.metadata);
49
+ if (configuredBucketBy) {
50
+ const configuredValue = this.readBucketValue(context, configuredBucketBy);
51
+ if (configuredValue) {
52
+ return configuredValue;
53
+ }
54
+ }
55
+ return context.userId ?? context.tenantId ?? '';
56
+ }
57
+ getMetadataBucketBy(metadata) {
58
+ const bucketBy = metadata.bucketBy;
59
+ return typeof bucketBy === 'string' && bucketBy.length > 0 ? bucketBy : undefined;
60
+ }
61
+ readBucketValue(context, bucketBy) {
62
+ if (bucketBy === 'userId') {
63
+ return context.userId ?? '';
64
+ }
65
+ if (bucketBy === 'tenantId') {
66
+ return context.tenantId ?? '';
67
+ }
68
+ if (bucketBy === 'environment') {
69
+ return context.environment ?? '';
70
+ }
71
+ if (bucketBy === 'targetingKey') {
72
+ return context.targetingKey ?? '';
73
+ }
74
+ return stringifyBucketValue(context.attributes?.[bucketBy]);
75
+ }
76
+ result(flagKey, value, source, reason, details = {}) {
77
+ return {
78
+ flagKey,
79
+ value,
80
+ result: value,
81
+ source,
82
+ reason,
83
+ defaultUsed: false,
84
+ ...details,
85
+ };
86
+ }
41
87
  };
42
88
  exports.FlagEvaluatorService = FlagEvaluatorService;
43
89
  exports.FlagEvaluatorService = FlagEvaluatorService = __decorate([
44
90
  (0, common_1.Injectable)()
45
91
  ], FlagEvaluatorService);
92
+ function stringifyBucketValue(value) {
93
+ if (value === undefined || value === null) {
94
+ return '';
95
+ }
96
+ return String(value);
97
+ }
46
98
  function compareOverrides(a, b) {
47
99
  const specificityDelta = Object.keys(b.attributes).length - Object.keys(a.attributes).length;
48
100
  if (specificityDelta !== 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"flag-evaluator.service.js","sourceRoot":"","sources":["../../src/services/flag-evaluator.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAG5C,wCAA4C;AAE5C,wEAA2E;AAUpE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC/B,QAAQ,CAAC,IAA8B,EAAE,OAA0B;QACjE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC7C,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC1D,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;gBAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;YAChD,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;YACzD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YACpD,CAAC;YAED,MAAM,MAAM,GAAG,IAAA,kBAAW,EAAC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC;YACrD,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;QACpE,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;IAEO,oBAAoB,CAC1B,SAAyB,EACzB,OAA0B;QAE1B,MAAM,iBAAiB,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAEnD,OAAO,CACL,SAAS;aACN,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAA,iDAA0B,EAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;aACxF,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CACrC,CAAC;IACJ,CAAC;CACF,CAAA;AAxCY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;GACA,oBAAoB,CAwChC;AAED,SAAS,gBAAgB,CAAC,CAAe,EAAE,CAAe;IACxD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAC7F,IAAI,gBAAgB,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM,aAAa,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC9C,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,cAAc,GAAG,wBAAwB,CAAC,CAAC,CAAC,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAC;IACjF,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAsB;IACtD,MAAM,SAAS,GAAG,QAAQ,CAAC,SAA0B,CAAC;IACtD,OAAO,SAAS,YAAY,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;AACzF,CAAC"}
1
+ {"version":3,"file":"flag-evaluator.service.js","sourceRoot":"","sources":["../../src/services/flag-evaluator.service.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- export { TestFeatureFlagModule } from './test-feature-flag.module';
1
+ export { TestFeatureFlagController, TestFeatureFlagModule, TestFeatureFlagRegistryOptions, } from './test-feature-flag.module';
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TestFeatureFlagModule = void 0;
3
+ exports.TestFeatureFlagModule = exports.TestFeatureFlagController = void 0;
4
4
  var test_feature_flag_module_1 = require("./test-feature-flag.module");
5
+ Object.defineProperty(exports, "TestFeatureFlagController", { enumerable: true, get: function () { return test_feature_flag_module_1.TestFeatureFlagController; } });
5
6
  Object.defineProperty(exports, "TestFeatureFlagModule", { enumerable: true, get: function () { return test_feature_flag_module_1.TestFeatureFlagModule; } });
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":";;;AAAA,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":";;;AAAA,uEAIoC;AAHlC,qIAAA,yBAAyB,OAAA;AACzB,iIAAA,qBAAqB,OAAA"}
@@ -1,4 +1,25 @@
1
1
  import { DynamicModule } from '@nestjs/common';
2
+ import { FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
3
+ import { BooleanEvaluationDetails, EvaluateBooleanOptions } from '../interfaces/evaluation-details.interface';
4
+ import { FlagKey, FlagRegistry } from '../interfaces/flag-registry.interface';
2
5
  export declare class TestFeatureFlagModule {
3
6
  static register(flags?: Record<string, boolean>): DynamicModule;
7
+ static registerRegistry<TFlags extends FlagRegistry>(flags: TFlags, options?: TestFeatureFlagRegistryOptions<TFlags>): DynamicModule;
8
+ private static createModule;
9
+ }
10
+ export interface TestFeatureFlagRegistryOptions<TFlags extends FlagRegistry> {
11
+ overrides?: Partial<Record<FlagKey<TFlags>, boolean>>;
12
+ }
13
+ export declare class TestFeatureFlagController<TFlags extends FlagRegistry = FlagRegistry> {
14
+ private readonly defaults;
15
+ private values;
16
+ constructor(defaults: Record<string, boolean>, overrides?: Partial<Record<FlagKey<TFlags>, boolean>>);
17
+ set<K extends FlagKey<TFlags>>(key: K, value: boolean): void;
18
+ reset(): void;
19
+ isEnabled(key: string, options?: EvaluateBooleanOptions): boolean;
20
+ evaluateAll(): Record<string, boolean>;
21
+ getDetails(key: string, options?: EvaluateBooleanOptions): BooleanEvaluationDetails;
22
+ findFlag(key: string): FeatureFlagWithOverrides;
23
+ findAll(): FeatureFlagWithOverrides[];
24
+ private getValue;
4
25
  }