@hyphen/sdk 1.2.0 → 1.4.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/README.md +110 -14
- package/dist/index.cjs +56 -15
- package/dist/index.d.cts +39 -26
- package/dist/index.d.ts +39 -26
- package/dist/index.js +56 -15
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ The Hyphen Node.js SDK is a JavaScript library that allows developers to easily
|
|
|
17
17
|
- [Toggle API](#toggle-api)
|
|
18
18
|
- [Toggle Hooks](#toggle-hooks)
|
|
19
19
|
- [Toggle Error Handling](#toggle-error-handling)
|
|
20
|
+
- [Toggle Caching](#toggle-caching)
|
|
21
|
+
- [Toggle Environment Variables](#toggle-environment-variables)
|
|
20
22
|
- [Toggle Self-Hosted](#toggle-self-hosted)
|
|
21
23
|
- [Contributing](#contributing)
|
|
22
24
|
- [Testing Your Changes](#testing-your-changes)
|
|
@@ -167,32 +169,32 @@ console.log('Boolean toggle value:', result); // true
|
|
|
167
169
|
| *applicationId* | `string` | The application ID for your Hyphen project. You can find this in the Hyphen dashboard. |
|
|
168
170
|
| *environment?* | `string` | The environment for your Hyphen project such as `production`. Default uses `process.env.NODE_ENV` |
|
|
169
171
|
| *context?* | `ToggleContext` | The context object that contains the user and custom attributes. This is optional. |
|
|
170
|
-
| *
|
|
172
|
+
| *caching?* | `{ ttl: number, generateCacheKeyFn: (context?: ToggleContext) => string}` | Whether to use the cache or not and a function to set the key. The `ttl` is in seconds |
|
|
171
173
|
|
|
172
174
|
## Toggle API
|
|
173
175
|
|
|
174
176
|
| Method | Parameters | Description |
|
|
175
177
|
|----------------|----------------|----------------|
|
|
176
178
|
| *setContext* | `context: ToggleContext` | Set the context for the toggle. This is optional. |
|
|
177
|
-
| *get<Type>* | `key: string, defaultValue: T, options?:
|
|
178
|
-
| *getBoolean* | `key: string, defaultValue: boolean, options?:
|
|
179
|
-
| *getNumber* | `key: string, defaultValue: number, options?:
|
|
180
|
-
| *getString* | `key: string, defaultValue: string, options?:
|
|
181
|
-
| *getObject<Type>* | `key: string, defaultValue: any, options?:
|
|
179
|
+
| *get<Type>* | `key: string, defaultValue: T, options?: ToggleGetOptions` | Get the value of a toggle. This is a generic method that can be used to get any type from toggle. |
|
|
180
|
+
| *getBoolean* | `key: string, defaultValue: boolean, options?: ToggleGetOptions` | Get the value of a boolean toggle. |
|
|
181
|
+
| *getNumber* | `key: string, defaultValue: number, options?: ToggleGetOptions` | Get the value of a number toggle. |
|
|
182
|
+
| *getString* | `key: string, defaultValue: string, options?: ToggleGetOptions` | Get the value of a string toggle. |
|
|
183
|
+
| *getObject<Type>* | `key: string, defaultValue: any, options?: ToggleGetOptions` | Get the value of a object toggle. |
|
|
182
184
|
|
|
183
185
|
## Toggle Hooks
|
|
184
186
|
|
|
185
187
|
The following hooks are available for Toggle:
|
|
186
188
|
| Hook | object | Description |
|
|
187
189
|
|----------------|----------------|----------------|
|
|
188
|
-
| *beforeGetBoolean* | `{ key: string, defaultValue:boolean, options?:
|
|
189
|
-
| *afterGetBoolean* | `{ key: string, defaultValue:boolean, options?:
|
|
190
|
-
| *beforeGetNumber* | `{ key: string, defaultValue:number, options?:
|
|
191
|
-
| *afterGetNumber* | `{ key: string, defaultValue:number, options?:
|
|
192
|
-
| *beforeGetString* | `{ key: string, defaultValue:string, options?:
|
|
193
|
-
| *afterGetString* | `{ key: string, defaultValue:string, options?:
|
|
194
|
-
| *beforeGetObject* | `{ key: string, defaultValue:any, options?:
|
|
195
|
-
| *afterGetObject* | `{ key: string, defaultValue:any, options?:
|
|
190
|
+
| *beforeGetBoolean* | `{ key: string, defaultValue:boolean, options?: ToggleGetOptions }` | Called before the boolean toggle is fetched. |
|
|
191
|
+
| *afterGetBoolean* | `{ key: string, defaultValue:boolean, options?: ToggleGetOptions, result: boolean }` | Called after the boolean toggle is fetched. |
|
|
192
|
+
| *beforeGetNumber* | `{ key: string, defaultValue:number, options?: ToggleGetOptions }` | Called before the number toggle is fetched. |
|
|
193
|
+
| *afterGetNumber* | `{ key: string, defaultValue:number, options?: ToggleGetOptions, result: number }` | Called after the number toggle is fetched. |
|
|
194
|
+
| *beforeGetString* | `{ key: string, defaultValue:string, options?: ToggleGetOptions }` | Called before the string toggle is fetched. |
|
|
195
|
+
| *afterGetString* | `{ key: string, defaultValue:string, options?: ToggleGetOptions, result: string }` | Called after the string toggle is fetched. |
|
|
196
|
+
| *beforeGetObject* | `{ key: string, defaultValue:any, options?: ToggleGetOptions }` | Called before the object toggle is fetched. |
|
|
197
|
+
| *afterGetObject* | `{ key: string, defaultValue:any, options?: ToggleGetOptions, result: any }` | Called after the object toggle is fetched. |
|
|
196
198
|
|
|
197
199
|
You can use the hooks to modify the request or the response. For example, you can use the `beforeGetBoolean` hook to log the request before it is sent to the server.
|
|
198
200
|
|
|
@@ -311,6 +313,100 @@ try {
|
|
|
311
313
|
}
|
|
312
314
|
```
|
|
313
315
|
|
|
316
|
+
## Toggle Caching
|
|
317
|
+
The SDK supports caching of toggle values to improve performance and reduce the number of requests made to the server. You can enable caching by providing a `caching` option in the constructor.
|
|
318
|
+
|
|
319
|
+
```javascript
|
|
320
|
+
import { Toggle, ToggleContext } from '@hyphen/sdk';
|
|
321
|
+
|
|
322
|
+
const context: ToggleContext = {
|
|
323
|
+
targetingKey: 'user-123',
|
|
324
|
+
ipAddress: '203.0.113.42',
|
|
325
|
+
customAttributes: {
|
|
326
|
+
subscriptionLevel: 'premium',
|
|
327
|
+
region: 'us-east',
|
|
328
|
+
},
|
|
329
|
+
user: {
|
|
330
|
+
id: 'user-123',
|
|
331
|
+
email: 'john.doe@example.com',
|
|
332
|
+
name: 'John Doe',
|
|
333
|
+
customAttributes: {
|
|
334
|
+
role: 'admin',
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const toggleOptions = {
|
|
340
|
+
publicApiKey: 'your_public_api_key',
|
|
341
|
+
applicationId: 'your_application_id',
|
|
342
|
+
context: context,
|
|
343
|
+
uris: [
|
|
344
|
+
'https://your-self-hosted-horizon-url',
|
|
345
|
+
],
|
|
346
|
+
caching: {
|
|
347
|
+
ttl: 60, // Cache for 60 seconds
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const toggle = new Toggle(toggleOptions);
|
|
351
|
+
|
|
352
|
+
const result = await toggle.getBoolean('hyphen-sdk-boolean', false);
|
|
353
|
+
console.log('Boolean toggle value:', result); // true
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
If you want to use a custom cache key generation function, you can provide a `generateCacheKeyFn` function in the `caching` option:
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
import { Toggle, ToggleContext } from '@hyphen/sdk';
|
|
360
|
+
|
|
361
|
+
const context: ToggleContext = {
|
|
362
|
+
targetingKey: 'user-123',
|
|
363
|
+
ipAddress: '203.0.113.42',
|
|
364
|
+
customAttributes: {
|
|
365
|
+
subscriptionLevel: 'premium',
|
|
366
|
+
region: 'us-east',
|
|
367
|
+
},
|
|
368
|
+
user: {
|
|
369
|
+
id: 'user-123',
|
|
370
|
+
email: 'john.doe@example.com',
|
|
371
|
+
name: 'John Doe',
|
|
372
|
+
customAttributes: {
|
|
373
|
+
role: 'admin',
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const toggleOptions = {
|
|
379
|
+
publicApiKey: 'your_public_api_key',
|
|
380
|
+
applicationId: 'your_application_id',
|
|
381
|
+
context: context,
|
|
382
|
+
uris: [
|
|
383
|
+
'https://your-self-hosted-horizon-url',
|
|
384
|
+
],
|
|
385
|
+
caching: {
|
|
386
|
+
ttl: 60, // Cache for 60 seconds
|
|
387
|
+
generateCacheKeyFn: (context) => {
|
|
388
|
+
return `toggle-${context?.targetingKey || 'default'}-hyphen-sdk-boolean`;
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
const toggle = new Toggle(toggleOptions);
|
|
394
|
+
|
|
395
|
+
const result = await toggle.getBoolean('hyphen-sdk-boolean', false);
|
|
396
|
+
console.log('Boolean toggle value:', result); // true
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
# Toggle Environment Variables
|
|
400
|
+
|
|
401
|
+
You can also use environment variables to set the `publicApiKey` and `applicationId`. This is useful for keeping your API keys secure and not hardcoding them in your code. To do this just set your `.env` file with the following variables:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
HYPHEN_PUBLIC_API_KEY=your_public_api_key
|
|
405
|
+
HYPHEN_APPLICATION_ID=your_application_id
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
On initialization of the `Toggle` class, the SDK will automatically check for these environment variables and use them if they are set. If they are not set, you will need to provide them in the constructor.
|
|
409
|
+
|
|
314
410
|
## Toggle Self-Hosted
|
|
315
411
|
|
|
316
412
|
Toggle uses [Horizon](https://hyphen.ai/horizon) to fetch the feature flags. If you are using a self-hosted version of Hyphen you can use the `uris` option in the constructor to set the url of your self-hosted version:
|
package/dist/index.cjs
CHANGED
|
@@ -39,8 +39,10 @@ module.exports = __toCommonJS(index_exports);
|
|
|
39
39
|
// src/toggle.ts
|
|
40
40
|
var import_node_process = __toESM(require("process"), 1);
|
|
41
41
|
var import_hookified = require("hookified");
|
|
42
|
+
var import_dotenv = __toESM(require("dotenv"), 1);
|
|
42
43
|
var import_server_sdk = require("@openfeature/server-sdk");
|
|
43
44
|
var import_openfeature_server_provider = require("@hyphen/openfeature-server-provider");
|
|
45
|
+
import_dotenv.default.config();
|
|
44
46
|
var ToggleHooks = /* @__PURE__ */ function(ToggleHooks2) {
|
|
45
47
|
ToggleHooks2["beforeGetBoolean"] = "beforeGetBoolean";
|
|
46
48
|
ToggleHooks2["afterGetBoolean"] = "afterGetBoolean";
|
|
@@ -56,36 +58,40 @@ var Toggle = class extends import_hookified.Hookified {
|
|
|
56
58
|
static {
|
|
57
59
|
__name(this, "Toggle");
|
|
58
60
|
}
|
|
59
|
-
_applicationId;
|
|
60
|
-
_publicApiKey =
|
|
61
|
+
_applicationId = import_node_process.default.env.HYPHEN_APPLICATION_ID;
|
|
62
|
+
_publicApiKey = import_node_process.default.env.HYPHEN_PUBLIC_API_KEY;
|
|
61
63
|
_environment;
|
|
62
64
|
_client;
|
|
63
65
|
_context;
|
|
64
66
|
_throwErrors = false;
|
|
65
67
|
_uris;
|
|
68
|
+
_caching;
|
|
66
69
|
/*
|
|
67
70
|
* Create a new Toggle instance. This will create a new client and set the options.
|
|
68
71
|
* @param {ToggleOptions}
|
|
69
72
|
*/
|
|
70
73
|
constructor(options) {
|
|
71
74
|
super();
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
75
|
+
this._throwErrors = options?.throwErrors ?? false;
|
|
76
|
+
this._applicationId = options?.applicationId;
|
|
77
|
+
if (options?.publicApiKey) {
|
|
78
|
+
this.setPublicApiKey(options.publicApiKey);
|
|
79
|
+
}
|
|
80
|
+
this._environment = options?.environment ?? import_node_process.default.env.NODE_ENV ?? "development";
|
|
81
|
+
this._context = options?.context;
|
|
82
|
+
this._uris = options?.uris;
|
|
83
|
+
this._caching = options?.caching;
|
|
78
84
|
}
|
|
79
85
|
/**
|
|
80
86
|
* Get the application ID
|
|
81
|
-
* @returns {string}
|
|
87
|
+
* @returns {string | undefined}
|
|
82
88
|
*/
|
|
83
89
|
get applicationId() {
|
|
84
90
|
return this._applicationId;
|
|
85
91
|
}
|
|
86
92
|
/**
|
|
87
93
|
* Set the application ID
|
|
88
|
-
* @param {string} value
|
|
94
|
+
* @param {string | undefined} value
|
|
89
95
|
*/
|
|
90
96
|
set applicationId(value) {
|
|
91
97
|
this._applicationId = value;
|
|
@@ -102,6 +108,11 @@ var Toggle = class extends import_hookified.Hookified {
|
|
|
102
108
|
* @param {string} value
|
|
103
109
|
*/
|
|
104
110
|
set publicApiKey(value) {
|
|
111
|
+
if (!value) {
|
|
112
|
+
this._publicApiKey = void 0;
|
|
113
|
+
this._client = void 0;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
105
116
|
this.setPublicApiKey(value);
|
|
106
117
|
}
|
|
107
118
|
/**
|
|
@@ -161,11 +172,25 @@ var Toggle = class extends import_hookified.Hookified {
|
|
|
161
172
|
this._uris = value;
|
|
162
173
|
}
|
|
163
174
|
/**
|
|
175
|
+
* Get the caching options.
|
|
176
|
+
* @returns {ToggleCachingOptions | undefined}
|
|
177
|
+
*/
|
|
178
|
+
get caching() {
|
|
179
|
+
return this._caching;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Set the caching options.
|
|
183
|
+
* @param {ToggleCachingOptions | undefined} value
|
|
184
|
+
*/
|
|
185
|
+
set caching(value) {
|
|
186
|
+
this._caching = value;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
164
189
|
* This is a helper function to set the public API key. It will check if the key starts with public_ and set it. If it
|
|
165
|
-
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
190
|
+
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
166
191
|
* it will emit an error and console warning and not set the key. Used by the constructor and publicApiKey setter.
|
|
167
|
-
* @param key
|
|
168
|
-
* @returns
|
|
192
|
+
* @param key
|
|
193
|
+
* @returns
|
|
169
194
|
*/
|
|
170
195
|
setPublicApiKey(key) {
|
|
171
196
|
if (!key.startsWith("public_")) {
|
|
@@ -194,12 +219,28 @@ var Toggle = class extends import_hookified.Hookified {
|
|
|
194
219
|
*/
|
|
195
220
|
async getClient() {
|
|
196
221
|
if (!this._client) {
|
|
222
|
+
console.log("Application ID:", this._applicationId);
|
|
223
|
+
if (this._applicationId === void 0 || this._applicationId.length === 0) {
|
|
224
|
+
const errorMessage = "Application ID is not set. You must set it before using the client or have the HYPHEN_APPLICATION_ID environment variable set.";
|
|
225
|
+
this.emit("error", new Error(errorMessage));
|
|
226
|
+
if (this._throwErrors) {
|
|
227
|
+
throw new Error(errorMessage);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
197
230
|
const options = {
|
|
198
231
|
application: this._applicationId,
|
|
199
232
|
environment: this._environment,
|
|
200
|
-
horizonUrls: this._uris
|
|
233
|
+
horizonUrls: this._uris,
|
|
234
|
+
cache: this._caching
|
|
201
235
|
};
|
|
202
|
-
|
|
236
|
+
if (this._publicApiKey && this._publicApiKey.length > 0) {
|
|
237
|
+
await import_server_sdk.OpenFeature.setProviderAndWait(new import_openfeature_server_provider.HyphenProvider(this._publicApiKey, options));
|
|
238
|
+
} else {
|
|
239
|
+
this.emit("error", new Error("Public API key is not set. You must set it before using the client or have the HYPHEN_PUBLIC_API_KEY environment variable set."));
|
|
240
|
+
if (this._throwErrors) {
|
|
241
|
+
throw new Error("Public API key is not set");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
203
244
|
this._client = import_server_sdk.OpenFeature.getClient(this._context);
|
|
204
245
|
}
|
|
205
246
|
return this._client;
|
package/dist/index.d.cts
CHANGED
|
@@ -12,17 +12,21 @@ declare enum ToggleHooks {
|
|
|
12
12
|
beforeGetObject = "beforeGetObject",
|
|
13
13
|
afterGetObject = "afterGetObject"
|
|
14
14
|
}
|
|
15
|
+
type ToggleCachingOptions = {
|
|
16
|
+
ttl?: number;
|
|
17
|
+
generateCacheKeyFn?: (context?: ToggleContext) => string;
|
|
18
|
+
};
|
|
15
19
|
type ToggleOptions = {
|
|
16
20
|
/**
|
|
17
|
-
* Your application name
|
|
21
|
+
* Your application name. If this is not set it will look for the HYPHEN_APPLICATION_ID environment variable.
|
|
18
22
|
* @type {string}
|
|
19
23
|
*/
|
|
20
|
-
applicationId
|
|
24
|
+
applicationId?: string;
|
|
21
25
|
/**
|
|
22
|
-
* Your Hyphen Public API key
|
|
26
|
+
* Your Hyphen Public API key. If this is not set it will look for the HYPHEN_PUBLIC_API_KEY environment variable.
|
|
23
27
|
* @type {string}
|
|
24
28
|
*/
|
|
25
|
-
publicApiKey
|
|
29
|
+
publicApiKey?: string;
|
|
26
30
|
/**
|
|
27
31
|
* Your environment name such as development, production. Default is what is set at NODE_ENV
|
|
28
32
|
* @type {string}
|
|
@@ -34,13 +38,11 @@ type ToggleOptions = {
|
|
|
34
38
|
* @type {ToggleContext}
|
|
35
39
|
*/
|
|
36
40
|
context?: ToggleContext;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ttl?: number;
|
|
43
|
-
};
|
|
41
|
+
/**
|
|
42
|
+
* Cache options to use for the request
|
|
43
|
+
* @type {ToggleCachingOptions}
|
|
44
|
+
*/
|
|
45
|
+
caching?: ToggleCachingOptions;
|
|
44
46
|
/**
|
|
45
47
|
* Throw errors in addition to emitting them
|
|
46
48
|
* @type {boolean}
|
|
@@ -55,7 +57,7 @@ type ToggleOptions = {
|
|
|
55
57
|
*/
|
|
56
58
|
uris?: string[];
|
|
57
59
|
};
|
|
58
|
-
type
|
|
60
|
+
type ToggleGetOptions = {
|
|
59
61
|
/**
|
|
60
62
|
* The context to use for evaluating feature flags
|
|
61
63
|
* @type {ToggleContext}
|
|
@@ -69,28 +71,29 @@ declare class Toggle extends Hookified {
|
|
|
69
71
|
private _client;
|
|
70
72
|
private _context;
|
|
71
73
|
private _throwErrors;
|
|
72
|
-
private _uris
|
|
73
|
-
|
|
74
|
+
private _uris;
|
|
75
|
+
private _caching;
|
|
76
|
+
constructor(options?: ToggleOptions);
|
|
74
77
|
/**
|
|
75
78
|
* Get the application ID
|
|
76
|
-
* @returns {string}
|
|
79
|
+
* @returns {string | undefined}
|
|
77
80
|
*/
|
|
78
|
-
get applicationId(): string;
|
|
81
|
+
get applicationId(): string | undefined;
|
|
79
82
|
/**
|
|
80
83
|
* Set the application ID
|
|
81
|
-
* @param {string} value
|
|
84
|
+
* @param {string | undefined} value
|
|
82
85
|
*/
|
|
83
|
-
set applicationId(value: string);
|
|
86
|
+
set applicationId(value: string | undefined);
|
|
84
87
|
/**
|
|
85
88
|
* Get the public API key
|
|
86
89
|
* @returns {string}
|
|
87
90
|
*/
|
|
88
|
-
get publicApiKey(): string;
|
|
91
|
+
get publicApiKey(): string | undefined;
|
|
89
92
|
/**
|
|
90
93
|
* Set the public API key
|
|
91
94
|
* @param {string} value
|
|
92
95
|
*/
|
|
93
|
-
set publicApiKey(value: string);
|
|
96
|
+
set publicApiKey(value: string | undefined);
|
|
94
97
|
/**
|
|
95
98
|
* Get the environment
|
|
96
99
|
* @returns {string}
|
|
@@ -131,6 +134,16 @@ declare class Toggle extends Hookified {
|
|
|
131
134
|
* @param {Array<string>} value
|
|
132
135
|
*/
|
|
133
136
|
set uris(value: string[] | undefined);
|
|
137
|
+
/**
|
|
138
|
+
* Get the caching options.
|
|
139
|
+
* @returns {ToggleCachingOptions | undefined}
|
|
140
|
+
*/
|
|
141
|
+
get caching(): ToggleCachingOptions | undefined;
|
|
142
|
+
/**
|
|
143
|
+
* Set the caching options.
|
|
144
|
+
* @param {ToggleCachingOptions | undefined} value
|
|
145
|
+
*/
|
|
146
|
+
set caching(value: ToggleCachingOptions | undefined);
|
|
134
147
|
/**
|
|
135
148
|
* This is a helper function to set the public API key. It will check if the key starts with public_ and set it. If it
|
|
136
149
|
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
@@ -159,7 +172,7 @@ declare class Toggle extends Hookified {
|
|
|
159
172
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
160
173
|
* @returns {Promise<T>}
|
|
161
174
|
*/
|
|
162
|
-
get<T>(key: string, defaultValue: T, options?:
|
|
175
|
+
get<T>(key: string, defaultValue: T, options?: ToggleGetOptions): Promise<T>;
|
|
163
176
|
/**
|
|
164
177
|
* Get a boolean value from the feature flag. This will check the type of the default value and call the
|
|
165
178
|
* appropriate function. It will also set the context if it is not set.
|
|
@@ -168,7 +181,7 @@ declare class Toggle extends Hookified {
|
|
|
168
181
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
169
182
|
* @returns {Promise<boolean>} - The value of the feature flag
|
|
170
183
|
*/
|
|
171
|
-
getBoolean(key: string, defaultValue: boolean, options?:
|
|
184
|
+
getBoolean(key: string, defaultValue: boolean, options?: ToggleGetOptions): Promise<boolean>;
|
|
172
185
|
/**
|
|
173
186
|
* Get a string value from the feature flag.
|
|
174
187
|
* @param {string} key - The key of the feature flag
|
|
@@ -176,8 +189,8 @@ declare class Toggle extends Hookified {
|
|
|
176
189
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
177
190
|
* @returns {Promise<string>} - The value of the feature flag
|
|
178
191
|
*/
|
|
179
|
-
getString(key: string, defaultValue: string, options?:
|
|
180
|
-
getNumber(key: string, defaultValue: number, options?:
|
|
192
|
+
getString(key: string, defaultValue: string, options?: ToggleGetOptions): Promise<string>;
|
|
193
|
+
getNumber(key: string, defaultValue: number, options?: ToggleGetOptions): Promise<number>;
|
|
181
194
|
/**
|
|
182
195
|
* Get an object value from the feature flag. This will check the type of the default value and call the
|
|
183
196
|
* appropriate function. It will also set the context if it is not set.
|
|
@@ -186,7 +199,7 @@ declare class Toggle extends Hookified {
|
|
|
186
199
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
187
200
|
* @returns {Promise<T>} - The value of the feature flag
|
|
188
201
|
*/
|
|
189
|
-
getObject<T>(key: string, defaultValue: T, options?:
|
|
202
|
+
getObject<T>(key: string, defaultValue: T, options?: ToggleGetOptions): Promise<T>;
|
|
190
203
|
}
|
|
191
204
|
|
|
192
|
-
export { Toggle, type
|
|
205
|
+
export { Toggle, type ToggleCachingOptions, type ToggleContext, type ToggleGetOptions, ToggleHooks, type ToggleOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,17 +12,21 @@ declare enum ToggleHooks {
|
|
|
12
12
|
beforeGetObject = "beforeGetObject",
|
|
13
13
|
afterGetObject = "afterGetObject"
|
|
14
14
|
}
|
|
15
|
+
type ToggleCachingOptions = {
|
|
16
|
+
ttl?: number;
|
|
17
|
+
generateCacheKeyFn?: (context?: ToggleContext) => string;
|
|
18
|
+
};
|
|
15
19
|
type ToggleOptions = {
|
|
16
20
|
/**
|
|
17
|
-
* Your application name
|
|
21
|
+
* Your application name. If this is not set it will look for the HYPHEN_APPLICATION_ID environment variable.
|
|
18
22
|
* @type {string}
|
|
19
23
|
*/
|
|
20
|
-
applicationId
|
|
24
|
+
applicationId?: string;
|
|
21
25
|
/**
|
|
22
|
-
* Your Hyphen Public API key
|
|
26
|
+
* Your Hyphen Public API key. If this is not set it will look for the HYPHEN_PUBLIC_API_KEY environment variable.
|
|
23
27
|
* @type {string}
|
|
24
28
|
*/
|
|
25
|
-
publicApiKey
|
|
29
|
+
publicApiKey?: string;
|
|
26
30
|
/**
|
|
27
31
|
* Your environment name such as development, production. Default is what is set at NODE_ENV
|
|
28
32
|
* @type {string}
|
|
@@ -34,13 +38,11 @@ type ToggleOptions = {
|
|
|
34
38
|
* @type {ToggleContext}
|
|
35
39
|
*/
|
|
36
40
|
context?: ToggleContext;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ttl?: number;
|
|
43
|
-
};
|
|
41
|
+
/**
|
|
42
|
+
* Cache options to use for the request
|
|
43
|
+
* @type {ToggleCachingOptions}
|
|
44
|
+
*/
|
|
45
|
+
caching?: ToggleCachingOptions;
|
|
44
46
|
/**
|
|
45
47
|
* Throw errors in addition to emitting them
|
|
46
48
|
* @type {boolean}
|
|
@@ -55,7 +57,7 @@ type ToggleOptions = {
|
|
|
55
57
|
*/
|
|
56
58
|
uris?: string[];
|
|
57
59
|
};
|
|
58
|
-
type
|
|
60
|
+
type ToggleGetOptions = {
|
|
59
61
|
/**
|
|
60
62
|
* The context to use for evaluating feature flags
|
|
61
63
|
* @type {ToggleContext}
|
|
@@ -69,28 +71,29 @@ declare class Toggle extends Hookified {
|
|
|
69
71
|
private _client;
|
|
70
72
|
private _context;
|
|
71
73
|
private _throwErrors;
|
|
72
|
-
private _uris
|
|
73
|
-
|
|
74
|
+
private _uris;
|
|
75
|
+
private _caching;
|
|
76
|
+
constructor(options?: ToggleOptions);
|
|
74
77
|
/**
|
|
75
78
|
* Get the application ID
|
|
76
|
-
* @returns {string}
|
|
79
|
+
* @returns {string | undefined}
|
|
77
80
|
*/
|
|
78
|
-
get applicationId(): string;
|
|
81
|
+
get applicationId(): string | undefined;
|
|
79
82
|
/**
|
|
80
83
|
* Set the application ID
|
|
81
|
-
* @param {string} value
|
|
84
|
+
* @param {string | undefined} value
|
|
82
85
|
*/
|
|
83
|
-
set applicationId(value: string);
|
|
86
|
+
set applicationId(value: string | undefined);
|
|
84
87
|
/**
|
|
85
88
|
* Get the public API key
|
|
86
89
|
* @returns {string}
|
|
87
90
|
*/
|
|
88
|
-
get publicApiKey(): string;
|
|
91
|
+
get publicApiKey(): string | undefined;
|
|
89
92
|
/**
|
|
90
93
|
* Set the public API key
|
|
91
94
|
* @param {string} value
|
|
92
95
|
*/
|
|
93
|
-
set publicApiKey(value: string);
|
|
96
|
+
set publicApiKey(value: string | undefined);
|
|
94
97
|
/**
|
|
95
98
|
* Get the environment
|
|
96
99
|
* @returns {string}
|
|
@@ -131,6 +134,16 @@ declare class Toggle extends Hookified {
|
|
|
131
134
|
* @param {Array<string>} value
|
|
132
135
|
*/
|
|
133
136
|
set uris(value: string[] | undefined);
|
|
137
|
+
/**
|
|
138
|
+
* Get the caching options.
|
|
139
|
+
* @returns {ToggleCachingOptions | undefined}
|
|
140
|
+
*/
|
|
141
|
+
get caching(): ToggleCachingOptions | undefined;
|
|
142
|
+
/**
|
|
143
|
+
* Set the caching options.
|
|
144
|
+
* @param {ToggleCachingOptions | undefined} value
|
|
145
|
+
*/
|
|
146
|
+
set caching(value: ToggleCachingOptions | undefined);
|
|
134
147
|
/**
|
|
135
148
|
* This is a helper function to set the public API key. It will check if the key starts with public_ and set it. If it
|
|
136
149
|
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
@@ -159,7 +172,7 @@ declare class Toggle extends Hookified {
|
|
|
159
172
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
160
173
|
* @returns {Promise<T>}
|
|
161
174
|
*/
|
|
162
|
-
get<T>(key: string, defaultValue: T, options?:
|
|
175
|
+
get<T>(key: string, defaultValue: T, options?: ToggleGetOptions): Promise<T>;
|
|
163
176
|
/**
|
|
164
177
|
* Get a boolean value from the feature flag. This will check the type of the default value and call the
|
|
165
178
|
* appropriate function. It will also set the context if it is not set.
|
|
@@ -168,7 +181,7 @@ declare class Toggle extends Hookified {
|
|
|
168
181
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
169
182
|
* @returns {Promise<boolean>} - The value of the feature flag
|
|
170
183
|
*/
|
|
171
|
-
getBoolean(key: string, defaultValue: boolean, options?:
|
|
184
|
+
getBoolean(key: string, defaultValue: boolean, options?: ToggleGetOptions): Promise<boolean>;
|
|
172
185
|
/**
|
|
173
186
|
* Get a string value from the feature flag.
|
|
174
187
|
* @param {string} key - The key of the feature flag
|
|
@@ -176,8 +189,8 @@ declare class Toggle extends Hookified {
|
|
|
176
189
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
177
190
|
* @returns {Promise<string>} - The value of the feature flag
|
|
178
191
|
*/
|
|
179
|
-
getString(key: string, defaultValue: string, options?:
|
|
180
|
-
getNumber(key: string, defaultValue: number, options?:
|
|
192
|
+
getString(key: string, defaultValue: string, options?: ToggleGetOptions): Promise<string>;
|
|
193
|
+
getNumber(key: string, defaultValue: number, options?: ToggleGetOptions): Promise<number>;
|
|
181
194
|
/**
|
|
182
195
|
* Get an object value from the feature flag. This will check the type of the default value and call the
|
|
183
196
|
* appropriate function. It will also set the context if it is not set.
|
|
@@ -186,7 +199,7 @@ declare class Toggle extends Hookified {
|
|
|
186
199
|
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
187
200
|
* @returns {Promise<T>} - The value of the feature flag
|
|
188
201
|
*/
|
|
189
|
-
getObject<T>(key: string, defaultValue: T, options?:
|
|
202
|
+
getObject<T>(key: string, defaultValue: T, options?: ToggleGetOptions): Promise<T>;
|
|
190
203
|
}
|
|
191
204
|
|
|
192
|
-
export { Toggle, type
|
|
205
|
+
export { Toggle, type ToggleCachingOptions, type ToggleContext, type ToggleGetOptions, ToggleHooks, type ToggleOptions };
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
4
4
|
// src/toggle.ts
|
|
5
5
|
import process from "process";
|
|
6
6
|
import { Hookified } from "hookified";
|
|
7
|
+
import dotenv from "dotenv";
|
|
7
8
|
import { OpenFeature } from "@openfeature/server-sdk";
|
|
8
9
|
import { HyphenProvider } from "@hyphen/openfeature-server-provider";
|
|
10
|
+
dotenv.config();
|
|
9
11
|
var ToggleHooks = /* @__PURE__ */ function(ToggleHooks2) {
|
|
10
12
|
ToggleHooks2["beforeGetBoolean"] = "beforeGetBoolean";
|
|
11
13
|
ToggleHooks2["afterGetBoolean"] = "afterGetBoolean";
|
|
@@ -21,36 +23,40 @@ var Toggle = class extends Hookified {
|
|
|
21
23
|
static {
|
|
22
24
|
__name(this, "Toggle");
|
|
23
25
|
}
|
|
24
|
-
_applicationId;
|
|
25
|
-
_publicApiKey =
|
|
26
|
+
_applicationId = process.env.HYPHEN_APPLICATION_ID;
|
|
27
|
+
_publicApiKey = process.env.HYPHEN_PUBLIC_API_KEY;
|
|
26
28
|
_environment;
|
|
27
29
|
_client;
|
|
28
30
|
_context;
|
|
29
31
|
_throwErrors = false;
|
|
30
32
|
_uris;
|
|
33
|
+
_caching;
|
|
31
34
|
/*
|
|
32
35
|
* Create a new Toggle instance. This will create a new client and set the options.
|
|
33
36
|
* @param {ToggleOptions}
|
|
34
37
|
*/
|
|
35
38
|
constructor(options) {
|
|
36
39
|
super();
|
|
37
|
-
this.
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
40
|
+
this._throwErrors = options?.throwErrors ?? false;
|
|
41
|
+
this._applicationId = options?.applicationId;
|
|
42
|
+
if (options?.publicApiKey) {
|
|
43
|
+
this.setPublicApiKey(options.publicApiKey);
|
|
44
|
+
}
|
|
45
|
+
this._environment = options?.environment ?? process.env.NODE_ENV ?? "development";
|
|
46
|
+
this._context = options?.context;
|
|
47
|
+
this._uris = options?.uris;
|
|
48
|
+
this._caching = options?.caching;
|
|
43
49
|
}
|
|
44
50
|
/**
|
|
45
51
|
* Get the application ID
|
|
46
|
-
* @returns {string}
|
|
52
|
+
* @returns {string | undefined}
|
|
47
53
|
*/
|
|
48
54
|
get applicationId() {
|
|
49
55
|
return this._applicationId;
|
|
50
56
|
}
|
|
51
57
|
/**
|
|
52
58
|
* Set the application ID
|
|
53
|
-
* @param {string} value
|
|
59
|
+
* @param {string | undefined} value
|
|
54
60
|
*/
|
|
55
61
|
set applicationId(value) {
|
|
56
62
|
this._applicationId = value;
|
|
@@ -67,6 +73,11 @@ var Toggle = class extends Hookified {
|
|
|
67
73
|
* @param {string} value
|
|
68
74
|
*/
|
|
69
75
|
set publicApiKey(value) {
|
|
76
|
+
if (!value) {
|
|
77
|
+
this._publicApiKey = void 0;
|
|
78
|
+
this._client = void 0;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
70
81
|
this.setPublicApiKey(value);
|
|
71
82
|
}
|
|
72
83
|
/**
|
|
@@ -126,11 +137,25 @@ var Toggle = class extends Hookified {
|
|
|
126
137
|
this._uris = value;
|
|
127
138
|
}
|
|
128
139
|
/**
|
|
140
|
+
* Get the caching options.
|
|
141
|
+
* @returns {ToggleCachingOptions | undefined}
|
|
142
|
+
*/
|
|
143
|
+
get caching() {
|
|
144
|
+
return this._caching;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Set the caching options.
|
|
148
|
+
* @param {ToggleCachingOptions | undefined} value
|
|
149
|
+
*/
|
|
150
|
+
set caching(value) {
|
|
151
|
+
this._caching = value;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
129
154
|
* This is a helper function to set the public API key. It will check if the key starts with public_ and set it. If it
|
|
130
|
-
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
155
|
+
* does set it will also set the client to undefined to force a new one to be created. If it does not,
|
|
131
156
|
* it will emit an error and console warning and not set the key. Used by the constructor and publicApiKey setter.
|
|
132
|
-
* @param key
|
|
133
|
-
* @returns
|
|
157
|
+
* @param key
|
|
158
|
+
* @returns
|
|
134
159
|
*/
|
|
135
160
|
setPublicApiKey(key) {
|
|
136
161
|
if (!key.startsWith("public_")) {
|
|
@@ -159,12 +184,28 @@ var Toggle = class extends Hookified {
|
|
|
159
184
|
*/
|
|
160
185
|
async getClient() {
|
|
161
186
|
if (!this._client) {
|
|
187
|
+
console.log("Application ID:", this._applicationId);
|
|
188
|
+
if (this._applicationId === void 0 || this._applicationId.length === 0) {
|
|
189
|
+
const errorMessage = "Application ID is not set. You must set it before using the client or have the HYPHEN_APPLICATION_ID environment variable set.";
|
|
190
|
+
this.emit("error", new Error(errorMessage));
|
|
191
|
+
if (this._throwErrors) {
|
|
192
|
+
throw new Error(errorMessage);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
162
195
|
const options = {
|
|
163
196
|
application: this._applicationId,
|
|
164
197
|
environment: this._environment,
|
|
165
|
-
horizonUrls: this._uris
|
|
198
|
+
horizonUrls: this._uris,
|
|
199
|
+
cache: this._caching
|
|
166
200
|
};
|
|
167
|
-
|
|
201
|
+
if (this._publicApiKey && this._publicApiKey.length > 0) {
|
|
202
|
+
await OpenFeature.setProviderAndWait(new HyphenProvider(this._publicApiKey, options));
|
|
203
|
+
} else {
|
|
204
|
+
this.emit("error", new Error("Public API key is not set. You must set it before using the client or have the HYPHEN_PUBLIC_API_KEY environment variable set."));
|
|
205
|
+
if (this._throwErrors) {
|
|
206
|
+
throw new Error("Public API key is not set");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
168
209
|
this._client = OpenFeature.getClient(this._context);
|
|
169
210
|
}
|
|
170
211
|
return this._client;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyphen/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Hyphen SDK for Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"require": "./dist/index.cjs"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"types": "dist/
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"test": "xo --fix && vitest run --coverage",
|
|
17
17
|
"test:ci": "xo && vitest run --coverage",
|
|
18
18
|
"build": "rimraf ./dist && tsup src/index.ts --format esm,cjs --dts --clean",
|
|
19
|
-
"clean": "rimraf ./dist",
|
|
19
|
+
"clean": "rimraf ./dist pnpm-lock.yaml node_modules coverage",
|
|
20
20
|
"prepublishOnly": "rimraf ./dist && tsup src/index.ts --format esm,cjs --dts --clean"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
"author": "Team Hyphen <hello@hyphen.ai>",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@swc/core": "^1.11.
|
|
33
|
-
"@types/node": "^22.15.
|
|
34
|
-
"@vitest/coverage-v8": "^3.1.
|
|
32
|
+
"@swc/core": "^1.11.29",
|
|
33
|
+
"@types/node": "^22.15.21",
|
|
34
|
+
"@vitest/coverage-v8": "^3.1.4",
|
|
35
35
|
"rimraf": "^6.0.1",
|
|
36
36
|
"tsd": "^0.32.0",
|
|
37
|
-
"tsup": "^8.
|
|
37
|
+
"tsup": "^8.5.0",
|
|
38
38
|
"typescript": "^5.8.3",
|
|
39
|
-
"vitest": "^3.1.
|
|
40
|
-
"xo": "^0.
|
|
39
|
+
"vitest": "^3.1.4",
|
|
40
|
+
"xo": "^1.0.0"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
43
43
|
"dist",
|