@openfeature/server-sdk 1.20.1 → 1.20.2

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/README.md CHANGED
@@ -16,8 +16,8 @@
16
16
  <img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
17
17
  </a>
18
18
  <!-- x-release-please-start-version -->
19
- <a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.20.1">
20
- <img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.20.1&color=blue&style=for-the-badge" />
19
+ <a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.20.2">
20
+ <img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.20.2&color=blue&style=for-the-badge" />
21
21
  </a>
22
22
  <!-- x-release-please-end -->
23
23
  <br/>
@@ -88,7 +88,7 @@ const client = OpenFeature.getClient();
88
88
  const v2Enabled = await client.getBooleanValue('v2_enabled', false);
89
89
 
90
90
  if (v2Enabled) {
91
- console.log("v2 is enabled");
91
+ console.log('v2 is enabled');
92
92
  }
93
93
  ```
94
94
 
@@ -98,19 +98,19 @@ See [here](https://open-feature.github.io/js-sdk/modules/_openfeature_server_sdk
98
98
 
99
99
  ## 🌟 Features
100
100
 
101
- | Status | Features | Description |
102
- | ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
103
- | ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
104
- | ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
105
- | ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
106
- | ✅ | [Logging](#logging) | Integrate with popular logging packages. |
107
- | ✅ | [Domains](#domains) | Logically bind clients with providers. |
108
- | ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
109
- | ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
110
- | ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. |
111
- | ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
112
- | ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
113
- | ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. |
101
+ | Status | Features | Description |
102
+ | ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
103
+ | ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
104
+ | ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
105
+ | ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
106
+ | ✅ | [Logging](#logging) | Integrate with popular logging packages. |
107
+ | ✅ | [Domains](#domains) | Logically bind clients with providers. |
108
+ | ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
109
+ | ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
110
+ | ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. |
111
+ | ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
112
+ | ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
113
+ | ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. |
114
114
 
115
115
  <sub>Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌</sub>
116
116
 
@@ -162,10 +162,7 @@ const primaryProvider = new YourPrimaryProvider();
162
162
  const backupProvider = new YourBackupProvider();
163
163
 
164
164
  // Create multi-provider with a strategy
165
- const multiProvider = new MultiProvider(
166
- [primaryProvider, backupProvider],
167
- new FirstMatchStrategy()
168
- );
165
+ const multiProvider = new MultiProvider([primaryProvider, backupProvider], new FirstMatchStrategy());
169
166
 
170
167
  // Register the multi-provider
171
168
  await OpenFeature.setProviderAndWait(multiProvider);
@@ -191,7 +188,7 @@ const oldProvider = new OldFlagProvider();
191
188
 
192
189
  const multiProvider = new MultiProvider(
193
190
  [newProvider, oldProvider], // New provider is consulted first
194
- new FirstMatchStrategy()
191
+ new FirstMatchStrategy(),
195
192
  );
196
193
 
197
194
  await OpenFeature.setProviderAndWait(multiProvider);
@@ -207,13 +204,10 @@ const providerA = new ProviderA();
207
204
  const providerB = new ProviderB();
208
205
 
209
206
  const multiProvider = new MultiProvider(
210
- [
211
- { provider: providerA },
212
- { provider: providerB }
213
- ],
207
+ [{ provider: providerA }, { provider: providerB }],
214
208
  new ComparisonStrategy(providerA, (resolutions) => {
215
209
  console.warn('Mismatch detected', resolutions);
216
- })
210
+ }),
217
211
  );
218
212
 
219
213
  await OpenFeature.setProviderAndWait(multiProvider);
@@ -227,7 +221,7 @@ If the flag management system you're using supports targeting, you can provide t
227
221
 
228
222
  ```ts
229
223
  // set a value to the global context
230
- OpenFeature.setContext({ region: "us-east-1" });
224
+ OpenFeature.setContext({ region: 'us-east-1' });
231
225
 
232
226
  // set a value to the client context
233
227
  const client = OpenFeature.getClient();
@@ -237,7 +231,7 @@ client.setContext({ version: process.env.APP_VERSION });
237
231
  const requestContext = {
238
232
  targetingKey: req.session.id,
239
233
  email: req.session.email,
240
- product: req.productId
234
+ product: req.productId,
241
235
  };
242
236
 
243
237
  const boolValue = await client.getBooleanValue('some-flag', false, requestContext);
@@ -255,7 +249,7 @@ If the hook you're looking for hasn't been created yet, see the [develop a hook]
255
249
  Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level.
256
250
 
257
251
  ```ts
258
- import { OpenFeature } from "@openfeature/server-sdk";
252
+ import { OpenFeature } from '@openfeature/server-sdk';
259
253
 
260
254
  // add a hook globally, to run on all evaluations
261
255
  OpenFeature.addHooks(new ExampleGlobalHook());
@@ -265,7 +259,7 @@ const client = OpenFeature.getClient();
265
259
  client.addHooks(new ExampleClientHook());
266
260
 
267
261
  // add a hook for this evaluation only
268
- const boolValue = await client.getBooleanValue("bool-flag", false, { hooks: [new ExampleHook()]});
262
+ const boolValue = await client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] });
269
263
  ```
270
264
 
271
265
  ### Logging
@@ -275,7 +269,7 @@ This behavior can be overridden by passing a custom logger either globally or pe
275
269
  A custom logger must implement the [Logger interface](../shared/src/logger/logger.ts).
276
270
 
277
271
  ```ts
278
- import type { Logger } from "@openfeature/server-sdk";
272
+ import type { Logger } from '@openfeature/server-sdk';
279
273
 
280
274
  // The logger can be anything that conforms with the Logger interface
281
275
  const logger: Logger = console;
@@ -295,28 +289,28 @@ A domain is a logical identifier which can be used to associate clients with a p
295
289
  If a domain has no associated provider, the default provider is used.
296
290
 
297
291
  ```ts
298
- import { OpenFeature, InMemoryProvider } from "@openfeature/server-sdk";
292
+ import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk';
299
293
 
300
294
  const myFlags = {
301
- 'v2_enabled': {
295
+ v2_enabled: {
302
296
  variants: {
303
297
  on: true,
304
- off: false
298
+ off: false,
305
299
  },
306
300
  disabled: false,
307
- defaultVariant: "on"
308
- }
301
+ defaultVariant: 'on',
302
+ },
309
303
  };
310
304
 
311
305
  // Registering the default provider
312
306
  OpenFeature.setProvider(InMemoryProvider(myFlags));
313
307
  // Registering a provider to a domain
314
- OpenFeature.setProvider("my-domain", new InMemoryProvider(someOtherFlags));
308
+ OpenFeature.setProvider('my-domain', new InMemoryProvider(someOtherFlags));
315
309
 
316
310
  // A Client bound to the default provider
317
311
  const clientWithDefault = OpenFeature.getClient();
318
312
  // A Client bound to the InMemoryProvider provider
319
- const domainScopedClient = OpenFeature.getClient("my-domain");
313
+ const domainScopedClient = OpenFeature.getClient('my-domain');
320
314
  ```
321
315
 
322
316
  Domains can be defined on a provider during registration.
@@ -353,22 +347,22 @@ Transaction context can be set where specific data is available (e.g. an auth se
353
347
  The following example shows an Express middleware using transaction context propagation to propagate the request ip and user id into request scoped transaction context.
354
348
 
355
349
  ```ts
356
- import express, { Request, Response, NextFunction } from "express";
350
+ import express, { Request, Response, NextFunction } from 'express';
357
351
  import { OpenFeature, AsyncLocalStorageTransactionContextPropagator } from '@openfeature/server-sdk';
358
352
 
359
- OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator())
353
+ OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator());
360
354
 
361
355
  /**
362
356
  * This example is based on an express middleware.
363
357
  */
364
358
  const app = express();
365
359
  app.use((req: Request, res: Response, next: NextFunction) => {
366
- const ip = res.headers.get("X-Forwarded-For")
360
+ const ip = res.headers.get('X-Forwarded-For');
367
361
  OpenFeature.setTransactionContext({ targetingKey: req.user.id, ipAddress: ip }, () => {
368
362
  // The transaction context is used in any flag evaluation throughout the whole call chain of next
369
363
  next();
370
364
  });
371
- })
365
+ });
372
366
  ```
373
367
 
374
368
  ### Tracking
@@ -394,7 +388,7 @@ This should only be called when your application is in the process of shutting d
394
388
  ```ts
395
389
  import { OpenFeature } from '@openfeature/server-sdk';
396
390
 
397
- await OpenFeature.close()
391
+ await OpenFeature.close();
398
392
  ```
399
393
 
400
394
  ## Extending
@@ -414,7 +408,7 @@ import {
414
408
  Logger,
415
409
  Provider,
416
410
  ProviderEventEmitter,
417
- ResolutionDetails
411
+ ResolutionDetails,
418
412
  } from '@openfeature/server-sdk';
419
413
 
420
414
  // implement the provider interface
@@ -426,16 +420,36 @@ class MyProvider implements Provider {
426
420
  } as const;
427
421
  // Optional provider managed hooks
428
422
  hooks?: Hook[];
429
- resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<boolean>> {
423
+ resolveBooleanEvaluation(
424
+ flagKey: string,
425
+ defaultValue: boolean,
426
+ context: EvaluationContext,
427
+ logger: Logger,
428
+ ): Promise<ResolutionDetails<boolean>> {
430
429
  // code to evaluate a boolean
431
430
  }
432
- resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<string>> {
431
+ resolveStringEvaluation(
432
+ flagKey: string,
433
+ defaultValue: string,
434
+ context: EvaluationContext,
435
+ logger: Logger,
436
+ ): Promise<ResolutionDetails<string>> {
433
437
  // code to evaluate a string
434
438
  }
435
- resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<number>> {
439
+ resolveNumberEvaluation(
440
+ flagKey: string,
441
+ defaultValue: number,
442
+ context: EvaluationContext,
443
+ logger: Logger,
444
+ ): Promise<ResolutionDetails<number>> {
436
445
  // code to evaluate a number
437
446
  }
438
- resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<T>> {
447
+ resolveObjectEvaluation<T extends JsonValue>(
448
+ flagKey: string,
449
+ defaultValue: T,
450
+ context: EvaluationContext,
451
+ logger: Logger,
452
+ ): Promise<ResolutionDetails<T>> {
439
453
  // code to evaluate an object
440
454
  }
441
455
 
@@ -460,7 +474,7 @@ This can be a new repository or included in [the existing contrib repository](ht
460
474
  Implement your own hook by conforming to the [Hook interface](../shared/src/hooks/hook.ts).
461
475
 
462
476
  ```ts
463
- import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/server-sdk";
477
+ import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';
464
478
 
465
479
  export class MyHook implements Hook {
466
480
  after(hookContext: HookContext, evaluationDetails: EvaluationDetails<FlagValue>) {