@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
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getFeatureZodSchema = getFeatureZodSchema;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const tagRegex = /^[a-z0-9-]+$/;
|
|
6
6
|
function isFlatObject(value) {
|
|
7
|
-
|
|
8
|
-
Object.keys(value).forEach(
|
|
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(
|
|
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
|
-
|
|
20
|
+
let message = `Unknown variable with value: ${variableValue}`;
|
|
21
21
|
if (path.length > 0) {
|
|
22
|
-
|
|
22
|
+
const lastPath = path[path.length - 1];
|
|
23
23
|
if (typeof lastPath === "string") {
|
|
24
|
-
message =
|
|
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
|
|
30
|
-
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:
|
|
40
|
-
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:
|
|
48
|
-
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:
|
|
59
|
-
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:
|
|
70
|
-
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:
|
|
81
|
-
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
|
-
|
|
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:
|
|
90
|
-
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:
|
|
102
|
-
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
|
-
|
|
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:
|
|
111
|
-
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
|
-
|
|
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:
|
|
127
|
-
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:
|
|
136
|
-
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
|
-
|
|
144
|
-
|
|
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(
|
|
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
|
-
|
|
156
|
-
message:
|
|
157
|
-
})
|
|
158
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
253
|
+
not: zod_1.z.array(zod_1.z.lazy(() => groupSegmentZodSchema)),
|
|
172
254
|
})
|
|
173
255
|
.strict(),
|
|
174
256
|
]);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
.union([zod_1.z.boolean(), zod_1.z.array(zod_1.z.string().refine(
|
|
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
|
-
|
|
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(
|
|
276
|
+
.refine((value) => value.length > 0, () => ({
|
|
194
277
|
message: "Must have at least one rule",
|
|
195
|
-
})
|
|
278
|
+
}))
|
|
196
279
|
// duplicate rules
|
|
197
|
-
.refine(
|
|
198
|
-
|
|
280
|
+
.refine((value) => {
|
|
281
|
+
const keys = value.map((v) => v.key);
|
|
199
282
|
return keys.length === new Set(keys).size;
|
|
200
|
-
},
|
|
201
|
-
message: "Duplicate rule keys found: " + value.map(
|
|
202
|
-
})
|
|
283
|
+
}, (value) => ({
|
|
284
|
+
message: "Duplicate rule keys found: " + value.map((v) => v.key).join(", "),
|
|
285
|
+
}))
|
|
203
286
|
// enforce catch-all rule
|
|
204
|
-
.refine(
|
|
287
|
+
.refine((value) => {
|
|
205
288
|
if (!projectConfig.enforceCatchAllRule) {
|
|
206
289
|
return true;
|
|
207
290
|
}
|
|
208
|
-
|
|
291
|
+
const hasCatchAllAsLastRule = value[value.length - 1].segments === "*";
|
|
209
292
|
return hasCatchAllAsLastRule;
|
|
210
|
-
},
|
|
211
|
-
message:
|
|
212
|
-
})
|
|
213
|
-
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
|
|
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(
|
|
261
|
-
message:
|
|
262
|
-
})
|
|
263
|
-
.refine(
|
|
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
|
-
},
|
|
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
|
-
.
|
|
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
|
-
|
|
319
|
-
.
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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(
|
|
344
|
-
|
|
395
|
+
.refine((value) => {
|
|
396
|
+
const variationValues = value.map((v) => v.value);
|
|
345
397
|
return variationValues.length === new Set(variationValues).size;
|
|
346
|
-
},
|
|
347
|
-
message: "Duplicate variation values found: " + value.map(
|
|
348
|
-
})
|
|
398
|
+
}, (value) => ({
|
|
399
|
+
message: "Duplicate variation values found: " + value.map((v) => v.value).join(", "),
|
|
400
|
+
}))
|
|
349
401
|
.optional(),
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
rules: projectConfig.environments === false
|
|
357
|
-
|
|
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(
|
|
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
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
|
460
|
+
// variations
|
|
372
461
|
if (value.variations) {
|
|
373
|
-
value.variations.forEach(
|
|
462
|
+
value.variations.forEach((variation, variationN) => {
|
|
374
463
|
if (!variation.variables) {
|
|
375
464
|
return;
|
|
376
465
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
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
|
}
|