@openfeature/js-sdk
Advanced tools
Comparing version
@@ -60,3 +60,2 @@ "use strict"; | ||
__export(src_exports, { | ||
ApiEvents: () => ApiEvents, | ||
DefaultLogger: () => DefaultLogger, | ||
@@ -75,3 +74,2 @@ ErrorCode: () => ErrorCode, | ||
ParseError: () => ParseError, | ||
ProviderEvents: () => ProviderEvents, | ||
SafeLogger: () => SafeLogger, | ||
@@ -85,13 +83,2 @@ StandardResolutionReasons: () => StandardResolutionReasons, | ||
// ../shared/src/types.ts | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Shutdown"] = "PROVIDER_SHUTDOWN"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var ApiEvents = /* @__PURE__ */ ((ApiEvents2) => { | ||
ApiEvents2["ProviderChanged"] = "providerChanged"; | ||
return ApiEvents2; | ||
})(ApiEvents || {}); | ||
var StandardResolutionReasons = { | ||
@@ -415,3 +402,2 @@ /** | ||
this._hooks = []; | ||
this._handlerWrappers = []; | ||
this.metadata = { | ||
@@ -602,3 +588,2 @@ name: options.name, | ||
0 && (module.exports = { | ||
ApiEvents, | ||
DefaultLogger, | ||
@@ -617,3 +602,2 @@ ErrorCode, | ||
ParseError, | ||
ProviderEvents, | ||
SafeLogger, | ||
@@ -620,0 +604,0 @@ StandardResolutionReasons, |
@@ -42,13 +42,2 @@ var __defProp = Object.defineProperty; | ||
// ../shared/src/types.ts | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Shutdown"] = "PROVIDER_SHUTDOWN"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var ApiEvents = /* @__PURE__ */ ((ApiEvents2) => { | ||
ApiEvents2["ProviderChanged"] = "providerChanged"; | ||
return ApiEvents2; | ||
})(ApiEvents || {}); | ||
var StandardResolutionReasons = { | ||
@@ -372,3 +361,2 @@ /** | ||
this._hooks = []; | ||
this._handlerWrappers = []; | ||
this.metadata = { | ||
@@ -558,3 +546,2 @@ name: options.name, | ||
export { | ||
ApiEvents, | ||
DefaultLogger, | ||
@@ -573,3 +560,2 @@ ErrorCode, | ||
ParseError, | ||
ProviderEvents, | ||
SafeLogger, | ||
@@ -576,0 +562,0 @@ StandardResolutionReasons, |
type PrimitiveValue = null | boolean | string | number; | ||
declare enum ProviderEvents { | ||
/** | ||
* The provider is ready to evaluate flags. | ||
*/ | ||
Ready = "PROVIDER_READY", | ||
/** | ||
* The provider is in an error state. | ||
*/ | ||
Error = "PROVIDER_ERROR", | ||
/** | ||
* The flag configuration in the source-of-truth has changed. | ||
*/ | ||
ConfigurationChanged = "PROVIDER_CONFIGURATION_CHANGED", | ||
/** | ||
* The provider is transitioning to a state of unavailability. | ||
*/ | ||
Shutdown = "PROVIDER_SHUTDOWN" | ||
} | ||
interface EventData { | ||
flagKeysChanged?: string[]; | ||
changeMetadata?: { | ||
[key: string]: boolean | string; | ||
}; | ||
} | ||
declare enum ApiEvents { | ||
ProviderChanged = "providerChanged" | ||
} | ||
interface Eventing { | ||
addHandler(notificationType: string, handler: Handler): void; | ||
} | ||
type EventContext = { | ||
notificationType: string; | ||
[key: string]: unknown; | ||
}; | ||
type Handler = (eventContext?: EventContext) => void; | ||
type EventCallbackMessage = (eventContext: EventContext) => void; | ||
type JsonObject = { | ||
@@ -549,3 +513,2 @@ [key: string]: JsonValue; | ||
private _clientLogger?; | ||
private _handlerWrappers; | ||
constructor(providerAccessor: () => Provider, globalLogger: () => Logger, options: OpenFeatureClientOptions, context?: EvaluationContext); | ||
@@ -622,2 +585,2 @@ setLogger(logger: Logger): OpenFeatureClient; | ||
export { ApiEvents, BeforeHookContext, Client, ClientMetadata, CommonProvider, DefaultLogger, ErrorCode, EvaluationContext, EvaluationContextValue, EvaluationDetails, EventCallbackMessage, EventContext, EventData, Eventing, Features, FlagEvaluationOptions, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GlobalApi, Handler, Hook, HookContext, HookHints, InvalidContextError, JsonArray, JsonObject, JsonValue, Logger, ManageContext, ManageLogger, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, ParseError, PrimitiveValue, Provider, ProviderEvents, ProviderMetadata, ResolutionDetails, ResolutionReason, SafeLogger, StandardResolutionReasons, TargetingKeyMissingError, TransactionContext, TransactionContextPropagator, TypeMismatchError }; | ||
export { BeforeHookContext, Client, ClientMetadata, CommonProvider, DefaultLogger, ErrorCode, EvaluationContext, EvaluationContextValue, EvaluationDetails, Features, FlagEvaluationOptions, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GlobalApi, Hook, HookContext, HookHints, InvalidContextError, JsonArray, JsonObject, JsonValue, Logger, ManageContext, ManageLogger, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, ParseError, PrimitiveValue, Provider, ProviderMetadata, ResolutionDetails, ResolutionReason, SafeLogger, StandardResolutionReasons, TargetingKeyMissingError, TransactionContext, TransactionContextPropagator, TypeMismatchError }; |
{ | ||
"name": "@openfeature/js-sdk", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "OpenFeature SDK for JavaScript", | ||
@@ -47,5 +47,12 @@ "main": "./dist/cjs/index.js", | ||
"homepage": "https://github.com/open-feature/js-sdk#readme", | ||
"engines": { | ||
"node": ">=16" | ||
}, | ||
"devDependencies": { | ||
"@openfeature/shared": "0.0.2" | ||
"@openfeature/shared": "0.0.3" | ||
}, | ||
"typedoc": { | ||
"displayName": "OpenFeature JS SDK", | ||
"entryPoint": "./src/index.ts" | ||
} | ||
} |
155
README.md
@@ -1,21 +0,55 @@ | ||
# @openfeature/js-sdk | ||
<!-- markdownlint-disable MD033 --> | ||
<p align="center"> | ||
<picture> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/open-feature/community/0e23508c163a6a1ac8c0ced3e4bd78faafe627c7/assets/logo/horizontal/white/openfeature-horizontal-white.svg"> | ||
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/open-feature/community/0e23508c163a6a1ac8c0ced3e4bd78faafe627c7/assets/logo/horizontal/black/openfeature-horizontal-black.svg"> | ||
<img align="center" alt="OpenFeature Logo"> | ||
</picture> | ||
</p> | ||
Server-side JavaScript implementation of intended for use in Node.JS and comparable runtimes | ||
## Installation | ||
<h2 align="center">OpenFeature Server SDK</h2> | ||
```shell | ||
[](https://www.repostatus.org/#active) | ||
[](https://www.npmjs.com/package/@openfeature/js-sdk) | ||
[](https://github.com/open-feature/spec/tree/v0.5.2) | ||
## 👋 Hey there! Thanks for checking out the OpenFeature Server SDK | ||
### What is OpenFeature? | ||
[OpenFeature][openfeature-website] is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool. | ||
### Why standardize feature flags? | ||
Standardizing feature flags unifies tools and vendors behind a common interface which avoids vendor lock-in at the code level. Additionally, it offers a framework for building extensions and integrations and allows providers to focus on their unique value proposition. | ||
## 🔍 Requirements: | ||
- Node.js version 16+ | ||
## 📦 Installation: | ||
### npm | ||
```sh | ||
npm install @openfeature/js-sdk | ||
``` | ||
or | ||
### yarn | ||
```shell | ||
```sh | ||
yarn add @openfeature/js-sdk | ||
``` | ||
## Usage | ||
## 🌟 Features: | ||
To configure the SDK you'll need to add a provider to the `OpenFeature` global singleton. From there, you can generate a `client` which is usable by your code. While you'll likely want a provider for your specific backend, we've provided a `NoopProvider`, which simply returns the default value. | ||
- support for various [providers](https://openfeature.dev/docs/reference/concepts/provider) | ||
- easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks) | ||
- handle flags of any type: bool, string, numeric and object | ||
- [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation | ||
## 🚀 Usage: | ||
### Basics: | ||
```typescript | ||
@@ -30,31 +64,63 @@ import { OpenFeature } from '@openfeature/js-sdk'; | ||
// get a bool value | ||
// get a bool flag value | ||
const boolValue = await client.getBooleanValue('boolFlag', false); | ||
``` | ||
// get a string value | ||
const stringValue = await client.getStringValue('stringFlag', 'default'); | ||
### Context-aware evaluation: | ||
// get an numeric value | ||
const numberValue = await client.getNumberValue('intFlag', 1); | ||
Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server. | ||
In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting). | ||
If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`. | ||
// get an object value | ||
const object = await client.getObjectValue<MyObject>('objectFlag', {}); | ||
```typescript | ||
// global context for static data | ||
OpenFeature.setContext({ appVersion: process.env.APP_VERSION }) | ||
// add a value to the invocation context | ||
const context: EvaluationContext = { | ||
myInvocationKey: 'myInvocationValue', | ||
// request context | ||
const requestContext = { | ||
targetingKey: req.session.id, | ||
email: req.session.email, | ||
product: req.productId | ||
}; | ||
const contextAwareValue = await client.getBooleanValue('boolFlag', false, context); | ||
// use merged contextual data to determine a flag value | ||
const boolValue = await client.getBooleanValue('some-flag', false, requestContext); | ||
``` | ||
A list of available providers can be found [here][server-side-artifacts]. | ||
### Providers: | ||
For complete documentation, visit: https://docs.openfeature.dev/docs/category/concepts | ||
To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. This can be a new repository or included in an existing contrib repository available under the OpenFeature organization. Finally, you’ll then need to write the provider itself. In most languages, this can be accomplished by implementing the provider interface exported by the OpenFeature SDK. | ||
## Hooks | ||
```typescript | ||
import { JsonValue, Provider, ResolutionDetails } from '@openfeature/js-sdk'; | ||
Implement your own hook by conforming to the [Hook interface][hook-interface]. | ||
// implement the provider interface | ||
class MyProvider implements Provider { | ||
readonly metadata = { | ||
name: 'My Provider', | ||
} as const; | ||
All of the hook stages (before, after, error, and finally) are optional. | ||
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean): ResolutionDetails<boolean> { | ||
// resolve a boolean flag value | ||
} | ||
resolveStringEvaluation(flagKey: string, defaultValue: string): ResolutionDetails<string> { | ||
// resolve a string flag value | ||
} | ||
resolveNumberEvaluation(flagKey: string, defaultValue: number): ResolutionDetails<number> { | ||
// resolve a numeric flag value | ||
} | ||
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T): ResolutionDetails<T> { | ||
// resolve an object flag value | ||
} | ||
``` | ||
See [here](https://openfeature.dev/docs/reference/technologies/server/javascript) for a catalog of available providers. | ||
### Hooks: | ||
Hooks are a mechanism that allow for the addition of arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validation of the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking. | ||
```typescript | ||
@@ -72,20 +138,33 @@ import { OpenFeature, Hook, HookContext } from '@openfeature/js-sdk'; | ||
Register the hook at global, client, or invocation level. | ||
See [here](https://openfeature.dev/docs/reference/technologies/server/javascript) for a catalog of available hooks. | ||
```typescript | ||
import { OpenFeature } from '@openfeature/js-sdk'; | ||
// This hook used is used for example purposes | ||
import { GlobalDebugHook, ClientDebugHook, InvocationDebugHook } from './debug-hook'; | ||
### Logging: | ||
// A global hook will run on every flag evaluation | ||
OpenFeature.addHooks(new GlobalDebugHook()); | ||
You can implement the `Logger` interface (compatible with the `console` object, and implementations from common logging libraries such as [winston](https://www.npmjs.com/package/winston)) and set it on the global API object. | ||
const client = OpenFeature.getClient('my-app'); | ||
// A client hook will run on every flag evaluation executed by this client | ||
client.addHooks(new ClientDebugHook()); | ||
```typescript | ||
// implement logger | ||
class MyLogger implements Logger { | ||
error(...args: unknown[]): void { | ||
// implement me | ||
} | ||
warn(...args: unknown[]): void { | ||
// implement me | ||
} | ||
info(...args: unknown[]): void { | ||
// implement me | ||
} | ||
debug(...args: unknown[]): void { | ||
// implement me | ||
} | ||
} | ||
// An invocation hook will only run on the registred flag evaluation method | ||
const boolValue = await client.getBooleanValue('boolFlag', false, {}, { hooks: [new InvocationDebugHook()] }); | ||
// set the logger | ||
OpenFeature.setLogger(new MyLogger()); | ||
``` | ||
A list of available hooks can be found [here][server-side-artifacts]. | ||
### Complete API documentation: | ||
See [here](https://open-feature.github.io/js-sdk/modules/OpenFeature_JS_SDK.html) for the complete API documentation. | ||
[openfeature-website]: https://openfeature.dev |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
169
87.78%0
-100%156511
-0.93%1706
-3.83%