@nestarc/feature-flag 0.2.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 (57) hide show
  1. package/README.md +206 -81
  2. package/dist/admin/feature-flag-admin.controller.d.ts +8 -6
  3. package/dist/admin/feature-flag-admin.controller.js +22 -4
  4. package/dist/admin/feature-flag-admin.controller.js.map +1 -1
  5. package/dist/admin/feature-flag-admin.dto.d.ts +30 -0
  6. package/dist/admin/feature-flag-admin.dto.js +116 -0
  7. package/dist/admin/feature-flag-admin.dto.js.map +1 -0
  8. package/dist/admin/targeting-attributes.validator.d.ts +6 -0
  9. package/dist/admin/targeting-attributes.validator.js +36 -0
  10. package/dist/admin/targeting-attributes.validator.js.map +1 -0
  11. package/dist/events/feature-flag.events.d.ts +38 -6
  12. package/dist/events/feature-flag.events.js +1 -0
  13. package/dist/events/feature-flag.events.js.map +1 -1
  14. package/dist/flag-registry.d.ts +24 -0
  15. package/dist/flag-registry.js +62 -0
  16. package/dist/flag-registry.js.map +1 -0
  17. package/dist/guards/feature-flag.guard.js +5 -1
  18. package/dist/guards/feature-flag.guard.js.map +1 -1
  19. package/dist/index.d.ts +6 -3
  20. package/dist/index.js +7 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/interfaces/evaluation-context.interface.d.ts +8 -3
  23. package/dist/interfaces/evaluation-details.interface.d.ts +29 -0
  24. package/dist/interfaces/evaluation-details.interface.js +3 -0
  25. package/dist/interfaces/evaluation-details.interface.js.map +1 -0
  26. package/dist/interfaces/feature-flag-options.interface.d.ts +3 -0
  27. package/dist/interfaces/feature-flag-repository.interface.d.ts +8 -6
  28. package/dist/interfaces/feature-flag.interface.d.ts +18 -9
  29. package/dist/interfaces/flag-registry.interface.d.ts +17 -0
  30. package/dist/interfaces/flag-registry.interface.js +3 -0
  31. package/dist/interfaces/flag-registry.interface.js.map +1 -0
  32. package/dist/openfeature.d.ts +26 -0
  33. package/dist/openfeature.js +96 -0
  34. package/dist/openfeature.js.map +1 -0
  35. package/dist/repositories/prisma-feature-flag.repository.d.ts +3 -3
  36. package/dist/repositories/prisma-feature-flag.repository.js +18 -14
  37. package/dist/repositories/prisma-feature-flag.repository.js.map +1 -1
  38. package/dist/services/feature-flag.service.d.ts +15 -7
  39. package/dist/services/feature-flag.service.js +126 -38
  40. package/dist/services/feature-flag.service.js.map +1 -1
  41. package/dist/services/flag-context-resolver.js +14 -3
  42. package/dist/services/flag-context-resolver.js.map +1 -1
  43. package/dist/services/flag-evaluator.service.d.ts +8 -8
  44. package/dist/services/flag-evaluator.service.js +90 -36
  45. package/dist/services/flag-evaluator.service.js.map +1 -1
  46. package/dist/testing/index.d.ts +1 -1
  47. package/dist/testing/index.js +2 -1
  48. package/dist/testing/index.js.map +1 -1
  49. package/dist/testing/test-feature-flag.module.d.ts +21 -0
  50. package/dist/testing/test-feature-flag.module.js +78 -19
  51. package/dist/testing/test-feature-flag.module.js.map +1 -1
  52. package/dist/utils/targeting-attributes.d.ts +9 -0
  53. package/dist/utils/targeting-attributes.js +44 -0
  54. package/dist/utils/targeting-attributes.js.map +1 -0
  55. package/package.json +18 -2
  56. package/prisma/migrations/20260512000000_attribute_targeting/migration.sql +59 -0
  57. package/prisma/schema.prisma +7 -9
@@ -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,4 +1,4 @@
1
- import { FeatureFlagRepository, OverrideCriteria } from '../interfaces/feature-flag-repository.interface';
1
+ import { FeatureFlagRepository, OverrideCriteria, UpdateOverrideInput } from '../interfaces/feature-flag-repository.interface';
2
2
  import { CreateFeatureFlagInput, UpdateFeatureFlagInput, FeatureFlagWithOverrides } from '../interfaces/feature-flag.interface';
3
3
  export declare class PrismaFeatureFlagRepository implements FeatureFlagRepository {
4
4
  private readonly prisma;
@@ -12,7 +12,7 @@ export declare class PrismaFeatureFlagRepository implements FeatureFlagRepositor
12
12
  findOverride(flagId: string, criteria: OverrideCriteria): Promise<{
13
13
  id: string;
14
14
  } | null>;
15
- createOverride(flagId: string, criteria: OverrideCriteria, enabled: boolean): Promise<void>;
16
- updateOverrideEnabled(id: string, enabled: boolean): Promise<void>;
15
+ createOverride(flagId: string, criteria: OverrideCriteria, enabled: boolean, priority: number): Promise<void>;
16
+ updateOverride(id: string, input: UpdateOverrideInput): Promise<void>;
17
17
  deleteOverride(id: string): Promise<void>;
18
18
  }
@@ -102,38 +102,42 @@ let PrismaFeatureFlagRepository = class PrismaFeatureFlagRepository {
102
102
  }
103
103
  async findOverride(flagId, criteria) {
104
104
  return this.prisma.featureFlagOverride.findFirst({
105
- where: { flagId, ...criteria },
105
+ where: {
106
+ flagId,
107
+ attributes: { equals: criteria.attributes },
108
+ },
106
109
  select: { id: true },
107
110
  });
108
111
  }
109
- async createOverride(flagId, criteria, enabled) {
112
+ async createOverride(flagId, criteria, enabled, priority) {
110
113
  try {
111
114
  await this.prisma.featureFlagOverride.create({
112
- data: { flagId, ...criteria, enabled },
115
+ data: {
116
+ flagId,
117
+ attributes: criteria.attributes,
118
+ priority,
119
+ enabled,
120
+ },
113
121
  });
114
122
  }
115
123
  catch (error) {
116
124
  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
- });
125
+ const existing = await this.findOverride(flagId, criteria);
122
126
  if (existing) {
123
- await this.prisma.featureFlagOverride.update({
124
- where: { id: existing.id },
125
- data: { enabled },
126
- });
127
+ await this.updateOverride(existing.id, { enabled, priority });
127
128
  return;
128
129
  }
129
130
  }
130
131
  throw error;
131
132
  }
132
133
  }
133
- async updateOverrideEnabled(id, enabled) {
134
+ async updateOverride(id, input) {
134
135
  await this.prisma.featureFlagOverride.update({
135
136
  where: { id },
136
- data: { enabled },
137
+ data: {
138
+ enabled: input.enabled,
139
+ priority: input.priority,
140
+ },
137
141
  });
138
142
  }
139
143
  async deleteOverride(id) {
@@ -1 +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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"}
1
+ {"version":3,"file":"prisma-feature-flag.repository.js","sourceRoot":"","sources":["../../src/repositories/prisma-feature-flag.repository.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,18 @@ 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>;
30
+ private normalizeOverrideAttributes;
28
31
  /**
29
32
  * Best-effort cache invalidation for mutation paths.
30
33
  * DB write already succeeded — cache failure should not fail the caller.
@@ -33,4 +36,9 @@ export declare class FeatureFlagService {
33
36
  private safeInvalidateCache;
34
37
  private resolveFlag;
35
38
  private resolveAllFlags;
39
+ private defaultDetails;
40
+ private resolveDefaultValue;
41
+ private shouldTrackExposure;
42
+ private emitEvaluation;
43
+ private emitExposure;
36
44
  }
@@ -19,6 +19,7 @@ const flag_evaluator_service_1 = require("./flag-evaluator.service");
19
19
  const flag_context_resolver_1 = require("./flag-context-resolver");
20
20
  const flag_event_publisher_1 = require("./flag-event-publisher");
21
21
  const feature_flag_events_1 = require("../events/feature-flag.events");
22
+ const targeting_attributes_1 = require("../utils/targeting-attributes");
22
23
  const CACHE_INVALIDATION_FAILED = 'feature-flag.cache.invalidation-failed';
23
24
  let FeatureFlagService = class FeatureFlagService {
24
25
  constructor(options, repository, cacheAdapter, evaluator, contextResolver, eventPublisher) {
@@ -32,23 +33,38 @@ let FeatureFlagService = class FeatureFlagService {
32
33
  get cacheTtlMs() {
33
34
  return this.options.cacheTtlMs ?? 30_000;
34
35
  }
35
- async isEnabled(flagKey, explicitContext) {
36
- const flag = await this.resolveFlag(flagKey);
37
- if (!flag) {
38
- return this.options.defaultOnMissing ?? false;
39
- }
40
- 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 = {}) {
41
40
  const startTime = Date.now();
42
- const { result, source } = this.evaluator.evaluate(flag, context);
43
- const evaluationTimeMs = Date.now() - startTime;
44
- this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.EVALUATED, {
45
- flagKey,
46
- result,
47
- context,
48
- source,
49
- evaluationTimeMs,
50
- });
51
- 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
+ }
52
68
  }
53
69
  async evaluateAll(explicitContext) {
54
70
  const flags = await this.resolveAllFlags();
@@ -59,46 +75,62 @@ let FeatureFlagService = class FeatureFlagService {
59
75
  }
60
76
  return result;
61
77
  }
62
- async create(input) {
78
+ async create(input, metadata = {}) {
63
79
  const flag = await this.repository.createFlag(input);
64
80
  await this.safeInvalidateCache();
65
- 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
+ });
66
86
  return flag;
67
87
  }
68
- async update(key, input) {
88
+ async update(key, input, metadata = {}) {
69
89
  const flag = await this.repository.updateFlag(key, input);
70
90
  await this.safeInvalidateCache(key);
71
- 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
+ });
72
96
  return flag;
73
97
  }
74
- async archive(key) {
98
+ async archive(key, metadata = {}) {
75
99
  const flag = await this.repository.archiveFlag(key);
76
100
  await this.safeInvalidateCache(key);
77
- 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
+ });
78
106
  return flag;
79
107
  }
80
- async setOverride(key, input) {
108
+ async setOverride(key, input, metadata = {}) {
109
+ const attributes = this.normalizeOverrideAttributes(input.attributes);
110
+ const priority = input.priority ?? 0;
81
111
  const flagId = await this.repository.findFlagIdByKey(key);
82
112
  if (!flagId) {
83
113
  throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
84
114
  }
85
- const criteria = {
86
- tenantId: input.tenantId ?? null,
87
- userId: input.userId ?? null,
88
- environment: input.environment ?? null,
89
- };
115
+ const criteria = { attributes };
90
116
  const existing = await this.repository.findOverride(flagId, criteria);
91
117
  if (existing) {
92
- await this.repository.updateOverrideEnabled(existing.id, input.enabled);
118
+ await this.repository.updateOverride(existing.id, {
119
+ enabled: input.enabled,
120
+ priority,
121
+ });
93
122
  }
94
123
  else {
95
- await this.repository.createOverride(flagId, criteria, input.enabled);
124
+ await this.repository.createOverride(flagId, criteria, input.enabled, priority);
96
125
  }
97
126
  await this.safeInvalidateCache(key);
98
127
  this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.OVERRIDE_SET, {
99
128
  flagKey: key,
100
- ...input,
129
+ attributes,
130
+ enabled: input.enabled,
131
+ priority,
101
132
  action: 'set',
133
+ ...metadata,
102
134
  });
103
135
  }
104
136
  async findAll() {
@@ -115,16 +147,13 @@ let FeatureFlagService = class FeatureFlagService {
115
147
  }
116
148
  return flag;
117
149
  }
118
- async removeOverride(key, input) {
150
+ async removeOverride(key, input, metadata = {}) {
151
+ const attributes = this.normalizeOverrideAttributes(input.attributes);
119
152
  const flagId = await this.repository.findFlagIdByKey(key);
120
153
  if (!flagId) {
121
154
  throw new common_1.NotFoundException(`Feature flag "${key}" not found`);
122
155
  }
123
- const criteria = {
124
- tenantId: input.tenantId ?? null,
125
- userId: input.userId ?? null,
126
- environment: input.environment ?? null,
127
- };
156
+ const criteria = { attributes };
128
157
  const existing = await this.repository.findOverride(flagId, criteria);
129
158
  if (existing) {
130
159
  await this.repository.deleteOverride(existing.id);
@@ -132,10 +161,19 @@ let FeatureFlagService = class FeatureFlagService {
132
161
  await this.safeInvalidateCache(key);
133
162
  this.eventPublisher.emit(feature_flag_events_1.FeatureFlagEvents.OVERRIDE_REMOVED, {
134
163
  flagKey: key,
135
- ...input,
164
+ attributes,
136
165
  action: 'removed',
166
+ ...metadata,
137
167
  });
138
168
  }
169
+ normalizeOverrideAttributes(input) {
170
+ try {
171
+ return (0, targeting_attributes_1.normalizeTargetingAttributes)(input, { allowEmpty: false });
172
+ }
173
+ catch (error) {
174
+ throw new common_1.BadRequestException(String(error instanceof Error ? error.message : error));
175
+ }
176
+ }
139
177
  /**
140
178
  * Best-effort cache invalidation for mutation paths.
141
179
  * DB write already succeeded — cache failure should not fail the caller.
@@ -170,6 +208,52 @@ let FeatureFlagService = class FeatureFlagService {
170
208
  await this.cacheAdapter.setAll(flags, this.cacheTtlMs);
171
209
  return flags;
172
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
+ }
173
257
  };
174
258
  exports.FeatureFlagService = FeatureFlagService;
175
259
  exports.FeatureFlagService = FeatureFlagService = __decorate([
@@ -181,4 +265,8 @@ exports.FeatureFlagService = FeatureFlagService = __decorate([
181
265
  flag_context_resolver_1.FlagContextResolver,
182
266
  flag_event_publisher_1.FlagEventPublisher])
183
267
  ], FeatureFlagService);
268
+ function readBooleanMetadata(metadata, key) {
269
+ const value = metadata?.[key];
270
+ return typeof value === 'boolean' ? value : undefined;
271
+ }
184
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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"}
@@ -23,10 +23,21 @@ let FlagContextResolver = class FlagContextResolver {
23
23
  this.tenantProvider = tenantProvider;
24
24
  }
25
25
  resolve(explicit) {
26
+ const userId = explicit?.userId !== undefined ? explicit.userId : this.flagContext.getUserId();
27
+ const tenantId = explicit?.tenantId !== undefined
28
+ ? explicit.tenantId
29
+ : this.tenantProvider.getCurrentTenantId();
30
+ const environment = explicit?.environment !== undefined ? explicit.environment : this.options.environment;
26
31
  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,
32
+ userId,
33
+ tenantId,
34
+ environment,
35
+ attributes: {
36
+ ...(explicit?.attributes ?? {}),
37
+ ...(userId !== undefined && { userId }),
38
+ ...(tenantId !== undefined && { tenantId }),
39
+ ...(environment !== undefined && { environment }),
40
+ },
30
41
  };
31
42
  }
32
43
  };
@@ -1 +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"}
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,MAAM,MAAM,GACV,QAAQ,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAClF,MAAM,QAAQ,GACZ,QAAQ,EAAE,QAAQ,KAAK,SAAS;YAC9B,CAAC,CAAC,QAAQ,CAAC,QAAQ;YACnB,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,CAAC;QAC/C,MAAM,WAAW,GACf,QAAQ,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;QAExF,OAAO;YACL,MAAM;YACN,QAAQ;YACR,WAAW;YACX,UAAU,EAAE;gBACV,GAAG,CAAC,QAAQ,EAAE,UAAU,IAAI,EAAE,CAAC;gBAC/B,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;gBACvC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAC3C,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,CAAC;aAClD;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA7BY,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,CA6B/B"}
@@ -1,12 +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;
7
+ private findMatchingOverride;
8
+ private resolveTargetingKey;
9
+ private getMetadataBucketBy;
10
+ private readBucketValue;
11
+ private result;
11
12
  }
12
- export {};