@openfeature/server-sdk 1.20.2 → 1.21.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/dist/types.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { BaseHook, FlagValue, EvaluationContext, HookHints, EvaluationDetails, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, ProviderEntryInput, ProviderMetadata, RegisteredProvider, BaseEvaluationStrategy, TrackingEventDetails, BaseStrategyProviderContext, BaseStrategyPerProviderContext, BaseProviderResolutionResult, BaseProviderResolutionSuccessResult, BaseProviderResolutionErrorResult, BaseFinalResult, BaseFirstMatchStrategy, BaseFirstSuccessfulStrategy, BaseComparisonStrategy, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core';
1
+ import { BaseHook, FlagValue, EvaluationContext, BooleanFlagKey, HookHints, EvaluationDetails, StringFlagKey, NumberFlagKey, ObjectFlagKey, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, ProviderEntryInput, ProviderMetadata, RegisteredProvider, BaseEvaluationStrategy, TrackingEventDetails, BaseStrategyProviderContext, BaseStrategyPerProviderContext, BaseProviderResolutionResult, BaseProviderResolutionSuccessResult, BaseProviderResolutionErrorResult, BaseFinalResult, BaseFirstMatchStrategy, BaseFirstSuccessfulStrategy, BaseComparisonStrategy, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core';
2
2
  export * from '@openfeature/core';
3
3
  export { ServerProviderEvents as ProviderEvents, ServerProviderStatus as ProviderStatus, StrategyEvaluationContext } from '@openfeature/core';
4
4
  import { EventEmitter } from 'node:events';
5
5
 
6
6
  type Hook<TData = Record<string, unknown>> = BaseHook<FlagValue, TData, Promise<EvaluationContext | void> | EvaluationContext | void, Promise<void> | void>;
7
7
 
8
+ type ConstrainedFlagKey<T> = T extends boolean ? BooleanFlagKey : T extends number ? NumberFlagKey : T extends string ? StringFlagKey : T extends JsonValue ? ObjectFlagKey : never;
8
9
  interface FlagEvaluationOptions {
9
10
  hooks?: Hook[];
10
11
  hookHints?: HookHints;
@@ -12,88 +13,88 @@ interface FlagEvaluationOptions {
12
13
  interface Features {
13
14
  /**
14
15
  * Performs a flag evaluation that returns a boolean.
15
- * @param {string} flagKey The flag key uniquely identifies a particular flag
16
+ * @param {BooleanFlagKey} flagKey The flag key uniquely identifies a particular flag
16
17
  * @param {boolean} defaultValue The value returned if an error occurs
17
18
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
18
19
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
19
20
  * @returns {Promise<boolean>} Flag evaluation response
20
21
  */
21
- getBooleanValue(flagKey: string, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<boolean>;
22
+ getBooleanValue(flagKey: BooleanFlagKey, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<boolean>;
22
23
  /**
23
24
  * Performs a flag evaluation that a returns an evaluation details object.
24
- * @param {string} flagKey The flag key uniquely identifies a particular flag
25
+ * @param {BooleanFlagKey} flagKey The flag key uniquely identifies a particular flag
25
26
  * @param {boolean} defaultValue The value returned if an error occurs
26
27
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
27
28
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
28
29
  * @returns {Promise<EvaluationDetails<boolean>>} Flag evaluation details response
29
30
  */
30
- getBooleanDetails(flagKey: string, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<boolean>>;
31
+ getBooleanDetails(flagKey: BooleanFlagKey, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<boolean>>;
31
32
  /**
32
33
  * Performs a flag evaluation that returns a string.
33
- * @param {string} flagKey The flag key uniquely identifies a particular flag
34
+ * @param {StringFlagKey} flagKey The flag key uniquely identifies a particular flag
34
35
  * @template {string} T A optional generic argument constraining the string
35
36
  * @param {T} defaultValue The value returned if an error occurs
36
37
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
37
38
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
38
39
  * @returns {Promise<T>} Flag evaluation response
39
40
  */
40
- getStringValue(flagKey: string, defaultValue: string, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<string>;
41
- getStringValue<T extends string = string>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
41
+ getStringValue(flagKey: StringFlagKey, defaultValue: string, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<string>;
42
+ getStringValue<T extends string = string>(flagKey: StringFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
42
43
  /**
43
44
  * Performs a flag evaluation that a returns an evaluation details object.
44
- * @param {string} flagKey The flag key uniquely identifies a particular flag
45
+ * @param {StringFlagKey} flagKey The flag key uniquely identifies a particular flag
45
46
  * @template {string} T A optional generic argument constraining the string
46
47
  * @param {T} defaultValue The value returned if an error occurs
47
48
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
48
49
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
49
50
  * @returns {Promise<EvaluationDetails<T>>} Flag evaluation details response
50
51
  */
51
- getStringDetails(flagKey: string, defaultValue: string, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<string>>;
52
- getStringDetails<T extends string = string>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
52
+ getStringDetails(flagKey: StringFlagKey, defaultValue: string, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<string>>;
53
+ getStringDetails<T extends string = string>(flagKey: StringFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
53
54
  /**
54
55
  * Performs a flag evaluation that returns a number.
55
- * @param {string} flagKey The flag key uniquely identifies a particular flag
56
+ * @param {NumberFlagKey} flagKey The flag key uniquely identifies a particular flag
56
57
  * @template {number} T A optional generic argument constraining the number
57
58
  * @param {T} defaultValue The value returned if an error occurs
58
59
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
59
60
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
60
61
  * @returns {Promise<T>} Flag evaluation response
61
62
  */
62
- getNumberValue(flagKey: string, defaultValue: number, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<number>;
63
- getNumberValue<T extends number = number>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
63
+ getNumberValue(flagKey: NumberFlagKey, defaultValue: number, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<number>;
64
+ getNumberValue<T extends number = number>(flagKey: NumberFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
64
65
  /**
65
66
  * Performs a flag evaluation that a returns an evaluation details object.
66
- * @param {string} flagKey The flag key uniquely identifies a particular flag
67
+ * @param {NumberFlagKey} flagKey The flag key uniquely identifies a particular flag
67
68
  * @template {number} T A optional generic argument constraining the number
68
69
  * @param {T} defaultValue The value returned if an error occurs
69
70
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
70
71
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
71
72
  * @returns {Promise<EvaluationDetails<T>>} Flag evaluation details response
72
73
  */
73
- getNumberDetails(flagKey: string, defaultValue: number, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<number>>;
74
- getNumberDetails<T extends number = number>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
74
+ getNumberDetails(flagKey: NumberFlagKey, defaultValue: number, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<number>>;
75
+ getNumberDetails<T extends number = number>(flagKey: NumberFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
75
76
  /**
76
77
  * Performs a flag evaluation that returns an object.
77
- * @param {string} flagKey The flag key uniquely identifies a particular flag
78
+ * @param {ObjectFlagKey} flagKey The flag key uniquely identifies a particular flag
78
79
  * @template {JsonValue} T A optional generic argument describing the structure
79
80
  * @param {T} defaultValue The value returned if an error occurs
80
81
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
81
82
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
82
83
  * @returns {Promise<T>} Flag evaluation response
83
84
  */
84
- getObjectValue(flagKey: string, defaultValue: JsonValue, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<JsonValue>;
85
- getObjectValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
85
+ getObjectValue(flagKey: ObjectFlagKey, defaultValue: JsonValue, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<JsonValue>;
86
+ getObjectValue<T extends JsonValue = JsonValue>(flagKey: ObjectFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>;
86
87
  /**
87
88
  * Performs a flag evaluation that a returns an evaluation details object.
88
- * @param {string} flagKey The flag key uniquely identifies a particular flag
89
+ * @param {ObjectFlagKey} flagKey The flag key uniquely identifies a particular flag
89
90
  * @template {JsonValue} T A optional generic argument describing the structure
90
91
  * @param {T} defaultValue The value returned if an error occurs
91
92
  * @param {EvaluationContext} context The evaluation context used on an individual flag evaluation
92
93
  * @param {FlagEvaluationOptions} options Additional flag evaluation options
93
94
  * @returns {Promise<EvaluationDetails<T>>} Flag evaluation details response
94
95
  */
95
- getObjectDetails(flagKey: string, defaultValue: JsonValue, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<JsonValue>>;
96
- getObjectDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
96
+ getObjectDetails(flagKey: ObjectFlagKey, defaultValue: JsonValue, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<JsonValue>>;
97
+ getObjectDetails<T extends JsonValue = JsonValue>(flagKey: ObjectFlagKey, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>;
97
98
  }
98
99
 
99
100
  /**
@@ -149,19 +150,23 @@ declare const NOOP_PROVIDER: NoopFeatureProvider;
149
150
  * but just for the in-memory provider.
150
151
  */
151
152
 
152
- type Variants<T> = Record<string, T>;
153
+ type NoInfer<T> = [T][T extends unknown ? 0 : never];
154
+ type Simplify<T> = {
155
+ [K in keyof T]: T[K];
156
+ } & {};
157
+ type FlagVariants<T extends string> = Record<T, boolean> | Record<T, string> | Record<T, number> | Record<T, JsonValue>;
153
158
  /**
154
159
  * A Feature Flag definition, containing it's specification
155
160
  */
156
- type Flag = {
161
+ type Flag<T extends string = string> = {
157
162
  /**
158
163
  * An object containing all possible flags mappings (variant -> flag value)
159
164
  */
160
- variants: Variants<boolean> | Variants<string> | Variants<number> | Variants<JsonValue>;
165
+ variants: FlagVariants<T>;
161
166
  /**
162
167
  * The variant it will resolve to in STATIC evaluation
163
168
  */
164
- defaultVariant: string;
169
+ defaultVariant: NoInfer<T>;
165
170
  /**
166
171
  * Determines if flag evaluation is enabled or not for this flag.
167
172
  * If false, falls back to the default value provided to the client
@@ -173,12 +178,22 @@ type Flag = {
173
178
  * If it does not return a valid variant it falls back to the default value provided to the client
174
179
  * @param EvaluationContext
175
180
  */
176
- contextEvaluator?: (ctx: EvaluationContext) => string;
181
+ contextEvaluator?: (ctx: EvaluationContext) => NoInfer<T>;
182
+ };
183
+ /**
184
+ * The configuration object for the InMemoryProvider, containing all flags and their specifications.
185
+ *
186
+ * The generic ensures that the keys of the `variants` object in each flag specification are consistent with the `defaultVariant` and the return type of `contextEvaluator`.
187
+ */
188
+ type FlagConfiguration<T extends Record<string, FlagVariants<string>> = Record<string, FlagVariants<string>>> = {
189
+ [K in keyof T]: Simplify<{
190
+ variants: T[K];
191
+ } & Omit<Flag<keyof T[K] & string>, 'variants'>>;
177
192
  };
178
- type FlagConfiguration = Record<string, Flag>;
179
193
 
180
194
  /**
181
195
  * A simple OpenFeature provider intended for demos and as a test stub.
196
+ * @deprecated Use {@link TypedInMemoryProvider} for type-safe flag configuration.
182
197
  */
183
198
  declare class InMemoryProvider implements Provider {
184
199
  readonly events: OpenFeatureEventEmitter;
@@ -200,6 +215,109 @@ declare class InMemoryProvider implements Provider {
200
215
  private resolveFlagWithReason;
201
216
  private lookupFlagValue;
202
217
  }
218
+ /**
219
+ * A simple OpenFeature provider intended for demos and as a test stub.
220
+ * @example
221
+ * ```
222
+ * const provider = new TypedInMemoryProvider({
223
+ * 'my-flag': {
224
+ * variants: { on: true, off: false },
225
+ * defaultVariant: 'on',
226
+ * contextEvaluator: (ctx) => ctx?.user?.id === '123' ? 'on' : 'off',
227
+ * disabled: false,
228
+ * },
229
+ * });
230
+ *
231
+ * const flags = {
232
+ * 'my-flag': {
233
+ * variants: { on: true, off: false },
234
+ * defaultVariant: 'on',
235
+ * contextEvaluator: (ctx) => ctx?.user?.id === '123' ? 'on' : 'off',
236
+ * disabled: false,
237
+ * },
238
+ * } as const; // 'as const' needed to preserve the `defaultVariant` narrow literal type rather than `string`
239
+ * const provider = new TypedInMemoryProvider(flags);
240
+ * ```
241
+ */
242
+ declare class TypedInMemoryProvider<T extends Record<string, FlagVariants<string>> = Record<string, FlagVariants<string>>> extends InMemoryProvider {
243
+ constructor(flagConfiguration?: FlagConfiguration<T>);
244
+ /**
245
+ * Overwrites the configured flags.
246
+ * @param { FlagConfiguration } flagConfiguration new flag configuration
247
+ * @example
248
+ * ```
249
+ * provider.putConfiguration({
250
+ * 'my-flag': {
251
+ * variants: { on: true, off: false },
252
+ * defaultVariant: 'on',
253
+ * contextEvaluator: (ctx) => ctx?.user?.id === '123' ? 'on' : 'off',
254
+ * disabled: false,
255
+ * },
256
+ * });
257
+ *
258
+ * const flags = {
259
+ * 'my-flag': {
260
+ * variants: { on: true, off: false },
261
+ * defaultVariant: 'on',
262
+ * contextEvaluator: (ctx) => ctx?.user?.id === '123' ? 'on' : 'off',
263
+ * disabled: false,
264
+ * },
265
+ * } as const; // 'as const' needed to preserve the `defaultVariant` narrow literal type rather than `string`
266
+ * provider.putConfiguration(flags);
267
+ * ```
268
+ */
269
+ putConfiguration<U extends Record<string, FlagVariants<string>> = Record<string, FlagVariants<string>>>(flagConfiguration: FlagConfiguration<U>): void;
270
+ }
271
+ /**
272
+ * The variants object for a flag in the {@link TypedInMemoryProvider}, containing all possible variants and their associated values.
273
+ *
274
+ * Can be used in combination with {@link InMemoryFlagConfiguration} to preserve type-safety when extending the provider class.
275
+ * @example
276
+ * ```
277
+ * export class CustomInMemoryProvider<
278
+ * T extends Record<string, InMemoryFlagVariants<string>> = Record<string, InMemoryFlagVariants<string>>,
279
+ * > extends TypedInMemoryProvider<T> {
280
+ * constructor(flagConfiguration: InMemoryFlagConfiguration<T>) {
281
+ * super(flagConfiguration);
282
+ * // custom logic ...
283
+ * }
284
+ *
285
+ * override putConfiguration<
286
+ * U extends Record<string, InMemoryFlagVariants<string>> = Record<string, InMemoryFlagVariants<string>>,
287
+ * >(flagConfiguration: InMemoryFlagConfiguration<U>) {
288
+ * super.putConfiguration(flagConfiguration);
289
+ * // custom logic ...
290
+ * }
291
+ * }
292
+ * ```
293
+ */
294
+ type InMemoryFlagVariants<T extends string> = FlagVariants<T>;
295
+ /**
296
+ * The configuration object for the {@link TypedInMemoryProvider}, containing all flags and their specifications.
297
+ *
298
+ * Can be used in combination with {@link InMemoryFlagVariants} to preserve type-safety when extending the provider class.
299
+ *
300
+ * The generic ensures that the keys of the `variants` object in each flag specification are consistent with the `defaultVariant` and the return type of `contextEvaluator`.
301
+ * @example
302
+ * ```
303
+ * export class CustomInMemoryProvider<
304
+ * T extends Record<string, InMemoryFlagVariants<string>> = Record<string, InMemoryFlagVariants<string>>,
305
+ * > extends TypedInMemoryProvider<T> {
306
+ * constructor(flagConfiguration: InMemoryFlagConfiguration<T>) {
307
+ * super(flagConfiguration);
308
+ * // custom logic ...
309
+ * }
310
+ *
311
+ * override putConfiguration<
312
+ * U extends Record<string, InMemoryFlagVariants<string>> = Record<string, InMemoryFlagVariants<string>>,
313
+ * >(flagConfiguration: InMemoryFlagConfiguration<U>) {
314
+ * super.putConfiguration(flagConfiguration);
315
+ * // custom logic ...
316
+ * }
317
+ * }
318
+ * ```
319
+ */
320
+ type InMemoryFlagConfiguration<T extends Record<string, FlagVariants<string>> = Record<string, FlagVariants<string>>> = FlagConfiguration<T>;
203
321
 
204
322
  /**
205
323
  * The OpenFeatureEventEmitter can be used by provider developers to emit
@@ -487,5 +605,5 @@ declare class OpenFeatureAPI extends OpenFeatureCommonAPI<ServerProviderStatus,
487
605
  */
488
606
  declare const OpenFeature: OpenFeatureAPI;
489
607
 
490
- export { AsyncLocalStorageTransactionContextPropagator, ComparisonStrategy, FirstMatchStrategy, FirstSuccessfulStrategy, InMemoryProvider, MultiProvider, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter };
491
- export type { Client, Features, FinalResult, FlagEvaluationOptions, Hook, ManageTransactionContextPropagator, Provider, ProviderResolutionErrorResult, ProviderResolutionResult, ProviderResolutionSuccessResult, StrategyPerProviderContext, StrategyProviderContext, Tracking, TransactionContext, TransactionContextPropagator };
608
+ export { AsyncLocalStorageTransactionContextPropagator, ComparisonStrategy, FirstMatchStrategy, FirstSuccessfulStrategy, InMemoryProvider, MultiProvider, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter, TypedInMemoryProvider };
609
+ export type { Client, ConstrainedFlagKey, Features, FinalResult, FlagEvaluationOptions, Hook, InMemoryFlagConfiguration, InMemoryFlagVariants, ManageTransactionContextPropagator, Provider, ProviderResolutionErrorResult, ProviderResolutionResult, ProviderResolutionSuccessResult, StrategyPerProviderContext, StrategyProviderContext, Tracking, TransactionContext, TransactionContextPropagator };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfeature/server-sdk",
3
- "version": "1.20.2",
3
+ "version": "1.21.0",
4
4
  "description": "OpenFeature SDK for JavaScript",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "files": [
@@ -48,9 +48,10 @@
48
48
  "node": ">=20"
49
49
  },
50
50
  "peerDependencies": {
51
- "@openfeature/core": "^1.9.2"
51
+ "@openfeature/core": "^1.10.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@openfeature/core": "^1.9.2"
55
- }
55
+ },
56
+ "sideEffects": false
56
57
  }