@featurevisor/sdk 0.9.0 → 0.10.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/CHANGELOG.md +19 -0
- package/dist/index.js +1 -1
- package/dist/index.js.gz +0 -0
- package/dist/index.js.map +1 -1
- package/lib/client.d.ts +3 -0
- package/lib/client.js +23 -8
- package/lib/client.js.map +1 -1
- package/lib/createInstance.d.ts +12 -1
- package/lib/createInstance.js +72 -15
- package/lib/createInstance.js.map +1 -1
- package/lib/createInstance.spec.d.ts +1 -0
- package/package.json +3 -3
- package/src/client.ts +31 -9
- package/src/createInstance.spec.ts +138 -0
- package/src/createInstance.ts +106 -23
package/src/createInstance.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DatafileContent } from "@featurevisor/types";
|
|
1
|
+
import { DatafileContent, Attributes } from "@featurevisor/types";
|
|
2
2
|
import { FeaturevisorSDK, ConfigureBucketValue, ActivationCallback } from "./client";
|
|
3
3
|
import { createLogger, Logger } from "./logger";
|
|
4
4
|
|
|
@@ -15,6 +15,10 @@ export interface InstanceOptions {
|
|
|
15
15
|
onReady?: ReadyCallback;
|
|
16
16
|
handleDatafileFetch?: (datafileUrl: string) => Promise<DatafileContent>;
|
|
17
17
|
logger?: Logger;
|
|
18
|
+
interceptAttributes?: (attributes: Attributes) => Attributes;
|
|
19
|
+
refreshInterval?: number; // seconds
|
|
20
|
+
onRefresh?: () => void;
|
|
21
|
+
onUpdate?: () => void;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
// @TODO: consider renaming it to FeaturevisorSDK in next breaking semver
|
|
@@ -48,16 +52,30 @@ export interface FeaturevisorInstance {
|
|
|
48
52
|
|
|
49
53
|
/**
|
|
50
54
|
* Additions
|
|
51
|
-
*
|
|
52
|
-
* @TODO
|
|
53
55
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
setLogLevels: Logger["setLevels"];
|
|
57
|
+
refresh: () => void;
|
|
58
|
+
startRefreshing: () => void;
|
|
59
|
+
stopRefreshing: () => void;
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
function
|
|
60
|
-
|
|
62
|
+
function fetchDatafileContent(datafileUrl, options: InstanceOptions): Promise<DatafileContent> {
|
|
63
|
+
if (options.handleDatafileFetch) {
|
|
64
|
+
return options.handleDatafileFetch(datafileUrl);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return fetch(datafileUrl).then((res) => res.json());
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getInstanceFromSdk(
|
|
71
|
+
sdk: FeaturevisorSDK,
|
|
72
|
+
options: InstanceOptions,
|
|
73
|
+
logger: Logger,
|
|
74
|
+
): FeaturevisorInstance {
|
|
75
|
+
let intervalId;
|
|
76
|
+
let refreshInProgress = false;
|
|
77
|
+
|
|
78
|
+
const instance: FeaturevisorInstance = {
|
|
61
79
|
// variation
|
|
62
80
|
getVariation: sdk.getVariation.bind(sdk),
|
|
63
81
|
getVariationBoolean: sdk.getVariationBoolean.bind(sdk),
|
|
@@ -82,11 +100,78 @@ function getInstanceFromSdk(sdk: FeaturevisorSDK, options: InstanceOptions): Fea
|
|
|
82
100
|
getVariableObject: sdk.getVariableObject.bind(sdk),
|
|
83
101
|
|
|
84
102
|
// additions
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
103
|
+
setLogLevels: logger.setLevels.bind(logger),
|
|
104
|
+
|
|
105
|
+
refresh() {
|
|
106
|
+
logger.debug("refreshing datafile");
|
|
107
|
+
|
|
108
|
+
if (refreshInProgress) {
|
|
109
|
+
return logger.warn("refresh in progress, skipping");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!options.datafileUrl) {
|
|
113
|
+
return logger.error("cannot refresh since `datafileUrl` is not provided");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
refreshInProgress = true;
|
|
117
|
+
|
|
118
|
+
fetchDatafileContent(options.datafileUrl, options)
|
|
119
|
+
.then((datafile) => {
|
|
120
|
+
const currentRevision = sdk.getRevision();
|
|
121
|
+
const newRevision = datafile.revision;
|
|
122
|
+
const isNotSameRevision = currentRevision !== newRevision;
|
|
123
|
+
|
|
124
|
+
sdk.setDatafile(datafile);
|
|
125
|
+
logger.info("refreshed datafile");
|
|
126
|
+
|
|
127
|
+
if (typeof options.onRefresh === "function") {
|
|
128
|
+
options.onRefresh();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (isNotSameRevision && typeof options.onUpdate === "function") {
|
|
132
|
+
options.onUpdate();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
refreshInProgress = false;
|
|
136
|
+
})
|
|
137
|
+
.catch((e) => {
|
|
138
|
+
logger.error("failed to refresh datafile", { error: e });
|
|
139
|
+
refreshInProgress = false;
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
startRefreshing() {
|
|
144
|
+
if (!options.datafileUrl) {
|
|
145
|
+
return logger.error("cannot start refreshing since `datafileUrl` is not provided");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (intervalId) {
|
|
149
|
+
return logger.warn("refreshing has already started");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!options.refreshInterval) {
|
|
153
|
+
return logger.warn("no `refreshInterval` option provided");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
intervalId = setInterval(() => {
|
|
157
|
+
instance.refresh();
|
|
158
|
+
}, options.refreshInterval * 1000);
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
stopRefreshing() {
|
|
162
|
+
if (!intervalId) {
|
|
163
|
+
return logger.warn("refreshing has not started yet");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
clearInterval(intervalId);
|
|
167
|
+
},
|
|
89
168
|
};
|
|
169
|
+
|
|
170
|
+
if (options.datafileUrl && options.refreshInterval) {
|
|
171
|
+
instance.startRefreshing();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return instance;
|
|
90
175
|
}
|
|
91
176
|
|
|
92
177
|
const emptyDatafile: DatafileContent = {
|
|
@@ -97,14 +182,6 @@ const emptyDatafile: DatafileContent = {
|
|
|
97
182
|
features: [],
|
|
98
183
|
};
|
|
99
184
|
|
|
100
|
-
function fetchDatafileContent(datafileUrl, options: InstanceOptions): Promise<DatafileContent> {
|
|
101
|
-
if (options.handleDatafileFetch) {
|
|
102
|
-
return options.handleDatafileFetch(datafileUrl);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return fetch(datafileUrl).then((res) => res.json());
|
|
106
|
-
}
|
|
107
|
-
|
|
108
185
|
export function createInstance(options: InstanceOptions) {
|
|
109
186
|
if (!options.datafile && !options.datafileUrl) {
|
|
110
187
|
throw new Error(
|
|
@@ -114,6 +191,10 @@ export function createInstance(options: InstanceOptions) {
|
|
|
114
191
|
|
|
115
192
|
const logger = options.logger || createLogger();
|
|
116
193
|
|
|
194
|
+
if (!options.datafileUrl && options.refreshInterval) {
|
|
195
|
+
logger.warn("refreshing datafile requires `datafileUrl` option");
|
|
196
|
+
}
|
|
197
|
+
|
|
117
198
|
// datafile content is already provided
|
|
118
199
|
if (options.datafile) {
|
|
119
200
|
const sdk = new FeaturevisorSDK({
|
|
@@ -121,6 +202,7 @@ export function createInstance(options: InstanceOptions) {
|
|
|
121
202
|
onActivation: options.onActivation,
|
|
122
203
|
configureBucketValue: options.configureBucketValue,
|
|
123
204
|
logger,
|
|
205
|
+
interceptAttributes: options.interceptAttributes,
|
|
124
206
|
});
|
|
125
207
|
|
|
126
208
|
if (typeof options.onReady === "function") {
|
|
@@ -131,7 +213,7 @@ export function createInstance(options: InstanceOptions) {
|
|
|
131
213
|
}, 0);
|
|
132
214
|
}
|
|
133
215
|
|
|
134
|
-
return getInstanceFromSdk(sdk, options);
|
|
216
|
+
return getInstanceFromSdk(sdk, options, logger);
|
|
135
217
|
}
|
|
136
218
|
|
|
137
219
|
// datafile has to be fetched
|
|
@@ -140,6 +222,7 @@ export function createInstance(options: InstanceOptions) {
|
|
|
140
222
|
onActivation: options.onActivation,
|
|
141
223
|
configureBucketValue: options.configureBucketValue,
|
|
142
224
|
logger,
|
|
225
|
+
interceptAttributes: options.interceptAttributes,
|
|
143
226
|
});
|
|
144
227
|
|
|
145
228
|
if (options.datafileUrl) {
|
|
@@ -152,10 +235,10 @@ export function createInstance(options: InstanceOptions) {
|
|
|
152
235
|
}
|
|
153
236
|
})
|
|
154
237
|
.catch((e) => {
|
|
155
|
-
|
|
238
|
+
logger.error("failed to fetch datafile:");
|
|
156
239
|
console.error(e);
|
|
157
240
|
});
|
|
158
241
|
}
|
|
159
242
|
|
|
160
|
-
return getInstanceFromSdk(sdk, options);
|
|
243
|
+
return getInstanceFromSdk(sdk, options, logger);
|
|
161
244
|
}
|