@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.
Files changed (251) hide show
  1. package/README.md +0 -6
  2. package/coverage/clover.xml +321 -237
  3. package/coverage/coverage-final.json +8 -8
  4. package/coverage/lcov-report/index.html +77 -47
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +14 -14
  6. package/coverage/lcov-report/lib/builder/index.html +16 -16
  7. package/coverage/lcov-report/lib/builder/revision.js.html +3 -3
  8. package/coverage/lcov-report/lib/builder/traffic.js.html +88 -64
  9. package/coverage/lcov-report/lib/list/index.html +116 -0
  10. package/coverage/lcov-report/lib/{tester → list}/matrix.js.html +90 -66
  11. package/coverage/lcov-report/lib/tester/helpers.js.html +295 -0
  12. package/coverage/lcov-report/lib/tester/index.html +20 -35
  13. package/coverage/lcov-report/src/builder/allocator.ts.html +2 -2
  14. package/coverage/lcov-report/src/builder/index.html +15 -15
  15. package/coverage/lcov-report/src/builder/revision.ts.html +1 -1
  16. package/coverage/lcov-report/src/builder/traffic.ts.html +96 -24
  17. package/coverage/lcov-report/src/list/index.html +116 -0
  18. package/coverage/lcov-report/src/{tester → list}/matrix.ts.html +87 -21
  19. package/coverage/lcov-report/src/tester/helpers.ts.html +313 -0
  20. package/coverage/lcov-report/src/tester/index.html +20 -35
  21. package/coverage/lcov.info +592 -436
  22. package/lib/assess-distribution/index.d.ts +1 -1
  23. package/lib/assess-distribution/index.js +102 -162
  24. package/lib/assess-distribution/index.js.map +1 -1
  25. package/lib/benchmark/index.js +87 -143
  26. package/lib/benchmark/index.js.map +1 -1
  27. package/lib/builder/allocator.d.ts +1 -1
  28. package/lib/builder/allocator.js +12 -12
  29. package/lib/builder/allocator.js.map +1 -1
  30. package/lib/builder/allocator.spec.js +22 -22
  31. package/lib/builder/allocator.spec.js.map +1 -1
  32. package/lib/builder/buildDatafile.d.ts +4 -3
  33. package/lib/builder/buildDatafile.js +311 -388
  34. package/lib/builder/buildDatafile.js.map +1 -1
  35. package/lib/builder/buildProject.d.ts +2 -1
  36. package/lib/builder/buildProject.js +96 -183
  37. package/lib/builder/buildProject.js.map +1 -1
  38. package/lib/builder/convertToV1.d.ts +10 -0
  39. package/lib/builder/convertToV1.js +119 -0
  40. package/lib/builder/convertToV1.js.map +1 -0
  41. package/lib/builder/getFeatureRanges.d.ts +1 -1
  42. package/lib/builder/getFeatureRanges.js +32 -105
  43. package/lib/builder/getFeatureRanges.js.map +1 -1
  44. package/lib/builder/hashes.d.ts +4 -0
  45. package/lib/builder/hashes.js +70 -0
  46. package/lib/builder/hashes.js.map +1 -0
  47. package/lib/builder/revision.js +2 -2
  48. package/lib/builder/revision.js.map +1 -1
  49. package/lib/builder/revision.spec.js +1 -1
  50. package/lib/builder/revision.spec.js.map +1 -1
  51. package/lib/builder/traffic.d.ts +1 -1
  52. package/lib/builder/traffic.js +57 -49
  53. package/lib/builder/traffic.js.map +1 -1
  54. package/lib/builder/traffic.spec.js +14 -14
  55. package/lib/builder/traffic.spec.js.map +1 -1
  56. package/lib/cli/cli.js +60 -129
  57. package/lib/cli/cli.js.map +1 -1
  58. package/lib/cli/plugins.js +14 -16
  59. package/lib/cli/plugins.js.map +1 -1
  60. package/lib/config/parsers.js +1 -1
  61. package/lib/config/parsers.js.map +1 -1
  62. package/lib/config/projectConfig.d.ts +8 -6
  63. package/lib/config/projectConfig.js +31 -72
  64. package/lib/config/projectConfig.js.map +1 -1
  65. package/lib/datasource/adapter.d.ts +1 -1
  66. package/lib/datasource/adapter.js +2 -5
  67. package/lib/datasource/adapter.js.map +1 -1
  68. package/lib/datasource/datasource.d.ts +2 -1
  69. package/lib/datasource/datasource.js +107 -148
  70. package/lib/datasource/datasource.js.map +1 -1
  71. package/lib/datasource/filesystemAdapter.d.ts +1 -1
  72. package/lib/datasource/filesystemAdapter.js +224 -360
  73. package/lib/datasource/filesystemAdapter.js.map +1 -1
  74. package/lib/evaluate/index.d.ts +1 -1
  75. package/lib/evaluate/index.js +120 -188
  76. package/lib/evaluate/index.js.map +1 -1
  77. package/lib/find-duplicate-segments/findDuplicateSegments.d.ts +1 -1
  78. package/lib/find-duplicate-segments/findDuplicateSegments.js +40 -128
  79. package/lib/find-duplicate-segments/findDuplicateSegments.js.map +1 -1
  80. package/lib/find-duplicate-segments/index.js +27 -82
  81. package/lib/find-duplicate-segments/index.js.map +1 -1
  82. package/lib/find-usage/index.d.ts +7 -5
  83. package/lib/find-usage/index.js +333 -507
  84. package/lib/find-usage/index.js.map +1 -1
  85. package/lib/generate-code/index.js +36 -91
  86. package/lib/generate-code/index.js.map +1 -1
  87. package/lib/generate-code/typescript.js +117 -157
  88. package/lib/generate-code/typescript.js.map +1 -1
  89. package/lib/index.d.ts +0 -1
  90. package/lib/index.js +0 -1
  91. package/lib/index.js.map +1 -1
  92. package/lib/info/index.js +45 -133
  93. package/lib/info/index.js.map +1 -1
  94. package/lib/init/index.d.ts +1 -1
  95. package/lib/init/index.js +16 -64
  96. package/lib/init/index.js.map +1 -1
  97. package/lib/linter/attributeSchema.d.ts +21 -6
  98. package/lib/linter/attributeSchema.js +18 -4
  99. package/lib/linter/attributeSchema.js.map +1 -1
  100. package/lib/linter/checkCircularDependency.d.ts +1 -1
  101. package/lib/linter/checkCircularDependency.js +22 -80
  102. package/lib/linter/checkCircularDependency.js.map +1 -1
  103. package/lib/linter/checkPercentageExceedingSlot.d.ts +1 -1
  104. package/lib/linter/checkPercentageExceedingSlot.js +36 -76
  105. package/lib/linter/checkPercentageExceedingSlot.js.map +1 -1
  106. package/lib/linter/conditionSchema.d.ts +1 -1
  107. package/lib/linter/conditionSchema.js +89 -41
  108. package/lib/linter/conditionSchema.js.map +1 -1
  109. package/lib/linter/featureSchema.d.ts +345 -197
  110. package/lib/linter/featureSchema.js +313 -172
  111. package/lib/linter/featureSchema.js.map +1 -1
  112. package/lib/linter/groupSchema.js +6 -6
  113. package/lib/linter/groupSchema.js.map +1 -1
  114. package/lib/linter/lintProject.js +306 -480
  115. package/lib/linter/lintProject.js.map +1 -1
  116. package/lib/linter/printError.js +7 -7
  117. package/lib/linter/printError.js.map +1 -1
  118. package/lib/linter/segmentSchema.js +2 -2
  119. package/lib/linter/segmentSchema.js.map +1 -1
  120. package/lib/linter/testSchema.d.ts +155 -3
  121. package/lib/linter/testSchema.js +47 -17
  122. package/lib/linter/testSchema.js.map +1 -1
  123. package/lib/list/index.d.ts +1 -0
  124. package/lib/list/index.js +349 -517
  125. package/lib/list/index.js.map +1 -1
  126. package/lib/{tester → list}/matrix.d.ts +1 -1
  127. package/lib/{tester → list}/matrix.js +50 -42
  128. package/lib/list/matrix.js.map +1 -0
  129. package/lib/{tester → list}/matrix.spec.js +7 -7
  130. package/lib/list/matrix.spec.js.map +1 -0
  131. package/lib/site/exportSite.js +25 -71
  132. package/lib/site/exportSite.js.map +1 -1
  133. package/lib/site/generateHistory.d.ts +1 -1
  134. package/lib/site/generateHistory.js +26 -82
  135. package/lib/site/generateHistory.js.map +1 -1
  136. package/lib/site/generateSiteSearchIndex.d.ts +1 -1
  137. package/lib/site/generateSiteSearchIndex.js +182 -259
  138. package/lib/site/generateSiteSearchIndex.js.map +1 -1
  139. package/lib/site/getLastModifiedFromHistory.d.ts +1 -1
  140. package/lib/site/getLastModifiedFromHistory.js +2 -2
  141. package/lib/site/getLastModifiedFromHistory.js.map +1 -1
  142. package/lib/site/getOwnerAndRepoFromUrl.js +6 -6
  143. package/lib/site/getOwnerAndRepoFromUrl.js.map +1 -1
  144. package/lib/site/getRelativePaths.js +7 -7
  145. package/lib/site/getRelativePaths.js.map +1 -1
  146. package/lib/site/getRepoDetails.js +20 -20
  147. package/lib/site/getRepoDetails.js.map +1 -1
  148. package/lib/site/index.js +25 -73
  149. package/lib/site/index.js.map +1 -1
  150. package/lib/site/serveSite.js +10 -10
  151. package/lib/site/serveSite.js.map +1 -1
  152. package/lib/tester/helpers.d.ts +2 -0
  153. package/lib/tester/helpers.js +71 -0
  154. package/lib/tester/helpers.js.map +1 -0
  155. package/lib/tester/helpers.spec.js +115 -0
  156. package/lib/tester/helpers.spec.js.map +1 -0
  157. package/lib/tester/index.d.ts +0 -1
  158. package/lib/tester/index.js +0 -1
  159. package/lib/tester/index.js.map +1 -1
  160. package/lib/tester/prettyDuration.js +11 -11
  161. package/lib/tester/prettyDuration.js.map +1 -1
  162. package/lib/tester/printTestResult.d.ts +1 -1
  163. package/lib/tester/printTestResult.js +35 -15
  164. package/lib/tester/printTestResult.js.map +1 -1
  165. package/lib/tester/testFeature.d.ts +4 -2
  166. package/lib/tester/testFeature.js +264 -226
  167. package/lib/tester/testFeature.js.map +1 -1
  168. package/lib/tester/testProject.d.ts +3 -7
  169. package/lib/tester/testProject.js +145 -246
  170. package/lib/tester/testProject.js.map +1 -1
  171. package/lib/tester/testSegment.d.ts +5 -2
  172. package/lib/tester/testSegment.js +65 -102
  173. package/lib/tester/testSegment.js.map +1 -1
  174. package/lib/utils/extractKeys.d.ts +2 -1
  175. package/lib/utils/extractKeys.js +57 -12
  176. package/lib/utils/extractKeys.js.map +1 -1
  177. package/lib/utils/git.d.ts +1 -1
  178. package/lib/utils/git.js +23 -23
  179. package/lib/utils/git.js.map +1 -1
  180. package/lib/utils/pretty.js +2 -4
  181. package/lib/utils/pretty.js.map +1 -1
  182. package/package.json +5 -6
  183. package/src/assess-distribution/index.ts +3 -2
  184. package/src/benchmark/index.ts +3 -3
  185. package/src/builder/allocator.spec.ts +1 -1
  186. package/src/builder/allocator.ts +1 -1
  187. package/src/builder/buildDatafile.ts +161 -124
  188. package/src/builder/buildProject.ts +6 -3
  189. package/src/builder/convertToV1.ts +166 -0
  190. package/src/builder/getFeatureRanges.ts +1 -1
  191. package/src/builder/hashes.ts +109 -0
  192. package/src/builder/traffic.ts +40 -16
  193. package/src/cli/cli.ts +1 -1
  194. package/src/cli/plugins.ts +0 -2
  195. package/src/config/projectConfig.ts +13 -10
  196. package/src/datasource/adapter.ts +1 -1
  197. package/src/datasource/datasource.ts +23 -2
  198. package/src/datasource/filesystemAdapter.ts +11 -12
  199. package/src/evaluate/index.ts +7 -6
  200. package/src/find-duplicate-segments/findDuplicateSegments.ts +1 -1
  201. package/src/find-usage/index.ts +111 -44
  202. package/src/generate-code/index.ts +1 -3
  203. package/src/generate-code/typescript.ts +7 -29
  204. package/src/index.ts +0 -1
  205. package/src/info/index.ts +2 -2
  206. package/src/init/index.ts +2 -2
  207. package/src/linter/attributeSchema.ts +18 -2
  208. package/src/linter/checkCircularDependency.ts +1 -1
  209. package/src/linter/checkPercentageExceedingSlot.ts +28 -8
  210. package/src/linter/conditionSchema.ts +66 -10
  211. package/src/linter/featureSchema.ts +312 -116
  212. package/src/linter/lintProject.ts +9 -4
  213. package/src/linter/testSchema.ts +42 -3
  214. package/src/list/index.ts +18 -30
  215. package/src/{tester → list}/matrix.ts +33 -11
  216. package/src/site/exportSite.ts +2 -4
  217. package/src/site/generateHistory.ts +1 -1
  218. package/src/site/generateSiteSearchIndex.ts +58 -50
  219. package/src/site/getLastModifiedFromHistory.ts +1 -1
  220. package/src/tester/helpers.spec.ts +149 -0
  221. package/src/tester/helpers.ts +76 -0
  222. package/src/tester/index.ts +0 -1
  223. package/src/tester/printTestResult.ts +25 -3
  224. package/src/tester/testFeature.ts +270 -124
  225. package/src/tester/testProject.ts +28 -49
  226. package/src/tester/testSegment.ts +48 -40
  227. package/src/utils/extractKeys.ts +58 -1
  228. package/src/utils/git.ts +1 -1
  229. package/tsconfig.cjs.json +1 -0
  230. package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +0 -151
  231. package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +0 -157
  232. package/lib/restore/index.d.ts +0 -4
  233. package/lib/restore/index.js +0 -91
  234. package/lib/restore/index.js.map +0 -1
  235. package/lib/tester/checkIfArraysAreEqual.d.ts +0 -1
  236. package/lib/tester/checkIfArraysAreEqual.js +0 -18
  237. package/lib/tester/checkIfArraysAreEqual.js.map +0 -1
  238. package/lib/tester/checkIfObjectsAreEqual.d.ts +0 -1
  239. package/lib/tester/checkIfObjectsAreEqual.js +0 -23
  240. package/lib/tester/checkIfObjectsAreEqual.js.map +0 -1
  241. package/lib/tester/checkIfObjectsAreEqual.spec.js +0 -26
  242. package/lib/tester/checkIfObjectsAreEqual.spec.js.map +0 -1
  243. package/lib/tester/matrix.js.map +0 -1
  244. package/lib/tester/matrix.spec.js.map +0 -1
  245. package/src/restore/index.ts +0 -42
  246. package/src/tester/checkIfArraysAreEqual.ts +0 -16
  247. package/src/tester/checkIfObjectsAreEqual.spec.ts +0 -31
  248. package/src/tester/checkIfObjectsAreEqual.ts +0 -24
  249. /package/lib/{tester → list}/matrix.spec.d.ts +0 -0
  250. /package/lib/tester/{checkIfObjectsAreEqual.spec.d.ts → helpers.spec.d.ts} +0 -0
  251. /package/src/{tester → list}/matrix.spec.ts +0 -0
@@ -1,407 +1,330 @@
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.getCustomDatafile = getCustomDatafile;
51
4
  exports.buildDatafile = buildDatafile;
52
- var fs = require("fs");
53
- var config_1 = require("../config");
54
- var utils_1 = require("../utils");
55
- var traffic_1 = require("./traffic");
56
- var getFeatureRanges_1 = require("./getFeatureRanges");
57
- function getCustomDatafile(options) {
58
- return __awaiter(this, void 0, void 0, function () {
59
- var featuresToInclude, requiredChain, existingState, datafileContent;
60
- return __generator(this, function (_a) {
61
- switch (_a.label) {
62
- case 0:
63
- if (!options.featureKey) return [3 /*break*/, 2];
64
- return [4 /*yield*/, options.datasource.getRequiredFeaturesChain(options.featureKey)];
65
- case 1:
66
- requiredChain = _a.sent();
67
- featuresToInclude = Array.from(requiredChain);
68
- _a.label = 2;
69
- case 2: return [4 /*yield*/, options.datasource.readState(options.environment)];
70
- case 3:
71
- existingState = _a.sent();
72
- return [4 /*yield*/, buildDatafile(options.projectConfig, options.datasource, {
73
- schemaVersion: options.schemaVersion || config_1.SCHEMA_VERSION,
74
- revision: options.revision || "tester",
75
- environment: options.environment,
76
- features: featuresToInclude,
77
- inflate: options.inflate,
78
- }, existingState)];
79
- case 4:
80
- datafileContent = _a.sent();
81
- return [2 /*return*/, datafileContent];
82
- }
83
- });
84
- });
5
+ const fs = require("fs");
6
+ const config_1 = require("../config");
7
+ const utils_1 = require("../utils");
8
+ const hashes_1 = require("./hashes");
9
+ const traffic_1 = require("./traffic");
10
+ const getFeatureRanges_1 = require("./getFeatureRanges");
11
+ const convertToV1_1 = require("./convertToV1");
12
+ async function getCustomDatafile(options) {
13
+ let featuresToInclude;
14
+ if (options.featureKey) {
15
+ const requiredChain = await options.datasource.getRequiredFeaturesChain(options.featureKey);
16
+ featuresToInclude = Array.from(requiredChain);
17
+ }
18
+ const existingState = await options.datasource.readState(options.environment);
19
+ const datafileContent = await buildDatafile(options.projectConfig, options.datasource, {
20
+ schemaVersion: options.schemaVersion || config_1.SCHEMA_VERSION,
21
+ revision: options.revision || "tester",
22
+ environment: options.environment,
23
+ features: featuresToInclude,
24
+ inflate: options.inflate,
25
+ }, existingState);
26
+ return datafileContent;
85
27
  }
86
- function buildDatafile(projectConfig, datasource, options, existingState) {
87
- return __awaiter(this, void 0, void 0, function () {
88
- var datafileContent, segmentKeysUsedByTag, attributeKeysUsedByTag, _a, featureRanges, featureIsInGroup, features, featuresDirectory, featureFiles, _i, featureFiles_1, featureKey, parsedFeature, expose, rules, force, exposeTags, _b, rules_1, parsedRule, extractedSegmentKeys, feature, segments, segmentsDirectory, segmentFiles, _c, segmentFiles_1, segmentKey, parsedSegment, extractedAttributeKeys, segment, attributes, attributesDirectory, attributeFiles, _d, attributeFiles_1, attributeKey, parsedAttribute, attribute, allFeatureKeys, allSegmentKeys, allAttributeKeys, i, _loop_1, _e, allFeatureKeys_1, featureKey, _loop_2, _f, allSegmentKeys_1, segmentKey, _loop_3, _g, allAttributeKeys_1, attributeKey, datafileContentV2;
89
- var _h;
90
- return __generator(this, function (_j) {
91
- switch (_j.label) {
92
- case 0:
93
- datafileContent = {
94
- schemaVersion: options.schemaVersion,
95
- revision: options.revision,
96
- attributes: [],
97
- segments: [],
98
- features: [],
99
- };
100
- segmentKeysUsedByTag = new Set();
101
- attributeKeysUsedByTag = new Set();
102
- return [4 /*yield*/, (0, getFeatureRanges_1.getFeatureRanges)(projectConfig, datasource)];
103
- case 1:
104
- _a = _j.sent(), featureRanges = _a.featureRanges, featureIsInGroup = _a.featureIsInGroup;
105
- features = [];
106
- featuresDirectory = projectConfig.featuresDirectoryPath;
107
- if (!fs.existsSync(featuresDirectory)) return [3 /*break*/, 6];
108
- return [4 /*yield*/, datasource.listFeatures()];
109
- case 2:
110
- featureFiles = _j.sent();
111
- _i = 0, featureFiles_1 = featureFiles;
112
- _j.label = 3;
113
- case 3:
114
- if (!(_i < featureFiles_1.length)) return [3 /*break*/, 6];
115
- featureKey = featureFiles_1[_i];
116
- return [4 /*yield*/, datasource.readFeature(featureKey)];
117
- case 4:
118
- parsedFeature = _j.sent();
119
- if (parsedFeature.archived === true) {
120
- return [3 /*break*/, 5];
121
- }
122
- if (options.tag && parsedFeature.tags.indexOf(options.tag) === -1) {
123
- return [3 /*break*/, 5];
124
- }
125
- if (options.features && options.features.indexOf(featureKey) === -1) {
126
- return [3 /*break*/, 5];
127
- }
128
- expose = void 0;
129
- rules = void 0;
130
- force = void 0;
131
- if (options.environment && parsedFeature.environments) {
132
- expose = parsedFeature.environments[options.environment].expose;
133
- rules = parsedFeature.environments[options.environment].rules;
134
- force = parsedFeature.environments[options.environment].force;
135
- }
136
- else {
137
- expose = parsedFeature.expose;
138
- rules = parsedFeature.rules;
139
- force = parsedFeature.force;
140
- }
141
- if (expose === false) {
142
- return [3 /*break*/, 5];
143
- }
144
- if (Array.isArray(expose)) {
145
- exposeTags = expose;
146
- if (options.tag && exposeTags.indexOf(options.tag) === -1) {
147
- return [3 /*break*/, 5];
148
- }
149
- }
150
- for (_b = 0, rules_1 = rules; _b < rules_1.length; _b++) {
151
- parsedRule = rules_1[_b];
152
- extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(parsedRule.segments);
153
- extractedSegmentKeys.forEach(function (segmentKey) { return segmentKeysUsedByTag.add(segmentKey); });
154
- }
155
- feature = {
156
- key: featureKey,
157
- deprecated: parsedFeature.deprecated === true ? true : undefined,
158
- bucketBy: parsedFeature.bucketBy || projectConfig.defaultBucketBy,
159
- required: parsedFeature.required,
160
- variations: Array.isArray(parsedFeature.variations)
161
- ? parsedFeature.variations.map(function (variation) {
162
- var mappedVariation = {
163
- value: variation.value,
164
- weight: variation.weight, // @TODO: added so state files can maintain weight info, but datafiles don't need this. find a way to remove it from datafiles later
165
- };
166
- if (!variation.variables) {
167
- return mappedVariation;
168
- }
169
- mappedVariation.variables = variation.variables.map(function (variable) {
170
- var mappedVariable = {
171
- key: variable.key,
172
- value: variable.value,
173
- };
174
- if (!variable.overrides) {
175
- return mappedVariable;
28
+ async function buildDatafile(projectConfig, datasource, options, existingState) {
29
+ const segmentKeysUsedByTag = new Set();
30
+ const attributeKeysUsedByTag = new Set();
31
+ const { featureRanges, featureIsInGroup } = await (0, getFeatureRanges_1.getFeatureRanges)(projectConfig, datasource);
32
+ // features
33
+ const features = [];
34
+ const featuresDirectory = projectConfig.featuresDirectoryPath;
35
+ if (fs.existsSync(featuresDirectory)) {
36
+ const featureFiles = await datasource.listFeatures();
37
+ for (const featureKey of featureFiles) {
38
+ const parsedFeature = await datasource.readFeature(featureKey);
39
+ if (parsedFeature.archived === true) {
40
+ continue;
41
+ }
42
+ if (options.tag && parsedFeature.tags.indexOf(options.tag) === -1) {
43
+ continue;
44
+ }
45
+ if (options.features && options.features.indexOf(featureKey) === -1) {
46
+ continue;
47
+ }
48
+ let expose;
49
+ let rules;
50
+ let force;
51
+ if (options.environment) {
52
+ expose = parsedFeature.expose?.[options.environment];
53
+ rules = parsedFeature.rules?.[options.environment];
54
+ force = parsedFeature.force?.[options.environment];
55
+ }
56
+ else {
57
+ expose = parsedFeature.expose;
58
+ rules = parsedFeature.rules;
59
+ force = parsedFeature.force;
60
+ }
61
+ if (expose === false) {
62
+ continue;
63
+ }
64
+ if (Array.isArray(expose)) {
65
+ const exposeTags = expose;
66
+ if (options.tag && exposeTags.indexOf(options.tag) === -1) {
67
+ continue;
68
+ }
69
+ }
70
+ for (const parsedRule of rules) {
71
+ const extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(parsedRule.segments);
72
+ extractedSegmentKeys.forEach((segmentKey) => segmentKeysUsedByTag.add(segmentKey));
73
+ }
74
+ const feature = {
75
+ key: featureKey,
76
+ deprecated: parsedFeature.deprecated === true ? true : undefined,
77
+ bucketBy: parsedFeature.bucketBy || projectConfig.defaultBucketBy,
78
+ required: parsedFeature.required,
79
+ disabledVariationValue: parsedFeature.disabledVariationValue,
80
+ variations: Array.isArray(parsedFeature.variations)
81
+ ? parsedFeature.variations.map((variation) => {
82
+ const mappedVariation = {
83
+ value: variation.value,
84
+ weight: variation.weight, // @NOTE: added so state files can maintain weight info, but datafiles don't need this. find a way to remove it from datafiles later
85
+ variables: variation.variables,
86
+ variableOverrides: variation.variableOverrides,
87
+ };
88
+ if (variation.variableOverrides) {
89
+ const variableOverrides = variation.variableOverrides;
90
+ const variableKeys = Object.keys(variableOverrides);
91
+ for (const variableKey of variableKeys) {
92
+ mappedVariation.variableOverrides[variableKey] = variableOverrides[variableKey].map((override) => {
93
+ if (typeof override.conditions !== "undefined") {
94
+ const extractedAttributeKeys = (0, utils_1.extractAttributeKeysFromConditions)(override.conditions);
95
+ extractedAttributeKeys.forEach((attributeKey) => attributeKeysUsedByTag.add(attributeKey));
96
+ return {
97
+ conditions: projectConfig.stringify && typeof override.conditions !== "string"
98
+ ? JSON.stringify(override.conditions)
99
+ : override.conditions,
100
+ value: override.value,
101
+ };
102
+ }
103
+ if (typeof override.segments !== "undefined") {
104
+ const extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(override.segments);
105
+ extractedSegmentKeys.forEach((segmentKey) => segmentKeysUsedByTag.add(segmentKey));
106
+ return {
107
+ segments: projectConfig.stringify && typeof override.segments !== "string"
108
+ ? JSON.stringify(override.segments)
109
+ : override.segments,
110
+ value: override.value,
111
+ };
176
112
  }
177
- mappedVariable.overrides = variable.overrides.map(function (override) {
178
- if (typeof override.conditions !== "undefined") {
179
- var extractedAttributeKeys = (0, utils_1.extractAttributeKeysFromConditions)(override.conditions);
180
- extractedAttributeKeys.forEach(function (attributeKey) {
181
- return attributeKeysUsedByTag.add(attributeKey);
182
- });
183
- return {
184
- conditions: projectConfig.stringify
185
- ? JSON.stringify(override.conditions)
186
- : override.conditions,
187
- value: override.value,
188
- };
189
- }
190
- if (typeof override.segments !== "undefined") {
191
- var extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(override.segments);
192
- extractedSegmentKeys.forEach(function (segmentKey) {
193
- return segmentKeysUsedByTag.add(segmentKey);
194
- });
195
- return {
196
- segments: typeof override.segments !== "string" && projectConfig.stringify
197
- ? JSON.stringify(override.segments)
198
- : override.segments,
199
- value: override.value,
200
- };
201
- }
202
- return override;
203
- });
204
- return mappedVariable;
113
+ return override;
205
114
  });
206
- return mappedVariation;
207
- })
208
- : undefined,
209
- traffic: (0, traffic_1.getTraffic)(parsedFeature.variations, rules, existingState.features[featureKey], featureRanges.get(featureKey) || []).map(function (t) {
210
- return __assign(__assign({}, t), { segments: typeof t.segments !== "string" && projectConfig.stringify
211
- ? JSON.stringify(t.segments)
212
- : t.segments });
213
- }),
214
- ranges: featureRanges.get(featureKey) || undefined,
115
+ }
116
+ }
117
+ return mappedVariation;
118
+ })
119
+ : undefined,
120
+ traffic: (0, traffic_1.getTraffic)(parsedFeature.variations, rules, existingState.features[featureKey], featureRanges.get(featureKey) || []).map((t) => {
121
+ return {
122
+ ...t,
123
+ segments: typeof t.segments !== "string" && projectConfig.stringify
124
+ ? JSON.stringify(t.segments)
125
+ : t.segments,
215
126
  };
216
- // update state in memory, so that next datafile build can use it (in case it contains the same feature)
217
- existingState.features[featureKey] = {
218
- variations: Array.isArray(feature.variations)
219
- ? feature.variations.map(function (v) {
127
+ }),
128
+ ranges: featureRanges.get(featureKey) || undefined,
129
+ };
130
+ // update state in memory, so that next datafile build can use it (in case it contains the same feature)
131
+ existingState.features[featureKey] = {
132
+ variations: Array.isArray(feature.variations)
133
+ ? feature.variations.map((v) => {
134
+ return {
135
+ value: v.value,
136
+ weight: v.weight || 0,
137
+ };
138
+ })
139
+ : undefined,
140
+ traffic: feature.traffic.map((t) => {
141
+ return {
142
+ key: t.key,
143
+ percentage: t.percentage,
144
+ allocation: t.allocation &&
145
+ t.allocation.map((a) => {
220
146
  return {
221
- value: v.value,
222
- weight: v.weight || 0,
147
+ variation: a.variation,
148
+ range: a.range,
223
149
  };
224
- })
225
- : undefined,
226
- traffic: feature.traffic.map(function (t) {
227
- return {
228
- key: t.key,
229
- percentage: t.percentage,
230
- allocation: t.allocation.map(function (a) {
231
- return {
232
- variation: a.variation,
233
- range: a.range,
234
- };
235
- }),
236
- };
237
- }),
238
- };
239
- if (featureIsInGroup[featureKey] === true) {
240
- feature.ranges = featureRanges.get(feature.key);
241
- }
242
- if (parsedFeature.variablesSchema) {
243
- feature.variablesSchema = parsedFeature.variablesSchema.map(function (v) {
244
- return {
245
- key: v.key,
246
- type: v.type,
247
- defaultValue: v.defaultValue,
248
- deprecated: v.deprecated === true ? true : undefined,
249
- };
250
- });
251
- }
252
- if (force) {
253
- feature.force = force;
254
- (_h = feature.force) === null || _h === void 0 ? void 0 : _h.forEach(function (f) {
255
- if (f.segments) {
256
- var extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(f.segments);
257
- extractedSegmentKeys.forEach(function (segmentKey) { return segmentKeysUsedByTag.add(segmentKey); });
258
- }
259
- });
260
- }
261
- features.push(feature);
262
- _j.label = 5;
263
- case 5:
264
- _i++;
265
- return [3 /*break*/, 3];
266
- case 6:
267
- segments = [];
268
- segmentsDirectory = projectConfig.segmentsDirectoryPath;
269
- if (!fs.existsSync(segmentsDirectory)) return [3 /*break*/, 11];
270
- return [4 /*yield*/, datasource.listSegments()];
271
- case 7:
272
- segmentFiles = _j.sent();
273
- _c = 0, segmentFiles_1 = segmentFiles;
274
- _j.label = 8;
275
- case 8:
276
- if (!(_c < segmentFiles_1.length)) return [3 /*break*/, 11];
277
- segmentKey = segmentFiles_1[_c];
278
- return [4 /*yield*/, datasource.readSegment(segmentKey)];
279
- case 9:
280
- parsedSegment = _j.sent();
281
- if (parsedSegment.archived === true) {
282
- return [3 /*break*/, 10];
283
- }
284
- if (segmentKeysUsedByTag.has(segmentKey) === false) {
285
- return [3 /*break*/, 10];
286
- }
287
- extractedAttributeKeys = (0, utils_1.extractAttributeKeysFromConditions)(parsedSegment.conditions);
288
- extractedAttributeKeys.forEach(function (attributeKey) { return attributeKeysUsedByTag.add(attributeKey); });
289
- segment = {
290
- key: segmentKey,
291
- conditions: typeof parsedSegment.conditions !== "string" && projectConfig.stringify === true
292
- ? JSON.stringify(parsedSegment.conditions)
293
- : parsedSegment.conditions,
150
+ }),
294
151
  };
295
- segments.push(segment);
296
- _j.label = 10;
297
- case 10:
298
- _c++;
299
- return [3 /*break*/, 8];
300
- case 11:
301
- attributes = [];
302
- attributesDirectory = projectConfig.attributesDirectoryPath;
303
- if (!fs.existsSync(attributesDirectory)) return [3 /*break*/, 16];
304
- return [4 /*yield*/, datasource.listAttributes()];
305
- case 12:
306
- attributeFiles = _j.sent();
307
- _d = 0, attributeFiles_1 = attributeFiles;
308
- _j.label = 13;
309
- case 13:
310
- if (!(_d < attributeFiles_1.length)) return [3 /*break*/, 16];
311
- attributeKey = attributeFiles_1[_d];
312
- return [4 /*yield*/, datasource.readAttribute(attributeKey)];
313
- case 14:
314
- parsedAttribute = _j.sent();
315
- if (parsedAttribute.archived === true) {
316
- return [3 /*break*/, 15];
317
- }
318
- if (attributeKeysUsedByTag.has(attributeKey) === false && !parsedAttribute.capture) {
319
- return [3 /*break*/, 15];
320
- }
321
- attribute = {
322
- key: attributeKey,
323
- type: parsedAttribute.type,
152
+ }),
153
+ };
154
+ if (featureIsInGroup[featureKey] === true) {
155
+ feature.ranges = featureRanges.get(featureKey);
156
+ }
157
+ if (parsedFeature.variablesSchema) {
158
+ const variableKeys = Object.keys(parsedFeature.variablesSchema);
159
+ feature.variablesSchema = {};
160
+ for (const variableKey of variableKeys) {
161
+ const v = parsedFeature.variablesSchema[variableKey];
162
+ feature.variablesSchema[variableKey] = {
163
+ key: variableKey,
164
+ type: v.type,
165
+ defaultValue: v.defaultValue,
166
+ deprecated: v.deprecated === true ? true : undefined,
167
+ useDefaultWhenDisabled: v.useDefaultWhenDisabled === true ? true : undefined,
168
+ disabledValue: typeof v.disabledValue !== "undefined" ? v.disabledValue : undefined,
324
169
  };
325
- if (parsedAttribute.capture === true) {
326
- attribute.capture = true;
327
- }
328
- attributes.push(attribute);
329
- _j.label = 15;
330
- case 15:
331
- _d++;
332
- return [3 /*break*/, 13];
333
- case 16:
334
- // inflate
335
- if (options.inflate) {
336
- allFeatureKeys = features.map(function (f) { return f.key; });
337
- allSegmentKeys = segments.map(function (s) { return s.key; });
338
- allAttributeKeys = attributes.map(function (a) { return a.key; });
339
- for (i = 0; i < options.inflate; i++) {
340
- _loop_1 = function (featureKey) {
341
- var originalFeature = features.find(function (f) { return f.key === featureKey; });
342
- features.unshift(__assign(__assign({}, originalFeature), { key: "".concat(originalFeature.key, "-").concat(i) }));
343
- };
344
- // feature
345
- for (_e = 0, allFeatureKeys_1 = allFeatureKeys; _e < allFeatureKeys_1.length; _e++) {
346
- featureKey = allFeatureKeys_1[_e];
347
- _loop_1(featureKey);
348
- }
349
- _loop_2 = function (segmentKey) {
350
- var originalSegment = segments.find(function (s) { return s.key === segmentKey; });
351
- segments.unshift(__assign(__assign({}, originalSegment), { key: "".concat(originalSegment.key, "-").concat(i) }));
352
- };
353
- // segment
354
- for (_f = 0, allSegmentKeys_1 = allSegmentKeys; _f < allSegmentKeys_1.length; _f++) {
355
- segmentKey = allSegmentKeys_1[_f];
356
- _loop_2(segmentKey);
357
- }
358
- _loop_3 = function (attributeKey) {
359
- var originalAttribute = attributes.find(function (a) { return a.key === attributeKey; });
360
- attributes.unshift(__assign(__assign({}, originalAttribute), { key: "".concat(originalAttribute.key, "-").concat(i) }));
361
- };
362
- // attribute
363
- for (_g = 0, allAttributeKeys_1 = allAttributeKeys; _g < allAttributeKeys_1.length; _g++) {
364
- attributeKey = allAttributeKeys_1[_g];
365
- _loop_3(attributeKey);
366
- }
367
- }
170
+ }
171
+ }
172
+ if (force) {
173
+ feature.force = force.map((f) => {
174
+ if (f.segments) {
175
+ const extractedSegmentKeys = (0, utils_1.extractSegmentKeysFromGroupSegments)(f.segments);
176
+ extractedSegmentKeys.forEach((segmentKey) => segmentKeysUsedByTag.add(segmentKey));
177
+ f.segments =
178
+ typeof f.segments !== "string" && projectConfig.stringify
179
+ ? JSON.stringify(f.segments)
180
+ : f.segments;
368
181
  }
369
- // schema v2
370
- if (options.schemaVersion === "2") {
371
- datafileContentV2 = {
372
- schemaVersion: "2",
373
- revision: options.revision,
374
- attributes: {},
375
- segments: {},
376
- features: {},
377
- };
378
- datafileContentV2.attributes = attributes.reduce(function (acc, attribute) {
379
- acc[attribute.key] = attribute;
380
- return acc;
381
- }, {});
382
- datafileContentV2.segments = segments.reduce(function (acc, segment) {
383
- acc[segment.key] = segment;
384
- return acc;
385
- }, {});
386
- datafileContentV2.features = features.reduce(function (acc, feature) {
387
- if (Array.isArray(feature.variablesSchema)) {
388
- feature.variablesSchema = feature.variablesSchema.reduce(function (vAcc, variableSchema) {
389
- vAcc[variableSchema.key] = variableSchema;
390
- return vAcc;
391
- }, {});
392
- }
393
- acc[feature.key] = feature;
394
- return acc;
395
- }, {});
396
- return [2 /*return*/, datafileContentV2];
182
+ if (f.conditions) {
183
+ f.conditions =
184
+ typeof f.conditions !== "string" && projectConfig.stringify
185
+ ? JSON.stringify(f.conditions)
186
+ : f.conditions;
397
187
  }
398
- // default behaviour
399
- datafileContent.attributes = attributes;
400
- datafileContent.segments = segments;
401
- datafileContent.features = features;
402
- return [2 /*return*/, datafileContent];
188
+ return f;
189
+ });
403
190
  }
191
+ features.push(feature);
192
+ }
193
+ }
194
+ // segments
195
+ const segments = [];
196
+ const segmentsDirectory = projectConfig.segmentsDirectoryPath;
197
+ if (fs.existsSync(segmentsDirectory)) {
198
+ const segmentFiles = await datasource.listSegments();
199
+ for (const segmentKey of segmentFiles) {
200
+ const parsedSegment = await datasource.readSegment(segmentKey);
201
+ if (parsedSegment.archived === true) {
202
+ continue;
203
+ }
204
+ if (segmentKeysUsedByTag.has(segmentKey) === false) {
205
+ continue;
206
+ }
207
+ const extractedAttributeKeys = (0, utils_1.extractAttributeKeysFromConditions)(parsedSegment.conditions);
208
+ extractedAttributeKeys.forEach((attributeKey) => attributeKeysUsedByTag.add(attributeKey));
209
+ const segment = {
210
+ key: segmentKey,
211
+ conditions: typeof parsedSegment.conditions !== "string" && projectConfig.stringify === true
212
+ ? JSON.stringify(parsedSegment.conditions)
213
+ : parsedSegment.conditions,
214
+ };
215
+ segments.push(segment);
216
+ }
217
+ }
218
+ // attributes
219
+ const attributes = [];
220
+ const attributesDirectory = projectConfig.attributesDirectoryPath;
221
+ if (fs.existsSync(attributesDirectory)) {
222
+ const attributeFiles = await datasource.listAttributes();
223
+ for (const attributeKey of attributeFiles) {
224
+ const parsedAttribute = await datasource.readAttribute(attributeKey);
225
+ if (parsedAttribute.archived === true) {
226
+ continue;
227
+ }
228
+ if (attributeKeysUsedByTag.has(attributeKey) === false) {
229
+ continue;
230
+ }
231
+ const attribute = {
232
+ key: attributeKey,
233
+ type: parsedAttribute.type,
234
+ };
235
+ attributes.push(attribute);
236
+ }
237
+ }
238
+ // inflate
239
+ if (options.inflate && options.inflate >= 2) {
240
+ const allFeatureKeys = features.map((f) => f.key);
241
+ const allSegmentKeys = segments.map((s) => s.key);
242
+ const allAttributeKeys = attributes.map((a) => a.key);
243
+ for (let i = 0; i < options.inflate - 1; i++) {
244
+ // feature
245
+ for (const featureKey of allFeatureKeys) {
246
+ const originalFeature = features.find((f) => f.key === featureKey);
247
+ features.unshift({
248
+ ...originalFeature,
249
+ key: `${originalFeature.key}-${i}`,
250
+ });
251
+ }
252
+ // segment
253
+ for (const segmentKey of allSegmentKeys) {
254
+ const originalSegment = segments.find((s) => s.key === segmentKey);
255
+ segments.unshift({
256
+ ...originalSegment,
257
+ key: `${originalSegment.key}-${i}`,
258
+ });
259
+ }
260
+ // attribute
261
+ for (const attributeKey of allAttributeKeys) {
262
+ const originalAttribute = attributes.find((a) => a.key === attributeKey);
263
+ attributes.unshift({
264
+ ...originalAttribute,
265
+ key: `${originalAttribute.key}-${i}`,
266
+ });
267
+ }
268
+ }
269
+ }
270
+ // schema v1
271
+ if (options.schemaVersion === "1") {
272
+ return (0, convertToV1_1.convertToV1)({
273
+ revision: options.revision,
274
+ projectConfig,
275
+ attributes,
276
+ features,
277
+ segments,
404
278
  });
279
+ }
280
+ // schema v2
281
+ const datafileContentV2 = {
282
+ schemaVersion: "2",
283
+ revision: options.revision,
284
+ segments: {},
285
+ features: {},
286
+ };
287
+ datafileContentV2.segments = segments.reduce((acc, segment) => {
288
+ // key check needed for supporting v1 datafile generation
289
+ if (segment.key) {
290
+ acc[segment.key] = segment;
291
+ delete acc[segment.key].key; // remove key from segment, as it is not needed in v2 datafile
292
+ }
293
+ return acc;
294
+ }, {});
295
+ datafileContentV2.features = features.reduce((acc, feature) => {
296
+ if (!feature.key) {
297
+ return acc;
298
+ }
299
+ const featureKey = feature.key;
300
+ const featureV2 = feature;
301
+ // remove key, as it is not needed in v2 datafile
302
+ delete featureV2.key;
303
+ // remove variablesSchema[key].key
304
+ if (featureV2.variablesSchema) {
305
+ for (const [variableKey, variable] of Object.entries(featureV2.variablesSchema)) {
306
+ if (variable.key) {
307
+ delete featureV2.variablesSchema[variableKey].key;
308
+ }
309
+ }
310
+ }
311
+ acc[featureKey] = featureV2;
312
+ return acc;
313
+ }, {});
314
+ // add feature hashes for change detection
315
+ const segmentHashes = (0, hashes_1.getSegmentHashes)(datafileContentV2.segments);
316
+ Object.keys(datafileContentV2.features).forEach((featureKey) => {
317
+ const hash = (0, hashes_1.generateHashForFeature)(featureKey, datafileContentV2.features, segmentHashes);
318
+ datafileContentV2.features[featureKey].hash = hash;
319
+ // check needed to support --inflate option
320
+ if (existingState.features[featureKey]) {
321
+ existingState.features[featureKey].hash = hash;
322
+ }
405
323
  });
324
+ if (options.revisionFromHash) {
325
+ const datafileHash = (0, hashes_1.generateHashForDatafile)(datafileContentV2);
326
+ datafileContentV2.revision = `${datafileHash}`;
327
+ }
328
+ return datafileContentV2;
406
329
  }
407
330
  //# sourceMappingURL=buildDatafile.js.map