flagsmith-nodejs 3.3.2 → 4.0.0-beta.1
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/.github/workflows/publish.yml +2 -2
- package/.github/workflows/pull_request.yaml +3 -4
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/models.d.ts +3 -3
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/models.js +20 -13
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/util.d.ts +1 -1
- package/build/cjs/flagsmith-engine/environments/util.js +23 -0
- package/build/cjs/flagsmith-engine/features/models.js +118 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/util.d.ts +1 -1
- package/build/cjs/flagsmith-engine/features/util.js +27 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/models.d.ts +2 -2
- package/build/cjs/flagsmith-engine/identities/models.js +48 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/traits/models.js +5 -4
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/util.d.ts +2 -2
- package/build/cjs/flagsmith-engine/identities/util.js +22 -0
- package/build/cjs/flagsmith-engine/index.d.ts +14 -0
- package/build/cjs/flagsmith-engine/index.js +75 -0
- package/build/cjs/flagsmith-engine/organisations/models.js +21 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/organisations/util.d.ts +1 -1
- package/build/cjs/flagsmith-engine/organisations/util.js +8 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/models.d.ts +2 -2
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/models.js +8 -5
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/util.d.ts +1 -1
- package/build/cjs/flagsmith-engine/projects/util.js +15 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/evaluators.d.ts +4 -4
- package/build/cjs/flagsmith-engine/segments/evaluators.js +37 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/models.d.ts +1 -1
- package/build/cjs/flagsmith-engine/segments/models.js +114 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/util.d.ts +1 -1
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/util.js +9 -11
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/collections.d.ts +1 -1
- package/build/cjs/flagsmith-engine/utils/collections.js +6 -0
- package/build/cjs/flagsmith-engine/utils/errors.js +6 -0
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/hashing/index.js +8 -11
- package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/index.js +5 -5
- package/build/{index.d.ts → cjs/index.d.ts} +3 -3
- package/build/{index.js → cjs/index.js} +17 -17
- package/build/cjs/package.json +1 -0
- package/build/{sdk → cjs/sdk}/analytics.d.ts +3 -0
- package/build/cjs/sdk/analytics.js +73 -0
- package/build/cjs/sdk/errors.js +9 -0
- package/build/{sdk → cjs/sdk}/index.d.ts +19 -18
- package/build/cjs/sdk/index.js +400 -0
- package/build/{sdk → cjs/sdk}/models.d.ts +2 -2
- package/build/cjs/sdk/models.js +101 -0
- package/build/{sdk → cjs/sdk}/offline_handlers.d.ts +1 -1
- package/build/cjs/sdk/offline_handlers.js +46 -0
- package/build/{sdk → cjs/sdk}/polling_manager.d.ts +1 -1
- package/build/cjs/sdk/polling_manager.js +29 -0
- package/build/{sdk → cjs/sdk}/types.d.ts +15 -7
- package/build/cjs/sdk/utils.d.ts +36 -0
- package/build/cjs/sdk/utils.js +63 -0
- package/build/esm/flagsmith-engine/environments/models.d.ts +22 -0
- package/build/esm/flagsmith-engine/environments/models.js +32 -0
- package/build/esm/flagsmith-engine/environments/util.d.ts +3 -0
- package/build/esm/flagsmith-engine/environments/util.js +18 -0
- package/build/esm/flagsmith-engine/features/constants.d.ts +4 -0
- package/build/esm/flagsmith-engine/features/constants.js +4 -0
- package/build/esm/flagsmith-engine/features/models.d.ts +37 -0
- package/build/esm/flagsmith-engine/features/models.js +110 -0
- package/build/esm/flagsmith-engine/features/util.d.ts +4 -0
- package/build/esm/flagsmith-engine/features/util.js +21 -0
- package/build/esm/flagsmith-engine/identities/models.d.ts +15 -0
- package/build/esm/flagsmith-engine/identities/models.js +44 -0
- package/build/esm/flagsmith-engine/identities/traits/models.d.ts +5 -0
- package/build/esm/flagsmith-engine/identities/traits/models.js +8 -0
- package/build/esm/flagsmith-engine/identities/util.d.ts +4 -0
- package/build/esm/flagsmith-engine/identities/util.js +17 -0
- package/build/esm/flagsmith-engine/index.d.ts +14 -0
- package/build/esm/flagsmith-engine/index.js +62 -0
- package/build/esm/flagsmith-engine/organisations/models.d.ts +9 -0
- package/build/esm/flagsmith-engine/organisations/models.js +17 -0
- package/build/esm/flagsmith-engine/organisations/util.d.ts +2 -0
- package/build/esm/flagsmith-engine/organisations/util.js +4 -0
- package/build/esm/flagsmith-engine/projects/models.d.ts +10 -0
- package/build/esm/flagsmith-engine/projects/models.js +13 -0
- package/build/esm/flagsmith-engine/projects/util.d.ts +2 -0
- package/build/esm/flagsmith-engine/projects/util.js +11 -0
- package/build/esm/flagsmith-engine/segments/constants.d.ts +34 -0
- package/build/esm/flagsmith-engine/segments/constants.js +36 -0
- package/build/esm/flagsmith-engine/segments/evaluators.d.ts +7 -0
- package/build/esm/flagsmith-engine/segments/evaluators.js +31 -0
- package/build/esm/flagsmith-engine/segments/models.d.ts +37 -0
- package/build/esm/flagsmith-engine/segments/models.js +102 -0
- package/build/esm/flagsmith-engine/segments/util.d.ts +6 -0
- package/build/esm/flagsmith-engine/segments/util.js +23 -0
- package/build/esm/flagsmith-engine/utils/collections.d.ts +3 -0
- package/build/esm/flagsmith-engine/utils/collections.js +2 -0
- package/build/esm/flagsmith-engine/utils/errors.d.ts +2 -0
- package/build/esm/flagsmith-engine/utils/errors.js +2 -0
- package/build/esm/flagsmith-engine/utils/hashing/index.d.ts +9 -0
- package/build/esm/flagsmith-engine/utils/hashing/index.js +50 -0
- package/build/esm/flagsmith-engine/utils/index.d.ts +1 -0
- package/build/esm/flagsmith-engine/utils/index.js +13 -0
- package/build/esm/index.d.ts +3 -0
- package/build/esm/index.js +4 -0
- package/build/esm/sdk/analytics.d.ts +35 -0
- package/build/esm/sdk/analytics.js +69 -0
- package/build/esm/sdk/errors.d.ts +4 -0
- package/build/esm/sdk/errors.js +4 -0
- package/build/esm/sdk/index.d.ts +131 -0
- package/build/esm/sdk/index.js +390 -0
- package/build/esm/sdk/models.d.ts +55 -0
- package/build/esm/sdk/models.js +94 -0
- package/build/esm/sdk/offline_handlers.d.ts +9 -0
- package/build/esm/sdk/offline_handlers.js +18 -0
- package/build/esm/sdk/polling_manager.d.ts +9 -0
- package/build/esm/sdk/polling_manager.js +25 -0
- package/build/esm/sdk/types.d.ts +38 -0
- package/build/esm/sdk/types.js +1 -0
- package/build/esm/sdk/utils.d.ts +36 -0
- package/build/esm/sdk/utils.js +56 -0
- package/flagsmith-engine/environments/models.ts +3 -3
- package/flagsmith-engine/environments/util.ts +4 -4
- package/flagsmith-engine/features/models.ts +1 -1
- package/flagsmith-engine/features/util.ts +1 -1
- package/flagsmith-engine/identities/models.ts +3 -4
- package/flagsmith-engine/identities/traits/models.ts +0 -1
- package/flagsmith-engine/identities/util.ts +4 -4
- package/flagsmith-engine/index.ts +13 -13
- package/flagsmith-engine/organisations/util.ts +1 -1
- package/flagsmith-engine/projects/models.ts +2 -2
- package/flagsmith-engine/projects/util.ts +4 -4
- package/flagsmith-engine/segments/evaluators.ts +6 -6
- package/flagsmith-engine/segments/models.ts +4 -4
- package/flagsmith-engine/segments/util.ts +3 -3
- package/flagsmith-engine/utils/collections.ts +1 -1
- package/flagsmith-engine/utils/index.ts +1 -1
- package/index.ts +4 -4
- package/package.json +21 -9
- package/sdk/analytics.ts +7 -5
- package/sdk/index.ts +55 -46
- package/sdk/models.ts +2 -3
- package/sdk/offline_handlers.ts +2 -2
- package/sdk/polling_manager.ts +2 -3
- package/sdk/types.ts +35 -24
- package/sdk/utils.ts +49 -29
- package/tests/engine/e2e/engine.test.ts +5 -5
- package/tests/engine/unit/engine.test.ts +5 -5
- package/tests/engine/unit/segments/segment_evaluators.test.ts +9 -9
- package/tests/engine/unit/utils/utils.test.ts +1 -1
- package/tests/sdk/analytics.test.ts +8 -13
- package/tests/sdk/data/identity-with-transient-traits.json +41 -0
- package/tests/sdk/data/transient-identity.json +29 -0
- package/tests/sdk/flagsmith-cache.test.ts +16 -32
- package/tests/sdk/flagsmith-environment-flags.test.ts +21 -36
- package/tests/sdk/flagsmith-identity-flags.test.ts +83 -32
- package/tests/sdk/flagsmith.test.ts +67 -99
- package/tests/sdk/offline-handlers.test.ts +4 -5
- package/tests/sdk/polling.test.ts +6 -8
- package/tests/sdk/utils.ts +19 -15
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.esm.json +7 -0
- package/tsconfig.json +7 -3
- package/vitest.config.ts +17 -0
- package/build/flagsmith-engine/environments/util.js +0 -27
- package/build/flagsmith-engine/features/models.js +0 -132
- package/build/flagsmith-engine/features/util.js +0 -27
- package/build/flagsmith-engine/identities/models.js +0 -113
- package/build/flagsmith-engine/identities/util.js +0 -46
- package/build/flagsmith-engine/index.d.ts +0 -14
- package/build/flagsmith-engine/index.js +0 -127
- package/build/flagsmith-engine/organisations/models.js +0 -21
- package/build/flagsmith-engine/organisations/util.js +0 -8
- package/build/flagsmith-engine/projects/util.js +0 -15
- package/build/flagsmith-engine/segments/evaluators.js +0 -45
- package/build/flagsmith-engine/segments/models.js +0 -147
- package/build/flagsmith-engine/utils/collections.js +0 -26
- package/build/flagsmith-engine/utils/errors.js +0 -26
- package/build/sdk/analytics.js +0 -120
- package/build/sdk/errors.js +0 -34
- package/build/sdk/index.js +0 -594
- package/build/sdk/models.js +0 -149
- package/build/sdk/offline_handlers.js +0 -66
- package/build/sdk/polling_manager.js +0 -72
- package/build/sdk/utils.d.ts +0 -12
- package/build/sdk/utils.js +0 -100
- package/jest.config.js +0 -5
- package/tests/index.js +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/constants.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/constants.js +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/models.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/traits/models.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/organisations/models.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/constants.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/constants.js +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/errors.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/hashing/index.d.ts +0 -0
- /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/index.d.ts +0 -0
- /package/build/{sdk → cjs/sdk}/errors.d.ts +0 -0
- /package/build/{sdk → cjs/sdk}/types.js +0 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { getEnvironmentFeatureStates, getIdentityFeatureStates } from '../flagsmith-engine/index.js';
|
|
2
|
+
import { buildEnvironmentModel } from '../flagsmith-engine/environments/util.js';
|
|
3
|
+
import { IdentityModel } from '../flagsmith-engine/index.js';
|
|
4
|
+
import { TraitModel } from '../flagsmith-engine/index.js';
|
|
5
|
+
import { AnalyticsProcessor } from './analytics.js';
|
|
6
|
+
import { FlagsmithAPIError } from './errors.js';
|
|
7
|
+
import { Flags } from './models.js';
|
|
8
|
+
import { EnvironmentDataPollingManager } from './polling_manager.js';
|
|
9
|
+
import { generateIdentitiesData, retryFetch } from './utils.js';
|
|
10
|
+
import { getIdentitySegments } from '../flagsmith-engine/segments/evaluators.js';
|
|
11
|
+
import { pino } from 'pino';
|
|
12
|
+
export { AnalyticsProcessor } from './analytics.js';
|
|
13
|
+
export { FlagsmithAPIError, FlagsmithClientError } from './errors.js';
|
|
14
|
+
export { DefaultFlag, Flags } from './models.js';
|
|
15
|
+
export { EnvironmentDataPollingManager } from './polling_manager.js';
|
|
16
|
+
const DEFAULT_API_URL = 'https://edge.api.flagsmith.com/api/v1/';
|
|
17
|
+
const DEFAULT_REQUEST_TIMEOUT_SECONDS = 10;
|
|
18
|
+
export class Flagsmith {
|
|
19
|
+
environmentKey = undefined;
|
|
20
|
+
apiUrl = undefined;
|
|
21
|
+
customHeaders;
|
|
22
|
+
agent;
|
|
23
|
+
requestTimeoutMs;
|
|
24
|
+
enableLocalEvaluation = false;
|
|
25
|
+
environmentRefreshIntervalSeconds = 60;
|
|
26
|
+
retries;
|
|
27
|
+
enableAnalytics = false;
|
|
28
|
+
defaultFlagHandler;
|
|
29
|
+
environmentFlagsUrl;
|
|
30
|
+
identitiesUrl;
|
|
31
|
+
environmentUrl;
|
|
32
|
+
environmentDataPollingManager;
|
|
33
|
+
environment;
|
|
34
|
+
offlineMode = false;
|
|
35
|
+
offlineHandler = undefined;
|
|
36
|
+
identitiesWithOverridesByIdentifier;
|
|
37
|
+
cache;
|
|
38
|
+
onEnvironmentChange;
|
|
39
|
+
analyticsProcessor;
|
|
40
|
+
logger;
|
|
41
|
+
customFetch;
|
|
42
|
+
/**
|
|
43
|
+
* A Flagsmith client.
|
|
44
|
+
*
|
|
45
|
+
* Provides an interface for interacting with the Flagsmith http API.
|
|
46
|
+
* Basic Usage::
|
|
47
|
+
*
|
|
48
|
+
* import flagsmith from Flagsmith
|
|
49
|
+
* const flagsmith = new Flagsmith({environmentKey: '<your API key>'});
|
|
50
|
+
* const environmentFlags = flagsmith.getEnvironmentFlags();
|
|
51
|
+
* const featureEnabled = environmentFlags.isFeatureEnabled('foo');
|
|
52
|
+
* const identityFlags = flagsmith.getIdentityFlags('identifier', {'foo': 'bar'});
|
|
53
|
+
* const featureEnabledForIdentity = identityFlags.isFeatureEnabled("foo")
|
|
54
|
+
*
|
|
55
|
+
* @param {string} data.environmentKey: The environment key obtained from Flagsmith interface
|
|
56
|
+
* Required unless offlineMode is True.
|
|
57
|
+
@param {string} data.apiUrl: Override the URL of the Flagsmith API to communicate with
|
|
58
|
+
@param data.customHeaders: Additional headers to add to requests made to the
|
|
59
|
+
Flagsmith API
|
|
60
|
+
@param {number} data.requestTimeoutSeconds: Number of seconds to wait for a request to
|
|
61
|
+
complete before terminating the request
|
|
62
|
+
@param {boolean} data.enableLocalEvaluation: Enables local evaluation of flags
|
|
63
|
+
@param {number} data.environmentRefreshIntervalSeconds: If using local evaluation,
|
|
64
|
+
specify the interval period between refreshes of local environment data
|
|
65
|
+
@param {number} data.retries: a urllib3.Retry object to use on all http requests to the
|
|
66
|
+
Flagsmith API
|
|
67
|
+
@param {boolean} data.enableAnalytics: if enabled, sends additional requests to the Flagsmith
|
|
68
|
+
API to power flag analytics charts
|
|
69
|
+
@param data.defaultFlagHandler: callable which will be used in the case where
|
|
70
|
+
flags cannot be retrieved from the API or a non-existent feature is
|
|
71
|
+
requested
|
|
72
|
+
@param data.logger: an instance of the pino Logger class to use for logging
|
|
73
|
+
@param {boolean} data.offlineMode: sets the client into offline mode. Relies on offlineHandler for
|
|
74
|
+
evaluating flags.
|
|
75
|
+
@param {BaseOfflineHandler} data.offlineHandler: provide a handler for offline logic. Used to get environment
|
|
76
|
+
document from another source when in offlineMode. Works in place of
|
|
77
|
+
defaultFlagHandler if offlineMode is not set and using remote evaluation.
|
|
78
|
+
*/
|
|
79
|
+
constructor(data = {}) {
|
|
80
|
+
// if (!data.offlineMode && !data.environmentKey) {
|
|
81
|
+
// throw new Error('ValueError: environmentKey is required.');
|
|
82
|
+
// }
|
|
83
|
+
this.agent = data.agent;
|
|
84
|
+
this.customFetch = data.fetch ?? fetch;
|
|
85
|
+
this.environmentKey = data.environmentKey;
|
|
86
|
+
this.apiUrl = data.apiUrl || this.apiUrl;
|
|
87
|
+
this.customHeaders = data.customHeaders;
|
|
88
|
+
this.requestTimeoutMs =
|
|
89
|
+
1000 * (data.requestTimeoutSeconds ?? DEFAULT_REQUEST_TIMEOUT_SECONDS);
|
|
90
|
+
this.enableLocalEvaluation = data.enableLocalEvaluation;
|
|
91
|
+
this.environmentRefreshIntervalSeconds =
|
|
92
|
+
data.environmentRefreshIntervalSeconds || this.environmentRefreshIntervalSeconds;
|
|
93
|
+
this.retries = data.retries;
|
|
94
|
+
this.enableAnalytics = data.enableAnalytics || false;
|
|
95
|
+
this.defaultFlagHandler = data.defaultFlagHandler;
|
|
96
|
+
this.onEnvironmentChange = data.onEnvironmentChange;
|
|
97
|
+
this.logger = data.logger || pino();
|
|
98
|
+
this.offlineMode = data.offlineMode || false;
|
|
99
|
+
this.offlineHandler = data.offlineHandler;
|
|
100
|
+
// argument validation
|
|
101
|
+
if (this.offlineMode && !this.offlineHandler) {
|
|
102
|
+
throw new Error('ValueError: offlineHandler must be provided to use offline mode.');
|
|
103
|
+
}
|
|
104
|
+
else if (this.defaultFlagHandler && this.offlineHandler) {
|
|
105
|
+
throw new Error('ValueError: Cannot use both defaultFlagHandler and offlineHandler.');
|
|
106
|
+
}
|
|
107
|
+
if (this.offlineHandler) {
|
|
108
|
+
this.environment = this.offlineHandler.getEnvironment();
|
|
109
|
+
}
|
|
110
|
+
if (!!data.cache) {
|
|
111
|
+
const missingMethods = ['has', 'get', 'set'].filter(method => data.cache && !data.cache[method]);
|
|
112
|
+
if (missingMethods.length > 0) {
|
|
113
|
+
throw new Error(`Please implement the following methods in your cache: ${missingMethods.join(', ')}`);
|
|
114
|
+
}
|
|
115
|
+
this.cache = data.cache;
|
|
116
|
+
}
|
|
117
|
+
if (!this.offlineMode) {
|
|
118
|
+
if (!this.environmentKey) {
|
|
119
|
+
throw new Error('ValueError: environmentKey is required.');
|
|
120
|
+
}
|
|
121
|
+
const apiUrl = data.apiUrl || DEFAULT_API_URL;
|
|
122
|
+
this.apiUrl = apiUrl.endsWith('/') ? apiUrl : `${apiUrl}/`;
|
|
123
|
+
this.environmentFlagsUrl = `${this.apiUrl}flags/`;
|
|
124
|
+
this.identitiesUrl = `${this.apiUrl}identities/`;
|
|
125
|
+
this.environmentUrl = `${this.apiUrl}environment-document/`;
|
|
126
|
+
if (this.enableLocalEvaluation) {
|
|
127
|
+
if (!this.environmentKey.startsWith('ser.')) {
|
|
128
|
+
console.error('In order to use local evaluation, please generate a server key in the environment settings page.');
|
|
129
|
+
}
|
|
130
|
+
this.environmentDataPollingManager = new EnvironmentDataPollingManager(this, this.environmentRefreshIntervalSeconds);
|
|
131
|
+
this.environmentDataPollingManager.start();
|
|
132
|
+
this.updateEnvironment();
|
|
133
|
+
}
|
|
134
|
+
this.analyticsProcessor = data.enableAnalytics
|
|
135
|
+
? new AnalyticsProcessor({
|
|
136
|
+
environmentKey: this.environmentKey,
|
|
137
|
+
baseApiUrl: this.apiUrl,
|
|
138
|
+
requestTimeoutMs: this.requestTimeoutMs,
|
|
139
|
+
logger: this.logger
|
|
140
|
+
})
|
|
141
|
+
: undefined;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get all the default for flags for the current environment.
|
|
146
|
+
*
|
|
147
|
+
* @returns Flags object holding all the flags for the current environment.
|
|
148
|
+
*/
|
|
149
|
+
async getEnvironmentFlags() {
|
|
150
|
+
const cachedItem = !!this.cache && (await this.cache.get(`flags`));
|
|
151
|
+
if (!!cachedItem) {
|
|
152
|
+
return cachedItem;
|
|
153
|
+
}
|
|
154
|
+
if (this.enableLocalEvaluation && !this.offlineMode) {
|
|
155
|
+
return new Promise((resolve, reject) => this.environmentPromise.then(() => {
|
|
156
|
+
resolve(this.getEnvironmentFlagsFromDocument());
|
|
157
|
+
}).catch(e => reject(e)));
|
|
158
|
+
}
|
|
159
|
+
if (this.environment) {
|
|
160
|
+
return this.getEnvironmentFlagsFromDocument();
|
|
161
|
+
}
|
|
162
|
+
return this.getEnvironmentFlagsFromApi();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get all the flags for the current environment for a given identity. Will also
|
|
166
|
+
upsert all traits to the Flagsmith API for future evaluations. Providing a
|
|
167
|
+
trait with a value of None will remove the trait from the identity if it exists.
|
|
168
|
+
*
|
|
169
|
+
* @param {string} identifier a unique identifier for the identity in the current
|
|
170
|
+
environment, e.g. email address, username, uuid
|
|
171
|
+
* @param {{[key:string]:any | ITraitConfig}} traits? a dictionary of traits to add / update on the identity in
|
|
172
|
+
Flagsmith, e.g. {"num_orders": 10} or {age: {value: 30, transient: true}}
|
|
173
|
+
* @returns Flags object holding all the flags for the given identity.
|
|
174
|
+
*/
|
|
175
|
+
async getIdentityFlags(identifier, traits, transient = false) {
|
|
176
|
+
if (!identifier) {
|
|
177
|
+
throw new Error('`identifier` argument is missing or invalid.');
|
|
178
|
+
}
|
|
179
|
+
const cachedItem = !!this.cache && (await this.cache.get(`flags-${identifier}`));
|
|
180
|
+
if (!!cachedItem) {
|
|
181
|
+
return cachedItem;
|
|
182
|
+
}
|
|
183
|
+
traits = traits || {};
|
|
184
|
+
if (this.enableLocalEvaluation) {
|
|
185
|
+
return new Promise((resolve, reject) => this.environmentPromise.then(() => {
|
|
186
|
+
resolve(this.getIdentityFlagsFromDocument(identifier, traits || {}));
|
|
187
|
+
}).catch(e => reject(e)));
|
|
188
|
+
}
|
|
189
|
+
if (this.offlineMode) {
|
|
190
|
+
return this.getIdentityFlagsFromDocument(identifier, traits || {});
|
|
191
|
+
}
|
|
192
|
+
return this.getIdentityFlagsFromApi(identifier, traits, transient);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get the segments for the current environment for a given identity. Will also
|
|
196
|
+
upsert all traits to the Flagsmith API for future evaluations. Providing a
|
|
197
|
+
trait with a value of None will remove the trait from the identity if it exists.
|
|
198
|
+
*
|
|
199
|
+
* @param {string} identifier a unique identifier for the identity in the current
|
|
200
|
+
environment, e.g. email address, username, uuid
|
|
201
|
+
* @param {{[key:string]:any}} traits? a dictionary of traits to add / update on the identity in
|
|
202
|
+
Flagsmith, e.g. {"num_orders": 10}
|
|
203
|
+
* @returns Segments that the given identity belongs to.
|
|
204
|
+
*/
|
|
205
|
+
getIdentitySegments(identifier, traits) {
|
|
206
|
+
if (!identifier) {
|
|
207
|
+
throw new Error('`identifier` argument is missing or invalid.');
|
|
208
|
+
}
|
|
209
|
+
traits = traits || {};
|
|
210
|
+
if (this.enableLocalEvaluation) {
|
|
211
|
+
return new Promise((resolve, reject) => {
|
|
212
|
+
return this.environmentPromise.then(() => {
|
|
213
|
+
const identityModel = this.getIdentityModel(identifier, Object.keys(traits || {}).map(key => ({
|
|
214
|
+
key,
|
|
215
|
+
value: traits?.[key]
|
|
216
|
+
})));
|
|
217
|
+
const segments = getIdentitySegments(this.environment, identityModel);
|
|
218
|
+
return resolve(segments);
|
|
219
|
+
}).catch(e => reject(e));
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
console.error('This function is only permitted with local evaluation.');
|
|
223
|
+
return Promise.resolve([]);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Updates the environment state for local flag evaluation.
|
|
227
|
+
* Sets a local promise to prevent race conditions in getIdentityFlags / getIdentitySegments.
|
|
228
|
+
* You only need to call this if you wish to bypass environmentRefreshIntervalSeconds.
|
|
229
|
+
*/
|
|
230
|
+
async updateEnvironment() {
|
|
231
|
+
try {
|
|
232
|
+
const request = this.getEnvironmentFromApi();
|
|
233
|
+
if (!this.environmentPromise) {
|
|
234
|
+
this.environmentPromise = request.then(res => {
|
|
235
|
+
this.environment = res;
|
|
236
|
+
});
|
|
237
|
+
await this.environmentPromise;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
this.environment = await request;
|
|
241
|
+
}
|
|
242
|
+
if (this.environment.identityOverrides?.length) {
|
|
243
|
+
this.identitiesWithOverridesByIdentifier = new Map(this.environment.identityOverrides.map(identity => [
|
|
244
|
+
identity.identifier,
|
|
245
|
+
identity
|
|
246
|
+
]));
|
|
247
|
+
}
|
|
248
|
+
if (this.onEnvironmentChange) {
|
|
249
|
+
this.onEnvironmentChange(null, this.environment);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
if (this.onEnvironmentChange) {
|
|
254
|
+
this.onEnvironmentChange(e, this.environment);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async close() {
|
|
259
|
+
this.environmentDataPollingManager?.stop();
|
|
260
|
+
}
|
|
261
|
+
async getJSONResponse(url, method, body) {
|
|
262
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
263
|
+
if (this.environmentKey) {
|
|
264
|
+
headers['X-Environment-Key'] = this.environmentKey;
|
|
265
|
+
}
|
|
266
|
+
if (this.customHeaders) {
|
|
267
|
+
for (const [k, v] of Object.entries(this.customHeaders)) {
|
|
268
|
+
headers[k] = v;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const data = await retryFetch(url, {
|
|
272
|
+
dispatcher: this.agent,
|
|
273
|
+
method: method,
|
|
274
|
+
body: JSON.stringify(body),
|
|
275
|
+
headers: headers
|
|
276
|
+
}, this.retries, this.requestTimeoutMs, this.customFetch);
|
|
277
|
+
if (data.status !== 200) {
|
|
278
|
+
throw new FlagsmithAPIError(`Invalid request made to Flagsmith API. Response status code: ${data.status}`);
|
|
279
|
+
}
|
|
280
|
+
return data.json();
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* This promise ensures that the environment is retrieved before attempting to locally evaluate.
|
|
284
|
+
*/
|
|
285
|
+
environmentPromise;
|
|
286
|
+
async getEnvironmentFromApi() {
|
|
287
|
+
if (!this.environmentUrl) {
|
|
288
|
+
throw new Error('`apiUrl` argument is missing or invalid.');
|
|
289
|
+
}
|
|
290
|
+
const environment_data = await this.getJSONResponse(this.environmentUrl, 'GET');
|
|
291
|
+
return buildEnvironmentModel(environment_data);
|
|
292
|
+
}
|
|
293
|
+
async getEnvironmentFlagsFromDocument() {
|
|
294
|
+
const flags = Flags.fromFeatureStateModels({
|
|
295
|
+
featureStates: getEnvironmentFeatureStates(this.environment),
|
|
296
|
+
analyticsProcessor: this.analyticsProcessor,
|
|
297
|
+
defaultFlagHandler: this.defaultFlagHandler
|
|
298
|
+
});
|
|
299
|
+
if (!!this.cache) {
|
|
300
|
+
await this.cache.set('flags', flags);
|
|
301
|
+
}
|
|
302
|
+
return flags;
|
|
303
|
+
}
|
|
304
|
+
async getIdentityFlagsFromDocument(identifier, traits) {
|
|
305
|
+
const identityModel = this.getIdentityModel(identifier, Object.keys(traits).map(key => ({
|
|
306
|
+
key,
|
|
307
|
+
value: traits[key]
|
|
308
|
+
})));
|
|
309
|
+
const featureStates = getIdentityFeatureStates(this.environment, identityModel);
|
|
310
|
+
const flags = Flags.fromFeatureStateModels({
|
|
311
|
+
featureStates: featureStates,
|
|
312
|
+
analyticsProcessor: this.analyticsProcessor,
|
|
313
|
+
defaultFlagHandler: this.defaultFlagHandler,
|
|
314
|
+
identityID: identityModel.djangoID || identityModel.compositeKey
|
|
315
|
+
});
|
|
316
|
+
if (!!this.cache) {
|
|
317
|
+
await this.cache.set(`flags-${identifier}`, flags);
|
|
318
|
+
}
|
|
319
|
+
return flags;
|
|
320
|
+
}
|
|
321
|
+
async getEnvironmentFlagsFromApi() {
|
|
322
|
+
if (!this.environmentFlagsUrl) {
|
|
323
|
+
throw new Error('`apiUrl` argument is missing or invalid.');
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
const apiFlags = await this.getJSONResponse(this.environmentFlagsUrl, 'GET');
|
|
327
|
+
const flags = Flags.fromAPIFlags({
|
|
328
|
+
apiFlags: apiFlags,
|
|
329
|
+
analyticsProcessor: this.analyticsProcessor,
|
|
330
|
+
defaultFlagHandler: this.defaultFlagHandler
|
|
331
|
+
});
|
|
332
|
+
if (!!this.cache) {
|
|
333
|
+
await this.cache.set('flags', flags);
|
|
334
|
+
}
|
|
335
|
+
return flags;
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
if (this.offlineHandler) {
|
|
339
|
+
return this.getEnvironmentFlagsFromDocument();
|
|
340
|
+
}
|
|
341
|
+
if (this.defaultFlagHandler) {
|
|
342
|
+
return new Flags({
|
|
343
|
+
flags: {},
|
|
344
|
+
defaultFlagHandler: this.defaultFlagHandler
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
throw e;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async getIdentityFlagsFromApi(identifier, traits, transient = false) {
|
|
351
|
+
if (!this.identitiesUrl) {
|
|
352
|
+
throw new Error('`apiUrl` argument is missing or invalid.');
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
const data = generateIdentitiesData(identifier, traits, transient);
|
|
356
|
+
const jsonResponse = await this.getJSONResponse(this.identitiesUrl, 'POST', data);
|
|
357
|
+
const flags = Flags.fromAPIFlags({
|
|
358
|
+
apiFlags: jsonResponse['flags'],
|
|
359
|
+
analyticsProcessor: this.analyticsProcessor,
|
|
360
|
+
defaultFlagHandler: this.defaultFlagHandler
|
|
361
|
+
});
|
|
362
|
+
if (!!this.cache) {
|
|
363
|
+
await this.cache.set(`flags-${identifier}`, flags);
|
|
364
|
+
}
|
|
365
|
+
return flags;
|
|
366
|
+
}
|
|
367
|
+
catch (e) {
|
|
368
|
+
if (this.offlineHandler) {
|
|
369
|
+
return this.getIdentityFlagsFromDocument(identifier, traits);
|
|
370
|
+
}
|
|
371
|
+
if (this.defaultFlagHandler) {
|
|
372
|
+
return new Flags({
|
|
373
|
+
flags: {},
|
|
374
|
+
defaultFlagHandler: this.defaultFlagHandler
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
throw e;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
getIdentityModel(identifier, traits) {
|
|
381
|
+
const traitModels = traits.map(trait => new TraitModel(trait.key, trait.value));
|
|
382
|
+
let identityWithOverrides = this.identitiesWithOverridesByIdentifier?.get(identifier);
|
|
383
|
+
if (identityWithOverrides) {
|
|
384
|
+
identityWithOverrides.updateTraits(traitModels);
|
|
385
|
+
return identityWithOverrides;
|
|
386
|
+
}
|
|
387
|
+
return new IdentityModel('0', traitModels, [], this.environment.apiKey, identifier);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
export default Flagsmith;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FeatureStateModel } from '../flagsmith-engine/features/models.js';
|
|
2
|
+
import { AnalyticsProcessor } from './analytics.js';
|
|
3
|
+
export declare class BaseFlag {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
value: string | number | boolean | undefined;
|
|
6
|
+
isDefault: boolean;
|
|
7
|
+
constructor(value: string | number | boolean | undefined, enabled: boolean, isDefault: boolean);
|
|
8
|
+
}
|
|
9
|
+
export declare class DefaultFlag extends BaseFlag {
|
|
10
|
+
constructor(value: string | number | boolean | undefined, enabled: boolean);
|
|
11
|
+
}
|
|
12
|
+
export declare class Flag extends BaseFlag {
|
|
13
|
+
featureId: number;
|
|
14
|
+
featureName: string;
|
|
15
|
+
constructor(params: {
|
|
16
|
+
value: string | number | boolean | undefined;
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
isDefault?: boolean;
|
|
19
|
+
featureId: number;
|
|
20
|
+
featureName: string;
|
|
21
|
+
});
|
|
22
|
+
static fromFeatureStateModel(fsm: FeatureStateModel, identityId: number | string | undefined): Flag;
|
|
23
|
+
static fromAPIFlag(flagData: any): Flag;
|
|
24
|
+
}
|
|
25
|
+
export declare class Flags {
|
|
26
|
+
flags: {
|
|
27
|
+
[key: string]: Flag;
|
|
28
|
+
};
|
|
29
|
+
defaultFlagHandler?: (featureName: string) => DefaultFlag;
|
|
30
|
+
analyticsProcessor?: AnalyticsProcessor;
|
|
31
|
+
constructor(data: {
|
|
32
|
+
flags: {
|
|
33
|
+
[key: string]: Flag;
|
|
34
|
+
};
|
|
35
|
+
defaultFlagHandler?: (v: string) => DefaultFlag;
|
|
36
|
+
analyticsProcessor?: AnalyticsProcessor;
|
|
37
|
+
});
|
|
38
|
+
static fromFeatureStateModels(data: {
|
|
39
|
+
featureStates: FeatureStateModel[];
|
|
40
|
+
analyticsProcessor?: AnalyticsProcessor;
|
|
41
|
+
defaultFlagHandler?: (f: string) => DefaultFlag;
|
|
42
|
+
identityID?: string | number;
|
|
43
|
+
}): Flags;
|
|
44
|
+
static fromAPIFlags(data: {
|
|
45
|
+
apiFlags: {
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}[];
|
|
48
|
+
analyticsProcessor?: AnalyticsProcessor;
|
|
49
|
+
defaultFlagHandler?: (v: string) => DefaultFlag;
|
|
50
|
+
}): Flags;
|
|
51
|
+
allFlags(): Flag[];
|
|
52
|
+
getFlag(featureName: string): BaseFlag;
|
|
53
|
+
getFeatureValue(featureName: string): any;
|
|
54
|
+
isFeatureEnabled(featureName: string): boolean;
|
|
55
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export class BaseFlag {
|
|
2
|
+
enabled;
|
|
3
|
+
value;
|
|
4
|
+
isDefault;
|
|
5
|
+
constructor(value, enabled, isDefault) {
|
|
6
|
+
this.value = value;
|
|
7
|
+
this.enabled = enabled;
|
|
8
|
+
this.isDefault = isDefault;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class DefaultFlag extends BaseFlag {
|
|
12
|
+
constructor(value, enabled) {
|
|
13
|
+
super(value, enabled, true);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class Flag extends BaseFlag {
|
|
17
|
+
featureId;
|
|
18
|
+
featureName;
|
|
19
|
+
constructor(params) {
|
|
20
|
+
super(params.value, params.enabled, !!params.isDefault);
|
|
21
|
+
this.featureId = params.featureId;
|
|
22
|
+
this.featureName = params.featureName;
|
|
23
|
+
}
|
|
24
|
+
static fromFeatureStateModel(fsm, identityId) {
|
|
25
|
+
return new Flag({
|
|
26
|
+
value: fsm.getValue(identityId),
|
|
27
|
+
enabled: fsm.enabled,
|
|
28
|
+
featureId: fsm.feature.id,
|
|
29
|
+
featureName: fsm.feature.name
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
static fromAPIFlag(flagData) {
|
|
33
|
+
return new Flag({
|
|
34
|
+
enabled: flagData['enabled'],
|
|
35
|
+
value: flagData['feature_state_value'] || flagData['value'],
|
|
36
|
+
featureId: flagData['feature']['id'],
|
|
37
|
+
featureName: flagData['feature']['name']
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export class Flags {
|
|
42
|
+
flags = {};
|
|
43
|
+
defaultFlagHandler;
|
|
44
|
+
analyticsProcessor;
|
|
45
|
+
constructor(data) {
|
|
46
|
+
this.flags = data.flags;
|
|
47
|
+
this.defaultFlagHandler = data.defaultFlagHandler;
|
|
48
|
+
this.analyticsProcessor = data.analyticsProcessor;
|
|
49
|
+
}
|
|
50
|
+
static fromFeatureStateModels(data) {
|
|
51
|
+
const flags = {};
|
|
52
|
+
for (const fs of data.featureStates) {
|
|
53
|
+
flags[fs.feature.name] = Flag.fromFeatureStateModel(fs, data.identityID);
|
|
54
|
+
}
|
|
55
|
+
return new Flags({
|
|
56
|
+
flags: flags,
|
|
57
|
+
defaultFlagHandler: data.defaultFlagHandler,
|
|
58
|
+
analyticsProcessor: data.analyticsProcessor
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
static fromAPIFlags(data) {
|
|
62
|
+
const flags = {};
|
|
63
|
+
for (const flagData of data.apiFlags) {
|
|
64
|
+
flags[flagData['feature']['name']] = Flag.fromAPIFlag(flagData);
|
|
65
|
+
}
|
|
66
|
+
return new Flags({
|
|
67
|
+
flags: flags,
|
|
68
|
+
defaultFlagHandler: data.defaultFlagHandler,
|
|
69
|
+
analyticsProcessor: data.analyticsProcessor
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
allFlags() {
|
|
73
|
+
return Object.values(this.flags);
|
|
74
|
+
}
|
|
75
|
+
getFlag(featureName) {
|
|
76
|
+
const flag = this.flags[featureName];
|
|
77
|
+
if (!flag) {
|
|
78
|
+
if (this.defaultFlagHandler) {
|
|
79
|
+
return this.defaultFlagHandler(featureName);
|
|
80
|
+
}
|
|
81
|
+
return { enabled: false, isDefault: true, value: undefined };
|
|
82
|
+
}
|
|
83
|
+
if (this.analyticsProcessor && flag.featureId) {
|
|
84
|
+
this.analyticsProcessor.trackFeature(flag.featureName);
|
|
85
|
+
}
|
|
86
|
+
return flag;
|
|
87
|
+
}
|
|
88
|
+
getFeatureValue(featureName) {
|
|
89
|
+
return this.getFlag(featureName).value;
|
|
90
|
+
}
|
|
91
|
+
isFeatureEnabled(featureName) {
|
|
92
|
+
return this.getFlag(featureName).enabled;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EnvironmentModel } from '../flagsmith-engine/environments/models.js';
|
|
2
|
+
export declare class BaseOfflineHandler {
|
|
3
|
+
getEnvironment(): EnvironmentModel;
|
|
4
|
+
}
|
|
5
|
+
export declare class LocalFileHandler extends BaseOfflineHandler {
|
|
6
|
+
environment: EnvironmentModel;
|
|
7
|
+
constructor(environment_document_path: string);
|
|
8
|
+
getEnvironment(): EnvironmentModel;
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { buildEnvironmentModel } from '../flagsmith-engine/environments/util.js';
|
|
3
|
+
export class BaseOfflineHandler {
|
|
4
|
+
getEnvironment() {
|
|
5
|
+
throw new Error('Not implemented');
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class LocalFileHandler extends BaseOfflineHandler {
|
|
9
|
+
environment;
|
|
10
|
+
constructor(environment_document_path) {
|
|
11
|
+
super();
|
|
12
|
+
const environment_document = fs.readFileSync(environment_document_path, 'utf8');
|
|
13
|
+
this.environment = buildEnvironmentModel(JSON.parse(environment_document));
|
|
14
|
+
}
|
|
15
|
+
getEnvironment() {
|
|
16
|
+
return this.environment;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class EnvironmentDataPollingManager {
|
|
2
|
+
interval;
|
|
3
|
+
main;
|
|
4
|
+
refreshIntervalSeconds;
|
|
5
|
+
constructor(main, refreshIntervalSeconds) {
|
|
6
|
+
this.main = main;
|
|
7
|
+
this.refreshIntervalSeconds = refreshIntervalSeconds;
|
|
8
|
+
}
|
|
9
|
+
start() {
|
|
10
|
+
const updateEnvironment = () => {
|
|
11
|
+
if (this.interval)
|
|
12
|
+
clearInterval(this.interval);
|
|
13
|
+
this.interval = setInterval(async () => {
|
|
14
|
+
await this.main.updateEnvironment();
|
|
15
|
+
}, this.refreshIntervalSeconds * 1000);
|
|
16
|
+
};
|
|
17
|
+
updateEnvironment();
|
|
18
|
+
}
|
|
19
|
+
stop() {
|
|
20
|
+
if (!this.interval) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
clearInterval(this.interval);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { DefaultFlag, Flags } from './models.js';
|
|
2
|
+
import { EnvironmentModel } from '../flagsmith-engine/index.js';
|
|
3
|
+
import { Dispatcher } from 'undici-types';
|
|
4
|
+
import { Logger } from 'pino';
|
|
5
|
+
import { BaseOfflineHandler } from './offline_handlers.js';
|
|
6
|
+
export type IFlagsmithValue<T = string | number | boolean | null> = T;
|
|
7
|
+
export interface FlagsmithCache {
|
|
8
|
+
get(key: string): Promise<Flags | undefined> | undefined;
|
|
9
|
+
set(key: string, value: Flags, ttl?: string | number): boolean | Promise<boolean>;
|
|
10
|
+
has(key: string): boolean | Promise<boolean>;
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}
|
|
13
|
+
export type Fetch = typeof fetch;
|
|
14
|
+
export interface FlagsmithConfig {
|
|
15
|
+
environmentKey?: string;
|
|
16
|
+
apiUrl?: string;
|
|
17
|
+
agent?: Dispatcher;
|
|
18
|
+
fetch?: Fetch;
|
|
19
|
+
customHeaders?: {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
requestTimeoutSeconds?: number;
|
|
23
|
+
enableLocalEvaluation?: boolean;
|
|
24
|
+
environmentRefreshIntervalSeconds?: number;
|
|
25
|
+
retries?: number;
|
|
26
|
+
enableAnalytics?: boolean;
|
|
27
|
+
defaultFlagHandler?: (featureName: string) => DefaultFlag;
|
|
28
|
+
cache?: FlagsmithCache;
|
|
29
|
+
onEnvironmentChange?: (error: Error | null, result: EnvironmentModel) => void;
|
|
30
|
+
logger?: Logger;
|
|
31
|
+
offlineMode?: boolean;
|
|
32
|
+
offlineHandler?: BaseOfflineHandler;
|
|
33
|
+
}
|
|
34
|
+
export interface ITraitConfig {
|
|
35
|
+
value: FlagsmithTraitValue;
|
|
36
|
+
transient?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare type FlagsmithTraitValue = IFlagsmithValue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Fetch, FlagsmithTraitValue, ITraitConfig } from './types.js';
|
|
2
|
+
import { Dispatcher } from "undici-types";
|
|
3
|
+
type Traits = {
|
|
4
|
+
[key: string]: ITraitConfig | FlagsmithTraitValue;
|
|
5
|
+
};
|
|
6
|
+
export declare function isTraitConfig(traitValue: ITraitConfig | FlagsmithTraitValue): traitValue is ITraitConfig;
|
|
7
|
+
export declare function generateIdentitiesData(identifier: string, traits: Traits, transient: boolean): {
|
|
8
|
+
identifier: string;
|
|
9
|
+
traits: ({
|
|
10
|
+
trait_key: string;
|
|
11
|
+
trait_value: string | number | boolean | null;
|
|
12
|
+
transient: boolean | undefined;
|
|
13
|
+
} | {
|
|
14
|
+
trait_key: string;
|
|
15
|
+
trait_value: string | number | boolean | null;
|
|
16
|
+
transient?: undefined;
|
|
17
|
+
})[];
|
|
18
|
+
transient: boolean;
|
|
19
|
+
} | {
|
|
20
|
+
identifier: string;
|
|
21
|
+
traits: ({
|
|
22
|
+
trait_key: string;
|
|
23
|
+
trait_value: string | number | boolean | null;
|
|
24
|
+
transient: boolean | undefined;
|
|
25
|
+
} | {
|
|
26
|
+
trait_key: string;
|
|
27
|
+
trait_value: string | number | boolean | null;
|
|
28
|
+
transient?: undefined;
|
|
29
|
+
})[];
|
|
30
|
+
transient?: undefined;
|
|
31
|
+
};
|
|
32
|
+
export declare const delay: (ms: number) => Promise<unknown>;
|
|
33
|
+
export declare const retryFetch: (url: string, fetchOptions: RequestInit & {
|
|
34
|
+
dispatcher?: Dispatcher;
|
|
35
|
+
}, retries: number | undefined, timeoutMs: number | undefined, customFetch: Fetch) => Promise<Response>;
|
|
36
|
+
export {};
|