@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,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getFeatureZodSchema = getFeatureZodSchema;
4
- var zod_1 = require("zod");
5
- var tagRegex = /^[a-z0-9-]+$/;
4
+ const zod_1 = require("zod");
5
+ const tagRegex = /^[a-z0-9-]+$/;
6
6
  function isFlatObject(value) {
7
- var isFlat = true;
8
- Object.keys(value).forEach(function (key) {
7
+ let isFlat = true;
8
+ Object.keys(value).forEach((key) => {
9
9
  if (typeof value[key] === "object") {
10
10
  isFlat = false;
11
11
  }
@@ -13,21 +13,21 @@ function isFlatObject(value) {
13
13
  return isFlat;
14
14
  }
15
15
  function isArrayOfStrings(value) {
16
- return Array.isArray(value) && value.every(function (v) { return typeof v === "string"; });
16
+ return Array.isArray(value) && value.every((v) => typeof v === "string");
17
17
  }
18
18
  function superRefineVariableValue(projectConfig, variableSchema, variableValue, path, ctx) {
19
19
  if (!variableSchema) {
20
- var message = "Unknown variable with value: ".concat(variableValue);
20
+ let message = `Unknown variable with value: ${variableValue}`;
21
21
  if (path.length > 0) {
22
- var lastPath = path[path.length - 1];
22
+ const lastPath = path[path.length - 1];
23
23
  if (typeof lastPath === "string") {
24
- message = "Unknown variable \"".concat(lastPath, "\" with value: ").concat(variableValue);
24
+ message = `Unknown variable "${lastPath}" with value: ${variableValue}`;
25
25
  }
26
26
  }
27
27
  ctx.addIssue({
28
28
  code: zod_1.z.ZodIssueCode.custom,
29
- message: message,
30
- path: path,
29
+ message,
30
+ path,
31
31
  });
32
32
  return;
33
33
  }
@@ -36,16 +36,16 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
36
36
  if (typeof variableValue !== "string") {
37
37
  ctx.addIssue({
38
38
  code: zod_1.z.ZodIssueCode.custom,
39
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): ").concat(variableValue),
40
- path: path,
39
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): ${variableValue}`,
40
+ path,
41
41
  });
42
42
  }
43
43
  if (projectConfig.maxVariableStringLength &&
44
44
  variableValue.length > projectConfig.maxVariableStringLength) {
45
45
  ctx.addIssue({
46
46
  code: zod_1.z.ZodIssueCode.custom,
47
- message: "Variable \"".concat(variableSchema.key, "\" value is too long (").concat(variableValue.length, " characters), max length is ").concat(projectConfig.maxVariableStringLength),
48
- path: path,
47
+ message: `Variable "${variableSchema.key}" value is too long (${variableValue.length} characters), max length is ${projectConfig.maxVariableStringLength}`,
48
+ path,
49
49
  });
50
50
  }
51
51
  return;
@@ -55,8 +55,8 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
55
55
  if (typeof variableValue !== "number") {
56
56
  ctx.addIssue({
57
57
  code: zod_1.z.ZodIssueCode.custom,
58
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): ").concat(variableValue),
59
- path: path,
58
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): ${variableValue}`,
59
+ path,
60
60
  });
61
61
  }
62
62
  return;
@@ -66,8 +66,8 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
66
66
  if (typeof variableValue !== "boolean") {
67
67
  ctx.addIssue({
68
68
  code: zod_1.z.ZodIssueCode.custom,
69
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): ").concat(variableValue),
70
- path: path,
69
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): ${variableValue}`,
70
+ path,
71
71
  });
72
72
  }
73
73
  return;
@@ -77,17 +77,17 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
77
77
  if (!Array.isArray(variableValue) || !isArrayOfStrings(variableValue)) {
78
78
  ctx.addIssue({
79
79
  code: zod_1.z.ZodIssueCode.custom,
80
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): \n\n").concat(variableValue, "\n\n"),
81
- path: path,
80
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): \n\n${variableValue}\n\n`,
81
+ path,
82
82
  });
83
83
  }
84
84
  if (projectConfig.maxVariableArrayStringifiedLength) {
85
- var stringified = JSON.stringify(variableValue);
85
+ const stringified = JSON.stringify(variableValue);
86
86
  if (stringified.length > projectConfig.maxVariableArrayStringifiedLength) {
87
87
  ctx.addIssue({
88
88
  code: zod_1.z.ZodIssueCode.custom,
89
- message: "Variable \"".concat(variableSchema.key, "\" array is too long (").concat(stringified.length, " characters), max length is ").concat(projectConfig.maxVariableArrayStringifiedLength),
90
- path: path,
89
+ message: `Variable "${variableSchema.key}" array is too long (${stringified.length} characters), max length is ${projectConfig.maxVariableArrayStringifiedLength}`,
90
+ path,
91
91
  });
92
92
  }
93
93
  }
@@ -98,17 +98,17 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
98
98
  if (typeof variableValue !== "object" || !isFlatObject(variableValue)) {
99
99
  ctx.addIssue({
100
100
  code: zod_1.z.ZodIssueCode.custom,
101
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): \n\n").concat(variableValue, "\n\n"),
102
- path: path,
101
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): \n\n${variableValue}\n\n`,
102
+ path,
103
103
  });
104
104
  }
105
105
  if (projectConfig.maxVariableObjectStringifiedLength) {
106
- var stringified = JSON.stringify(variableValue);
106
+ const stringified = JSON.stringify(variableValue);
107
107
  if (stringified.length > projectConfig.maxVariableObjectStringifiedLength) {
108
108
  ctx.addIssue({
109
109
  code: zod_1.z.ZodIssueCode.custom,
110
- message: "Variable \"".concat(variableSchema.key, "\" object is too long (").concat(stringified.length, " characters), max length is ").concat(projectConfig.maxVariableObjectStringifiedLength),
111
- path: path,
110
+ message: `Variable "${variableSchema.key}" object is too long (${stringified.length} characters), max length is ${projectConfig.maxVariableObjectStringifiedLength}`,
111
+ path,
112
112
  });
113
113
  }
114
114
  }
@@ -119,65 +119,147 @@ function superRefineVariableValue(projectConfig, variableSchema, variableValue,
119
119
  try {
120
120
  JSON.parse(variableValue);
121
121
  if (projectConfig.maxVariableJSONStringifiedLength) {
122
- var stringified = variableValue;
122
+ const stringified = variableValue;
123
123
  if (stringified.length > projectConfig.maxVariableJSONStringifiedLength) {
124
124
  ctx.addIssue({
125
125
  code: zod_1.z.ZodIssueCode.custom,
126
- message: "Variable \"".concat(variableSchema.key, "\" JSON is too long (").concat(stringified.length, " characters), max length is ").concat(projectConfig.maxVariableJSONStringifiedLength),
127
- path: path,
126
+ message: `Variable "${variableSchema.key}" JSON is too long (${stringified.length} characters), max length is ${projectConfig.maxVariableJSONStringifiedLength}`,
127
+ path,
128
128
  });
129
129
  }
130
130
  }
131
+ // eslint-disable-next-line
131
132
  }
132
133
  catch (e) {
133
134
  ctx.addIssue({
134
135
  code: zod_1.z.ZodIssueCode.custom,
135
- message: "Invalid value for variable \"".concat(variableSchema.key, "\" (").concat(variableSchema.type, "): \n\n").concat(variableValue, "\n\n"),
136
- path: path,
136
+ message: `Invalid value for variable "${variableSchema.key}" (${variableSchema.type}): \n\n${variableValue}\n\n`,
137
+ path,
137
138
  });
138
139
  }
139
140
  return;
140
141
  }
141
142
  }
143
+ function refineForce({ ctx, parsedFeature, // eslint-disable-line
144
+ variableSchemaByKey, variationValues, force, pathPrefix, projectConfig, }) {
145
+ force.forEach((f, fN) => {
146
+ // force[n].variation
147
+ if (f.variation) {
148
+ if (variationValues.indexOf(f.variation) === -1) {
149
+ ctx.addIssue({
150
+ code: zod_1.z.ZodIssueCode.custom,
151
+ message: `Unknown variation "${f.variation}" in force`,
152
+ path: [...pathPrefix, fN, "variation"],
153
+ });
154
+ }
155
+ }
156
+ // force[n].variables[key]
157
+ if (f.variables) {
158
+ Object.keys(f.variables).forEach((variableKey) => {
159
+ superRefineVariableValue(projectConfig, variableSchemaByKey[variableKey], f.variables[variableKey], pathPrefix.concat([fN, "variables", variableKey]), ctx);
160
+ });
161
+ }
162
+ });
163
+ }
164
+ function refineRules({ ctx, parsedFeature, variableSchemaByKey, variationValues, rules, pathPrefix, projectConfig, }) {
165
+ rules.forEach((rule, ruleN) => {
166
+ // rules[n].variables[key]
167
+ if (rule.variables) {
168
+ Object.keys(rule.variables).forEach((variableKey) => {
169
+ superRefineVariableValue(projectConfig, variableSchemaByKey[variableKey], rule.variables[variableKey], pathPrefix.concat([ruleN, "variables", variableKey]), ctx);
170
+ });
171
+ }
172
+ // rules[n].variationWeights
173
+ if (rule.variationWeights) {
174
+ if (!parsedFeature.variations) {
175
+ ctx.addIssue({
176
+ code: zod_1.z.ZodIssueCode.custom,
177
+ message: "Variation weights are overridden from rule, but no variations are present in feature.",
178
+ path: pathPrefix.concat([ruleN, "variationWeights"]),
179
+ });
180
+ }
181
+ else {
182
+ const overriddenVariationValues = Object.keys(rule.variationWeights);
183
+ const overriddenVariationWeights = Object.values(rule.variationWeights);
184
+ // unique keys
185
+ if (overriddenVariationValues.length !== new Set(overriddenVariationValues).size) {
186
+ ctx.addIssue({
187
+ code: zod_1.z.ZodIssueCode.custom,
188
+ message: "Duplicate variation values found in variationWeights: " +
189
+ overriddenVariationValues.join(", "),
190
+ path: pathPrefix.concat([ruleN, "variationWeights"]),
191
+ });
192
+ }
193
+ // all original variations must be used
194
+ const missingVariations = variationValues.filter((v) => !overriddenVariationValues.includes(v));
195
+ if (missingVariations.length > 0) {
196
+ ctx.addIssue({
197
+ code: zod_1.z.ZodIssueCode.custom,
198
+ message: "Missing variations: " + missingVariations.join(", "),
199
+ path: pathPrefix.concat([ruleN, "variationWeights"]),
200
+ });
201
+ }
202
+ // unknown variations
203
+ const unknownVariations = overriddenVariationValues.filter((v) => !variationValues.includes(v));
204
+ if (unknownVariations.length > 0) {
205
+ ctx.addIssue({
206
+ code: zod_1.z.ZodIssueCode.custom,
207
+ message: "Variation weights contain unknown variations: " + unknownVariations.join(", "),
208
+ path: pathPrefix.concat([ruleN, "variationWeights"]),
209
+ });
210
+ }
211
+ // weights sum must be 100
212
+ const weightsSum = overriddenVariationWeights.reduce((sum, weight) => sum + weight, 0);
213
+ if (weightsSum !== 100) {
214
+ ctx.addIssue({
215
+ code: zod_1.z.ZodIssueCode.custom,
216
+ message: "Variation weights must sum to 100",
217
+ path: pathPrefix.concat([ruleN, "variationWeights"]),
218
+ });
219
+ }
220
+ }
221
+ }
222
+ });
223
+ }
142
224
  function getFeatureZodSchema(projectConfig, conditionsZodSchema, availableAttributeKeys, availableSegmentKeys, availableFeatureKeys) {
143
- var variationValueZodSchema = zod_1.z.string().min(1);
144
- var variableValueZodSchema = zod_1.z.union([
225
+ const variationValueZodSchema = zod_1.z.string().min(1);
226
+ const variableValueZodSchema = zod_1.z.union([
145
227
  zod_1.z.string(),
146
228
  zod_1.z.number(),
147
229
  zod_1.z.boolean(),
148
230
  zod_1.z.array(zod_1.z.string()),
149
- zod_1.z.record(zod_1.z.unknown()).refine(function (value) {
231
+ zod_1.z.record(zod_1.z.unknown()).refine((value) => {
150
232
  return isFlatObject(value);
151
233
  }, {
152
234
  message: "object is not flat",
153
235
  }),
154
236
  ]);
155
- var plainGroupSegment = zod_1.z.string().refine(function (value) { return value === "*" || availableSegmentKeys.includes(value); }, function (value) { return ({
156
- message: "Unknown segment key \"".concat(value, "\""),
157
- }); });
158
- var andOrNotGroupSegment = zod_1.z.union([
237
+ const plainGroupSegment = zod_1.z.string().refine((value) => value === "*" || availableSegmentKeys.includes(value), (value) => ({
238
+ message: `Unknown segment key "${value}"`,
239
+ }));
240
+ const andOrNotGroupSegment = zod_1.z.union([
159
241
  zod_1.z
160
242
  .object({
161
- and: zod_1.z.array(zod_1.z.lazy(function () { return groupSegmentZodSchema; })),
243
+ and: zod_1.z.array(zod_1.z.lazy(() => groupSegmentZodSchema)),
162
244
  })
163
245
  .strict(),
164
246
  zod_1.z
165
247
  .object({
166
- or: zod_1.z.array(zod_1.z.lazy(function () { return groupSegmentZodSchema; })),
248
+ or: zod_1.z.array(zod_1.z.lazy(() => groupSegmentZodSchema)),
167
249
  })
168
250
  .strict(),
169
251
  zod_1.z
170
252
  .object({
171
- not: zod_1.z.array(zod_1.z.lazy(function () { return groupSegmentZodSchema; })),
253
+ not: zod_1.z.array(zod_1.z.lazy(() => groupSegmentZodSchema)),
172
254
  })
173
255
  .strict(),
174
256
  ]);
175
- var groupSegmentZodSchema = zod_1.z.union([andOrNotGroupSegment, plainGroupSegment]);
176
- var groupSegmentsZodSchema = zod_1.z.union([zod_1.z.array(groupSegmentZodSchema), groupSegmentZodSchema]);
177
- var exposeSchema = zod_1.z
178
- .union([zod_1.z.boolean(), zod_1.z.array(zod_1.z.string().refine(function (value) { return projectConfig.tags.includes(value); }))])
257
+ const groupSegmentZodSchema = zod_1.z.union([andOrNotGroupSegment, plainGroupSegment]);
258
+ const groupSegmentsZodSchema = zod_1.z.union([zod_1.z.array(groupSegmentZodSchema), groupSegmentZodSchema]);
259
+ const exposeSchema = zod_1.z
260
+ .union([zod_1.z.boolean(), zod_1.z.array(zod_1.z.string().refine((value) => projectConfig.tags.includes(value)))])
179
261
  .optional();
180
- var rulesSchema = zod_1.z
262
+ const rulesSchema = zod_1.z
181
263
  .array(zod_1.z
182
264
  .object({
183
265
  key: zod_1.z.string(),
@@ -187,30 +269,31 @@ function getFeatureZodSchema(projectConfig, conditionsZodSchema, availableAttrib
187
269
  enabled: zod_1.z.boolean().optional(),
188
270
  variation: variationValueZodSchema.optional(),
189
271
  variables: zod_1.z.record(variableValueZodSchema).optional(),
272
+ variationWeights: zod_1.z.record(zod_1.z.number().min(0).max(100)).optional(),
190
273
  })
191
274
  .strict())
192
275
  // must have at least one rule
193
- .refine(function (value) { return value.length > 0; }, function () { return ({
276
+ .refine((value) => value.length > 0, () => ({
194
277
  message: "Must have at least one rule",
195
- }); })
278
+ }))
196
279
  // duplicate rules
197
- .refine(function (value) {
198
- var keys = value.map(function (v) { return v.key; });
280
+ .refine((value) => {
281
+ const keys = value.map((v) => v.key);
199
282
  return keys.length === new Set(keys).size;
200
- }, function (value) { return ({
201
- message: "Duplicate rule keys found: " + value.map(function (v) { return v.key; }).join(", "),
202
- }); })
283
+ }, (value) => ({
284
+ message: "Duplicate rule keys found: " + value.map((v) => v.key).join(", "),
285
+ }))
203
286
  // enforce catch-all rule
204
- .refine(function (value) {
287
+ .refine((value) => {
205
288
  if (!projectConfig.enforceCatchAllRule) {
206
289
  return true;
207
290
  }
208
- var hasCatchAllAsLastRule = value[value.length - 1].segments === "*";
291
+ const hasCatchAllAsLastRule = value[value.length - 1].segments === "*";
209
292
  return hasCatchAllAsLastRule;
210
- }, function () { return ({
211
- message: "Missing catch-all rule with `segments: \"*\"` at the end",
212
- }); });
213
- var forceSchema = zod_1.z
293
+ }, () => ({
294
+ message: `Missing catch-all rule with \`segments: "*"\` at the end`,
295
+ }));
296
+ const forceSchema = zod_1.z
214
297
  .array(zod_1.z.union([
215
298
  zod_1.z
216
299
  .object({
@@ -230,41 +313,27 @@ function getFeatureZodSchema(projectConfig, conditionsZodSchema, availableAttrib
230
313
  .strict(),
231
314
  ]))
232
315
  .optional();
233
- var environmentZodSchema = zod_1.z
234
- .object({
235
- expose: exposeSchema,
236
- rules: rulesSchema,
237
- force: forceSchema,
238
- })
239
- .strict();
240
- var allEnvironmentsZodSchema = zod_1.z.never();
241
- if (Array.isArray(projectConfig.environments)) {
242
- var allEnvironmentsSchema_1 = {};
243
- projectConfig.environments.forEach(function (environmentKey) {
244
- allEnvironmentsSchema_1[environmentKey] = environmentZodSchema;
245
- });
246
- allEnvironmentsZodSchema = zod_1.z.object(allEnvironmentsSchema_1).strict();
247
- }
248
- var attributeKeyZodSchema = zod_1.z.string().refine(function (value) { return value === "*" || availableAttributeKeys.includes(value); }, function (value) { return ({
249
- message: "Unknown attribute \"".concat(value, "\""),
250
- }); });
251
- var featureKeyZodSchema = zod_1.z.string().refine(function (value) { return availableFeatureKeys.includes(value); }, function (value) { return ({
252
- message: "Unknown feature \"".concat(value, "\""),
253
- }); });
254
- var featureZodSchema = zod_1.z
316
+ const attributeKeyZodSchema = zod_1.z.string().refine((value) => value === "*" || availableAttributeKeys.includes(value), (value) => ({
317
+ message: `Unknown attribute "${value}"`,
318
+ }));
319
+ const featureKeyZodSchema = zod_1.z.string().refine((value) => availableFeatureKeys.includes(value), (value) => ({
320
+ message: `Unknown feature "${value}"`,
321
+ }));
322
+ const environmentKeys = projectConfig.environments || [];
323
+ const featureZodSchema = zod_1.z
255
324
  .object({
256
325
  archived: zod_1.z.boolean().optional(),
257
326
  deprecated: zod_1.z.boolean().optional(),
258
327
  description: zod_1.z.string(),
259
328
  tags: zod_1.z
260
- .array(zod_1.z.string().refine(function (value) { return tagRegex.test(value); }, function (value) { return ({
261
- message: "Tag \"".concat(value, "\" must be lower cased and alphanumeric, and may contain hyphens."),
262
- }); }))
263
- .refine(function (value) {
329
+ .array(zod_1.z.string().refine((value) => tagRegex.test(value), (value) => ({
330
+ message: `Tag "${value}" must be lower cased and alphanumeric, and may contain hyphens.`,
331
+ })))
332
+ .refine((value) => {
264
333
  return value.length === new Set(value).size;
265
- }, function (value) { return ({
334
+ }, (value) => ({
266
335
  message: "Duplicate tags found: " + value.join(", "),
267
- }); }),
336
+ })),
268
337
  required: zod_1.z
269
338
  .array(zod_1.z.union([
270
339
  featureKeyZodSchema,
@@ -285,124 +354,196 @@ function getFeatureZodSchema(projectConfig, conditionsZodSchema, availableAttrib
285
354
  })
286
355
  .strict(),
287
356
  ]),
288
- // @TODO: in v2, this will become a dictionary
289
357
  variablesSchema: zod_1.z
290
- .array(zod_1.z
358
+ .record(zod_1.z
291
359
  .object({
292
360
  deprecated: zod_1.z.boolean().optional(),
293
- key: zod_1.z
294
- .string()
295
- .min(1)
296
- .refine(function (value) { return value !== "variation"; }, {
297
- message: "variable key cannot be \"variation\"",
298
- }),
299
361
  type: zod_1.z.enum(["string", "integer", "boolean", "double", "array", "object", "json"]),
300
362
  description: zod_1.z.string().optional(),
301
363
  defaultValue: variableValueZodSchema,
364
+ useDefaultWhenDisabled: zod_1.z.boolean().optional(),
365
+ disabledValue: variableValueZodSchema.optional(),
302
366
  })
303
367
  .strict())
304
- .refine(function (value) {
305
- var keys = value.map(function (v) { return v.key; });
306
- return keys.length === new Set(keys).size;
307
- }, function (value) { return ({
308
- message: "Duplicate variable keys found: " + value.map(function (v) { return v.key; }).join(", "),
309
- }); })
310
368
  .optional(),
369
+ disabledVariationValue: variationValueZodSchema.optional(),
311
370
  variations: zod_1.z
312
371
  .array(zod_1.z
313
372
  .object({
314
373
  description: zod_1.z.string().optional(),
315
374
  value: variationValueZodSchema,
316
375
  weight: zod_1.z.number().min(0).max(100),
317
- variables: zod_1.z
318
- .array(zod_1.z
319
- .object({
320
- key: zod_1.z.string().min(1),
321
- value: variableValueZodSchema,
322
- overrides: zod_1.z
323
- .array(zod_1.z.union([
324
- zod_1.z
325
- .object({
326
- conditions: conditionsZodSchema,
327
- value: variableValueZodSchema,
328
- })
329
- .strict(),
330
- zod_1.z
331
- .object({
332
- segments: groupSegmentsZodSchema,
333
- value: variableValueZodSchema,
334
- })
335
- .strict(),
336
- ]))
337
- .optional(),
338
- })
339
- .strict())
376
+ variables: zod_1.z.record(variableValueZodSchema).optional(),
377
+ variableOverrides: zod_1.z
378
+ .record(zod_1.z.array(zod_1.z.union([
379
+ zod_1.z
380
+ .object({
381
+ conditions: conditionsZodSchema,
382
+ value: variableValueZodSchema,
383
+ })
384
+ .strict(),
385
+ zod_1.z
386
+ .object({
387
+ segments: groupSegmentsZodSchema,
388
+ value: variableValueZodSchema,
389
+ })
390
+ .strict(),
391
+ ])))
340
392
  .optional(),
341
393
  })
342
394
  .strict())
343
- .refine(function (value) {
344
- var variationValues = value.map(function (v) { return v.value; });
395
+ .refine((value) => {
396
+ const variationValues = value.map((v) => v.value);
345
397
  return variationValues.length === new Set(variationValues).size;
346
- }, function (value) { return ({
347
- message: "Duplicate variation values found: " + value.map(function (v) { return v.value; }).join(", "),
348
- }); })
398
+ }, (value) => ({
399
+ message: "Duplicate variation values found: " + value.map((v) => v.value).join(", "),
400
+ }))
349
401
  .optional(),
350
- // with environments
351
- environments: Array.isArray(projectConfig.environments)
352
- ? allEnvironmentsZodSchema
353
- : zod_1.z.never().optional(),
354
- // no environments
355
- expose: projectConfig.environments === false ? exposeSchema : zod_1.z.never().optional(),
356
- rules: projectConfig.environments === false ? rulesSchema : zod_1.z.never().optional(),
357
- force: projectConfig.environments === false ? forceSchema : zod_1.z.never().optional(),
402
+ expose: projectConfig.environments === false
403
+ ? exposeSchema.optional()
404
+ : zod_1.z.record(zod_1.z.enum(environmentKeys), exposeSchema).optional(),
405
+ force: projectConfig.environments === false
406
+ ? forceSchema
407
+ : zod_1.z.record(zod_1.z.enum(environmentKeys), forceSchema).optional(),
408
+ rules: projectConfig.environments === false
409
+ ? rulesSchema
410
+ : zod_1.z.record(zod_1.z.enum(environmentKeys), rulesSchema),
358
411
  })
359
412
  .strict()
360
- .superRefine(function (value, ctx) {
413
+ .superRefine((value, ctx) => {
414
+ // disabledVariationValue
415
+ if (value.disabledVariationValue) {
416
+ if (!value.variations) {
417
+ ctx.addIssue({
418
+ code: zod_1.z.ZodIssueCode.custom,
419
+ message: "Disabled variation value is set, but no variations are present in feature.",
420
+ path: ["disabledVariationValue"],
421
+ });
422
+ }
423
+ else {
424
+ const variationValues = value.variations.map((v) => v.value);
425
+ if (variationValues.indexOf(value.disabledVariationValue) === -1) {
426
+ ctx.addIssue({
427
+ code: zod_1.z.ZodIssueCode.custom,
428
+ message: `Disabled variation value "${value.disabledVariationValue}" is not one of the defined variations: ${variationValues.join(", ")}`,
429
+ path: ["disabledVariationValue"],
430
+ });
431
+ }
432
+ }
433
+ }
361
434
  if (!value.variablesSchema) {
362
435
  return;
363
436
  }
364
- var allVariablesSchema = value.variablesSchema;
365
- var variableSchemaByKey = {};
366
- // variablesSchema[n].defaultValue
367
- allVariablesSchema.forEach(function (variableSchema, n) {
368
- variableSchemaByKey[variableSchema.key] = variableSchema;
369
- superRefineVariableValue(projectConfig, variableSchema, variableSchema.defaultValue, ["variablesSchema", n, "defaultValue"], ctx);
437
+ const variableSchemaByKey = value.variablesSchema;
438
+ const variationValues = [];
439
+ if (value.variations) {
440
+ value.variations.forEach((variation) => {
441
+ variationValues.push(variation.value);
442
+ });
443
+ }
444
+ // variablesSchema[key]
445
+ const variableKeys = Object.keys(variableSchemaByKey);
446
+ variableKeys.forEach((variableKey) => {
447
+ const variableSchema = variableSchemaByKey[variableKey];
448
+ if (variableKey === "variation") {
449
+ ctx.addIssue({
450
+ code: zod_1.z.ZodIssueCode.custom,
451
+ message: `Variable key "${variableKey}" is reserved and cannot be used.`,
452
+ path: ["variablesSchema", variableKey],
453
+ });
454
+ }
455
+ // defaultValue
456
+ superRefineVariableValue(projectConfig, variableSchema, variableSchema.defaultValue, ["variablesSchema", variableKey, "defaultValue"], ctx);
457
+ // disabledValue
458
+ superRefineVariableValue(projectConfig, variableSchema, variableSchema.defaultValue, ["variablesSchema", variableKey, "disabledValue"], ctx);
370
459
  });
371
- // variations[n].variables[n].value
460
+ // variations
372
461
  if (value.variations) {
373
- value.variations.forEach(function (variation, variationN) {
462
+ value.variations.forEach((variation, variationN) => {
374
463
  if (!variation.variables) {
375
464
  return;
376
465
  }
377
- variation.variables.forEach(function (variable, variableN) {
378
- superRefineVariableValue(projectConfig, variableSchemaByKey[variable.key], variable.value, ["variations", variationN, "variables", variableN, "value"], ctx);
379
- // variations[n].variables[n].overrides[n].value
380
- if (variable.overrides) {
381
- variable.overrides.forEach(function (override, overrideN) {
382
- superRefineVariableValue(projectConfig, variableSchemaByKey[variable.key], override.value, [
383
- "variations",
384
- variationN,
385
- "variables",
386
- variableN,
387
- "overrides",
388
- overrideN,
389
- "value",
390
- ], ctx);
391
- });
466
+ // variations[n].variables[key]
467
+ for (const variableKey of Object.keys(variation.variables)) {
468
+ const variableValue = variation.variables[variableKey];
469
+ superRefineVariableValue(projectConfig, variableSchemaByKey[variableKey], variableValue, ["variations", variationN, "variables", variableKey], ctx);
470
+ // variations[n].variableOverrides[n].value
471
+ if (variation.variableOverrides) {
472
+ for (const variableKey of Object.keys(variation.variableOverrides)) {
473
+ const overrides = variation.variableOverrides[variableKey];
474
+ if (Array.isArray(overrides)) {
475
+ overrides.forEach((override, overrideN) => {
476
+ superRefineVariableValue(projectConfig, variableSchemaByKey[variableKey], override.value, [
477
+ "variations",
478
+ variationN,
479
+ "variableOverrides",
480
+ variableKey,
481
+ overrideN,
482
+ "value",
483
+ ], ctx);
484
+ });
485
+ }
486
+ }
392
487
  }
393
- });
488
+ }
394
489
  });
395
490
  }
396
- // environments[key].rules[n].variables[key]
397
- Object.keys(value.environments).forEach(function (environmentKey) {
398
- value.environments[environmentKey].rules.forEach(function (rule, ruleN) {
399
- if (rule.variables) {
400
- Object.keys(rule.variables).forEach(function (variableKey) {
401
- superRefineVariableValue(projectConfig, variableSchemaByKey[variableKey], rule.variables[variableKey], ["environments", environmentKey, "rules", ruleN, "variables", variableKey], ctx);
491
+ if (environmentKeys.length > 0) {
492
+ // with environments
493
+ for (const environmentKey of environmentKeys) {
494
+ // rules
495
+ if (value.rules && value.rules[environmentKey]) {
496
+ refineRules({
497
+ parsedFeature: value,
498
+ variableSchemaByKey,
499
+ variationValues,
500
+ rules: value.rules[environmentKey],
501
+ pathPrefix: ["rules", environmentKey],
502
+ ctx,
503
+ projectConfig,
402
504
  });
403
505
  }
404
- });
405
- });
506
+ // force
507
+ if (value.force && value.force[environmentKey]) {
508
+ refineForce({
509
+ parsedFeature: value,
510
+ variableSchemaByKey,
511
+ variationValues,
512
+ force: value.force[environmentKey],
513
+ pathPrefix: ["force", environmentKey],
514
+ ctx,
515
+ projectConfig,
516
+ });
517
+ }
518
+ }
519
+ }
520
+ else {
521
+ // no environments
522
+ // rules
523
+ if (value.rules) {
524
+ refineRules({
525
+ parsedFeature: value,
526
+ variableSchemaByKey,
527
+ variationValues,
528
+ rules: value.rules,
529
+ pathPrefix: ["rules"],
530
+ ctx,
531
+ projectConfig,
532
+ });
533
+ }
534
+ // force
535
+ if (value.force) {
536
+ refineForce({
537
+ parsedFeature: value,
538
+ variableSchemaByKey,
539
+ variationValues,
540
+ force: value.force,
541
+ pathPrefix: ["force"],
542
+ ctx,
543
+ projectConfig,
544
+ });
545
+ }
546
+ }
406
547
  });
407
548
  return featureZodSchema;
408
549
  }