Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit a289baa

Browse files
prepare 6.2.3 release (#234)
1 parent 69bd010 commit a289baa

File tree

8 files changed

+320
-250
lines changed

8 files changed

+320
-250
lines changed

evaluator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const util = require('util');
55
const stringifyAttrs = require('./utils/stringifyAttrs');
66
const { safeAsyncEachSeries } = require('./utils/asyncUtils');
77

8-
const builtins = ['key', 'ip', 'country', 'email', 'firstName', 'lastName', 'avatar', 'name', 'anonymous'];
8+
const builtins = ['key', 'secondary', 'ip', 'country', 'email', 'firstName', 'lastName', 'avatar', 'name', 'anonymous'];
99
const userAttrsToStringifyForEvaluation = ['key', 'secondary'];
1010
// Currently we are not stringifying the rest of the built-in attributes prior to evaluation, only for events.
1111
// This is because it could affect evaluation results for existing users (ch35206).

event_factory.js

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
function EventFactory(withReasons) {
2-
const ef = {};
3-
4-
function isExperiment(flag, reason) {
5-
if (reason) {
6-
// If the reason says we're in an experiment, we are. Otherwise, apply
7-
// the legacy rule exclusion logic.
8-
if (reason.inExperiment) {
9-
return true;
10-
}
11-
switch (reason.kind) {
12-
case 'RULE_MATCH': {
13-
const index = reason.ruleIndex;
14-
if (index !== undefined) {
15-
const rules = flag.rules || [];
16-
return index >= 0 && index < rules.length && !!rules[index].trackEvents;
17-
}
18-
break;
1+
function isExperiment(flag, reason) {
2+
if (reason) {
3+
// If the reason says we're in an experiment, we are. Otherwise, apply
4+
// the legacy rule exclusion logic.
5+
if (reason.inExperiment) {
6+
return true;
7+
}
8+
switch (reason.kind) {
9+
case 'RULE_MATCH': {
10+
const index = reason.ruleIndex;
11+
if (index !== undefined) {
12+
const rules = flag.rules || [];
13+
return index >= 0 && index < rules.length && !!rules[index].trackEvents;
1914
}
20-
case 'FALLTHROUGH':
21-
return !!flag.trackEventsFallthrough;
15+
break;
2216
}
17+
case 'FALLTHROUGH':
18+
return !!flag.trackEventsFallthrough;
2319
}
24-
return false;
2520
}
21+
return false;
22+
}
23+
24+
function EventFactory(withReasons) {
25+
const ef = {};
2626

2727
ef.newEvalEvent = (flag, user, detail, defaultVal, prereqOfFlag) => {
2828
const addExperimentData = isExperiment(flag, detail.reason);
@@ -128,4 +128,7 @@ function EventFactory(withReasons) {
128128
return ef;
129129
}
130130

131-
module.exports = EventFactory;
131+
module.exports = {
132+
EventFactory,
133+
isExperiment,
134+
};

flags_state.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1-
function FlagsStateBuilder(valid) {
1+
function FlagsStateBuilder(valid, withReasons) {
22
const builder = {};
33
const flagValues = {};
44
const flagMetadata = {};
55

6-
builder.addFlag = (flag, value, variation, reason, detailsOnlyIfTracked) => {
6+
builder.addFlag = (flag, value, variation, reason, trackEvents, trackReason, detailsOnlyIfTracked) => {
77
flagValues[flag.key] = value;
88
const meta = {};
9-
if (!detailsOnlyIfTracked || flag.trackEvents || flag.debugEventsUntilDate) {
10-
meta.version = flag.version;
11-
if (reason) {
12-
meta.reason = reason;
13-
}
14-
}
159
if (variation !== undefined && variation !== null) {
1610
meta.variation = variation;
1711
}
18-
if (flag.trackEvents) {
12+
const omitDetails =
13+
detailsOnlyIfTracked &&
14+
!trackEvents &&
15+
!trackReason &&
16+
(flag.debugEventsUntilDate === undefined || flag.debugEventsUntilDate === null);
17+
if (!omitDetails) {
18+
meta.version = flag.version;
19+
}
20+
if (reason && (trackReason || (withReasons && !omitDetails))) {
21+
meta.reason = reason;
22+
}
23+
if (trackEvents) {
1924
meta.trackEvents = true;
2025
}
26+
if (trackReason) {
27+
meta.trackReason = true;
28+
}
2129
if (flag.debugEventsUntilDate !== undefined && flag.debugEventsUntilDate !== null) {
2230
meta.debugEventsUntilDate = flag.debugEventsUntilDate;
2331
}

index.js

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const FeatureStoreEventWrapper = require('./feature_store_event_wrapper');
44
const FileDataSource = require('./file_data_source');
55
const Requestor = require('./requestor');
66
const EventEmitter = require('events').EventEmitter;
7-
const EventFactory = require('./event_factory');
7+
const { EventFactory, isExperiment } = require('./event_factory');
88
const EventProcessor = require('./event_processor');
99
const PollingProcessor = require('./polling');
1010
const StreamingProcessor = require('./streaming');
@@ -298,50 +298,71 @@ const newClient = function (sdkKey, originalConfig) {
298298
options = options || {};
299299
}
300300
return wrapPromiseCallback(
301-
new Promise((resolve, reject) => {
301+
(async () => {
302302
if (client.isOffline()) {
303303
config.logger.info('allFlagsState() called in offline mode. Returning empty state.');
304-
return resolve(FlagsStateBuilder(false).build());
304+
return FlagsStateBuilder(false).build();
305305
}
306306

307307
if (!user) {
308308
config.logger.info('allFlagsState() called without user. Returning empty state.');
309-
return resolve(FlagsStateBuilder(false).build());
309+
return FlagsStateBuilder(false).build();
310+
}
311+
312+
let valid = true;
313+
314+
if (!initComplete) {
315+
const inited = await new Promise(resolve => config.featureStore.initialized(resolve));
316+
if (inited) {
317+
config.logger.warn(
318+
'Called allFlagsState before client initialization; using last known values from data store'
319+
);
320+
} else {
321+
config.logger.warn(
322+
'Called allFlagsState before client initialization. Data store not available; returning empty state'
323+
);
324+
valid = false;
325+
}
310326
}
311327

312-
const builder = FlagsStateBuilder(true);
328+
const builder = FlagsStateBuilder(valid, options.withReasons);
313329
const clientOnly = options.clientSideOnly;
314-
const withReasons = options.withReasons;
315330
const detailsOnlyIfTracked = options.detailsOnlyForTrackedFlags;
316-
config.featureStore.all(dataKind.features, flags => {
317-
safeAsyncEach(
318-
flags,
319-
(flag, iterateeCb) => {
320-
if (clientOnly && !flag.clientSide) {
321-
iterateeCb();
322-
} else {
323-
// At the moment, we don't send any events here
324-
evaluator.evaluate(flag, user, eventFactoryDefault, (err, detail) => {
325-
if (err !== null) {
326-
maybeReportError(
327-
new Error('Error for feature flag "' + flag.key + '" while evaluating all flags: ' + err)
328-
);
329-
}
330-
builder.addFlag(
331-
flag,
332-
detail.value,
333-
detail.variationIndex,
334-
withReasons ? detail.reason : null,
335-
detailsOnlyIfTracked
336-
);
331+
332+
return await new Promise((resolve, reject) =>
333+
config.featureStore.all(dataKind.features, flags => {
334+
safeAsyncEach(
335+
flags,
336+
(flag, iterateeCb) => {
337+
if (clientOnly && !flag.clientSide) {
337338
iterateeCb();
338-
});
339-
}
340-
},
341-
err => (err ? reject(err) : resolve(builder.build()))
342-
);
343-
});
344-
}),
339+
} else {
340+
// At the moment, we don't send any events here
341+
evaluator.evaluate(flag, user, eventFactoryDefault, (err, detail) => {
342+
if (err !== null) {
343+
maybeReportError(
344+
new Error('Error for feature flag "' + flag.key + '" while evaluating all flags: ' + err)
345+
);
346+
}
347+
const requireExperimentData = isExperiment(flag, detail.reason);
348+
builder.addFlag(
349+
flag,
350+
detail.value,
351+
detail.variationIndex,
352+
detail.reason,
353+
flag.trackEvents || requireExperimentData,
354+
requireExperimentData,
355+
detailsOnlyIfTracked
356+
);
357+
iterateeCb();
358+
});
359+
}
360+
},
361+
err => (err ? reject(err) : resolve(builder.build()))
362+
);
363+
})
364+
);
365+
})(),
345366
callback
346367
);
347368
};

operators.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ function semVerOperator(fn) {
4444
}
4545

4646
function parseSemVer(input) {
47+
if (typeof input !== 'string') {
48+
return null;
49+
}
4750
if (input.startsWith('v')) {
4851
// the semver library tolerates a leading "v", but the standard does not.
4952
return null;

0 commit comments

Comments
 (0)