@splitsoftware/splitio 10.22.4 → 10.22.5-rc.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/CHANGES.txt +25 -19
- package/README.md +6 -6
- package/es/index.js +0 -15
- package/es/settings/defaults/version.js +1 -1
- package/es/sync/offline/splitsParserFromFile.js +27 -26
- package/lib/index.js +0 -15
- package/lib/settings/defaults/version.js +1 -1
- package/lib/sync/offline/splitsParserFromFile.js +27 -26
- package/package.json +7 -2
- package/src/index.js +0 -16
- package/src/platform/EventEmitter.js +95 -95
- package/src/settings/defaults/version.js +1 -1
- package/src/sync/offline/splitsParserFromFile.js +27 -26
- package/types/client/index.d.ts +1 -1
- package/types/index.d.ts +1 -1
- package/types/server/index.d.ts +1 -1
- package/types/splitio.d.ts +96 -93
|
@@ -72,10 +72,10 @@ function checkListener(listener) {
|
|
|
72
72
|
|
|
73
73
|
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
74
74
|
enumerable: true,
|
|
75
|
-
get: function() {
|
|
75
|
+
get: function () {
|
|
76
76
|
return defaultMaxListeners;
|
|
77
77
|
},
|
|
78
|
-
set: function(arg) {
|
|
78
|
+
set: function (arg) {
|
|
79
79
|
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
|
80
80
|
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
|
|
81
81
|
}
|
|
@@ -83,10 +83,10 @@ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
|
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
EventEmitter.init = function() {
|
|
86
|
+
EventEmitter.init = function () {
|
|
87
87
|
|
|
88
88
|
if (this._events === undefined ||
|
|
89
|
-
|
|
89
|
+
this._events === Object.getPrototypeOf(this)._events) {
|
|
90
90
|
this._events = Object.create(null);
|
|
91
91
|
this._eventsCount = 0;
|
|
92
92
|
}
|
|
@@ -205,9 +205,9 @@ function _addListener(target, type, listener, prepend) {
|
|
|
205
205
|
// No error code for this since it is a Warning
|
|
206
206
|
// eslint-disable-next-line no-restricted-syntax
|
|
207
207
|
var w = new Error('Possible EventEmitter memory leak detected. ' +
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
existing.length + ' ' + String(type) + ' listeners ' +
|
|
209
|
+
'added. Use emitter.setMaxListeners() to ' +
|
|
210
|
+
'increase limit');
|
|
211
211
|
w.name = 'MaxListenersExceededWarning';
|
|
212
212
|
w.emitter = target;
|
|
213
213
|
w.type = type;
|
|
@@ -226,9 +226,9 @@ EventEmitter.prototype.addListener = function addListener(type, listener) {
|
|
|
226
226
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
227
227
|
|
|
228
228
|
EventEmitter.prototype.prependListener =
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
229
|
+
function prependListener(type, listener) {
|
|
230
|
+
return _addListener(this, type, listener, true);
|
|
231
|
+
};
|
|
232
232
|
|
|
233
233
|
function onceWrapper() {
|
|
234
234
|
if (!this.fired) {
|
|
@@ -255,117 +255,117 @@ EventEmitter.prototype.once = function once(type, listener) {
|
|
|
255
255
|
};
|
|
256
256
|
|
|
257
257
|
EventEmitter.prototype.prependOnceListener =
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
function prependOnceListener(type, listener) {
|
|
259
|
+
checkListener(listener);
|
|
260
|
+
this.prependListener(type, _onceWrap(this, type, listener));
|
|
261
|
+
return this;
|
|
262
|
+
};
|
|
263
263
|
|
|
264
264
|
// Emits a 'removeListener' event if and only if the listener was removed.
|
|
265
265
|
EventEmitter.prototype.removeListener =
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
function removeListener(type, listener) {
|
|
267
|
+
var list, events, position, i, originalListener;
|
|
268
268
|
|
|
269
|
-
|
|
269
|
+
checkListener(listener);
|
|
270
270
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
events = this._events;
|
|
272
|
+
if (events === undefined)
|
|
273
|
+
return this;
|
|
274
274
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
list = events[type];
|
|
276
|
+
if (list === undefined)
|
|
277
|
+
return this;
|
|
278
278
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
279
|
+
if (list === listener || list.listener === listener) {
|
|
280
|
+
if (--this._eventsCount === 0)
|
|
281
|
+
this._events = Object.create(null);
|
|
282
|
+
else {
|
|
283
|
+
delete events[type];
|
|
284
|
+
if (events.removeListener)
|
|
285
|
+
this.emit('removeListener', type, list.listener || listener);
|
|
286
|
+
}
|
|
287
|
+
} else if (typeof list !== 'function') {
|
|
288
|
+
position = -1;
|
|
289
|
+
|
|
290
|
+
for (i = list.length - 1; i >= 0; i--) {
|
|
291
|
+
if (list[i] === listener || list[i].listener === listener) {
|
|
292
|
+
originalListener = list[i].listener;
|
|
293
|
+
position = i;
|
|
294
|
+
break;
|
|
296
295
|
}
|
|
296
|
+
}
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
if (position < 0)
|
|
299
|
+
return this;
|
|
300
300
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
301
|
+
if (position === 0)
|
|
302
|
+
list.shift();
|
|
303
|
+
else {
|
|
304
|
+
spliceOne(list, position);
|
|
305
|
+
}
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
if (list.length === 1)
|
|
308
|
+
events[type] = list[0];
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
310
|
+
if (events.removeListener !== undefined)
|
|
311
|
+
this.emit('removeListener', type, originalListener || listener);
|
|
312
|
+
}
|
|
313
313
|
|
|
314
|
-
|
|
315
|
-
|
|
314
|
+
return this;
|
|
315
|
+
};
|
|
316
316
|
|
|
317
317
|
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
318
318
|
|
|
319
319
|
EventEmitter.prototype.removeAllListeners =
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
function removeAllListeners(type) {
|
|
321
|
+
var listeners, events, i;
|
|
322
322
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
// not listening for removeListener, no need to emit
|
|
328
|
-
if (events.removeListener === undefined) {
|
|
329
|
-
if (arguments.length === 0) {
|
|
330
|
-
this._events = Object.create(null);
|
|
331
|
-
this._eventsCount = 0;
|
|
332
|
-
} else if (events[type] !== undefined) {
|
|
333
|
-
if (--this._eventsCount === 0)
|
|
334
|
-
this._events = Object.create(null);
|
|
335
|
-
else
|
|
336
|
-
delete events[type];
|
|
337
|
-
}
|
|
338
|
-
return this;
|
|
339
|
-
}
|
|
323
|
+
events = this._events;
|
|
324
|
+
if (events === undefined)
|
|
325
|
+
return this;
|
|
340
326
|
|
|
341
|
-
|
|
327
|
+
// not listening for removeListener, no need to emit
|
|
328
|
+
if (events.removeListener === undefined) {
|
|
342
329
|
if (arguments.length === 0) {
|
|
343
|
-
var keys = Object.keys(events);
|
|
344
|
-
var key;
|
|
345
|
-
for (i = 0; i < keys.length; ++i) {
|
|
346
|
-
key = keys[i];
|
|
347
|
-
if (key === 'removeListener') continue;
|
|
348
|
-
this.removeAllListeners(key);
|
|
349
|
-
}
|
|
350
|
-
this.removeAllListeners('removeListener');
|
|
351
330
|
this._events = Object.create(null);
|
|
352
331
|
this._eventsCount = 0;
|
|
353
|
-
|
|
332
|
+
} else if (events[type] !== undefined) {
|
|
333
|
+
if (--this._eventsCount === 0)
|
|
334
|
+
this._events = Object.create(null);
|
|
335
|
+
else
|
|
336
|
+
delete events[type];
|
|
354
337
|
}
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// emit removeListener for all listeners on all events
|
|
342
|
+
if (arguments.length === 0) {
|
|
343
|
+
var keys = Object.keys(events);
|
|
344
|
+
var key;
|
|
345
|
+
for (i = 0; i < keys.length; ++i) {
|
|
346
|
+
key = keys[i];
|
|
347
|
+
if (key === 'removeListener') continue;
|
|
348
|
+
this.removeAllListeners(key);
|
|
349
|
+
}
|
|
350
|
+
this.removeAllListeners('removeListener');
|
|
351
|
+
this._events = Object.create(null);
|
|
352
|
+
this._eventsCount = 0;
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
355
|
|
|
356
|
-
|
|
356
|
+
listeners = events[type];
|
|
357
357
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
358
|
+
if (typeof listeners === 'function') {
|
|
359
|
+
this.removeListener(type, listeners);
|
|
360
|
+
} else if (listeners !== undefined) {
|
|
361
|
+
// LIFO order
|
|
362
|
+
for (i = listeners.length - 1; i >= 0; i--) {
|
|
363
|
+
this.removeListener(type, listeners[i]);
|
|
365
364
|
}
|
|
365
|
+
}
|
|
366
366
|
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
return this;
|
|
368
|
+
};
|
|
369
369
|
|
|
370
370
|
function _listeners(target, type, unwrap) {
|
|
371
371
|
var events = target._events;
|
|
@@ -392,7 +392,7 @@ EventEmitter.prototype.rawListeners = function rawListeners(type) {
|
|
|
392
392
|
return _listeners(this, type, false);
|
|
393
393
|
};
|
|
394
394
|
|
|
395
|
-
EventEmitter.listenerCount = function(emitter, type) {
|
|
395
|
+
EventEmitter.listenerCount = function (emitter, type) {
|
|
396
396
|
if (typeof emitter.listenerCount === 'function') {
|
|
397
397
|
return emitter.listenerCount(type);
|
|
398
398
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageVersion = '10.22.
|
|
1
|
+
export const packageVersion = '10.22.5-rc.0';
|
|
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
|
|
|
4
4
|
import { isString, endsWith, find, forOwn, uniq, } from '@splitsoftware/splitio-commons/src/utils/lang';
|
|
5
5
|
import { parseCondition } from '@splitsoftware/splitio-commons/src/sync/offline/splitsParser/parseCondition';
|
|
6
6
|
|
|
7
|
-
const logPrefix = 'sync:offline:
|
|
7
|
+
const logPrefix = 'sync:offline:fetcher: ';
|
|
8
8
|
|
|
9
9
|
const DEFAULT_FILENAME = '.split';
|
|
10
10
|
|
|
@@ -12,19 +12,20 @@ function configFilesPath(configFilePath) {
|
|
|
12
12
|
if (configFilePath === DEFAULT_FILENAME || !isString(configFilePath)) {
|
|
13
13
|
let root = process.env.HOME;
|
|
14
14
|
|
|
15
|
+
// @TODO env var not documented in help center
|
|
15
16
|
if (process.env.SPLIT_CONFIG_ROOT) root = process.env.SPLIT_CONFIG_ROOT;
|
|
16
17
|
|
|
17
|
-
if (!root) throw new Error('Missing
|
|
18
|
+
if (!root) throw new Error('Missing root of the feature flags mock file.');
|
|
18
19
|
|
|
19
20
|
configFilePath = path.join(root, DEFAULT_FILENAME);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
// Validate the extensions
|
|
23
24
|
if (!(endsWith(configFilePath, '.yaml', true) || endsWith(configFilePath, '.yml', true) || endsWith(configFilePath, '.split', true)))
|
|
24
|
-
throw new Error(`Invalid extension specified for
|
|
25
|
+
throw new Error(`Invalid extension specified for feature flags mock file. Accepted extensions are ".yml" and ".yaml". Your specified file is ${configFilePath}`);
|
|
25
26
|
|
|
26
27
|
if (!fs.existsSync(configFilePath))
|
|
27
|
-
throw new Error(`
|
|
28
|
+
throw new Error(`Feature flags mock file not found in ${configFilePath} - Please review the file location.`);
|
|
28
29
|
|
|
29
30
|
return configFilePath;
|
|
30
31
|
}
|
|
@@ -32,11 +33,11 @@ function configFilesPath(configFilePath) {
|
|
|
32
33
|
// This function is not pure nor meant to be. Here we apply modifications to cover
|
|
33
34
|
// for behaviour that's ensured by the BE.
|
|
34
35
|
function arrangeConditions(mocksData) {
|
|
35
|
-
// Iterate through each
|
|
36
|
+
// Iterate through each feature flag data
|
|
36
37
|
forOwn(mocksData, data => {
|
|
37
38
|
const conditions = data.conditions;
|
|
38
39
|
|
|
39
|
-
// On the manager, as
|
|
40
|
+
// On the manager, as feature flag JSONs come with all treatments on the partitions prop,
|
|
40
41
|
// we'll add all the treatments to the first condition.
|
|
41
42
|
const firstRolloutCondition = find(conditions, cond => cond.conditionType === 'ROLLOUT');
|
|
42
43
|
// Malformed mocks may have
|
|
@@ -63,9 +64,9 @@ export function splitsParserFromFileFactory() {
|
|
|
63
64
|
|
|
64
65
|
let previousMock = 'NO_MOCK_LOADED';
|
|
65
66
|
|
|
66
|
-
// Parse `.split` configuration file and return a map of
|
|
67
|
-
function
|
|
68
|
-
const
|
|
67
|
+
// Parse `.split` configuration file and return a map of feature flag objects
|
|
68
|
+
function readFeatureFlagConfigFile(log, filePath) {
|
|
69
|
+
const FEATURE_FLAG_POSITION = 0;
|
|
69
70
|
const TREATMENT_POSITION = 1;
|
|
70
71
|
let data;
|
|
71
72
|
|
|
@@ -80,7 +81,7 @@ export function splitsParserFromFileFactory() {
|
|
|
80
81
|
if (data === previousMock) return false;
|
|
81
82
|
previousMock = data;
|
|
82
83
|
|
|
83
|
-
const
|
|
84
|
+
const featureFlagObjects = data.split(/\r?\n/).reduce((accum, line, index) => {
|
|
84
85
|
let tuple = line.trim();
|
|
85
86
|
|
|
86
87
|
if (tuple === '' || tuple.charAt(0) === '#') {
|
|
@@ -91,19 +92,19 @@ export function splitsParserFromFileFactory() {
|
|
|
91
92
|
if (tuple.length !== 2) {
|
|
92
93
|
log.debug(logPrefix + `Ignoring line since it does not have exactly two columns #${index}`);
|
|
93
94
|
} else {
|
|
94
|
-
const
|
|
95
|
+
const featureFlagName = tuple[FEATURE_FLAG_POSITION];
|
|
95
96
|
const condition = parseCondition({ treatment: tuple[TREATMENT_POSITION] });
|
|
96
|
-
accum[
|
|
97
|
+
accum[featureFlagName] = { conditions: [condition], configurations: {}, trafficTypeName: 'localhost' };
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
return accum;
|
|
101
102
|
}, {});
|
|
102
103
|
|
|
103
|
-
return
|
|
104
|
+
return featureFlagObjects;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
// Parse `.yml` or `.yaml` configuration files and return a map of
|
|
107
|
+
// Parse `.yml` or `.yaml` configuration files and return a map of feature flag objects
|
|
107
108
|
function readYAMLConfigFile(log, filePath) {
|
|
108
109
|
let data = '';
|
|
109
110
|
let yamldoc = null;
|
|
@@ -122,28 +123,28 @@ export function splitsParserFromFileFactory() {
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
// Each entry will be mapped to a condition, but we'll also keep the configurations map.
|
|
125
|
-
const mocksData = (yamldoc).reduce((accum,
|
|
126
|
-
const
|
|
126
|
+
const mocksData = (yamldoc).reduce((accum, featureFlagEntry) => {
|
|
127
|
+
const featureFlagName = Object.keys(featureFlagEntry)[0];
|
|
127
128
|
|
|
128
|
-
if (!
|
|
129
|
+
if (!featureFlagName || !isString(featureFlagEntry[featureFlagName].treatment))
|
|
129
130
|
log.error(logPrefix + 'Ignoring entry on YAML since the format is incorrect.');
|
|
130
131
|
|
|
131
|
-
const mockData =
|
|
132
|
+
const mockData = featureFlagEntry[featureFlagName];
|
|
132
133
|
|
|
133
|
-
// "Template" for each
|
|
134
|
-
if (!accum[
|
|
135
|
-
accum[
|
|
134
|
+
// "Template" for each feature flag accumulated data
|
|
135
|
+
if (!accum[featureFlagName]) {
|
|
136
|
+
accum[featureFlagName] = {
|
|
136
137
|
configurations: {}, conditions: [], treatments: [], trafficTypeName: 'localhost'
|
|
137
138
|
};
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
// Assign the config if there is one on the mock
|
|
141
|
-
if (mockData.config) accum[
|
|
142
|
+
if (mockData.config) accum[featureFlagName].configurations[mockData.treatment] = mockData.config;
|
|
142
143
|
// Parse the condition from the entry.
|
|
143
144
|
const condition = parseCondition(mockData);
|
|
144
|
-
accum[
|
|
145
|
+
accum[featureFlagName].conditions[condition.conditionType === 'ROLLOUT' ? 'push' : 'unshift'](condition);
|
|
145
146
|
// Also keep track of the treatments, will be useful for manager functionality.
|
|
146
|
-
accum[
|
|
147
|
+
accum[featureFlagName].treatments.push(mockData.treatment);
|
|
147
148
|
|
|
148
149
|
return accum;
|
|
149
150
|
}, {});
|
|
@@ -154,14 +155,14 @@ export function splitsParserFromFileFactory() {
|
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
// Load the content of a configuration file into an Object
|
|
157
|
-
return function
|
|
158
|
+
return function featureFlagsParserFromFile({ features, log }) {
|
|
158
159
|
const filePath = configFilesPath(features);
|
|
159
160
|
let mockData;
|
|
160
161
|
|
|
161
162
|
// If we have a filePath, it means the extension is correct, choose the parser.
|
|
162
163
|
if (endsWith(filePath, '.split')) {
|
|
163
164
|
log.warn(logPrefix + '.split mocks will be deprecated soon in favor of YAML files, which provide more targeting power. Take a look in our documentation.');
|
|
164
|
-
mockData =
|
|
165
|
+
mockData = readFeatureFlagConfigFile(log, filePath);
|
|
165
166
|
} else {
|
|
166
167
|
mockData = readYAMLConfigFile(log, filePath);
|
|
167
168
|
}
|
package/types/client/index.d.ts
CHANGED
package/types/index.d.ts
CHANGED
package/types/server/index.d.ts
CHANGED