Skip to content

Commit 1fdebc4

Browse files
authored
fix: publish as @openfeature/server-sdk (#593)
Publishing under new name, with updated bootstrap SHA. Not a real fix, will correct that in release notes. Signed-off-by: Todd Baert <[email protected]>
1 parent 64eadd1 commit 1fdebc4

File tree

4 files changed

+316
-7
lines changed

4 files changed

+316
-7
lines changed

package-lock.json

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/server/README.md

Lines changed: 306 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,309 @@
77
</picture>
88
</p>
99

10-
<h2 align="center">This package has been deprecated. It's been renamed (moved without changes) to @openfeature/server-sdk.</h2>
10+
<h2 align="center">OpenFeature Node.js SDK</h2>
11+
12+
<!-- x-hide-in-docs-end -->
13+
<!-- The 'github-badges' class is used in the docs -->
14+
<p align="center" class="github-badges">
15+
<a href="https://github.com/open-feature/spec/tree/v0.7.0">
16+
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.7.0&color=yellow&style=for-the-badge" />
17+
</a>
18+
<!-- x-release-please-start-version -->
19+
<a href="https://github.com/open-feature/js-sdk/releases/tag/js-sdk-v1.6.1">
20+
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.6.1&color=blue&style=for-the-badge" />
21+
</a>
22+
<!-- x-release-please-end -->
23+
<br/>
24+
<a href="https://open-feature.github.io/js-sdk/modules/OpenFeature_JS_SDK.html">
25+
<img alt="API Reference" src="https://img.shields.io/badge/reference-teal?logo=javascript&logoColor=white" />
26+
</a>
27+
<a href="https://www.npmjs.com/package/@openfeature/js-sdk">
28+
<img alt="NPM Download" src="https://img.shields.io/npm/dm/%40openfeature%2Fjs-sdk" />
29+
</a>
30+
<a href="https://codecov.io/gh/open-feature/js-sdk">
31+
<img alt="codecov" src="https://codecov.io/gh/open-feature/js-sdk/branch/main/graph/badge.svg?token=3DC5XOEHMY" />
32+
</a>
33+
<a href="https://bestpractices.coreinfrastructure.org/projects/6594">
34+
<img alt="CII Best Practices" src="https://bestpractices.coreinfrastructure.org/projects/6594/badge" />
35+
</a>
36+
</p>
37+
<!-- x-hide-in-docs-start -->
38+
39+
[OpenFeature](https://openfeature.dev) is an open standard that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.
40+
41+
<!-- x-hide-in-docs-end -->
42+
43+
## 🚀 Quick start
44+
45+
### Requirements
46+
47+
- Node.js version 16+
48+
49+
### Install
50+
51+
#### npm
52+
53+
```sh
54+
npm install --save @openfeature/js-sdk
55+
```
56+
57+
#### yarn
58+
59+
```sh
60+
yarn add @openfeature/js-sdk
61+
```
62+
63+
### Usage
64+
65+
```ts
66+
import { OpenFeature } from '@openfeature/js-sdk';
67+
68+
// Register your feature flag provider
69+
OpenFeature.setProvider(new YourProviderOfChoice());
70+
71+
// create a new client
72+
const client = OpenFeature.getClient();
73+
74+
// Evaluate your feature flag
75+
const v2Enabled = await client.getBooleanValue('v2_enabled', false);
76+
77+
if (v2Enabled) {
78+
console.log("v2 is enabled");
79+
}
80+
```
81+
82+
### API Reference
83+
84+
See [here](https://open-feature.github.io/js-sdk/modules/OpenFeature_JS_SDK.html) for the complete API documentation.
85+
86+
## 🌟 Features
87+
88+
| Status | Features | Description |
89+
| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
90+
|| [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
91+
|| [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
92+
|| [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
93+
|| [Logging](#logging) | Integrate with popular logging packages. |
94+
|| [Named clients](#named-clients) | Utilize multiple providers in a single application. |
95+
|| [Eventing](#eventing) | React to state changes in the provider or flag management system. |
96+
|| [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
97+
|| [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
98+
99+
<sub>Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌</sub>
100+
101+
### Providers
102+
103+
[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK.
104+
Look [here](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Bcategory%5D%5B0%5D=Server-side&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=JavaScript) for a complete list of available providers.
105+
If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself.
106+
107+
Once you've added a provider as a dependency, it can be registered with OpenFeature like this:
108+
109+
```ts
110+
OpenFeature.setProvider(new MyProvider())
111+
```
112+
113+
In some situations, it may be beneficial to register multiple providers in the same application.
114+
This is possible using [named clients](#named-clients), which is covered in more details below.
115+
116+
### Targeting
117+
118+
Sometimes, the value of a flag must consider some dynamic criteria about the application or user, such as the user's location, IP, email address, or the server's location.
119+
In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting).
120+
If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context).
121+
122+
```ts
123+
// set a value to the global context
124+
OpenFeature.setContext({ region: "us-east-1" });
125+
126+
// set a value to the client context
127+
const client = OpenFeature.getClient();
128+
client.setContext({ version: process.env.APP_VERSION });
129+
130+
// set a value to the invocation context
131+
const requestContext = {
132+
targetingKey: req.session.id,
133+
email: req.session.email,
134+
product: req.productId
135+
};
136+
137+
const boolValue = await client.getBooleanValue('some-flag', false, requestContext);
138+
```
139+
140+
### Hooks
141+
142+
[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle
143+
Look [here](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Bcategory%5D%5B0%5D=Server-side&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=JavaScript) for a complete list of available hooks.
144+
If the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself.
145+
146+
Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level.
147+
148+
```ts
149+
import { OpenFeature } from "@openfeature/js-sdk";
150+
151+
// add a hook globally, to run on all evaluations
152+
OpenFeature.addHooks(new ExampleGlobalHook());
153+
154+
// add a hook on this client, to run on all evaluations made by this client
155+
const client = OpenFeature.getClient();
156+
client.addHooks(new ExampleClientHook());
157+
158+
// add a hook for this evaluation only
159+
const boolValue = await client.getBooleanValue("bool-flag", false, { hooks: [new ExampleHook()]});
160+
```
161+
162+
### Logging
163+
164+
The JS SDK will log warning and errors to the console by default.
165+
This behavior can be overridden by passing a custom logger either globally or per client.
166+
A custom logger must implement the [Logger interface](../shared/src/logger/logger.ts).
167+
168+
```ts
169+
import type { Logger } from "@openfeature/js-sdk";
170+
171+
// The logger can be anything that conforms with the Logger interface
172+
const logger: Logger = console;
173+
174+
// Sets a global logger
175+
OpenFeature.setLogger(logger);
176+
177+
// Sets a client logger
178+
const client = OpenFeature.getClient();
179+
client.setLogger(logger);
180+
```
181+
182+
### Named clients
183+
184+
Clients can be given a name.
185+
A name is a logical identifier which can be used to associate clients with a particular provider.
186+
If a name has no associated provider, the global provider is used.
187+
188+
```ts
189+
import { OpenFeature, InMemoryProvider } from "@openfeature/js-sdk";
190+
191+
const myFlags = {
192+
'v2_enabled': {
193+
variants: {
194+
on: true,
195+
off: false
196+
},
197+
disabled: false,
198+
defaultVariant: "on"
199+
}
200+
};
201+
202+
// Registering the default provider
203+
OpenFeature.setProvider(InMemoryProvider(myFlags));
204+
// Registering a named provider
205+
OpenFeature.setProvider("otherClient", new InMemoryProvider(someOtherFlags));
206+
207+
// A Client backed by default provider
208+
const clientWithDefault = OpenFeature.getClient();
209+
// A Client backed by NewCachedProvider
210+
const clientForCache = OpenFeature.getClient("otherClient");
211+
```
212+
213+
### Eventing
214+
215+
Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions.
216+
Initialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider.
217+
Some providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`.
218+
219+
Please refer to the documentation of the provider you're using to see what events are supported.
220+
221+
```ts
222+
import { OpenFeature, ProviderEvents } from '@openfeature/js-sdk';
223+
224+
// OpenFeature API
225+
OpenFeature.addHandler(ProviderEvents.Ready, (eventDetails) => {
226+
console.log(`Ready event from: ${eventDetails?.clientName}:`, eventDetails);
227+
});
228+
229+
// Specific client
230+
const client = OpenFeature.getClient();
231+
client.addHandler(ProviderEvents.Error, (eventDetails) => {
232+
console.log(`Error event from: ${eventDetails?.clientName}:`, eventDetails);
233+
});
234+
```
235+
236+
### Shutdown
237+
238+
The OpenFeature API provides a close function to perform a cleanup of all registered providers.
239+
This should only be called when your application is in the process of shutting down.
240+
241+
```ts
242+
import { OpenFeature } from '@openfeature/js-sdk';
243+
244+
await OpenFeature.close()
245+
```
246+
247+
## Extending
248+
249+
### Develop a provider
250+
251+
To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency.
252+
This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/js-sdk-contrib) available under the OpenFeature organization.
253+
You’ll then need to write the provider by implementing the [Provider interface](./src/provider/provider.ts) exported by the OpenFeature SDK.
254+
255+
```ts
256+
import { JsonValue, Provider, ResolutionDetails } from '@openfeature/js-sdk';
257+
258+
// implement the provider interface
259+
class MyProvider implements Provider {
260+
261+
readonly metadata = {
262+
name: 'My Provider',
263+
} as const;
264+
265+
// Optional provider managed hooks
266+
hooks?: Hook<FlagValue>[];
267+
268+
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<boolean>> {
269+
// code to evaluate a boolean
270+
}
271+
272+
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<string>> {
273+
// code to evaluate a string
274+
}
275+
276+
resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<number>> {
277+
// code to evaluate a number
278+
}
279+
280+
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<T>> {
281+
// code to evaluate an object
282+
}
283+
284+
status?: ProviderStatus | undefined;
285+
events?: OpenFeatureEventEmitter | undefined;
286+
287+
initialize?(context?: EvaluationContext | undefined): Promise<void> {
288+
// code to initialize your provider
289+
}
290+
291+
onClose?(): Promise<void> {
292+
// code to shut down your provider
293+
}
294+
}
295+
```
296+
297+
> Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=provider&projects=&template=document-provider.yaml&title=%5BProvider%5D%3A+) so we can add it to the docs!
298+
299+
### Develop a hook
300+
301+
To develop a hook, you need to create a new project and include the OpenFeature SDK as a dependency.
302+
This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/js-sdk-contrib) available under the OpenFeature organization.
303+
Implement your own hook by conforming to the [Hook interface](../shared/src/hooks/hook.ts).
304+
305+
```ts
306+
import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/js-sdk";
307+
308+
export class MyHook implements Hook {
309+
after(hookContext: HookContext, evaluationDetails: EvaluationDetails<FlagValue>) {
310+
// code that runs when there's an error during a flag evaluation
311+
}
312+
}
313+
```
314+
315+
> Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs!

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "@openfeature/js-sdk",
2+
"name": "@openfeature/server-sdk",
33
"version": "1.6.1",
44
"description": "OpenFeature SDK for JavaScript",
55
"main": "./dist/cjs/index.js",

release-please-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"bootstrap-sha": "7456ee0aec02284b2bd8a1ab4142ed3b04f54bac",
2+
"bootstrap-sha": "64eadd1b615997440ab4a246b941a24d13abd220",
33
"separate-pull-requests": true,
44
"plugins": ["node-workspace"],
55
"packages": {

0 commit comments

Comments
 (0)