@featurevisor/core 1.35.3 → 2.0.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 +0 -6
- package/coverage/clover.xml +321 -237
- package/coverage/coverage-final.json +8 -8
- package/coverage/lcov-report/index.html +77 -47
- package/coverage/lcov-report/lib/builder/allocator.js.html +14 -14
- package/coverage/lcov-report/lib/builder/index.html +16 -16
- package/coverage/lcov-report/lib/builder/revision.js.html +3 -3
- package/coverage/lcov-report/lib/builder/traffic.js.html +88 -64
- package/coverage/lcov-report/lib/list/index.html +116 -0
- package/coverage/lcov-report/lib/{tester → list}/matrix.js.html +90 -66
- package/coverage/lcov-report/lib/tester/helpers.js.html +295 -0
- package/coverage/lcov-report/lib/tester/index.html +20 -35
- package/coverage/lcov-report/src/builder/allocator.ts.html +2 -2
- package/coverage/lcov-report/src/builder/index.html +15 -15
- package/coverage/lcov-report/src/builder/revision.ts.html +1 -1
- package/coverage/lcov-report/src/builder/traffic.ts.html +96 -24
- package/coverage/lcov-report/src/list/index.html +116 -0
- package/coverage/lcov-report/src/{tester → list}/matrix.ts.html +87 -21
- package/coverage/lcov-report/src/tester/helpers.ts.html +313 -0
- package/coverage/lcov-report/src/tester/index.html +20 -35
- package/coverage/lcov.info +592 -436
- package/lib/assess-distribution/index.d.ts +1 -1
- package/lib/assess-distribution/index.js +102 -162
- package/lib/assess-distribution/index.js.map +1 -1
- package/lib/benchmark/index.js +87 -143
- package/lib/benchmark/index.js.map +1 -1
- package/lib/builder/allocator.d.ts +1 -1
- package/lib/builder/allocator.js +12 -12
- package/lib/builder/allocator.js.map +1 -1
- package/lib/builder/allocator.spec.js +22 -22
- package/lib/builder/allocator.spec.js.map +1 -1
- package/lib/builder/buildDatafile.d.ts +4 -3
- package/lib/builder/buildDatafile.js +311 -388
- package/lib/builder/buildDatafile.js.map +1 -1
- package/lib/builder/buildProject.d.ts +2 -1
- package/lib/builder/buildProject.js +96 -183
- package/lib/builder/buildProject.js.map +1 -1
- package/lib/builder/convertToV1.d.ts +10 -0
- package/lib/builder/convertToV1.js +119 -0
- package/lib/builder/convertToV1.js.map +1 -0
- package/lib/builder/getFeatureRanges.d.ts +1 -1
- package/lib/builder/getFeatureRanges.js +32 -105
- package/lib/builder/getFeatureRanges.js.map +1 -1
- package/lib/builder/hashes.d.ts +4 -0
- package/lib/builder/hashes.js +70 -0
- package/lib/builder/hashes.js.map +1 -0
- package/lib/builder/revision.js +2 -2
- package/lib/builder/revision.js.map +1 -1
- package/lib/builder/revision.spec.js +1 -1
- package/lib/builder/revision.spec.js.map +1 -1
- package/lib/builder/traffic.d.ts +1 -1
- package/lib/builder/traffic.js +57 -49
- package/lib/builder/traffic.js.map +1 -1
- package/lib/builder/traffic.spec.js +14 -14
- package/lib/builder/traffic.spec.js.map +1 -1
- package/lib/cli/cli.js +60 -129
- package/lib/cli/cli.js.map +1 -1
- package/lib/cli/plugins.js +14 -16
- package/lib/cli/plugins.js.map +1 -1
- package/lib/config/parsers.js +1 -1
- package/lib/config/parsers.js.map +1 -1
- package/lib/config/projectConfig.d.ts +8 -6
- package/lib/config/projectConfig.js +31 -72
- package/lib/config/projectConfig.js.map +1 -1
- package/lib/datasource/adapter.d.ts +1 -1
- package/lib/datasource/adapter.js +2 -5
- package/lib/datasource/adapter.js.map +1 -1
- package/lib/datasource/datasource.d.ts +2 -1
- package/lib/datasource/datasource.js +107 -148
- package/lib/datasource/datasource.js.map +1 -1
- package/lib/datasource/filesystemAdapter.d.ts +1 -1
- package/lib/datasource/filesystemAdapter.js +224 -360
- package/lib/datasource/filesystemAdapter.js.map +1 -1
- package/lib/evaluate/index.d.ts +1 -1
- package/lib/evaluate/index.js +120 -188
- package/lib/evaluate/index.js.map +1 -1
- package/lib/find-duplicate-segments/findDuplicateSegments.d.ts +1 -1
- package/lib/find-duplicate-segments/findDuplicateSegments.js +40 -128
- package/lib/find-duplicate-segments/findDuplicateSegments.js.map +1 -1
- package/lib/find-duplicate-segments/index.js +27 -82
- package/lib/find-duplicate-segments/index.js.map +1 -1
- package/lib/find-usage/index.d.ts +7 -5
- package/lib/find-usage/index.js +333 -507
- package/lib/find-usage/index.js.map +1 -1
- package/lib/generate-code/index.js +36 -91
- package/lib/generate-code/index.js.map +1 -1
- package/lib/generate-code/typescript.js +117 -157
- package/lib/generate-code/typescript.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/info/index.js +45 -133
- package/lib/info/index.js.map +1 -1
- package/lib/init/index.d.ts +1 -1
- package/lib/init/index.js +16 -64
- package/lib/init/index.js.map +1 -1
- package/lib/linter/attributeSchema.d.ts +21 -6
- package/lib/linter/attributeSchema.js +18 -4
- package/lib/linter/attributeSchema.js.map +1 -1
- package/lib/linter/checkCircularDependency.d.ts +1 -1
- package/lib/linter/checkCircularDependency.js +22 -80
- package/lib/linter/checkCircularDependency.js.map +1 -1
- package/lib/linter/checkPercentageExceedingSlot.d.ts +1 -1
- package/lib/linter/checkPercentageExceedingSlot.js +36 -76
- package/lib/linter/checkPercentageExceedingSlot.js.map +1 -1
- package/lib/linter/conditionSchema.d.ts +1 -1
- package/lib/linter/conditionSchema.js +89 -41
- package/lib/linter/conditionSchema.js.map +1 -1
- package/lib/linter/featureSchema.d.ts +345 -197
- package/lib/linter/featureSchema.js +313 -172
- package/lib/linter/featureSchema.js.map +1 -1
- package/lib/linter/groupSchema.js +6 -6
- package/lib/linter/groupSchema.js.map +1 -1
- package/lib/linter/lintProject.js +306 -480
- package/lib/linter/lintProject.js.map +1 -1
- package/lib/linter/printError.js +7 -7
- package/lib/linter/printError.js.map +1 -1
- package/lib/linter/segmentSchema.js +2 -2
- package/lib/linter/segmentSchema.js.map +1 -1
- package/lib/linter/testSchema.d.ts +155 -3
- package/lib/linter/testSchema.js +47 -17
- package/lib/linter/testSchema.js.map +1 -1
- package/lib/list/index.d.ts +1 -0
- package/lib/list/index.js +349 -517
- package/lib/list/index.js.map +1 -1
- package/lib/{tester → list}/matrix.d.ts +1 -1
- package/lib/{tester → list}/matrix.js +50 -42
- package/lib/list/matrix.js.map +1 -0
- package/lib/{tester → list}/matrix.spec.js +7 -7
- package/lib/list/matrix.spec.js.map +1 -0
- package/lib/site/exportSite.js +25 -71
- package/lib/site/exportSite.js.map +1 -1
- package/lib/site/generateHistory.d.ts +1 -1
- package/lib/site/generateHistory.js +26 -82
- package/lib/site/generateHistory.js.map +1 -1
- package/lib/site/generateSiteSearchIndex.d.ts +1 -1
- package/lib/site/generateSiteSearchIndex.js +182 -259
- package/lib/site/generateSiteSearchIndex.js.map +1 -1
- package/lib/site/getLastModifiedFromHistory.d.ts +1 -1
- package/lib/site/getLastModifiedFromHistory.js +2 -2
- package/lib/site/getLastModifiedFromHistory.js.map +1 -1
- package/lib/site/getOwnerAndRepoFromUrl.js +6 -6
- package/lib/site/getOwnerAndRepoFromUrl.js.map +1 -1
- package/lib/site/getRelativePaths.js +7 -7
- package/lib/site/getRelativePaths.js.map +1 -1
- package/lib/site/getRepoDetails.js +20 -20
- package/lib/site/getRepoDetails.js.map +1 -1
- package/lib/site/index.js +25 -73
- package/lib/site/index.js.map +1 -1
- package/lib/site/serveSite.js +10 -10
- package/lib/site/serveSite.js.map +1 -1
- package/lib/tester/helpers.d.ts +2 -0
- package/lib/tester/helpers.js +71 -0
- package/lib/tester/helpers.js.map +1 -0
- package/lib/tester/helpers.spec.js +115 -0
- package/lib/tester/helpers.spec.js.map +1 -0
- package/lib/tester/index.d.ts +0 -1
- package/lib/tester/index.js +0 -1
- package/lib/tester/index.js.map +1 -1
- package/lib/tester/prettyDuration.js +11 -11
- package/lib/tester/prettyDuration.js.map +1 -1
- package/lib/tester/printTestResult.d.ts +1 -1
- package/lib/tester/printTestResult.js +35 -15
- package/lib/tester/printTestResult.js.map +1 -1
- package/lib/tester/testFeature.d.ts +4 -2
- package/lib/tester/testFeature.js +264 -226
- package/lib/tester/testFeature.js.map +1 -1
- package/lib/tester/testProject.d.ts +3 -7
- package/lib/tester/testProject.js +145 -246
- package/lib/tester/testProject.js.map +1 -1
- package/lib/tester/testSegment.d.ts +5 -2
- package/lib/tester/testSegment.js +65 -102
- package/lib/tester/testSegment.js.map +1 -1
- package/lib/utils/extractKeys.d.ts +2 -1
- package/lib/utils/extractKeys.js +57 -12
- package/lib/utils/extractKeys.js.map +1 -1
- package/lib/utils/git.d.ts +1 -1
- package/lib/utils/git.js +23 -23
- package/lib/utils/git.js.map +1 -1
- package/lib/utils/pretty.js +2 -4
- package/lib/utils/pretty.js.map +1 -1
- package/package.json +5 -6
- package/src/assess-distribution/index.ts +3 -2
- package/src/benchmark/index.ts +3 -3
- package/src/builder/allocator.spec.ts +1 -1
- package/src/builder/allocator.ts +1 -1
- package/src/builder/buildDatafile.ts +161 -124
- package/src/builder/buildProject.ts +6 -3
- package/src/builder/convertToV1.ts +166 -0
- package/src/builder/getFeatureRanges.ts +1 -1
- package/src/builder/hashes.ts +109 -0
- package/src/builder/traffic.ts +40 -16
- package/src/cli/cli.ts +1 -1
- package/src/cli/plugins.ts +0 -2
- package/src/config/projectConfig.ts +13 -10
- package/src/datasource/adapter.ts +1 -1
- package/src/datasource/datasource.ts +23 -2
- package/src/datasource/filesystemAdapter.ts +11 -12
- package/src/evaluate/index.ts +7 -6
- package/src/find-duplicate-segments/findDuplicateSegments.ts +1 -1
- package/src/find-usage/index.ts +111 -44
- package/src/generate-code/index.ts +1 -3
- package/src/generate-code/typescript.ts +7 -29
- package/src/index.ts +0 -1
- package/src/info/index.ts +2 -2
- package/src/init/index.ts +2 -2
- package/src/linter/attributeSchema.ts +18 -2
- package/src/linter/checkCircularDependency.ts +1 -1
- package/src/linter/checkPercentageExceedingSlot.ts +28 -8
- package/src/linter/conditionSchema.ts +66 -10
- package/src/linter/featureSchema.ts +312 -116
- package/src/linter/lintProject.ts +9 -4
- package/src/linter/testSchema.ts +42 -3
- package/src/list/index.ts +18 -30
- package/src/{tester → list}/matrix.ts +33 -11
- package/src/site/exportSite.ts +2 -4
- package/src/site/generateHistory.ts +1 -1
- package/src/site/generateSiteSearchIndex.ts +58 -50
- package/src/site/getLastModifiedFromHistory.ts +1 -1
- package/src/tester/helpers.spec.ts +149 -0
- package/src/tester/helpers.ts +76 -0
- package/src/tester/index.ts +0 -1
- package/src/tester/printTestResult.ts +25 -3
- package/src/tester/testFeature.ts +270 -124
- package/src/tester/testProject.ts +28 -49
- package/src/tester/testSegment.ts +48 -40
- package/src/utils/extractKeys.ts +58 -1
- package/src/utils/git.ts +1 -1
- package/tsconfig.cjs.json +1 -0
- package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +0 -151
- package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +0 -157
- package/lib/restore/index.d.ts +0 -4
- package/lib/restore/index.js +0 -91
- package/lib/restore/index.js.map +0 -1
- package/lib/tester/checkIfArraysAreEqual.d.ts +0 -1
- package/lib/tester/checkIfArraysAreEqual.js +0 -18
- package/lib/tester/checkIfArraysAreEqual.js.map +0 -1
- package/lib/tester/checkIfObjectsAreEqual.d.ts +0 -1
- package/lib/tester/checkIfObjectsAreEqual.js +0 -23
- package/lib/tester/checkIfObjectsAreEqual.js.map +0 -1
- package/lib/tester/checkIfObjectsAreEqual.spec.js +0 -26
- package/lib/tester/checkIfObjectsAreEqual.spec.js.map +0 -1
- package/lib/tester/matrix.js.map +0 -1
- package/lib/tester/matrix.spec.js.map +0 -1
- package/src/restore/index.ts +0 -42
- package/src/tester/checkIfArraysAreEqual.ts +0 -16
- package/src/tester/checkIfObjectsAreEqual.spec.ts +0 -31
- package/src/tester/checkIfObjectsAreEqual.ts +0 -24
- /package/lib/{tester → list}/matrix.spec.d.ts +0 -0
- /package/lib/tester/{checkIfObjectsAreEqual.spec.d.ts → helpers.spec.d.ts} +0 -0
- /package/src/{tester → list}/matrix.spec.ts +0 -0
|
@@ -1,110 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
3
|
exports.getFeatureRanges = getFeatureRanges;
|
|
51
|
-
|
|
52
|
-
function getFeatureRanges(projectConfig, datasource) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
var end = accumulatedPercentage + slot.percentage * 1000;
|
|
84
|
-
featureRangesForFeature.push([start, end]);
|
|
85
|
-
featureRanges.set(slot.feature, featureRangesForFeature);
|
|
86
|
-
}
|
|
87
|
-
accumulatedPercentage += slot.percentage * 1000;
|
|
88
|
-
});
|
|
89
|
-
return [2 /*return*/];
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
_i = 0, groupFiles_1 = groupFiles;
|
|
94
|
-
_a.label = 2;
|
|
95
|
-
case 2:
|
|
96
|
-
if (!(_i < groupFiles_1.length)) return [3 /*break*/, 5];
|
|
97
|
-
groupKey = groupFiles_1[_i];
|
|
98
|
-
return [5 /*yield**/, _loop_1(groupKey)];
|
|
99
|
-
case 3:
|
|
100
|
-
_a.sent();
|
|
101
|
-
_a.label = 4;
|
|
102
|
-
case 4:
|
|
103
|
-
_i++;
|
|
104
|
-
return [3 /*break*/, 2];
|
|
105
|
-
case 5: return [2 /*return*/, { featureRanges: featureRanges, featureIsInGroup: featureIsInGroup }];
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
});
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
async function getFeatureRanges(projectConfig, datasource) {
|
|
6
|
+
const featureRanges = new Map();
|
|
7
|
+
const featureIsInGroup = {}; // featureKey => boolean
|
|
8
|
+
const groups = [];
|
|
9
|
+
if (fs.existsSync(projectConfig.groupsDirectoryPath)) {
|
|
10
|
+
const groupFiles = await datasource.listGroups();
|
|
11
|
+
for (const groupKey of groupFiles) {
|
|
12
|
+
const parsedGroup = await datasource.readGroup(groupKey);
|
|
13
|
+
groups.push({
|
|
14
|
+
...parsedGroup,
|
|
15
|
+
key: groupKey,
|
|
16
|
+
});
|
|
17
|
+
let accumulatedPercentage = 0;
|
|
18
|
+
parsedGroup.slots.forEach(function (slot, slotIndex) {
|
|
19
|
+
const isFirstSlot = slotIndex === 0;
|
|
20
|
+
if (slot.feature) {
|
|
21
|
+
const featureKey = slot.feature;
|
|
22
|
+
if (typeof featureKey === "string") {
|
|
23
|
+
featureIsInGroup[featureKey] = true;
|
|
24
|
+
}
|
|
25
|
+
const featureRangesForFeature = featureRanges.get(featureKey) || [];
|
|
26
|
+
const start = isFirstSlot ? accumulatedPercentage : accumulatedPercentage + 1;
|
|
27
|
+
const end = accumulatedPercentage + slot.percentage * 1000;
|
|
28
|
+
featureRangesForFeature.push([start, end]);
|
|
29
|
+
featureRanges.set(slot.feature, featureRangesForFeature);
|
|
30
|
+
}
|
|
31
|
+
accumulatedPercentage += slot.percentage * 1000;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { featureRanges, featureIsInGroup };
|
|
109
36
|
}
|
|
110
37
|
//# sourceMappingURL=getFeatureRanges.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFeatureRanges.js","sourceRoot":"","sources":["../../src/builder/getFeatureRanges.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getFeatureRanges.js","sourceRoot":"","sources":["../../src/builder/getFeatureRanges.ts"],"names":[],"mappings":";;AAcA,4CA8CC;AA5DD,yBAAyB;AAclB,KAAK,UAAU,gBAAgB,CACpC,aAA4B,EAC5B,UAAsB;IAEtB,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuB,CAAC;IACrD,MAAM,gBAAgB,GAAG,EAAE,CAAC,CAAC,wBAAwB;IAErD,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACrD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QAEjD,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAEzD,MAAM,CAAC,IAAI,CAAC;gBACV,GAAG,WAAW;gBACd,GAAG,EAAE,QAAQ;aACd,CAAC,CAAC;YAEH,IAAI,qBAAqB,GAAG,CAAC,CAAC;YAC9B,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,SAAS;gBACjD,MAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAC;gBAEpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;oBAEhC,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;wBACnC,gBAAgB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;oBACtC,CAAC;oBAED,MAAM,uBAAuB,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;oBAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,GAAG,CAAC,CAAC;oBAC9E,MAAM,GAAG,GAAG,qBAAqB,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;oBAE3D,uBAAuB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;oBAE3C,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;gBAC3D,CAAC;gBAED,qBAAqB,IAAI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YAClD,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FeatureKey, Feature, SegmentKey, Segment, DatafileContent } from "@featurevisor/types";
|
|
2
|
+
export declare function getSegmentHashes(segments: Record<SegmentKey, Segment>): Record<SegmentKey, string>;
|
|
3
|
+
export declare function generateHashForFeature(featureKey: FeatureKey, features: Record<FeatureKey, Feature>, segmentHashes: Record<SegmentKey, string>): string;
|
|
4
|
+
export declare function generateHashForDatafile(datafileContent: DatafileContent): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSegmentHashes = getSegmentHashes;
|
|
4
|
+
exports.generateHashForFeature = generateHashForFeature;
|
|
5
|
+
exports.generateHashForDatafile = generateHashForDatafile;
|
|
6
|
+
const crypto = require("crypto");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
const base62chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
9
|
+
function generateHashFromString(str, length = 10) {
|
|
10
|
+
const hashBuffer = crypto.createHash("sha256").update(str).digest();
|
|
11
|
+
// Convert buffer to base62 (alphanumeric)
|
|
12
|
+
let num = BigInt("0x" + hashBuffer.toString("hex"));
|
|
13
|
+
let base62 = "";
|
|
14
|
+
while (num > 0) {
|
|
15
|
+
// Convert the remainder to a number for indexing
|
|
16
|
+
const remainder = Number(num % 62n);
|
|
17
|
+
base62 = base62chars[remainder] + base62;
|
|
18
|
+
num = num / 62n;
|
|
19
|
+
}
|
|
20
|
+
// Return first 10 chars for a short hash (adjust length as needed)
|
|
21
|
+
return base62.slice(0, length);
|
|
22
|
+
}
|
|
23
|
+
function getSegmentHashes(segments) {
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const segmentKey of Object.keys(segments)) {
|
|
26
|
+
const segment = segments[segmentKey];
|
|
27
|
+
result[segmentKey] = generateHashFromString(JSON.stringify({
|
|
28
|
+
conditions: segment.conditions,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function generateHashForFeature(featureKey, features, segmentHashes) {
|
|
34
|
+
const feature = features[featureKey];
|
|
35
|
+
if (!feature) {
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
const requiredFeatureKeys = [];
|
|
39
|
+
if (feature.required) {
|
|
40
|
+
for (const r of feature.required) {
|
|
41
|
+
if (typeof r === "string") {
|
|
42
|
+
requiredFeatureKeys.push(r);
|
|
43
|
+
}
|
|
44
|
+
if (typeof r === "object" && r.key) {
|
|
45
|
+
requiredFeatureKeys.push(r.key);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const requiredFeatureHashes = requiredFeatureKeys.map((key) => generateHashForFeature(key, features, segmentHashes));
|
|
50
|
+
const usedSegments = (0, utils_1.extractSegmentsFromFeature)(feature);
|
|
51
|
+
const usedSegmentHashes = Object.keys(usedSegments).map((segmentKey) => segmentHashes[segmentKey]);
|
|
52
|
+
return generateHashFromString(JSON.stringify({
|
|
53
|
+
featureKey,
|
|
54
|
+
feature,
|
|
55
|
+
requiredFeatureHashes,
|
|
56
|
+
usedSegmentHashes,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
function generateHashForDatafile(datafileContent) {
|
|
60
|
+
const featureHashes = Object.keys(datafileContent.features).reduce((acc, featureKey) => {
|
|
61
|
+
acc[featureKey] = datafileContent.features[featureKey].hash || "";
|
|
62
|
+
return acc;
|
|
63
|
+
}, {});
|
|
64
|
+
const hash = generateHashFromString(JSON.stringify({
|
|
65
|
+
schemaVersion: datafileContent.schemaVersion,
|
|
66
|
+
featureHashes,
|
|
67
|
+
}));
|
|
68
|
+
return hash;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=hashes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashes.js","sourceRoot":"","sources":["../../src/builder/hashes.ts"],"names":[],"mappings":";;AA+BA,4CAeC;AAED,wDAyCC;AAED,0DAiBC;AA5GD,iCAAiC;AAUjC,oCAAsD;AAEtD,MAAM,WAAW,GAAG,gEAAgE,CAAC;AAErF,SAAS,sBAAsB,CAAC,GAAW,EAAE,MAAM,GAAG,EAAE;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;IAEpE,0CAA0C;IAC1C,IAAI,GAAG,GAAG,MAAM,CAAC,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC;QACf,iDAAiD;QACjD,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;QACpC,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC;QACzC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,mEAAmE;IACnE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,SAAgB,gBAAgB,CAC9B,QAAqC;IAErC,MAAM,MAAM,GAA+B,EAAE,CAAC;IAE9C,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,UAAU,CAAC,GAAG,sBAAsB,CACzC,IAAI,CAAC,SAAS,CAAC;YACb,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,sBAAsB,CACpC,UAAsB,EACtB,QAAqC,EACrC,aAAyC;IAEzC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAErC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,mBAAmB,GAAa,EAAE,CAAC;IACzC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC1B,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC;YAED,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;gBACnC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC5D,sBAAsB,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CACrD,CAAC;IAEF,MAAM,YAAY,GAAG,IAAA,kCAA0B,EAAC,OAAO,CAAC,CAAC;IACzD,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CACrD,CAAC,UAAU,EAAE,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,CAC1C,CAAC;IAEF,OAAO,sBAAsB,CAC3B,IAAI,CAAC,SAAS,CAAC;QACb,UAAU;QACV,OAAO;QACP,qBAAqB;QACrB,iBAAiB;KAClB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAgB,uBAAuB,CAAC,eAAgC;IACtE,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,MAAM,CAChE,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE;QAClB,GAAG,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAClE,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAgC,CACjC,CAAC;IAEF,MAAM,IAAI,GAAG,sBAAsB,CACjC,IAAI,CAAC,SAAS,CAAC;QACb,aAAa,EAAE,eAAe,CAAC,aAAa;QAC5C,aAAa;KACd,CAAC,CACH,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/lib/builder/revision.js
CHANGED
|
@@ -11,8 +11,8 @@ function getNextRevision(currentRevision) {
|
|
|
11
11
|
return (parseInt(currentRevision, 10) + 1).toString();
|
|
12
12
|
}
|
|
13
13
|
// If the string is a semver, parse the patch version out of it, increment it by one and return it.
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const parts = currentRevision.split(".");
|
|
15
|
+
const lastPart = parseInt(parts[parts.length - 1], 10);
|
|
16
16
|
if (!isNaN(lastPart)) {
|
|
17
17
|
return (lastPart + 1).toString();
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revision.js","sourceRoot":"","sources":["../../src/builder/revision.ts"],"names":[],"mappings":";;AAAA,0CAqBC;AArBD,SAAgB,eAAe,CAAC,eAAuB;IACrD,yEAAyE;IACzE,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,GAAG,CAAC;IACb,CAAC;IAED,4EAA4E;IAC5E,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxD,CAAC;IAED,mGAAmG;IACnG,
|
|
1
|
+
{"version":3,"file":"revision.js","sourceRoot":"","sources":["../../src/builder/revision.ts"],"names":[],"mappings":";;AAAA,0CAqBC;AArBD,SAAgB,eAAe,CAAC,eAAuB;IACrD,yEAAyE;IACzE,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,GAAG,CAAC;IACb,CAAC;IAED,4EAA4E;IAC5E,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxD,CAAC;IAED,mGAAmG;IACnG,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEvD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnC,CAAC;IAED,yDAAyD;IACzD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const revision_1 = require("./revision");
|
|
4
4
|
describe("core: Revision", function () {
|
|
5
5
|
it("should be a function", function () {
|
|
6
6
|
expect(typeof revision_1.getNextRevision).toEqual("function");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revision.spec.js","sourceRoot":"","sources":["../../src/builder/revision.spec.ts"],"names":[],"mappings":";;AAAA,
|
|
1
|
+
{"version":3,"file":"revision.spec.js","sourceRoot":"","sources":["../../src/builder/revision.spec.ts"],"names":[],"mappings":";;AAAA,yCAA6C;AAE7C,QAAQ,CAAC,gBAAgB,EAAE;IACzB,EAAE,CAAC,sBAAsB,EAAE;QACzB,MAAM,CAAC,OAAO,0BAAe,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE;QACtC,gBAAgB;QAChB,MAAM,CAAC,IAAA,0BAAe,EAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,CAAC,IAAA,0BAAe,EAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAEpD,iBAAiB;QACjB,MAAM,CAAC,IAAA,0BAAe,EAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAA,0BAAe,EAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEhD,gBAAgB;QAChB,MAAM,CAAC,IAAA,0BAAe,EAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAA,0BAAe,EAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAA,0BAAe,EAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/builder/traffic.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Rule, ExistingFeature, Traffic, Variation, Range, Percentage } from "@featurevisor/types";
|
|
1
|
+
import type { Rule, ExistingFeature, Traffic, Variation, Range, Percentage } from "@featurevisor/types";
|
|
2
2
|
export declare function detectIfVariationsChanged(yamlVariations: Variation[] | undefined, // as exists in latest YAML
|
|
3
3
|
existingFeature?: ExistingFeature): boolean;
|
|
4
4
|
export declare function getRulePercentageDiff(trafficPercentage: Percentage, // 0 to 100k
|
package/lib/builder/traffic.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.detectIfVariationsChanged = detectIfVariationsChanged;
|
|
|
4
4
|
exports.getRulePercentageDiff = getRulePercentageDiff;
|
|
5
5
|
exports.detectIfRangesChanged = detectIfRangesChanged;
|
|
6
6
|
exports.getTraffic = getTraffic;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const sdk_1 = require("@featurevisor/sdk");
|
|
8
|
+
const allocator_1 = require("./allocator");
|
|
9
9
|
function detectIfVariationsChanged(yamlVariations, // as exists in latest YAML
|
|
10
10
|
existingFeature) {
|
|
11
11
|
if (!existingFeature || typeof existingFeature.variations === "undefined") {
|
|
@@ -17,26 +17,20 @@ existingFeature) {
|
|
|
17
17
|
// variations didn't exist before, and not even now
|
|
18
18
|
return false;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
? JSON.stringify(yamlVariations.map(
|
|
22
|
-
var value = _a.value, weight = _a.weight;
|
|
23
|
-
return ({ value: value, weight: weight });
|
|
24
|
-
}))
|
|
20
|
+
const checkVariations = Array.isArray(yamlVariations)
|
|
21
|
+
? JSON.stringify(yamlVariations.map(({ value, weight }) => ({ value, weight })))
|
|
25
22
|
: undefined;
|
|
26
|
-
return (JSON.stringify(existingFeature.variations.map(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
weight: weight,
|
|
31
|
-
});
|
|
32
|
-
})) !== checkVariations);
|
|
23
|
+
return (JSON.stringify(existingFeature.variations.map(({ value, weight }) => ({
|
|
24
|
+
value,
|
|
25
|
+
weight,
|
|
26
|
+
}))) !== checkVariations);
|
|
33
27
|
}
|
|
34
28
|
function getRulePercentageDiff(trafficPercentage, // 0 to 100k
|
|
35
29
|
existingTrafficRule) {
|
|
36
30
|
if (!existingTrafficRule) {
|
|
37
31
|
return 0;
|
|
38
32
|
}
|
|
39
|
-
|
|
33
|
+
const existingPercentage = existingTrafficRule.percentage;
|
|
40
34
|
return trafficPercentage - existingPercentage;
|
|
41
35
|
}
|
|
42
36
|
function detectIfRangesChanged(availableRanges, // as exists in latest YAML
|
|
@@ -56,16 +50,17 @@ variations, parsedRules,
|
|
|
56
50
|
existingFeature,
|
|
57
51
|
// ranges from group slots
|
|
58
52
|
ranges) {
|
|
59
|
-
|
|
60
|
-
// @
|
|
61
|
-
|
|
53
|
+
const result = [];
|
|
54
|
+
// @NOTE: may be pass from builder directly?
|
|
55
|
+
const availableRanges = ranges && ranges.length > 0 ? ranges : [[0, sdk_1.MAX_BUCKETED_NUMBER]];
|
|
62
56
|
parsedRules.forEach(function (parsedRule) {
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
const rulePercentage = parsedRule.percentage; // 0 - 100
|
|
58
|
+
const traffic = {
|
|
65
59
|
key: parsedRule.key,
|
|
66
60
|
segments: parsedRule.segments,
|
|
67
61
|
percentage: rulePercentage * (sdk_1.MAX_BUCKETED_NUMBER / 100),
|
|
68
62
|
allocation: [],
|
|
63
|
+
variationWeights: parsedRule.variationWeights,
|
|
69
64
|
};
|
|
70
65
|
// overrides
|
|
71
66
|
if (parsedRule.variables) {
|
|
@@ -75,53 +70,66 @@ ranges) {
|
|
|
75
70
|
traffic.variation = parsedRule.variation;
|
|
76
71
|
}
|
|
77
72
|
// detect changes
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
const variationsChanged = detectIfVariationsChanged(variations, existingFeature);
|
|
74
|
+
const existingTrafficRule = existingFeature?.traffic.find((t) => t.key === parsedRule.key);
|
|
75
|
+
const rulePercentageDiff = getRulePercentageDiff(traffic.percentage, existingTrafficRule);
|
|
76
|
+
const rangesChanged = detectIfRangesChanged(availableRanges, existingFeature);
|
|
77
|
+
const needsRebucketing = !existingTrafficRule || // new rule
|
|
83
78
|
variationsChanged || // variations changed
|
|
84
79
|
rulePercentageDiff < 0 || // percentage decreased
|
|
85
|
-
rangesChanged
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
rangesChanged || // belongs to a group, and group ranges changed
|
|
81
|
+
// @NOTE: this means, if variationWeights is present, it will always rebucket.
|
|
82
|
+
// worth checking if we can maintain consistent bucketing for this use case as well.
|
|
83
|
+
// but this use case is unlikely to hit in practice because it doesn't matter if the feature itself is 100% rolled out.
|
|
84
|
+
traffic.variationWeights; // variation weights overridden
|
|
85
|
+
let updatedAvailableRanges = JSON.parse(JSON.stringify(availableRanges));
|
|
86
|
+
if (existingTrafficRule && existingTrafficRule.allocation && !needsRebucketing) {
|
|
88
87
|
// increase: build on top of existing allocations
|
|
89
|
-
|
|
90
|
-
traffic.allocation = existingTrafficRule.allocation.map(function (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
variation: variation,
|
|
88
|
+
let existingSum = 0;
|
|
89
|
+
traffic.allocation = existingTrafficRule.allocation.map(function ({ variation, range }) {
|
|
90
|
+
const result = {
|
|
91
|
+
variation,
|
|
94
92
|
range: range,
|
|
95
93
|
};
|
|
96
|
-
|
|
94
|
+
existingSum += range[1] - range[0];
|
|
97
95
|
return result;
|
|
98
96
|
});
|
|
99
|
-
updatedAvailableRanges = (0, allocator_1.getUpdatedAvailableRangesAfterFilling)(availableRanges,
|
|
97
|
+
updatedAvailableRanges = (0, allocator_1.getUpdatedAvailableRangesAfterFilling)(availableRanges, existingSum);
|
|
100
98
|
}
|
|
101
99
|
if (Array.isArray(variations)) {
|
|
102
100
|
variations.forEach(function (variation) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
let weight = variation.weight;
|
|
102
|
+
if (traffic.variationWeights && traffic.variationWeights[variation.value]) {
|
|
103
|
+
// override weight from rule
|
|
104
|
+
weight = traffic.variationWeights[variation.value];
|
|
105
|
+
}
|
|
106
|
+
const percentage = weight * (sdk_1.MAX_BUCKETED_NUMBER / 100);
|
|
107
|
+
const toFillValue = needsRebucketing
|
|
106
108
|
? percentage * (rulePercentage / 100) // whole value
|
|
107
109
|
: (weight / 100) * rulePercentageDiff; // incrementing
|
|
108
|
-
|
|
110
|
+
const rangesToFill = (0, allocator_1.getAllocation)(updatedAvailableRanges, toFillValue);
|
|
109
111
|
rangesToFill.forEach(function (range) {
|
|
110
|
-
traffic.allocation
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
if (traffic.allocation) {
|
|
113
|
+
traffic.allocation.push({
|
|
114
|
+
variation: variation.value,
|
|
115
|
+
range,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
114
118
|
});
|
|
115
119
|
updatedAvailableRanges = (0, allocator_1.getUpdatedAvailableRangesAfterFilling)(updatedAvailableRanges, toFillValue);
|
|
116
120
|
});
|
|
117
121
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
if (traffic.allocation) {
|
|
123
|
+
traffic.allocation = traffic.allocation.filter((a) => {
|
|
124
|
+
if (a.range && a.range[0] === a.range[1]) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
});
|
|
129
|
+
if (traffic.allocation.length === 0) {
|
|
130
|
+
delete traffic.allocation;
|
|
121
131
|
}
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
// @TODO: in v2, remove "allocation" property if an empty array
|
|
132
|
+
}
|
|
125
133
|
result.push(traffic);
|
|
126
134
|
});
|
|
127
135
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traffic.js","sourceRoot":"","sources":["../../src/builder/traffic.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"traffic.js","sourceRoot":"","sources":["../../src/builder/traffic.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const traffic_1 = require("./traffic");
|
|
4
4
|
describe("core: Traffic", function () {
|
|
5
5
|
it("should be a function", function () {
|
|
6
6
|
expect(typeof traffic_1.getTraffic).toEqual("function");
|
|
7
7
|
});
|
|
8
8
|
it("should allocate traffic for 100-0 weight on two variations", function () {
|
|
9
|
-
|
|
9
|
+
const result = (0, traffic_1.getTraffic)(
|
|
10
10
|
// parsed variations from YAML
|
|
11
11
|
[
|
|
12
12
|
{
|
|
@@ -43,7 +43,7 @@ describe("core: Traffic", function () {
|
|
|
43
43
|
]);
|
|
44
44
|
});
|
|
45
45
|
it("should allocate traffic for 0-100 weight on two variations", function () {
|
|
46
|
-
|
|
46
|
+
const result = (0, traffic_1.getTraffic)(
|
|
47
47
|
// parsed variations from YAML
|
|
48
48
|
[
|
|
49
49
|
{
|
|
@@ -85,7 +85,7 @@ describe("core: Traffic", function () {
|
|
|
85
85
|
]);
|
|
86
86
|
});
|
|
87
87
|
it("should allocate traffic for 0-100 weight on two variations, with rule percentage going from 80% to 100%", function () {
|
|
88
|
-
|
|
88
|
+
const result = (0, traffic_1.getTraffic)(
|
|
89
89
|
// parsed variations from YAML
|
|
90
90
|
[
|
|
91
91
|
{
|
|
@@ -150,7 +150,7 @@ describe("core: Traffic", function () {
|
|
|
150
150
|
]);
|
|
151
151
|
});
|
|
152
152
|
it("should allocate traffic for 0-100 weight on two variations, with rule percentage going from 100% to 80%", function () {
|
|
153
|
-
|
|
153
|
+
const result = (0, traffic_1.getTraffic)(
|
|
154
154
|
// parsed variations from YAML
|
|
155
155
|
[
|
|
156
156
|
{
|
|
@@ -215,7 +215,7 @@ describe("core: Traffic", function () {
|
|
|
215
215
|
]);
|
|
216
216
|
});
|
|
217
217
|
it("should allocate traffic for existing variations state of 0-100 weights", function () {
|
|
218
|
-
|
|
218
|
+
const result = (0, traffic_1.getTraffic)(
|
|
219
219
|
// parsed variations from YAML
|
|
220
220
|
[
|
|
221
221
|
{
|
|
@@ -279,7 +279,7 @@ describe("core: Traffic", function () {
|
|
|
279
279
|
]);
|
|
280
280
|
});
|
|
281
281
|
it("should allocate traffic for 50-50 weight on two variations", function () {
|
|
282
|
-
|
|
282
|
+
const result = (0, traffic_1.getTraffic)(
|
|
283
283
|
// parsed variations from YAML
|
|
284
284
|
[
|
|
285
285
|
{
|
|
@@ -320,7 +320,7 @@ describe("core: Traffic", function () {
|
|
|
320
320
|
]);
|
|
321
321
|
});
|
|
322
322
|
it("should allocate traffic for weight with two decimal places among three variations", function () {
|
|
323
|
-
|
|
323
|
+
const result = (0, traffic_1.getTraffic)(
|
|
324
324
|
// parsed variations from YAML
|
|
325
325
|
[
|
|
326
326
|
{
|
|
@@ -369,7 +369,7 @@ describe("core: Traffic", function () {
|
|
|
369
369
|
]);
|
|
370
370
|
});
|
|
371
371
|
it("should allocate against previous known allocation, increasing from 80% to 90%, with same variations and weight", function () {
|
|
372
|
-
|
|
372
|
+
const result = (0, traffic_1.getTraffic)(
|
|
373
373
|
// parsed variations from YAML
|
|
374
374
|
[
|
|
375
375
|
{
|
|
@@ -447,7 +447,7 @@ describe("core: Traffic", function () {
|
|
|
447
447
|
]);
|
|
448
448
|
});
|
|
449
449
|
it("should allocate against previous known allocation, decreasing from 80% to 70%, with same variations and weight", function () {
|
|
450
|
-
|
|
450
|
+
const result = (0, traffic_1.getTraffic)(
|
|
451
451
|
// parsed variations from YAML
|
|
452
452
|
[
|
|
453
453
|
{
|
|
@@ -515,7 +515,7 @@ describe("core: Traffic", function () {
|
|
|
515
515
|
]);
|
|
516
516
|
});
|
|
517
517
|
it("should allocate against previous known allocation, increasing from 80% to 90%, with new added variation", function () {
|
|
518
|
-
|
|
518
|
+
const result = (0, traffic_1.getTraffic)(
|
|
519
519
|
// parsed variations from YAML
|
|
520
520
|
[
|
|
521
521
|
{
|
|
@@ -591,7 +591,7 @@ describe("core: Traffic", function () {
|
|
|
591
591
|
]);
|
|
592
592
|
});
|
|
593
593
|
it("should allocate against previous known allocation, increasing from 80% to 100%, with new added variation, totalling 4 variations", function () {
|
|
594
|
-
|
|
594
|
+
const result = (0, traffic_1.getTraffic)(
|
|
595
595
|
// parsed variations from YAML
|
|
596
596
|
[
|
|
597
597
|
{
|
|
@@ -675,7 +675,7 @@ describe("core: Traffic", function () {
|
|
|
675
675
|
]);
|
|
676
676
|
});
|
|
677
677
|
it("should allocate against previous known allocation, staying at same 100%, removing variations from 4 to 2", function () {
|
|
678
|
-
|
|
678
|
+
const result = (0, traffic_1.getTraffic)(
|
|
679
679
|
// parsed variations from YAML
|
|
680
680
|
[
|
|
681
681
|
{
|
|
@@ -759,7 +759,7 @@ describe("core: Traffic", function () {
|
|
|
759
759
|
]);
|
|
760
760
|
});
|
|
761
761
|
it("should allocate against previous known allocation, decreasing from 100% to 80%, removing variations from 4 to 2", function () {
|
|
762
|
-
|
|
762
|
+
const result = (0, traffic_1.getTraffic)(
|
|
763
763
|
// parsed variations from YAML
|
|
764
764
|
[
|
|
765
765
|
{
|