@featurevisor/core 1.35.2 → 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/CHANGELOG.md +8 -0
- 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 +90 -63
- 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 +101 -23
- 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 -48
- 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 +41 -15
- 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
package/lib/find-usage/index.js
CHANGED
|
@@ -1,541 +1,367 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
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);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
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;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.findUsagePlugin = void 0;
|
|
40
4
|
exports.findAllUsageInFeatures = findAllUsageInFeatures;
|
|
41
5
|
exports.findAllUsageInSegments = findAllUsageInSegments;
|
|
6
|
+
exports.findFeatureUsage = findFeatureUsage;
|
|
42
7
|
exports.findSegmentUsage = findSegmentUsage;
|
|
43
8
|
exports.findAttributeUsage = findAttributeUsage;
|
|
44
9
|
exports.findUnusedSegments = findUnusedSegments;
|
|
45
10
|
exports.findUnusedAttributes = findUnusedAttributes;
|
|
46
11
|
exports.findUsageInProject = findUsageInProject;
|
|
47
|
-
|
|
48
|
-
function findAllUsageInFeatures(deps) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (typeof required === "string") {
|
|
75
|
-
usageInFeatures[featureKey].features.add(required);
|
|
76
|
-
}
|
|
77
|
-
else if (typeof required === "object" && required.key) {
|
|
78
|
-
usageInFeatures[featureKey].features.add(required.key);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
// bucketBy
|
|
83
|
-
if (feature.bucketBy) {
|
|
84
|
-
if (typeof feature.bucketBy === "string") {
|
|
85
|
-
usageInFeatures[featureKey].attributes.add(feature.bucketBy);
|
|
86
|
-
}
|
|
87
|
-
else if (Array.isArray(feature.bucketBy)) {
|
|
88
|
-
feature.bucketBy.forEach(function (b) { return usageInFeatures[featureKey].attributes.add(b); });
|
|
89
|
-
}
|
|
90
|
-
else if (typeof feature.bucketBy === "object" && feature.bucketBy.or) {
|
|
91
|
-
feature.bucketBy.or.forEach(function (b) { return usageInFeatures[featureKey].attributes.add(b); });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// variable overrides inside variations
|
|
95
|
-
if (feature.variations) {
|
|
96
|
-
feature.variations.forEach(function (variation) {
|
|
97
|
-
if (variation.variables) {
|
|
98
|
-
variation.variables.forEach(function (variable) {
|
|
99
|
-
if (variable.overrides) {
|
|
100
|
-
variable.overrides.forEach(function (override) {
|
|
101
|
-
if (override.segments) {
|
|
102
|
-
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(override.segments).forEach(function (segmentKey) {
|
|
103
|
-
return usageInFeatures[featureKey].segments.add(segmentKey);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
if (override.conditions) {
|
|
107
|
-
(0, extractKeys_1.extractAttributeKeysFromConditions)(override.conditions).forEach(function (attributeKey) {
|
|
108
|
-
return usageInFeatures[featureKey].attributes.add(attributeKey);
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
// with environments
|
|
118
|
-
if (Array.isArray(projectConfig.environments)) {
|
|
119
|
-
projectConfig.environments.forEach(function (environment) {
|
|
120
|
-
var _a, _b;
|
|
121
|
-
if (!feature.environments) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
// force
|
|
125
|
-
if (feature.environments[environment].force) {
|
|
126
|
-
(_a = feature.environments[environment].force) === null || _a === void 0 ? void 0 : _a.forEach(function (force) {
|
|
127
|
-
if (force.segments) {
|
|
128
|
-
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(force.segments).forEach(function (segmentKey) {
|
|
129
|
-
return usageInFeatures[featureKey].segments.add(segmentKey);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
if (force.conditions) {
|
|
133
|
-
(0, extractKeys_1.extractAttributeKeysFromConditions)(force.conditions).forEach(function (attributeKey) {
|
|
134
|
-
return usageInFeatures[featureKey].attributes.add(attributeKey);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
// rules
|
|
140
|
-
if (feature.environments[environment].rules) {
|
|
141
|
-
(_b = feature.environments[environment].rules) === null || _b === void 0 ? void 0 : _b.forEach(function (rule) {
|
|
142
|
-
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(rule.segments).forEach(function (segmentKey) {
|
|
143
|
-
return usageInFeatures[featureKey].segments.add(segmentKey);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
// no environments
|
|
150
|
-
if (projectConfig.environments === false) {
|
|
151
|
-
// force
|
|
152
|
-
if (feature.force) {
|
|
153
|
-
feature.force.forEach(function (force) {
|
|
154
|
-
if (force.segments) {
|
|
155
|
-
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(force.segments).forEach(function (segmentKey) {
|
|
156
|
-
return usageInFeatures[featureKey].segments.add(segmentKey);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
if (force.conditions) {
|
|
160
|
-
(0, extractKeys_1.extractAttributeKeysFromConditions)(force.conditions).forEach(function (attributeKey) {
|
|
161
|
-
return usageInFeatures[featureKey].attributes.add(attributeKey);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
// rules
|
|
167
|
-
if (feature.rules) {
|
|
168
|
-
feature.rules.forEach(function (rule) {
|
|
169
|
-
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(rule.segments).forEach(function (segmentKey) {
|
|
170
|
-
return usageInFeatures[featureKey].segments.add(segmentKey);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return [2 /*return*/];
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
_i = 0, featureKeys_1 = featureKeys;
|
|
180
|
-
_a.label = 2;
|
|
181
|
-
case 2:
|
|
182
|
-
if (!(_i < featureKeys_1.length)) return [3 /*break*/, 5];
|
|
183
|
-
featureKey = featureKeys_1[_i];
|
|
184
|
-
return [5 /*yield**/, _loop_1(featureKey)];
|
|
185
|
-
case 3:
|
|
186
|
-
_a.sent();
|
|
187
|
-
_a.label = 4;
|
|
188
|
-
case 4:
|
|
189
|
-
_i++;
|
|
190
|
-
return [3 /*break*/, 2];
|
|
191
|
-
case 5: return [2 /*return*/, usageInFeatures];
|
|
12
|
+
const extractKeys_1 = require("../utils/extractKeys");
|
|
13
|
+
async function findAllUsageInFeatures(deps) {
|
|
14
|
+
const { datasource, projectConfig } = deps;
|
|
15
|
+
const usageInFeatures = {};
|
|
16
|
+
const featureKeys = await datasource.listFeatures();
|
|
17
|
+
for (const featureKey of featureKeys) {
|
|
18
|
+
const feature = await datasource.readFeature(featureKey);
|
|
19
|
+
usageInFeatures[featureKey] = {
|
|
20
|
+
features: new Set(),
|
|
21
|
+
segments: new Set(),
|
|
22
|
+
attributes: new Set(),
|
|
23
|
+
};
|
|
24
|
+
// required
|
|
25
|
+
if (feature.required) {
|
|
26
|
+
feature.required.forEach((required) => {
|
|
27
|
+
if (typeof required === "string") {
|
|
28
|
+
usageInFeatures[featureKey].features.add(required);
|
|
29
|
+
}
|
|
30
|
+
else if (typeof required === "object" && required.key) {
|
|
31
|
+
usageInFeatures[featureKey].features.add(required.key);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// bucketBy
|
|
36
|
+
if (feature.bucketBy) {
|
|
37
|
+
if (typeof feature.bucketBy === "string") {
|
|
38
|
+
usageInFeatures[featureKey].attributes.add(feature.bucketBy);
|
|
192
39
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
function findAllUsageInSegments(deps) {
|
|
197
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
198
|
-
var datasource, usageInSegments, segmentKeys, _loop_2, _i, segmentKeys_1, segmentKey;
|
|
199
|
-
return __generator(this, function (_a) {
|
|
200
|
-
switch (_a.label) {
|
|
201
|
-
case 0:
|
|
202
|
-
datasource = deps.datasource;
|
|
203
|
-
usageInSegments = {};
|
|
204
|
-
return [4 /*yield*/, datasource.listSegments()];
|
|
205
|
-
case 1:
|
|
206
|
-
segmentKeys = _a.sent();
|
|
207
|
-
_loop_2 = function (segmentKey) {
|
|
208
|
-
var segment;
|
|
209
|
-
return __generator(this, function (_b) {
|
|
210
|
-
switch (_b.label) {
|
|
211
|
-
case 0: return [4 /*yield*/, datasource.readSegment(segmentKey)];
|
|
212
|
-
case 1:
|
|
213
|
-
segment = _b.sent();
|
|
214
|
-
usageInSegments[segmentKey] = {
|
|
215
|
-
attributes: new Set(),
|
|
216
|
-
};
|
|
217
|
-
(0, extractKeys_1.extractAttributeKeysFromConditions)(segment.conditions).forEach(function (attributeKey) {
|
|
218
|
-
usageInSegments[segmentKey].attributes.add(attributeKey);
|
|
219
|
-
});
|
|
220
|
-
return [2 /*return*/];
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
};
|
|
224
|
-
_i = 0, segmentKeys_1 = segmentKeys;
|
|
225
|
-
_a.label = 2;
|
|
226
|
-
case 2:
|
|
227
|
-
if (!(_i < segmentKeys_1.length)) return [3 /*break*/, 5];
|
|
228
|
-
segmentKey = segmentKeys_1[_i];
|
|
229
|
-
return [5 /*yield**/, _loop_2(segmentKey)];
|
|
230
|
-
case 3:
|
|
231
|
-
_a.sent();
|
|
232
|
-
_a.label = 4;
|
|
233
|
-
case 4:
|
|
234
|
-
_i++;
|
|
235
|
-
return [3 /*break*/, 2];
|
|
236
|
-
case 5: return [2 /*return*/, usageInSegments];
|
|
40
|
+
else if (Array.isArray(feature.bucketBy)) {
|
|
41
|
+
feature.bucketBy.forEach((b) => usageInFeatures[featureKey].attributes.add(b));
|
|
237
42
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
function findSegmentUsage(deps, segmentKey) {
|
|
242
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
243
|
-
var usedInFeatures, usageInFeatures, featureKey;
|
|
244
|
-
return __generator(this, function (_a) {
|
|
245
|
-
switch (_a.label) {
|
|
246
|
-
case 0:
|
|
247
|
-
usedInFeatures = new Set();
|
|
248
|
-
return [4 /*yield*/, findAllUsageInFeatures(deps)];
|
|
249
|
-
case 1:
|
|
250
|
-
usageInFeatures = _a.sent();
|
|
251
|
-
for (featureKey in usageInFeatures) {
|
|
252
|
-
if (usageInFeatures[featureKey].segments.has(segmentKey)) {
|
|
253
|
-
usedInFeatures.add(featureKey);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return [2 /*return*/, usedInFeatures];
|
|
43
|
+
else if (typeof feature.bucketBy === "object" && feature.bucketBy.or) {
|
|
44
|
+
feature.bucketBy.or.forEach((b) => usageInFeatures[featureKey].attributes.add(b));
|
|
257
45
|
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return [4 /*yield*/, findAllUsageInSegments(deps)];
|
|
275
|
-
case 2:
|
|
276
|
-
usageInSegments = _a.sent();
|
|
277
|
-
for (featureKey in usageInFeatures) {
|
|
278
|
-
if (usageInFeatures[featureKey].attributes.has(attributeKey)) {
|
|
279
|
-
usedIn.features.add(featureKey);
|
|
46
|
+
}
|
|
47
|
+
// variable overrides inside variations
|
|
48
|
+
if (feature.variations) {
|
|
49
|
+
feature.variations.forEach((variation) => {
|
|
50
|
+
if (variation.variableOverrides) {
|
|
51
|
+
Object.keys(variation.variableOverrides).forEach((variableKey) => {
|
|
52
|
+
const overrides = variation.variableOverrides?.[variableKey];
|
|
53
|
+
if (overrides) {
|
|
54
|
+
overrides.forEach((override) => {
|
|
55
|
+
if (override.segments) {
|
|
56
|
+
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(override.segments).forEach((segmentKey) => usageInFeatures[featureKey].segments.add(segmentKey));
|
|
57
|
+
}
|
|
58
|
+
if (override.conditions) {
|
|
59
|
+
(0, extractKeys_1.extractAttributeKeysFromConditions)(override.conditions).forEach((attributeKey) => usageInFeatures[featureKey].attributes.add(attributeKey));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
280
62
|
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// with environments
|
|
68
|
+
if (Array.isArray(projectConfig.environments)) {
|
|
69
|
+
projectConfig.environments.forEach((environment) => {
|
|
70
|
+
// force
|
|
71
|
+
if (feature.force && feature.force[environment]) {
|
|
72
|
+
feature.force[environment].forEach((force) => {
|
|
73
|
+
if (force.segments) {
|
|
74
|
+
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(force.segments).forEach((segmentKey) => usageInFeatures[featureKey].segments.add(segmentKey));
|
|
285
75
|
}
|
|
76
|
+
if (force.conditions) {
|
|
77
|
+
(0, extractKeys_1.extractAttributeKeysFromConditions)(force.conditions).forEach((attributeKey) => usageInFeatures[featureKey].attributes.add(attributeKey));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// rules
|
|
82
|
+
if (feature.rules && feature.rules[environment]) {
|
|
83
|
+
feature.rules[environment].forEach((rule) => {
|
|
84
|
+
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(rule.segments).forEach((segmentKey) => usageInFeatures[featureKey].segments.add(segmentKey));
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// no environments
|
|
90
|
+
if (projectConfig.environments === false) {
|
|
91
|
+
// force
|
|
92
|
+
if (Array.isArray(feature.force)) {
|
|
93
|
+
feature.force.forEach((force) => {
|
|
94
|
+
if (force.segments) {
|
|
95
|
+
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(force.segments).forEach((segmentKey) => usageInFeatures[featureKey].segments.add(segmentKey));
|
|
96
|
+
}
|
|
97
|
+
if (force.conditions) {
|
|
98
|
+
(0, extractKeys_1.extractAttributeKeysFromConditions)(force.conditions).forEach((attributeKey) => usageInFeatures[featureKey].attributes.add(attributeKey));
|
|
286
99
|
}
|
|
287
|
-
|
|
100
|
+
});
|
|
288
101
|
}
|
|
102
|
+
// rules
|
|
103
|
+
if (Array.isArray(feature.rules)) {
|
|
104
|
+
feature.rules.forEach((rule) => {
|
|
105
|
+
(0, extractKeys_1.extractSegmentKeysFromGroupSegments)(rule.segments).forEach((segmentKey) => usageInFeatures[featureKey].segments.add(segmentKey));
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return usageInFeatures;
|
|
111
|
+
}
|
|
112
|
+
async function findAllUsageInSegments(deps) {
|
|
113
|
+
const { datasource } = deps;
|
|
114
|
+
const usageInSegments = {};
|
|
115
|
+
const segmentKeys = await datasource.listSegments();
|
|
116
|
+
for (const segmentKey of segmentKeys) {
|
|
117
|
+
const segment = await datasource.readSegment(segmentKey);
|
|
118
|
+
usageInSegments[segmentKey] = {
|
|
119
|
+
attributes: new Set(),
|
|
120
|
+
};
|
|
121
|
+
(0, extractKeys_1.extractAttributeKeysFromConditions)(segment.conditions).forEach((attributeKey) => {
|
|
122
|
+
usageInSegments[segmentKey].attributes.add(attributeKey);
|
|
289
123
|
});
|
|
290
|
-
}
|
|
124
|
+
}
|
|
125
|
+
return usageInSegments;
|
|
291
126
|
}
|
|
292
|
-
function
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
127
|
+
async function findFeatureUsage(usageInFeatures, searchFeatureKey) {
|
|
128
|
+
const usedInFeatures = new Set();
|
|
129
|
+
for (const featureKey in usageInFeatures) {
|
|
130
|
+
if (usageInFeatures[featureKey].features.has(searchFeatureKey)) {
|
|
131
|
+
usedInFeatures.add(featureKey);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return usedInFeatures;
|
|
135
|
+
}
|
|
136
|
+
async function findSegmentUsage(usageInFeatures, segmentKey) {
|
|
137
|
+
const usedInFeatures = new Set();
|
|
138
|
+
for (const featureKey in usageInFeatures) {
|
|
139
|
+
if (usageInFeatures[featureKey].segments.has(segmentKey)) {
|
|
140
|
+
usedInFeatures.add(featureKey);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return usedInFeatures;
|
|
144
|
+
}
|
|
145
|
+
async function findAttributeUsage(usageInFeatures, usageInSegments, attributeKey) {
|
|
146
|
+
const usedIn = {
|
|
147
|
+
features: new Set(),
|
|
148
|
+
segments: new Set(),
|
|
149
|
+
};
|
|
150
|
+
for (const featureKey in usageInFeatures) {
|
|
151
|
+
if (usageInFeatures[featureKey].attributes.has(attributeKey)) {
|
|
152
|
+
usedIn.features.add(featureKey);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const segmentKey in usageInSegments) {
|
|
156
|
+
if (usageInSegments[segmentKey].attributes.has(attributeKey)) {
|
|
157
|
+
usedIn.segments.add(segmentKey);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return usedIn;
|
|
161
|
+
}
|
|
162
|
+
async function findUnusedSegments(deps, usageInFeatures) {
|
|
163
|
+
const { datasource } = deps;
|
|
164
|
+
const unusedSegments = new Set();
|
|
165
|
+
const allSegmentKeys = await datasource.listSegments();
|
|
166
|
+
const usedSegmentKeys = new Set();
|
|
167
|
+
for (const featureKey in usageInFeatures) {
|
|
168
|
+
usageInFeatures[featureKey].segments.forEach((segmentKey) => {
|
|
169
|
+
usedSegmentKeys.add(segmentKey);
|
|
319
170
|
});
|
|
171
|
+
}
|
|
172
|
+
allSegmentKeys.forEach((segmentKey) => {
|
|
173
|
+
if (!usedSegmentKeys.has(segmentKey)) {
|
|
174
|
+
unusedSegments.add(segmentKey);
|
|
175
|
+
}
|
|
320
176
|
});
|
|
177
|
+
return unusedSegments;
|
|
321
178
|
}
|
|
322
|
-
function findUnusedAttributes(deps) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return [4 /*yield*/, datasource.listAttributes()];
|
|
331
|
-
case 1:
|
|
332
|
-
allAttributeKeys = _a.sent();
|
|
333
|
-
return [4 /*yield*/, findAllUsageInFeatures(deps)];
|
|
334
|
-
case 2:
|
|
335
|
-
usageInFeatures = _a.sent();
|
|
336
|
-
return [4 /*yield*/, findAllUsageInSegments(deps)];
|
|
337
|
-
case 3:
|
|
338
|
-
usageInSegments = _a.sent();
|
|
339
|
-
usedAttributeKeys = new Set();
|
|
340
|
-
for (featureKey in usageInFeatures) {
|
|
341
|
-
usageInFeatures[featureKey].attributes.forEach(function (attributeKey) {
|
|
342
|
-
usedAttributeKeys.add(attributeKey);
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
for (segmentKey in usageInSegments) {
|
|
346
|
-
usageInSegments[segmentKey].attributes.forEach(function (attributeKey) {
|
|
347
|
-
usedAttributeKeys.add(attributeKey);
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
allAttributeKeys.forEach(function (attributeKey) {
|
|
351
|
-
if (!usedAttributeKeys.has(attributeKey)) {
|
|
352
|
-
unusedAttributes.add(attributeKey);
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
return [2 /*return*/, unusedAttributes];
|
|
356
|
-
}
|
|
179
|
+
async function findUnusedAttributes(deps, usageInFeatures, usageInSegments) {
|
|
180
|
+
const { datasource } = deps;
|
|
181
|
+
const unusedAttributes = new Set();
|
|
182
|
+
const allAttributeKeys = await datasource.listAttributes();
|
|
183
|
+
const usedAttributeKeys = new Set();
|
|
184
|
+
for (const featureKey in usageInFeatures) {
|
|
185
|
+
usageInFeatures[featureKey].attributes.forEach((attributeKey) => {
|
|
186
|
+
usedAttributeKeys.add(attributeKey);
|
|
357
187
|
});
|
|
188
|
+
}
|
|
189
|
+
for (const segmentKey in usageInSegments) {
|
|
190
|
+
usageInSegments[segmentKey].attributes.forEach((attributeKey) => {
|
|
191
|
+
usedAttributeKeys.add(attributeKey);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
allAttributeKeys.forEach((attributeKey) => {
|
|
195
|
+
if (!usedAttributeKeys.has(attributeKey)) {
|
|
196
|
+
unusedAttributes.add(attributeKey);
|
|
197
|
+
}
|
|
358
198
|
});
|
|
199
|
+
return unusedAttributes;
|
|
359
200
|
}
|
|
360
|
-
function findUsageInProject(deps, options) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
201
|
+
async function findUsageInProject(deps, options) {
|
|
202
|
+
const { datasource } = deps;
|
|
203
|
+
console.log("");
|
|
204
|
+
const usageInFeatures = await findAllUsageInFeatures(deps);
|
|
205
|
+
const usageInSegments = await findAllUsageInSegments(deps);
|
|
206
|
+
// feature
|
|
207
|
+
if (options.feature) {
|
|
208
|
+
const usedInFeatures = await findFeatureUsage(usageInFeatures, options.feature);
|
|
209
|
+
if (usedInFeatures.size === 0) {
|
|
210
|
+
console.log(`Feature "${options.feature}" is not used in any features.`);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
console.log(`Feature "${options.feature}" is used in the following features:\n`);
|
|
214
|
+
for (const featureKey of Array.from(usedInFeatures)) {
|
|
215
|
+
if (options.authors) {
|
|
216
|
+
const entries = await datasource.listHistoryEntries("feature", featureKey);
|
|
217
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
218
|
+
console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
console.log(` - ${featureKey}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// segment
|
|
228
|
+
if (options.segment) {
|
|
229
|
+
const usedInFeatures = await findSegmentUsage(usageInFeatures, options.segment);
|
|
230
|
+
if (usedInFeatures.size === 0) {
|
|
231
|
+
console.log(`Segment "${options.segment}" is not used in any features.`);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
console.log(`Segment "${options.segment}" is used in the following features:\n`);
|
|
235
|
+
for (const featureKey of Array.from(usedInFeatures)) {
|
|
236
|
+
if (options.authors) {
|
|
237
|
+
const entries = await datasource.listHistoryEntries("feature", featureKey);
|
|
238
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
239
|
+
console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
console.log(` - ${featureKey}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
// attribute
|
|
249
|
+
if (options.attribute) {
|
|
250
|
+
const usedIn = await findAttributeUsage(usageInFeatures, usageInSegments, options.attribute);
|
|
251
|
+
if (usedIn.features.size === 0 && usedIn.segments.size === 0) {
|
|
252
|
+
console.log(`Attribute "${options.attribute}" is not used in any features or segments.`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (usedIn.segments.size > 0) {
|
|
256
|
+
console.log(`Attribute "${options.attribute}" is used in the following segments:\n`);
|
|
257
|
+
for (const segmentKey of Array.from(usedIn.segments)) {
|
|
258
|
+
if (options.authors) {
|
|
259
|
+
const entries = await datasource.listHistoryEntries("segment", segmentKey);
|
|
260
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
261
|
+
console.log(` - ${segmentKey} (Authors: ${authors.join(", ")})`);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
console.log(` - ${segmentKey}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// features affected by above segments
|
|
268
|
+
const affectedFeatures = new Set();
|
|
269
|
+
for (const segmentKey of Array.from(usedIn.segments)) {
|
|
270
|
+
const featureKeys = await findSegmentUsage(usageInFeatures, segmentKey);
|
|
271
|
+
featureKeys.forEach((featureKey) => affectedFeatures.add(featureKey));
|
|
272
|
+
}
|
|
273
|
+
if (affectedFeatures.size > 0) {
|
|
274
|
+
console.log(`\nSegments above are used in the following features:\n`);
|
|
275
|
+
for (const featureKey of Array.from(affectedFeatures)) {
|
|
276
|
+
if (options.authors) {
|
|
277
|
+
const entries = await datasource.listHistoryEntries("feature", featureKey);
|
|
278
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
279
|
+
console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log(` - ${featureKey}`);
|
|
404
283
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
_b = 0, _c = Array.from(usedIn.features);
|
|
408
|
-
_k.label = 10;
|
|
409
|
-
case 10:
|
|
410
|
-
if (!(_b < _c.length)) return [3 /*break*/, 14];
|
|
411
|
-
featureKey = _c[_b];
|
|
412
|
-
if (!options.authors) return [3 /*break*/, 12];
|
|
413
|
-
return [4 /*yield*/, datasource.listHistoryEntries("feature", featureKey)];
|
|
414
|
-
case 11:
|
|
415
|
-
entries = _k.sent();
|
|
416
|
-
authors = Array.from(new Set(entries.map(function (entry) { return entry.author; })));
|
|
417
|
-
console.log(" - ".concat(featureKey, " (Authors: ").concat(authors.join(", "), ")"));
|
|
418
|
-
return [3 /*break*/, 13];
|
|
419
|
-
case 12:
|
|
420
|
-
console.log(" - ".concat(featureKey));
|
|
421
|
-
_k.label = 13;
|
|
422
|
-
case 13:
|
|
423
|
-
_b++;
|
|
424
|
-
return [3 /*break*/, 10];
|
|
425
|
-
case 14:
|
|
426
|
-
console.log("");
|
|
427
|
-
_k.label = 15;
|
|
428
|
-
case 15:
|
|
429
|
-
if (!(usedIn.segments.size > 0)) return [3 /*break*/, 20];
|
|
430
|
-
console.log("Attribute \"".concat(options.attribute, "\" is used in the following segments:\n"));
|
|
431
|
-
_d = 0, _e = Array.from(usedIn.segments);
|
|
432
|
-
_k.label = 16;
|
|
433
|
-
case 16:
|
|
434
|
-
if (!(_d < _e.length)) return [3 /*break*/, 20];
|
|
435
|
-
segmentKey = _e[_d];
|
|
436
|
-
if (!options.authors) return [3 /*break*/, 18];
|
|
437
|
-
return [4 /*yield*/, datasource.listHistoryEntries("segment", segmentKey)];
|
|
438
|
-
case 17:
|
|
439
|
-
entries = _k.sent();
|
|
440
|
-
authors = Array.from(new Set(entries.map(function (entry) { return entry.author; })));
|
|
441
|
-
console.log(" - ".concat(segmentKey, " (Authors: ").concat(authors.join(", "), ")"));
|
|
442
|
-
return [3 /*break*/, 19];
|
|
443
|
-
case 18:
|
|
444
|
-
console.log(" - ".concat(segmentKey));
|
|
445
|
-
_k.label = 19;
|
|
446
|
-
case 19:
|
|
447
|
-
_d++;
|
|
448
|
-
return [3 /*break*/, 16];
|
|
449
|
-
case 20: return [2 /*return*/];
|
|
450
|
-
case 21:
|
|
451
|
-
if (!options.unusedSegments) return [3 /*break*/, 29];
|
|
452
|
-
return [4 /*yield*/, findUnusedSegments(deps)];
|
|
453
|
-
case 22:
|
|
454
|
-
unusedSegments = _k.sent();
|
|
455
|
-
if (!(unusedSegments.size === 0)) return [3 /*break*/, 23];
|
|
456
|
-
console.log("No unused segments found.");
|
|
457
|
-
return [3 /*break*/, 28];
|
|
458
|
-
case 23:
|
|
459
|
-
console.log("Unused segments:\n");
|
|
460
|
-
_f = 0, _g = Array.from(unusedSegments);
|
|
461
|
-
_k.label = 24;
|
|
462
|
-
case 24:
|
|
463
|
-
if (!(_f < _g.length)) return [3 /*break*/, 28];
|
|
464
|
-
segmentKey = _g[_f];
|
|
465
|
-
if (!options.authors) return [3 /*break*/, 26];
|
|
466
|
-
return [4 /*yield*/, datasource.listHistoryEntries("segment", segmentKey)];
|
|
467
|
-
case 25:
|
|
468
|
-
entries = _k.sent();
|
|
469
|
-
authors = Array.from(new Set(entries.map(function (entry) { return entry.author; })));
|
|
470
|
-
console.log(" - ".concat(segmentKey, " (Authors: ").concat(authors.join(", "), ")"));
|
|
471
|
-
return [3 /*break*/, 27];
|
|
472
|
-
case 26:
|
|
473
|
-
console.log(" - ".concat(segmentKey));
|
|
474
|
-
_k.label = 27;
|
|
475
|
-
case 27:
|
|
476
|
-
_f++;
|
|
477
|
-
return [3 /*break*/, 24];
|
|
478
|
-
case 28: return [2 /*return*/];
|
|
479
|
-
case 29:
|
|
480
|
-
if (!options.unusedAttributes) return [3 /*break*/, 37];
|
|
481
|
-
return [4 /*yield*/, findUnusedAttributes(deps)];
|
|
482
|
-
case 30:
|
|
483
|
-
unusedAttributes = _k.sent();
|
|
484
|
-
if (!(unusedAttributes.size === 0)) return [3 /*break*/, 31];
|
|
485
|
-
console.log("No unused attributes found.");
|
|
486
|
-
return [3 /*break*/, 36];
|
|
487
|
-
case 31:
|
|
488
|
-
console.log("Unused attributes:\n");
|
|
489
|
-
_h = 0, _j = Array.from(unusedAttributes);
|
|
490
|
-
_k.label = 32;
|
|
491
|
-
case 32:
|
|
492
|
-
if (!(_h < _j.length)) return [3 /*break*/, 36];
|
|
493
|
-
attributeKey = _j[_h];
|
|
494
|
-
if (!options.authors) return [3 /*break*/, 34];
|
|
495
|
-
return [4 /*yield*/, datasource.listHistoryEntries("attribute", attributeKey)];
|
|
496
|
-
case 33:
|
|
497
|
-
entries = _k.sent();
|
|
498
|
-
authors = Array.from(new Set(entries.map(function (entry) { return entry.author; })));
|
|
499
|
-
console.log(" - ".concat(attributeKey, " (Authors: ").concat(authors.join(", "), ")"));
|
|
500
|
-
return [3 /*break*/, 35];
|
|
501
|
-
case 34:
|
|
502
|
-
console.log(" - ".concat(attributeKey));
|
|
503
|
-
_k.label = 35;
|
|
504
|
-
case 35:
|
|
505
|
-
_h++;
|
|
506
|
-
return [3 /*break*/, 32];
|
|
507
|
-
case 36: return [2 /*return*/];
|
|
508
|
-
case 37:
|
|
509
|
-
console.log("Please specify a segment or attribute.");
|
|
510
|
-
return [2 /*return*/];
|
|
284
|
+
}
|
|
285
|
+
console.log("");
|
|
511
286
|
}
|
|
512
|
-
}
|
|
513
|
-
|
|
287
|
+
}
|
|
288
|
+
if (usedIn.features.size > 0) {
|
|
289
|
+
console.log(`Attribute "${options.attribute}" is used directly in the following features:\n`);
|
|
290
|
+
for (const featureKey of Array.from(usedIn.features)) {
|
|
291
|
+
if (options.authors) {
|
|
292
|
+
const entries = await datasource.listHistoryEntries("feature", featureKey);
|
|
293
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
294
|
+
console.log(` - ${featureKey} (Authors: ${authors.join(", ")})`);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
console.log(` - ${featureKey}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
console.log("");
|
|
301
|
+
}
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
// unused segments
|
|
305
|
+
if (options.unusedSegments) {
|
|
306
|
+
const unusedSegments = await findUnusedSegments(deps, usageInFeatures);
|
|
307
|
+
if (unusedSegments.size === 0) {
|
|
308
|
+
console.log("No unused segments found.");
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
console.log("Unused segments:\n");
|
|
312
|
+
for (const segmentKey of Array.from(unusedSegments)) {
|
|
313
|
+
if (options.authors) {
|
|
314
|
+
const entries = await datasource.listHistoryEntries("segment", segmentKey);
|
|
315
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
316
|
+
console.log(` - ${segmentKey} (Authors: ${authors.join(", ")})`);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
console.log(` - ${segmentKey}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
// unused attributes
|
|
326
|
+
if (options.unusedAttributes) {
|
|
327
|
+
const unusedAttributes = await findUnusedAttributes(deps, usageInFeatures, usageInSegments);
|
|
328
|
+
if (unusedAttributes.size === 0) {
|
|
329
|
+
console.log("No unused attributes found.");
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
console.log("Unused attributes:\n");
|
|
333
|
+
for (const attributeKey of Array.from(unusedAttributes)) {
|
|
334
|
+
if (options.authors) {
|
|
335
|
+
const entries = await datasource.listHistoryEntries("attribute", attributeKey);
|
|
336
|
+
const authors = Array.from(new Set(entries.map((entry) => entry.author)));
|
|
337
|
+
console.log(` - ${attributeKey} (Authors: ${authors.join(", ")})`);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
console.log(` - ${attributeKey}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
console.log("Please specify a segment or attribute.");
|
|
514
347
|
}
|
|
515
348
|
exports.findUsagePlugin = {
|
|
516
349
|
command: "find-usage",
|
|
517
|
-
handler:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
unusedAttributes: parsed.unusedAttributes,
|
|
531
|
-
authors: parsed.authors,
|
|
532
|
-
})];
|
|
533
|
-
case 1:
|
|
534
|
-
_c.sent();
|
|
535
|
-
return [2 /*return*/];
|
|
536
|
-
}
|
|
350
|
+
handler: async ({ rootDirectoryPath, projectConfig, datasource, parsed }) => {
|
|
351
|
+
await findUsageInProject({
|
|
352
|
+
rootDirectoryPath,
|
|
353
|
+
projectConfig,
|
|
354
|
+
datasource,
|
|
355
|
+
options: parsed,
|
|
356
|
+
}, {
|
|
357
|
+
feature: parsed.feature,
|
|
358
|
+
segment: parsed.segment,
|
|
359
|
+
attribute: parsed.attribute,
|
|
360
|
+
unusedSegments: parsed.unusedSegments,
|
|
361
|
+
unusedAttributes: parsed.unusedAttributes,
|
|
362
|
+
authors: parsed.authors,
|
|
537
363
|
});
|
|
538
|
-
}
|
|
364
|
+
},
|
|
539
365
|
examples: [
|
|
540
366
|
{
|
|
541
367
|
command: "find-usage --segment=<segmentKey>",
|