@nestarc/feature-flag 0.4.0 → 0.6.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.
- package/CHANGELOG.md +186 -0
- package/README.md +130 -681
- package/dist/admin/feature-flag-admin.dto.d.ts +4 -3
- package/dist/admin/feature-flag-admin.dto.js +19 -13
- package/dist/admin/feature-flag-admin.dto.js.map +1 -1
- package/dist/feature-flag.module.d.ts +4 -1
- package/dist/feature-flag.module.js +37 -10
- package/dist/feature-flag.module.js.map +1 -1
- package/dist/flag-registry.js +3 -0
- package/dist/flag-registry.js.map +1 -1
- package/dist/interfaces/evaluation-context.interface.d.ts +5 -5
- package/dist/interfaces/evaluation-details.interface.d.ts +2 -0
- package/dist/interfaces/feature-flag-options.interface.d.ts +19 -5
- package/dist/interfaces/feature-flag.interface.d.ts +2 -2
- package/dist/openfeature.d.ts +6 -9
- package/dist/openfeature.js +38 -8
- package/dist/openfeature.js.map +1 -1
- package/dist/repositories/prisma-feature-flag.repository.js +9 -6
- package/dist/repositories/prisma-feature-flag.repository.js.map +1 -1
- package/dist/services/feature-flag.service.js +4 -2
- package/dist/services/feature-flag.service.js.map +1 -1
- package/dist/services/flag-context-resolver.js +1 -0
- package/dist/services/flag-context-resolver.js.map +1 -1
- package/docs/usage.md +720 -0
- package/package.json +30 -10
- package/prisma/schema.prisma +3 -2
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { EvaluationContext } from '../interfaces/evaluation-context.interface';
|
|
2
|
-
import { EvaluateBooleanOptions } from '../interfaces/evaluation-details.interface';
|
|
2
|
+
import { BucketBy, EvaluateBooleanOptions } from '../interfaces/evaluation-details.interface';
|
|
3
3
|
import { TargetingAttributes } from '../interfaces/feature-flag.interface';
|
|
4
4
|
export declare class CreateFeatureFlagDto {
|
|
5
5
|
key: string;
|
|
6
|
-
description?: string;
|
|
6
|
+
description?: string | null;
|
|
7
7
|
enabled?: boolean;
|
|
8
8
|
percentage?: number;
|
|
9
9
|
metadata?: Record<string, unknown>;
|
|
10
10
|
}
|
|
11
11
|
export declare class UpdateFeatureFlagDto {
|
|
12
|
-
description?: string;
|
|
12
|
+
description?: string | null;
|
|
13
13
|
enabled?: boolean;
|
|
14
14
|
percentage?: number;
|
|
15
15
|
metadata?: Record<string, unknown>;
|
|
@@ -24,6 +24,7 @@ export declare class RemoveOverrideDto {
|
|
|
24
24
|
}
|
|
25
25
|
export declare class EvaluateFeatureFlagDto implements EvaluateBooleanOptions {
|
|
26
26
|
context?: EvaluationContext;
|
|
27
|
+
bucketBy?: BucketBy;
|
|
27
28
|
defaultValue?: boolean;
|
|
28
29
|
trackExposure?: boolean;
|
|
29
30
|
includeContextInEvent?: boolean;
|
|
@@ -23,22 +23,22 @@ __decorate([
|
|
|
23
23
|
__decorate([
|
|
24
24
|
(0, class_validator_1.IsOptional)(),
|
|
25
25
|
(0, class_validator_1.IsString)(),
|
|
26
|
-
__metadata("design:type",
|
|
26
|
+
__metadata("design:type", Object)
|
|
27
27
|
], CreateFeatureFlagDto.prototype, "description", void 0);
|
|
28
28
|
__decorate([
|
|
29
|
-
(0, class_validator_1.
|
|
29
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
30
30
|
(0, class_validator_1.IsBoolean)(),
|
|
31
31
|
__metadata("design:type", Boolean)
|
|
32
32
|
], CreateFeatureFlagDto.prototype, "enabled", void 0);
|
|
33
33
|
__decorate([
|
|
34
|
-
(0, class_validator_1.
|
|
34
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
35
35
|
(0, class_validator_1.IsInt)(),
|
|
36
36
|
(0, class_validator_1.Min)(0),
|
|
37
37
|
(0, class_validator_1.Max)(100),
|
|
38
38
|
__metadata("design:type", Number)
|
|
39
39
|
], CreateFeatureFlagDto.prototype, "percentage", void 0);
|
|
40
40
|
__decorate([
|
|
41
|
-
(0, class_validator_1.
|
|
41
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
42
42
|
(0, class_validator_1.IsObject)(),
|
|
43
43
|
__metadata("design:type", Object)
|
|
44
44
|
], CreateFeatureFlagDto.prototype, "metadata", void 0);
|
|
@@ -48,22 +48,22 @@ exports.UpdateFeatureFlagDto = UpdateFeatureFlagDto;
|
|
|
48
48
|
__decorate([
|
|
49
49
|
(0, class_validator_1.IsOptional)(),
|
|
50
50
|
(0, class_validator_1.IsString)(),
|
|
51
|
-
__metadata("design:type",
|
|
51
|
+
__metadata("design:type", Object)
|
|
52
52
|
], UpdateFeatureFlagDto.prototype, "description", void 0);
|
|
53
53
|
__decorate([
|
|
54
|
-
(0, class_validator_1.
|
|
54
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
55
55
|
(0, class_validator_1.IsBoolean)(),
|
|
56
56
|
__metadata("design:type", Boolean)
|
|
57
57
|
], UpdateFeatureFlagDto.prototype, "enabled", void 0);
|
|
58
58
|
__decorate([
|
|
59
|
-
(0, class_validator_1.
|
|
59
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
60
60
|
(0, class_validator_1.IsInt)(),
|
|
61
61
|
(0, class_validator_1.Min)(0),
|
|
62
62
|
(0, class_validator_1.Max)(100),
|
|
63
63
|
__metadata("design:type", Number)
|
|
64
64
|
], UpdateFeatureFlagDto.prototype, "percentage", void 0);
|
|
65
65
|
__decorate([
|
|
66
|
-
(0, class_validator_1.
|
|
66
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
67
67
|
(0, class_validator_1.IsObject)(),
|
|
68
68
|
__metadata("design:type", Object)
|
|
69
69
|
], UpdateFeatureFlagDto.prototype, "metadata", void 0);
|
|
@@ -79,7 +79,7 @@ __decorate([
|
|
|
79
79
|
__metadata("design:type", Boolean)
|
|
80
80
|
], SetOverrideDto.prototype, "enabled", void 0);
|
|
81
81
|
__decorate([
|
|
82
|
-
(0, class_validator_1.
|
|
82
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
83
83
|
(0, class_validator_1.IsInt)(),
|
|
84
84
|
__metadata("design:type", Number)
|
|
85
85
|
], SetOverrideDto.prototype, "priority", void 0);
|
|
@@ -94,22 +94,28 @@ class EvaluateFeatureFlagDto {
|
|
|
94
94
|
}
|
|
95
95
|
exports.EvaluateFeatureFlagDto = EvaluateFeatureFlagDto;
|
|
96
96
|
__decorate([
|
|
97
|
-
(0, class_validator_1.
|
|
97
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
98
98
|
(0, class_validator_1.IsObject)(),
|
|
99
99
|
__metadata("design:type", Object)
|
|
100
100
|
], EvaluateFeatureFlagDto.prototype, "context", void 0);
|
|
101
101
|
__decorate([
|
|
102
|
-
(0, class_validator_1.
|
|
102
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
103
|
+
(0, class_validator_1.IsString)(),
|
|
104
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
105
|
+
__metadata("design:type", String)
|
|
106
|
+
], EvaluateFeatureFlagDto.prototype, "bucketBy", void 0);
|
|
107
|
+
__decorate([
|
|
108
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
103
109
|
(0, class_validator_1.IsBoolean)(),
|
|
104
110
|
__metadata("design:type", Boolean)
|
|
105
111
|
], EvaluateFeatureFlagDto.prototype, "defaultValue", void 0);
|
|
106
112
|
__decorate([
|
|
107
|
-
(0, class_validator_1.
|
|
113
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
108
114
|
(0, class_validator_1.IsBoolean)(),
|
|
109
115
|
__metadata("design:type", Boolean)
|
|
110
116
|
], EvaluateFeatureFlagDto.prototype, "trackExposure", void 0);
|
|
111
117
|
__decorate([
|
|
112
|
-
(0, class_validator_1.
|
|
118
|
+
(0, class_validator_1.ValidateIf)((_object, value) => value !== undefined),
|
|
113
119
|
(0, class_validator_1.IsBoolean)(),
|
|
114
120
|
__metadata("design:type", Boolean)
|
|
115
121
|
], EvaluateFeatureFlagDto.prototype, "includeContextInEvent", void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flag-admin.dto.js","sourceRoot":"","sources":["../../src/admin/feature-flag-admin.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"feature-flag-admin.dto.js","sourceRoot":"","sources":["../../src/admin/feature-flag-admin.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAUyB;AAIzB,qFAAyE;AAEzE,MAAa,oBAAoB;CAsBhC;AAtBD,oDAsBC;AAnBC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;iDACA;AAIb;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;yDACiB;AAI5B;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,2BAAS,GAAE;;qDACM;AAMlB;IAJC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,uBAAK,GAAE;IACP,IAAA,qBAAG,EAAC,CAAC,CAAC;IACN,IAAA,qBAAG,EAAC,GAAG,CAAC;;wDACW;AAIpB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,0BAAQ,GAAE;;sDACwB;AAGrC,MAAa,oBAAoB;CAkBhC;AAlBD,oDAkBC;AAfC;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;yDACiB;AAI5B;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,2BAAS,GAAE;;qDACM;AAMlB;IAJC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,uBAAK,GAAE;IACP,IAAA,qBAAG,EAAC,CAAC,CAAC;IACN,IAAA,qBAAG,EAAC,GAAG,CAAC;;wDACW;AAIpB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,0BAAQ,GAAE;;sDACwB;AAGrC,MAAa,cAAc;CAU1B;AAVD,wCAUC;AARC;IADC,IAAA,sDAAqB,GAAE;;kDACS;AAGjC;IADC,IAAA,2BAAS,GAAE;;+CACM;AAIlB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,uBAAK,GAAE;;gDACU;AAGpB,MAAa,iBAAiB;CAG7B;AAHD,8CAGC;AADC;IADC,IAAA,sDAAqB,GAAE;;qDACS;AAGnC,MAAa,sBAAsB;CAqBlC;AArBD,wDAqBC;AAlBC;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,0BAAQ,GAAE;;uDACiB;AAK5B;IAHC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;wDACO;AAIpB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,2BAAS,GAAE;;4DACW;AAIvB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,2BAAS,GAAE;;6DACY;AAIxB;IAFC,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;IACnD,IAAA,2BAAS,GAAE;;qEACoB"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
|
|
2
2
|
import { FeatureFlagModuleAsyncOptions, FeatureFlagModuleOptions } from './interfaces/feature-flag-options.interface';
|
|
3
3
|
export interface FeatureFlagModuleRootOptions extends FeatureFlagModuleOptions {
|
|
4
|
-
|
|
4
|
+
/** Prisma client used by the default repository. Required unless repository is provided. */
|
|
5
|
+
prisma?: any;
|
|
5
6
|
}
|
|
6
7
|
export interface FeatureFlagModuleRootAsyncOptions extends FeatureFlagModuleAsyncOptions {
|
|
7
8
|
useFactory?: (...args: any[]) => Promise<FeatureFlagModuleRootOptions> | FeatureFlagModuleRootOptions;
|
|
@@ -10,5 +11,7 @@ export declare class FeatureFlagModule implements NestModule {
|
|
|
10
11
|
configure(consumer: MiddlewareConsumer): void;
|
|
11
12
|
static forRoot(options: FeatureFlagModuleRootOptions): DynamicModule;
|
|
12
13
|
static forRootAsync(options: FeatureFlagModuleRootAsyncOptions): DynamicModule;
|
|
14
|
+
private static createRepository;
|
|
15
|
+
private static createTenantDelegate;
|
|
13
16
|
private static createAsyncProviders;
|
|
14
17
|
}
|
|
@@ -32,12 +32,11 @@ const coreProviders = [
|
|
|
32
32
|
];
|
|
33
33
|
let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
|
|
34
34
|
configure(consumer) {
|
|
35
|
-
consumer
|
|
36
|
-
.apply(flag_context_middleware_1.FlagContextMiddleware)
|
|
37
|
-
.forRoutes({ path: '(.*)', method: common_1.RequestMethod.ALL });
|
|
35
|
+
consumer.apply(flag_context_middleware_1.FlagContextMiddleware).forRoutes({ path: '(.*)', method: common_1.RequestMethod.ALL });
|
|
38
36
|
}
|
|
39
37
|
static forRoot(options) {
|
|
40
38
|
const { prisma, ...moduleOptions } = options;
|
|
39
|
+
const repository = this.createRepository(prisma, options.repository);
|
|
41
40
|
let eventProvider = { provide: 'EVENT_EMITTER', useValue: null };
|
|
42
41
|
if (options.emitEvents) {
|
|
43
42
|
try {
|
|
@@ -60,12 +59,14 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
|
|
|
60
59
|
},
|
|
61
60
|
{
|
|
62
61
|
provide: feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
|
|
63
|
-
useValue:
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
|
|
67
|
-
useClass: default_tenant_context_provider_1.DefaultTenantContextProvider,
|
|
62
|
+
useValue: repository,
|
|
68
63
|
},
|
|
64
|
+
options.tenantContextProvider
|
|
65
|
+
? {
|
|
66
|
+
provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
|
|
67
|
+
useValue: this.createTenantDelegate(options.tenantContextProvider),
|
|
68
|
+
}
|
|
69
|
+
: { provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER, useClass: default_tenant_context_provider_1.DefaultTenantContextProvider },
|
|
69
70
|
...coreProviders,
|
|
70
71
|
],
|
|
71
72
|
exports: [
|
|
@@ -113,12 +114,15 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
|
|
|
113
114
|
},
|
|
114
115
|
{
|
|
115
116
|
provide: feature_flag_constants_1.FEATURE_FLAG_REPOSITORY,
|
|
116
|
-
useFactory: (full) =>
|
|
117
|
+
useFactory: (full) => this.createRepository(full.prisma, full.repository),
|
|
117
118
|
inject: [FULL_OPTIONS],
|
|
118
119
|
},
|
|
119
120
|
{
|
|
120
121
|
provide: feature_flag_constants_1.TENANT_CONTEXT_PROVIDER,
|
|
121
|
-
|
|
122
|
+
useFactory: (full, moduleRef) => full.tenantContextProvider
|
|
123
|
+
? this.createTenantDelegate(full.tenantContextProvider)
|
|
124
|
+
: new default_tenant_context_provider_1.DefaultTenantContextProvider(moduleRef),
|
|
125
|
+
inject: [FULL_OPTIONS, core_1.ModuleRef],
|
|
122
126
|
},
|
|
123
127
|
...coreProviders,
|
|
124
128
|
],
|
|
@@ -132,6 +136,29 @@ let FeatureFlagModule = FeatureFlagModule_1 = class FeatureFlagModule {
|
|
|
132
136
|
],
|
|
133
137
|
};
|
|
134
138
|
}
|
|
139
|
+
static createRepository(prisma, repository) {
|
|
140
|
+
if (repository) {
|
|
141
|
+
// Delegate only the storage port: the caller owns the supplied instance's lifecycle.
|
|
142
|
+
return {
|
|
143
|
+
createFlag: repository.createFlag.bind(repository),
|
|
144
|
+
updateFlag: repository.updateFlag.bind(repository),
|
|
145
|
+
archiveFlag: repository.archiveFlag.bind(repository),
|
|
146
|
+
findFlagByKey: repository.findFlagByKey.bind(repository),
|
|
147
|
+
findFlagIdByKey: repository.findFlagIdByKey.bind(repository),
|
|
148
|
+
findAllActiveFlags: repository.findAllActiveFlags.bind(repository),
|
|
149
|
+
findOverride: repository.findOverride.bind(repository),
|
|
150
|
+
createOverride: repository.createOverride.bind(repository),
|
|
151
|
+
updateOverride: repository.updateOverride.bind(repository),
|
|
152
|
+
deleteOverride: repository.deleteOverride.bind(repository),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (prisma)
|
|
156
|
+
return new prisma_feature_flag_repository_1.PrismaFeatureFlagRepository(prisma);
|
|
157
|
+
throw new Error('FeatureFlagModule requires either a prisma client or a custom repository.');
|
|
158
|
+
}
|
|
159
|
+
static createTenantDelegate(provider) {
|
|
160
|
+
return { getCurrentTenantId: provider.getCurrentTenantId.bind(provider) };
|
|
161
|
+
}
|
|
135
162
|
static createAsyncProviders(options) {
|
|
136
163
|
if (options.useFactory) {
|
|
137
164
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flag.module.js","sourceRoot":"","sources":["../src/feature-flag.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAOwB;AACxB,uCAAyC;AACzC,qEAKkC;AAMlC,0EAAqE;AACrE,uEAAkE;AAClE,kGAA4F;AAC5F,gGAA0F;AAC1F,8EAAyE;AACzE,0DAAsD;AACtD,4EAAuE;AACvE,0EAAqE;AACrE,oEAA+D;AAC/D,kFAA6E;
|
|
1
|
+
{"version":3,"file":"feature-flag.module.js","sourceRoot":"","sources":["../src/feature-flag.module.ts"],"names":[],"mappings":"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"}
|
package/dist/flag-registry.js
CHANGED
|
@@ -39,6 +39,9 @@ function mergeRegistryOptions(definition, options = {}) {
|
|
|
39
39
|
const merged = {
|
|
40
40
|
defaultValue: definition.defaultValue,
|
|
41
41
|
};
|
|
42
|
+
if (definition.bucketBy !== undefined) {
|
|
43
|
+
merged.bucketBy = definition.bucketBy;
|
|
44
|
+
}
|
|
42
45
|
if (definition.trackExposure !== undefined) {
|
|
43
46
|
merged.trackExposure = definition.trackExposure;
|
|
44
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flag-registry.js","sourceRoot":"","sources":["../src/flag-registry.ts"],"names":[],"mappings":";;AA8CA,kCAEC;AAED,0DAeC;AAED,kEAUC;AAED,wDAeC;AA9FD,gFAAkE;AA8ClE,SAAgB,WAAW,CAAoC,KAAa;IAC1E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,uBAAuB,CACrC,OAA2B,EAC3B,QAAgB;IAEhB,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CACvC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QACvF,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAC7C,OAAO,CAAC,eAAe,CACrB,OAAO,EACP,OAAO,EACP,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CACjD;KACJ,CAAC;AACJ,CAAC;AAED,SAAgB,2BAA2B,CACzC,QAAgB;IAEhB,OAAO;QACL,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CACrC,IAAA,oCAAW,EAAC,OAAO,EAAE;YACnB,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,YAAY;YAC5C,GAAG,OAAO;SACX,CAAC;KACL,CAAC;AACJ,CAAC;AAED,SAAgB,sBAAsB,CACpC,QAAsC,EACtC,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAE/D,OAAO;QACL,GAAG,QAAQ;QACX,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAChC,OAAO;QACP,SAAS;QACT,MAAM;KACP,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAC3B,UAAgC,EAChC,UAAkC,EAAE;IAEpC,MAAM,MAAM,GAA2B;QACrC,YAAY,EAAE,UAAU,CAAC,YAAY;KACtC,CAAC;IAEF,IAAI,UAAU,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,CAAC,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,sBAAsB,CAC7B,GAAS,EACT,OAAc,EACd,SAAgB;IAEhB,IAAI,SAAS,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAgC;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC"}
|
|
1
|
+
{"version":3,"file":"flag-registry.js","sourceRoot":"","sources":["../src/flag-registry.ts"],"names":[],"mappings":";;AA8CA,kCAEC;AAED,0DAeC;AAED,kEAUC;AAED,wDAeC;AA9FD,gFAAkE;AA8ClE,SAAgB,WAAW,CAAoC,KAAa;IAC1E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,uBAAuB,CACrC,OAA2B,EAC3B,QAAgB;IAEhB,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CACvC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QACvF,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAC7C,OAAO,CAAC,eAAe,CACrB,OAAO,EACP,OAAO,EACP,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CACjD;KACJ,CAAC;AACJ,CAAC;AAED,SAAgB,2BAA2B,CACzC,QAAgB;IAEhB,OAAO;QACL,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CACrC,IAAA,oCAAW,EAAC,OAAO,EAAE;YACnB,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,YAAY;YAC5C,GAAG,OAAO;SACX,CAAC;KACL,CAAC;AACJ,CAAC;AAED,SAAgB,sBAAsB,CACpC,QAAsC,EACtC,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAE/D,OAAO;QACL,GAAG,QAAQ;QACX,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAChC,OAAO;QACP,SAAS;QACT,MAAM;KACP,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAC3B,UAAgC,EAChC,UAAkC,EAAE;IAEpC,MAAM,MAAM,GAA2B;QACrC,YAAY,EAAE,UAAU,CAAC,YAAY;KACtC,CAAC;IAEF,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;IACxC,CAAC;IAED,IAAI,UAAU,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,CAAC,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,sBAAsB,CAC7B,GAAS,EACT,OAAc,EACd,SAAgB;IAEhB,IAAI,SAAS,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAgC;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { TargetingAttributes } from './feature-flag.interface';
|
|
2
2
|
export interface EvaluationContext {
|
|
3
|
-
/** User ID
|
|
3
|
+
/** User ID for targeting and percentage bucketing. Null suppresses the ambient user ID. */
|
|
4
4
|
userId?: string | null;
|
|
5
|
-
/** Tenant ID
|
|
5
|
+
/** Tenant ID for targeting and percentage bucketing, including without a tenancy package. Null suppresses the ambient tenant ID. */
|
|
6
6
|
tenantId?: string | null;
|
|
7
|
-
/** Environment
|
|
8
|
-
environment?: string;
|
|
9
|
-
/**
|
|
7
|
+
/** Environment defaults to module options. An explicit value or null overrides that default. */
|
|
8
|
+
environment?: string | null;
|
|
9
|
+
/** Non-empty stable key for percentage bucketing; takes precedence over bucketBy. Null or an empty string allows normal fallback. */
|
|
10
10
|
targetingKey?: string | null;
|
|
11
11
|
/** Additional exact-match targeting attributes */
|
|
12
12
|
attributes?: TargetingAttributes;
|
|
@@ -4,6 +4,8 @@ export type BucketBy = 'userId' | 'tenantId' | 'environment' | 'targetingKey' |
|
|
|
4
4
|
export interface EvaluateBooleanOptions {
|
|
5
5
|
/** Invocation-level default used when the flag is missing or evaluation fails. */
|
|
6
6
|
defaultValue?: boolean;
|
|
7
|
+
/** Percentage bucket attribute, overriding registry and flag metadata. A non-empty context.targetingKey takes precedence. */
|
|
8
|
+
bucketBy?: BucketBy;
|
|
7
9
|
/** Emit an exposure event for this evaluation. */
|
|
8
10
|
trackExposure?: boolean;
|
|
9
11
|
/** Include the full resolved context in evaluation/exposure events. */
|
|
@@ -2,27 +2,41 @@ import { ModuleMetadata, Type } from '@nestjs/common';
|
|
|
2
2
|
import { Request } from 'express';
|
|
3
3
|
import { CacheAdapter } from './cache-adapter.interface';
|
|
4
4
|
import { FlagRegistry } from './flag-registry.interface';
|
|
5
|
+
import { FeatureFlagRepository } from './feature-flag-repository.interface';
|
|
6
|
+
import { TenantContextProvider } from './tenant-context-provider.interface';
|
|
5
7
|
export interface FeatureFlagModuleOptions {
|
|
6
8
|
/** Current environment (e.g., 'development', 'staging', 'production') */
|
|
7
9
|
environment: string;
|
|
8
|
-
/** Cache TTL in milliseconds. 0
|
|
10
|
+
/** Cache TTL in milliseconds. 0 skips cache writes; existing shared entries can still be read. Default: 30000. */
|
|
9
11
|
cacheTtlMs?: number;
|
|
10
12
|
/** Extract user ID from request. Returns null if user is not authenticated. */
|
|
11
13
|
userIdExtractor?: (req: Request) => string | null;
|
|
12
|
-
/**
|
|
14
|
+
/** Fallback for an individual missing/error evaluation when no higher-priority default is supplied. Default: false. */
|
|
13
15
|
defaultOnMissing?: boolean;
|
|
14
|
-
/**
|
|
16
|
+
/** Enable lifecycle/evaluation events through an imported EventEmitterModule. Exposure events also require opt-in. Default: false. */
|
|
15
17
|
emitEvents?: boolean;
|
|
16
18
|
/** Custom cache adapter implementation. If not provided, an in-memory cache is used. */
|
|
17
19
|
cacheAdapter?: CacheAdapter;
|
|
20
|
+
/**
|
|
21
|
+
* Custom storage instance. Takes precedence over prisma when both are provided.
|
|
22
|
+
* Its declaring module/caller owns initialization and cleanup. The exported
|
|
23
|
+
* FEATURE_FLAG_REPOSITORY token delegates storage methods without lifecycle hooks.
|
|
24
|
+
*/
|
|
25
|
+
repository?: FeatureFlagRepository;
|
|
26
|
+
/**
|
|
27
|
+
* Custom tenant resolver instance. Defaults to the optional @nestarc/tenancy integration.
|
|
28
|
+
* Its declaring module/caller owns initialization and cleanup. The exported
|
|
29
|
+
* TENANT_CONTEXT_PROVIDER token delegates resolution without lifecycle hooks.
|
|
30
|
+
*/
|
|
31
|
+
tenantContextProvider?: TenantContextProvider;
|
|
18
32
|
/** Optional type-safe flag registry used for defaults and evaluation metadata. */
|
|
19
33
|
flags?: FlagRegistry;
|
|
20
34
|
}
|
|
21
35
|
export interface FeatureFlagModuleOptionsFactory {
|
|
22
36
|
createFeatureFlagOptions(): Promise<FeatureFlagModuleOptions & {
|
|
23
|
-
prisma
|
|
37
|
+
prisma?: any;
|
|
24
38
|
}> | (FeatureFlagModuleOptions & {
|
|
25
|
-
prisma
|
|
39
|
+
prisma?: any;
|
|
26
40
|
});
|
|
27
41
|
}
|
|
28
42
|
export interface FeatureFlagModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
@@ -2,13 +2,13 @@ export type TargetingAttributeValue = string | number | boolean | null;
|
|
|
2
2
|
export type TargetingAttributes = Record<string, TargetingAttributeValue>;
|
|
3
3
|
export interface CreateFeatureFlagInput {
|
|
4
4
|
key: string;
|
|
5
|
-
description?: string;
|
|
5
|
+
description?: string | null;
|
|
6
6
|
enabled?: boolean;
|
|
7
7
|
percentage?: number;
|
|
8
8
|
metadata?: Record<string, unknown>;
|
|
9
9
|
}
|
|
10
10
|
export interface UpdateFeatureFlagInput {
|
|
11
|
-
description?: string;
|
|
11
|
+
description?: string | null;
|
|
12
12
|
enabled?: boolean;
|
|
13
13
|
percentage?: number;
|
|
14
14
|
metadata?: Record<string, unknown>;
|
package/dist/openfeature.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FlagMetadata, Provider, ResolutionDetails } from '@openfeature/server-sdk';
|
|
2
|
+
import type { FeatureFlagService } from './services/feature-flag.service';
|
|
2
3
|
export interface OpenFeatureBooleanProviderOptions {
|
|
3
4
|
name?: string;
|
|
4
5
|
}
|
|
@@ -9,18 +10,14 @@ export interface OpenFeatureEvaluationContext {
|
|
|
9
10
|
environment?: unknown;
|
|
10
11
|
[key: string]: unknown;
|
|
11
12
|
}
|
|
12
|
-
export interface OpenFeatureBooleanResolutionDetails {
|
|
13
|
-
value: boolean;
|
|
13
|
+
export interface OpenFeatureBooleanResolutionDetails extends ResolutionDetails<boolean> {
|
|
14
14
|
reason: string;
|
|
15
|
-
|
|
16
|
-
errorCode?: string;
|
|
17
|
-
errorMessage?: string;
|
|
18
|
-
flagMetadata: Record<string, unknown>;
|
|
15
|
+
flagMetadata: FlagMetadata;
|
|
19
16
|
}
|
|
20
|
-
export interface OpenFeatureBooleanProvider {
|
|
17
|
+
export interface OpenFeatureBooleanProvider extends Provider {
|
|
21
18
|
metadata: {
|
|
22
19
|
name: string;
|
|
23
20
|
};
|
|
24
21
|
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: OpenFeatureEvaluationContext): Promise<OpenFeatureBooleanResolutionDetails>;
|
|
25
22
|
}
|
|
26
|
-
export declare function createOpenFeatureBooleanProvider(service: FeatureFlagService, options?: OpenFeatureBooleanProviderOptions): OpenFeatureBooleanProvider;
|
|
23
|
+
export declare function createOpenFeatureBooleanProvider(service: Pick<FeatureFlagService, 'evaluateBoolean'>, options?: OpenFeatureBooleanProviderOptions): OpenFeatureBooleanProvider;
|
package/dist/openfeature.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.createOpenFeatureBooleanProvider = createOpenFeatureBooleanProvider;
|
|
|
4
4
|
const targeting_attributes_1 = require("./utils/targeting-attributes");
|
|
5
5
|
function createOpenFeatureBooleanProvider(service, options = {}) {
|
|
6
6
|
return {
|
|
7
|
+
runsOn: 'server',
|
|
7
8
|
metadata: {
|
|
8
9
|
name: options.name ?? '@nestarc/feature-flag',
|
|
9
10
|
},
|
|
@@ -16,16 +17,36 @@ function createOpenFeatureBooleanProvider(service, options = {}) {
|
|
|
16
17
|
return {
|
|
17
18
|
value: defaultValue,
|
|
18
19
|
reason: 'ERROR',
|
|
19
|
-
errorCode:
|
|
20
|
+
errorCode: errorCodes.GENERAL,
|
|
20
21
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
21
22
|
flagMetadata: {
|
|
22
23
|
source: 'default',
|
|
23
24
|
localReason: 'ERROR',
|
|
24
25
|
defaultUsed: true,
|
|
26
|
+
localErrorCode: error instanceof Error ? error.constructor.name : 'Error',
|
|
25
27
|
},
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
},
|
|
31
|
+
resolveStringEvaluation: async (_flagKey, defaultValue) => unsupportedType(defaultValue),
|
|
32
|
+
resolveNumberEvaluation: async (_flagKey, defaultValue) => unsupportedType(defaultValue),
|
|
33
|
+
resolveObjectEvaluation: async (_flagKey, defaultValue) => unsupportedType(defaultValue),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Keep the SDK optional at runtime. Its string enum values are verified by the
|
|
37
|
+
// SDK integration tests; importing the enum as a value would load the SDK.
|
|
38
|
+
const errorCodes = {
|
|
39
|
+
GENERAL: 'GENERAL',
|
|
40
|
+
FLAG_NOT_FOUND: 'FLAG_NOT_FOUND',
|
|
41
|
+
TYPE_MISMATCH: 'TYPE_MISMATCH',
|
|
42
|
+
};
|
|
43
|
+
function unsupportedType(defaultValue) {
|
|
44
|
+
return {
|
|
45
|
+
value: defaultValue,
|
|
46
|
+
reason: 'ERROR',
|
|
47
|
+
errorCode: errorCodes.TYPE_MISMATCH,
|
|
48
|
+
errorMessage: '@nestarc/feature-flag supports boolean flags only',
|
|
49
|
+
flagMetadata: { source: 'default', defaultUsed: true },
|
|
29
50
|
};
|
|
30
51
|
}
|
|
31
52
|
function toEvaluationContext(context) {
|
|
@@ -42,7 +63,7 @@ function toEvaluationContext(context) {
|
|
|
42
63
|
targetingKey: readString(context.targetingKey),
|
|
43
64
|
userId: readString(context.userId),
|
|
44
65
|
tenantId: readString(context.tenantId),
|
|
45
|
-
environment: readString(context.environment)
|
|
66
|
+
environment: readString(context.environment),
|
|
46
67
|
attributes,
|
|
47
68
|
};
|
|
48
69
|
}
|
|
@@ -50,16 +71,25 @@ function toOpenFeatureResolution(details) {
|
|
|
50
71
|
return {
|
|
51
72
|
value: details.value,
|
|
52
73
|
reason: mapOpenFeatureReason(details.reason),
|
|
53
|
-
errorCode: details.
|
|
74
|
+
errorCode: details.reason === 'FLAG_NOT_FOUND'
|
|
75
|
+
? errorCodes.FLAG_NOT_FOUND
|
|
76
|
+
: details.reason === 'ERROR'
|
|
77
|
+
? errorCodes.GENERAL
|
|
78
|
+
: undefined,
|
|
54
79
|
errorMessage: details.errorMessage,
|
|
55
80
|
flagMetadata: {
|
|
56
81
|
source: details.source,
|
|
57
82
|
localReason: details.reason,
|
|
58
83
|
defaultUsed: details.defaultUsed,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
84
|
+
...(details.matchedOverrideId !== undefined && {
|
|
85
|
+
matchedOverrideId: details.matchedOverrideId,
|
|
86
|
+
}),
|
|
87
|
+
...(details.bucket !== undefined && { bucket: details.bucket }),
|
|
88
|
+
...(details.targetingKey !== undefined && { targetingKey: details.targetingKey }),
|
|
89
|
+
...(details.evaluationTimeMs !== undefined && {
|
|
90
|
+
evaluationTimeMs: details.evaluationTimeMs,
|
|
91
|
+
}),
|
|
92
|
+
...(details.errorCode !== undefined && { localErrorCode: details.errorCode }),
|
|
63
93
|
},
|
|
64
94
|
};
|
|
65
95
|
}
|
|
@@ -70,9 +100,9 @@ function mapOpenFeatureReason(reason) {
|
|
|
70
100
|
case 'PERCENTAGE_MATCH':
|
|
71
101
|
case 'PERCENTAGE_MISS':
|
|
72
102
|
return 'SPLIT';
|
|
73
|
-
case 'FLAG_NOT_FOUND':
|
|
74
103
|
case 'PERCENTAGE_NO_TARGETING_KEY':
|
|
75
104
|
return 'DEFAULT';
|
|
105
|
+
case 'FLAG_NOT_FOUND':
|
|
76
106
|
case 'ERROR':
|
|
77
107
|
return 'ERROR';
|
|
78
108
|
case 'ARCHIVED':
|
package/dist/openfeature.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openfeature.js","sourceRoot":"","sources":["../src/openfeature.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"openfeature.js","sourceRoot":"","sources":["../src/openfeature.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,15 +17,18 @@ function isPrismaError(error, code) {
|
|
|
17
17
|
'code' in error &&
|
|
18
18
|
error.code === code);
|
|
19
19
|
}
|
|
20
|
+
function assertValidPercentage(percentage) {
|
|
21
|
+
if (!Number.isInteger(percentage) || percentage < 0 || percentage > 100) {
|
|
22
|
+
throw new common_1.BadRequestException('percentage must be an integer between 0 and 100');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
20
25
|
let PrismaFeatureFlagRepository = class PrismaFeatureFlagRepository {
|
|
21
26
|
constructor(prisma) {
|
|
22
27
|
this.prisma = prisma;
|
|
23
28
|
}
|
|
24
29
|
async createFlag(input) {
|
|
25
|
-
const percentage = input.percentage
|
|
26
|
-
|
|
27
|
-
throw new common_1.BadRequestException(`percentage must be between 0 and 100, got ${percentage}`);
|
|
28
|
-
}
|
|
30
|
+
const percentage = input.percentage === undefined ? 0 : input.percentage;
|
|
31
|
+
assertValidPercentage(percentage);
|
|
29
32
|
try {
|
|
30
33
|
return await this.prisma.featureFlag.create({
|
|
31
34
|
data: {
|
|
@@ -46,8 +49,8 @@ let PrismaFeatureFlagRepository = class PrismaFeatureFlagRepository {
|
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
async updateFlag(key, input) {
|
|
49
|
-
if (input.percentage !== undefined
|
|
50
|
-
|
|
52
|
+
if (input.percentage !== undefined) {
|
|
53
|
+
assertValidPercentage(input.percentage);
|
|
51
54
|
}
|
|
52
55
|
try {
|
|
53
56
|
return await this.prisma.featureFlag.update({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-feature-flag.repository.js","sourceRoot":"","sources":["../../src/repositories/prisma-feature-flag.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAYxB,SAAS,aAAa,CAAC,KAAc,EAAE,IAAY;IACjD,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACd,KAAa,CAAC,IAAI,KAAK,IAAI,CAC7B,CAAC;AACJ,CAAC;AAGM,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;IACtC,YAA6B,MAAW;QAAX,WAAM,GAAN,MAAM,CAAK;IAAG,CAAC;IAE5C,KAAK,CAAC,UAAU,CAAC,KAA6B;QAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"prisma-feature-flag.repository.js","sourceRoot":"","sources":["../../src/repositories/prisma-feature-flag.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,7 +46,7 @@ let FeatureFlagService = class FeatureFlagService {
|
|
|
46
46
|
const details = flag
|
|
47
47
|
? {
|
|
48
48
|
...this.evaluator.evaluate(flag, context, {
|
|
49
|
-
bucketBy: registryDefinition?.bucketBy,
|
|
49
|
+
bucketBy: evaluationOptions.bucketBy ?? registryDefinition?.bucketBy,
|
|
50
50
|
}),
|
|
51
51
|
evaluationTimeMs: Date.now() - startTime,
|
|
52
52
|
}
|
|
@@ -71,7 +71,9 @@ let FeatureFlagService = class FeatureFlagService {
|
|
|
71
71
|
const context = this.contextResolver.resolve(explicitContext);
|
|
72
72
|
const result = {};
|
|
73
73
|
for (const flag of flags) {
|
|
74
|
-
result[flag.key] = this.evaluator.evaluate(flag, context
|
|
74
|
+
result[flag.key] = this.evaluator.evaluate(flag, context, {
|
|
75
|
+
bucketBy: this.options.flags?.[flag.key]?.bucketBy,
|
|
76
|
+
}).result;
|
|
75
77
|
}
|
|
76
78
|
return result;
|
|
77
79
|
}
|