unleash-client
Advanced tools
Comparing version 3.16.1 to 3.17.0
# Changelog | ||
# 3.17.0 | ||
- feat: Only initialize the SDK once. (#368) | ||
- fix: upgrade semver to 7.3.8 | ||
- fix: add resolution for debug | ||
- fix: add resolution for minimatch | ||
- fix: add resolution for qs | ||
- fix: add resolution for json5 | ||
- fix: update yarn.lock | ||
- docs: Update the readme with info from docs.getunleash (#399) | ||
- docs: minor fix in README | ||
- chore(deps): update dependency debug to v4 (#402) | ||
- chore(deps): update dependency json5 to v2 (#401) | ||
- chore(deps): update dependency eslint to v8.31.0 (#394) | ||
- chore(deps): update dependency nock to v13.3.0 (#400) | ||
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v5.48.1 (#395) | ||
- chore(deps): update dependency eslint-config-prettier to v8.6.0 (#396) | ||
- chore(deps): update dependency prettier to v2.8.2 (#398) | ||
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v5.47.1 (#346) | ||
- chore(deps): update dependency typescript to v4.9.4 (#386) | ||
- chore(deps): update dependency sinon to v15 (#391) | ||
- chore(deps): update dependency @types/node to v18 (#380) | ||
- chore(deps): update dependency @types/node to v14.18.36 (#382) | ||
- chore(deps): update dependency eslint to v8.30.0 (#367) | ||
- chore(deps): update dependency prettier to v2.8.1 (#387) | ||
# 3.16.1 | ||
- fix: handle socket hang up gracefully. (#392) | ||
- chore(deps): update dependency @types/semver to v7.3.13 (#383) | ||
- chore(deps): update dependency lint-staged to v12.5.0 (#369) | ||
- chore(deps): update dependency @types/node to v14.18.32 (#365) | ||
- chore: Update build-details | ||
# 3.16.0 | ||
- fix: Emit "unchanged" event (#376) | ||
- chore(deps): update dependency @types/murmurhash3js to v3.0.3 (#373) | ||
- Add project to payload (#364) | ||
- chore(deps): update dependency eslint to v8.23.0 (#363) | ||
- chore(deps): update dependency typescript to v4.8.2 (#362) | ||
- chore(deps): update dependency @types/semver to v7.3.12 (#361) | ||
- chore(deps): update dependency eslint to v8.22.0 (#356) | ||
- chore(deps): update dependency @types/make-fetch-happen to v10 (#357) | ||
- chore(deps): update dependency @unleash/client-specification to v4.2.2 (#355) | ||
- chore(deps): update dependency @types/node to v14.18.26 (#354) | ||
- meta: add stale bot config (reference unleash/.github) (#352) | ||
- chore: Update build-details | ||
# 3.15.0 | ||
@@ -4,0 +52,0 @@ - feat: add impression events (#336) |
@@ -8,3 +8,3 @@ const { initialize, isEnabled } = require('../lib'); | ||
const client = initialize({ | ||
const unleash = initialize({ | ||
appName: 'my-application', | ||
@@ -18,5 +18,5 @@ url, | ||
client.on('error', console.error); | ||
client.on('warn', console.log); | ||
client.on('ready', () => { | ||
unleash.on('error', console.error); | ||
unleash.on('warn', console.log); | ||
unleash.on('ready', () => { | ||
console.log('ready!') | ||
@@ -23,0 +23,0 @@ }); |
@@ -23,3 +23,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -26,0 +26,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -1,1 +0,1 @@ | ||
{ "name": "unleash-client-node", "version": "3.16.0", "sdkVersion": "unleash-client-node:3.16.0" } | ||
{ "name": "unleash-client-node", "version": "3.16.1", "sdkVersion": "unleash-client-node:3.16.1" } |
export interface CustomHeaders { | ||
[key: string]: string; | ||
} | ||
export declare type CustomHeadersFunction = () => Promise<CustomHeaders>; | ||
export type CustomHeadersFunction = () => Promise<CustomHeaders>; | ||
//# sourceMappingURL=headers.d.ts.map |
import { Context } from './context'; | ||
export declare type FallbackFunction = (name: string, context: Context) => boolean; | ||
export type FallbackFunction = (name: string, context: Context) => boolean; | ||
export declare function createFallbackFunction(name: string, context: Context, fallback?: FallbackFunction | boolean): Function; | ||
@@ -7,2 +7,3 @@ export declare function resolveContextValue(context: Context, field: string): string | undefined; | ||
export declare function generateInstanceId(instanceId?: string): string; | ||
export declare function generateHashOfObject(o: Object): string; | ||
//# sourceMappingURL=helpers.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateInstanceId = exports.safeName = exports.resolveContextValue = exports.createFallbackFunction = void 0; | ||
exports.generateHashOfObject = exports.generateInstanceId = exports.safeName = exports.resolveContextValue = exports.createFallbackFunction = void 0; | ||
var os_1 = require("os"); | ||
var murmurHash3 = require("murmurhash3js"); | ||
function createFallbackFunction(name, context, fallback) { | ||
@@ -47,2 +48,7 @@ if (typeof fallback === 'function') { | ||
exports.generateInstanceId = generateInstanceId; | ||
function generateHashOfObject(o) { | ||
var oAsString = JSON.stringify(o); | ||
return murmurHash3.x86.hash128(oAsString); | ||
} | ||
exports.generateHashOfObject = generateHashOfObject; | ||
//# sourceMappingURL=helpers.js.map |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -54,7 +54,3 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
function initialize(options) { | ||
if (instance) { | ||
instance.emit(events_2.UnleashEvents.Warn, 'This global unleash instance is initialized multiple times.'); | ||
} | ||
instance = new unleash_1.Unleash(options); | ||
instance.on('error', function () { }); | ||
instance = unleash_1.Unleash.getInstance(options); | ||
return instance; | ||
@@ -61,0 +57,0 @@ } |
@@ -32,3 +32,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -35,0 +35,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -20,0 +20,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -43,3 +43,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -46,0 +46,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -20,0 +20,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -20,0 +20,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -41,3 +41,3 @@ import { Context } from '../context'; | ||
} | ||
export declare type OperatorImpl = (constraint: Constraint, context: Context) => boolean; | ||
export type OperatorImpl = (constraint: Constraint, context: Context) => boolean; | ||
export declare class Strategy { | ||
@@ -44,0 +44,0 @@ name: string; |
@@ -38,2 +38,3 @@ /// <reference types="node" /> | ||
disableAutoStart?: boolean; | ||
skipInstanceCountWarning?: boolean; | ||
} | ||
@@ -45,2 +46,5 @@ export interface StaticContext { | ||
export declare class Unleash extends EventEmitter { | ||
private static configSignature?; | ||
private static instance?; | ||
private static instanceCount; | ||
private repository; | ||
@@ -52,3 +56,10 @@ private client; | ||
private ready; | ||
constructor({ appName, environment, projectName, instanceId, url, refreshInterval, metricsInterval, disableMetrics, backupPath, strategies, repository, namePrefix, customHeaders, customHeadersFunction, timeout, httpOptions, tags, bootstrap, bootstrapOverride, storageProvider, disableAutoStart, }: UnleashConfig); | ||
constructor({ appName, environment, projectName, instanceId, url, refreshInterval, metricsInterval, disableMetrics, backupPath, strategies, repository, namePrefix, customHeaders, customHeadersFunction, timeout, httpOptions, tags, bootstrap, bootstrapOverride, storageProvider, disableAutoStart, skipInstanceCountWarning, }: UnleashConfig); | ||
/** | ||
* Will only give you an instance the first time you call the method, | ||
* and then return the same instance. | ||
* @param config The Unleash Config. | ||
* @returns the Unleash instance | ||
*/ | ||
static getInstance(config: UnleashConfig): Unleash; | ||
private cleanUnleashUrl; | ||
@@ -55,0 +66,0 @@ start(): Promise<void>; |
@@ -43,3 +43,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -84,6 +84,19 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
function Unleash(_a) { | ||
var appName = _a.appName, _b = _a.environment, environment = _b === void 0 ? 'default' : _b, projectName = _a.projectName, instanceId = _a.instanceId, url = _a.url, _c = _a.refreshInterval, refreshInterval = _c === void 0 ? 15 * 1000 : _c, _d = _a.metricsInterval, metricsInterval = _d === void 0 ? 60 * 1000 : _d, _e = _a.disableMetrics, disableMetrics = _e === void 0 ? false : _e, _f = _a.backupPath, backupPath = _f === void 0 ? BACKUP_PATH : _f, _g = _a.strategies, strategies = _g === void 0 ? [] : _g, repository = _a.repository, namePrefix = _a.namePrefix, customHeaders = _a.customHeaders, customHeadersFunction = _a.customHeadersFunction, timeout = _a.timeout, httpOptions = _a.httpOptions, tags = _a.tags, _h = _a.bootstrap, bootstrap = _h === void 0 ? {} : _h, bootstrapOverride = _a.bootstrapOverride, storageProvider = _a.storageProvider, _j = _a.disableAutoStart, disableAutoStart = _j === void 0 ? false : _j; | ||
var appName = _a.appName, _b = _a.environment, environment = _b === void 0 ? 'default' : _b, projectName = _a.projectName, instanceId = _a.instanceId, url = _a.url, _c = _a.refreshInterval, refreshInterval = _c === void 0 ? 15 * 1000 : _c, _d = _a.metricsInterval, metricsInterval = _d === void 0 ? 60 * 1000 : _d, _e = _a.disableMetrics, disableMetrics = _e === void 0 ? false : _e, _f = _a.backupPath, backupPath = _f === void 0 ? BACKUP_PATH : _f, _g = _a.strategies, strategies = _g === void 0 ? [] : _g, repository = _a.repository, namePrefix = _a.namePrefix, customHeaders = _a.customHeaders, customHeadersFunction = _a.customHeadersFunction, timeout = _a.timeout, httpOptions = _a.httpOptions, tags = _a.tags, _h = _a.bootstrap, bootstrap = _h === void 0 ? {} : _h, bootstrapOverride = _a.bootstrapOverride, storageProvider = _a.storageProvider, _j = _a.disableAutoStart, disableAutoStart = _j === void 0 ? false : _j, _k = _a.skipInstanceCountWarning, skipInstanceCountWarning = _k === void 0 ? false : _k; | ||
var _this = _super.call(this) || this; | ||
_this.synchronized = false; | ||
_this.ready = false; | ||
Unleash.instanceCount++; | ||
_this.on(events_2.UnleashEvents.Error, function (error) { | ||
// Only if there does not exist other listeners for this event. | ||
if (_this.listenerCount(events_2.UnleashEvents.Error) === 1) { | ||
console.error(error); | ||
} | ||
}); | ||
if (!skipInstanceCountWarning && Unleash.instanceCount > 10) { | ||
process.nextTick(function () { | ||
var error = new Error('The unleash SDK has been initialized more than 10 times'); | ||
_this.emit(events_2.UnleashEvents.Error, error); | ||
}); | ||
} | ||
if (!url) { | ||
@@ -177,2 +190,21 @@ throw new Error('Unleash API "url" is required'); | ||
} | ||
/** | ||
* Will only give you an instance the first time you call the method, | ||
* and then return the same instance. | ||
* @param config The Unleash Config. | ||
* @returns the Unleash instance | ||
*/ | ||
Unleash.getInstance = function (config) { | ||
var configSignature = (0, helpers_1.generateHashOfObject)(config); | ||
if (Unleash.instance) { | ||
if (configSignature !== Unleash.configSignature) { | ||
throw new Error('You already have an Unleash instance with a different configuration.'); | ||
} | ||
return Unleash.instance; | ||
} | ||
var instance = new Unleash(config); | ||
Unleash.instance = instance; | ||
Unleash.configSignature = configSignature; | ||
return instance; | ||
}; | ||
Unleash.prototype.cleanUnleashUrl = function (url) { | ||
@@ -208,2 +240,5 @@ var _this = this; | ||
this.metrics.stop(); | ||
Unleash.instance = undefined; | ||
Unleash.configSignature = undefined; | ||
Unleash.instanceCount--; | ||
}; | ||
@@ -271,5 +306,7 @@ Unleash.prototype.isEnabled = function (name, context, fallback) { | ||
}; | ||
Unleash.instanceCount = 0; | ||
return Unleash; | ||
}(events_1.EventEmitter)); | ||
exports.Unleash = Unleash; | ||
; | ||
//# sourceMappingURL=unleash.js.map |
{ | ||
"name": "unleash-client", | ||
"version": "3.16.1", | ||
"version": "3.17.0", | ||
"description": "Unleash Client for Node", | ||
@@ -32,6 +32,6 @@ "license": "Apache-2.0", | ||
"dependencies": { | ||
"ip": "^1.1.5", | ||
"ip": "^1.1.8", | ||
"make-fetch-happen": "^10.2.1", | ||
"murmurhash3js": "^3.0.1", | ||
"semver": "^7.3.5" | ||
"semver": "^7.3.8" | ||
}, | ||
@@ -51,5 +51,5 @@ "engines": { | ||
"@types/murmurhash3js": "3.0.3", | ||
"@types/node": "14.18.32", | ||
"@types/node": "18.11.18", | ||
"@types/semver": "7.3.13", | ||
"@typescript-eslint/eslint-plugin": "5.29.0", | ||
"@typescript-eslint/eslint-plugin": "5.48.1", | ||
"@unleash/client-specification": "4.2.2", | ||
@@ -60,6 +60,6 @@ "ava": "3.15.0", | ||
"del-cli": "4.0.1", | ||
"eslint": "8.23.0", | ||
"eslint": "8.31.0", | ||
"eslint-config-airbnb-base": "15.0.0", | ||
"eslint-config-airbnb-typescript": "12.3.1", | ||
"eslint-config-prettier": "8.5.0", | ||
"eslint-config-prettier": "8.6.0", | ||
"eslint-plugin-import": "2.26.0", | ||
@@ -71,12 +71,16 @@ "eslint-plugin-prettier": "4.0.0", | ||
"mkdirp": "1.0.4", | ||
"nock": "13.2.4", | ||
"nock": "13.3.0", | ||
"nyc": "15.1.0", | ||
"prettier": "2.7.1", | ||
"prettier": "2.8.2", | ||
"redis": "4.0.6", | ||
"sinon": "13.0.2", | ||
"typescript": "4.8.2" | ||
"sinon": "15.0.1", | ||
"typescript": "4.9.4" | ||
}, | ||
"resolutions": { | ||
"ansi-regex": "^5.0.1", | ||
"json-schema": "^0.4.0" | ||
"debug": "^4.0.0", | ||
"json-schema": "^0.4.0", | ||
"json5": "^2.0.0", | ||
"qs": "^6.5.3", | ||
"minimatch": "^3.0.5" | ||
}, | ||
@@ -83,0 +87,0 @@ "nyc": { |
228
README.md
# Unleash Client SDK for Node.js | ||
![npm](https://img.shields.io/npm/v/unleash-client) | ||
![npm](https://img.shields.io/npm/dm/unleash-client) | ||
[![Unleash node SDK on npm](https://img.shields.io/npm/v/unleash-client)](https://www.npmjs.com/package/unleash-client) | ||
![npm downloads](https://img.shields.io/npm/dm/unleash-client) | ||
[![Build Status](https://github.com/Unleash/unleash-client-node/workflows/Build/badge.svg)](https://github.com/Unleash/unleash-client-node/actions) | ||
@@ -9,7 +9,4 @@ [![Code Climate](https://codeclimate.com/github/Unleash/unleash-client-node/badges/gpa.svg)](https://codeclimate.com/github/Unleash/unleash-client-node) | ||
Unleash Client SDK for Node.js. It is compatible with: | ||
The official Unleash client SDK for Node.js. | ||
- [Unleash Enterprise](https://www.unleash-hosted.com) | ||
- [Unleash Open-Source](https://github.com/Unleash/unleash) | ||
## Getting started | ||
@@ -20,34 +17,66 @@ | ||
```bash | ||
$ npm install unleash-client --save | ||
npm install unleash-client | ||
``` | ||
or | ||
```bash | ||
yarn add unleash-client | ||
``` | ||
(Or any other tool you like.) | ||
### 2. Initialize unleash-client | ||
It is recommended to initialize the Unleash client SDK as early as possible in your node.js | ||
application. The SDK will set-up a in-memory repository, and poll updates from the unleash-server at | ||
regular intervals. | ||
Once installed, you must initialize the SDK in your application. By default, Unleash initialization | ||
is asynchronous, but if you need it to be synchronous, you can | ||
[block until the SDK has synchronized with the server](#synchronous-initialization). | ||
Note that until the SDK has synchronized with the API, all features will evaluate to `false` unless | ||
you a [bootstrapped configuration](#bootstrap). | ||
--- | ||
💡 **Tip**: All code samples in this section will initialize the SDK and try to connect to the | ||
Unleash instance you point it to. You will need an Unleash instance and a | ||
[server-side API token](https://docs.getunleash.io/reference/api-tokens-and-client-keys#client-tokens) | ||
for the connection to be successful. | ||
--- | ||
We recommend that you initialize the Unleash client SDK **as early as possible** in your | ||
application. The SDK will set up an in-memory repository and poll for updates from the Unleash | ||
server at regular intervals. | ||
```js | ||
const { initialize } = require('unleash-client'); | ||
const unleash = initialize({ | ||
url: 'http://unleash.herokuapp.com/api/', | ||
appName: 'my-app-name', | ||
instanceId: 'my-unique-instance-id', | ||
customHeaders: { | ||
Authorization: 'API token', | ||
}, | ||
url: 'https://YOUR-API-URL', | ||
appName: 'my-node-name', | ||
customHeaders: { Authorization: 'SOME-SECRET' }, | ||
}); | ||
``` | ||
unleash.on('synchronized', () => { | ||
// Unleash is ready to serve updated feature toggles. | ||
The `initialize` function will configure a **global** Unleash instance. If you call this method | ||
multiple times, the global instance will be changed. You will **not** create multiple instances. | ||
// Check a feature flag | ||
const isEnabled = unleash.isEnabled('some-toggle'); | ||
#### How do I know when it's ready? | ||
// Check the variant | ||
const variant = unleash.getVariant('app.ToggleY'); | ||
Because the SDK takes care of talking to the server in the background, it can be difficult to know | ||
exactly when it has connected and is ready to evaluate toggles. If you want to run some code when | ||
the SDK becomes ready, you can listen for the `'synchronized'` event: | ||
```js | ||
unleash.on('synchronized', () => { | ||
// the SDK has synchronized with the server | ||
// and is ready to serve | ||
}); | ||
``` | ||
Be aware that the `initialize` function will configure a _global_ Unleash instance. If you call this method multiple times the global instance will be changed. | ||
Refer to the [events reference](#events) later in this document for more information on events and | ||
an exhaustive list of all the events the SDK can emit. | ||
The `initialize` function will configure and create a _global_ Unleash instance. When a global instance exists, calling this method has no effect. Call the `destroy` function to remove the globally configured instance. | ||
#### Constructing the Unleash client directly | ||
@@ -57,3 +86,3 @@ | ||
**Important:** When using the Unleash client directly, you **must** handle errors yourself. Do this by attaching an event listener to the `error` event, as shown in the example below. If you don't do this, your application may crash either on startup or at runtime if it can't reach the Unleash server or if it encounters other errors. | ||
When using the Unleash client directly, you **should not create new Unleash instances on every request**. Most applications are expected to only have a single Unleash instance (singleton). Each Unleash instance will maintain a connection to the Unleash API, which may result in flooding the Unleash API. | ||
@@ -64,7 +93,5 @@ ```js | ||
const unleash = new Unleash({ | ||
appName: 'my-app-name', | ||
url: 'http://unleash.herokuapp.com', | ||
customHeaders: { | ||
Authorization: 'API token', | ||
}, | ||
url: 'https://YOUR-API-URL', | ||
appName: 'my-node-name', | ||
customHeaders: { Authorization: 'SOME-SECRET' }, | ||
}); | ||
@@ -74,11 +101,11 @@ | ||
// required error handling when using unleash directly | ||
// optional error handling when using unleash directly | ||
unleash.on('error', console.error); | ||
``` | ||
#### Block until Unleash SDK has synchronized | ||
#### Synchronous initialization | ||
You can also use the `startUnleash` function, and `await` for the SDK to have fully synchronized | ||
with the unleash-api. This allows you to secure that the SDK is not operating on locally and | ||
potential stale feature toggle configuration. | ||
You can also use the `startUnleash` function and `await` to wait for the SDK to have fully | ||
synchronized with the Unleash API. This guarantees that the SDK is not operating on local and | ||
potentially stale feature toggle configuration. | ||
@@ -89,7 +116,5 @@ ```js | ||
const unleash = await startUnleash({ | ||
appName: 'async-unleash', | ||
url: 'http://unleash.herokuapp.com/api/', | ||
customHeaders: { | ||
Authorization: 'API token', | ||
}, | ||
url: 'https://YOUR-API-URL', | ||
appName: 'my-node-name', | ||
customHeaders: { Authorization: 'SOME-SECRET' }, | ||
}); | ||
@@ -101,2 +126,51 @@ | ||
### 3. Check features | ||
With the SDK initialized, you can use it to check the states of your feature toggles in your | ||
application. | ||
The primary way to check feature toggle status is to use the `isEnabled` method on the SDK. It takes | ||
the name of the feature and returns `true` or `false` based on whether the feature is enabled or | ||
not. | ||
```javascript | ||
setInterval(() => { | ||
if (unleash.isEnabled('DemoToggle')) { | ||
console.log('Toggle enabled'); | ||
} else { | ||
console.log('Toggle disabled'); | ||
} | ||
}, 1000); | ||
``` | ||
👀 **Note**: In this example, we've wrapped the `isEnabled` call inside a `setInterval` function. In | ||
the event that all your app does is to start the SDK and check a feature status, this is will keep a | ||
node app running until the SDK has synchronized with the Unleash API. It is **not** required in | ||
normal apps. | ||
#### Providing an Unleash context | ||
Calling the `isEnabled` method with just a feature name will work in simple use cases, but in many | ||
cases you'll also want to provide an | ||
[Unleash context](https://docs.getunleash.io/reference/unleash-context). The SDK uses the Unleash | ||
context to evaluate any | ||
[activation strategy](https://docs.getunleash.io/reference/activation-strategies) with | ||
[strategy constraints](https://docs.getunleash.io/reference/strategy-constraints), and also to | ||
evaluate some of the built-in strategies. | ||
The `isEnabled` accepts an Unleash context object as a second argument: | ||
```js | ||
const unleashContext = { | ||
userId: '123', | ||
sessionId: 'some-session-id', | ||
remoteAddress: '127.0.0.1', | ||
properties: { | ||
region: 'EMEA', | ||
}, | ||
}; | ||
const enabled = unleash.isEnabled('someToggle', unleashContext); | ||
``` | ||
### 4. Stop unleash | ||
@@ -114,21 +188,12 @@ | ||
The client comes with implementations for the built-in activation strategies provided by unleash. | ||
The client comes supports all built-in activation strategies provided by Unleash. | ||
- DefaultStrategy | ||
- UserIdStrategy | ||
- FlexibleRolloutStrategy | ||
- GradualRolloutUserIdStrategy | ||
- GradualRolloutSessionIdStrategy | ||
- GradualRolloutRandomStrategy | ||
- RemoteAddressStrategy | ||
- ApplicationHostnameStrategy | ||
Read more about | ||
[activation strategies in the official docs](https://docs.getunleash.io/reference/activation-strategies). | ||
Read more about the strategies in | ||
[activation-strategy.md](https://github.com/Unleash/unleash/blob/main/docs/activation-strategies.md). | ||
### Unleash context | ||
In order to use some of the common activation strategies you must provide a | ||
[unleash-context](https://github.com/Unleash/unleash/blob/main/docs/unleash-context.md). This | ||
client SDK allows you to send in the unleash context as part of the `isEnabled` call: | ||
In order to use some of the common activation strategies you must provide an | ||
[Unleash context](https://docs.getunleash.io/reference/unleash-context). This client SDK allows you | ||
to send in the unleash context as part of the `isEnabled` call: | ||
@@ -150,3 +215,4 @@ ```javascript | ||
- **appName** - The application name / codebase name (required). | ||
- **environment** - The active environment this application is running in. Automatically populated in the Unleash Context (optional). | ||
- **environment** - The active environment this application is running in. Automatically populated | ||
in the Unleash Context (optional). | ||
- **instanceId** - A unique identifier, should/could be somewhat unique. | ||
@@ -167,3 +233,4 @@ - **refreshInterval** - The poll interval to check for updates. Defaults to 15000ms. | ||
- **namePrefix** - Only fetch feature toggles with the provided name prefix. | ||
- **tags** - Only fetch feature toggles tagged with the list of tags. E.g.: `[{type: 'simple', value: 'proxy'}]`. | ||
- **tags** - Only fetch feature toggles tagged with the list of tags. E.g.: | ||
`[{type: 'simple', value: 'proxy'}]`. | ||
@@ -214,3 +281,3 @@ ## Custom strategies | ||
| changed | `object` data | is emitted each time the client gets new toggle state from server and changes has been made | | ||
| impression | `object` data | is emitted for every user impression (isEnabled / getVariant) | | ||
| impression | `object` data | is emitted for every user impression (isEnabled / getVariant) | | ||
@@ -223,5 +290,5 @@ Example usage: | ||
const unleash = initialize({ | ||
appName: 'my-app-name', | ||
url: 'http://unleash.herokuapp.com/api/', | ||
customHeaders: { | ||
appName: 'my-app-name', | ||
url: 'http://unleash.herokuapp.com/api/', | ||
customHeaders: { | ||
Authorization: 'API token', | ||
@@ -238,8 +305,8 @@ }, | ||
unleash.once('registered', () => { | ||
// Do something after the client has registered with the server api. | ||
// NB! It might not have received updated feature toggles yet. | ||
// Do something after the client has registered with the server api. | ||
// NB! It might not have received updated feature toggles yet. | ||
}); | ||
unleash.once('changed', () => { | ||
console.log(`Demo is enabled: ${unleash.isEnabled('Demo')}`); | ||
console.log(`Demo is enabled: ${unleash.isEnabled('Demo')}`); | ||
}); | ||
@@ -254,3 +321,7 @@ | ||
The Node.js SDK supports a bootstrap parameter, allowing you to load the initial feature toggle configuration from somewhere else than the Unleash API. The bootstrap `data` can be provided as an argument directly to the SDK, as a `filePath` to load or as a `url` to fetch the content from. Bootstrap is a convenient way to increase resilience, where the SDK can still load fresh toggle configuration from the bootstrap location, even if the Unleash API should be unavailable at startup. | ||
The Node.js SDK supports a bootstrap parameter, allowing you to load the initial feature toggle | ||
configuration from somewhere else than the Unleash API. The bootstrap `data` can be provided as an | ||
argument directly to the SDK, as a `filePath` to load or as a `url` to fetch the content from. | ||
Bootstrap is a convenient way to increase resilience, where the SDK can still load fresh toggle | ||
configuration from the bootstrap location, even if the Unleash API should be unavailable at startup. | ||
@@ -278,9 +349,7 @@ **1. Bootstrap with data passed as an argument** | ||
}, | ||
] | ||
], | ||
}, | ||
}); | ||
``` | ||
**2. Bootstrap via a URL** | ||
@@ -298,7 +367,6 @@ | ||
urlHeaders: { | ||
Authorization: 'bootstrap', | ||
} | ||
Authorization: 'bootstrap', | ||
}, | ||
}, | ||
}); | ||
``` | ||
@@ -316,6 +384,5 @@ | ||
bootstrap: { | ||
filePath: '/tmp/some-bootstrap.json', | ||
filePath: '/tmp/some-bootstrap.json', | ||
}, | ||
}); | ||
``` | ||
@@ -351,3 +418,6 @@ | ||
By default this SDK will use a store provider that writes a backup of the feature toggle configuration to a **file on disk**. This happens every time it receives updated configuration from the Unleash API. You can swap out the store provider with either the provided in-memory store provider or a custom store provider implemented by you. | ||
By default this SDK will use a store provider that writes a backup of the feature toggle | ||
configuration to a **file on disk**. This happens every time it receives updated configuration from | ||
the Unleash API. You can swap out the store provider with either the provided in-memory store | ||
provider or a custom store provider implemented by you. | ||
@@ -357,6 +427,3 @@ **1. Use InMemStorageProvider** | ||
```js | ||
const { | ||
initialize, | ||
InMemStorageProvider, | ||
} = require('unleash-client'); | ||
const { initialize, InMemStorageProvider } = require('unleash-client'); | ||
@@ -376,6 +443,3 @@ const client = initialize({ | ||
```js | ||
const { | ||
initialize, | ||
InMemStorageProvider, | ||
} = require('unleash-client'); | ||
const { initialize, InMemStorageProvider } = require('unleash-client'); | ||
@@ -389,3 +453,2 @@ const { createClient } = require('redis'); | ||
await client.set(key, JSON.stringify(data)); | ||
} | ||
@@ -410,3 +473,2 @@ async get(key) { | ||
## Custom repository | ||
@@ -413,0 +475,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
269246
3362
460
Updatedip@^1.1.8
Updatedsemver@^7.3.8