@featurevisor/core 1.5.1 → 1.7.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 (61) hide show
  1. package/.eslintcache +1 -1
  2. package/CHANGELOG.md +22 -0
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/lcov-report/index.html +1 -1
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  6. package/coverage/lcov-report/lib/builder/index.html +1 -1
  7. package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
  8. package/coverage/lcov-report/lib/tester/checkIfObjectsAreEqual.js.html +1 -1
  9. package/coverage/lcov-report/lib/tester/index.html +1 -1
  10. package/coverage/lcov-report/lib/tester/matrix.js.html +1 -1
  11. package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
  12. package/coverage/lcov-report/src/builder/index.html +1 -1
  13. package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
  14. package/coverage/lcov-report/src/tester/checkIfObjectsAreEqual.ts.html +1 -1
  15. package/coverage/lcov-report/src/tester/index.html +1 -1
  16. package/coverage/lcov-report/src/tester/matrix.ts.html +1 -1
  17. package/lib/linter/attributeSchema.d.ts +17 -2
  18. package/lib/linter/attributeSchema.js +13 -11
  19. package/lib/linter/attributeSchema.js.map +1 -1
  20. package/lib/linter/checkPercentageExceedingSlot.d.ts +3 -0
  21. package/lib/linter/checkPercentageExceedingSlot.js +86 -0
  22. package/lib/linter/checkPercentageExceedingSlot.js.map +1 -0
  23. package/lib/linter/conditionSchema.d.ts +2 -2
  24. package/lib/linter/conditionSchema.js +112 -57
  25. package/lib/linter/conditionSchema.js.map +1 -1
  26. package/lib/linter/featureSchema.d.ts +229 -2
  27. package/lib/linter/featureSchema.js +195 -139
  28. package/lib/linter/featureSchema.js.map +1 -1
  29. package/lib/linter/groupSchema.d.ts +32 -2
  30. package/lib/linter/groupSchema.js +28 -97
  31. package/lib/linter/groupSchema.js.map +1 -1
  32. package/lib/linter/lintProject.d.ts +5 -1
  33. package/lib/linter/lintProject.js +213 -139
  34. package/lib/linter/lintProject.js.map +1 -1
  35. package/lib/linter/printError.d.ts +2 -0
  36. package/lib/linter/printError.js +20 -0
  37. package/lib/linter/printError.js.map +1 -0
  38. package/lib/linter/segmentSchema.d.ts +14 -2
  39. package/lib/linter/segmentSchema.js +12 -10
  40. package/lib/linter/segmentSchema.js.map +1 -1
  41. package/lib/linter/testSchema.d.ts +90 -2
  42. package/lib/linter/testSchema.js +49 -38
  43. package/lib/linter/testSchema.js.map +1 -1
  44. package/lib/tester/cliFormat.d.ts +1 -0
  45. package/lib/tester/cliFormat.js +2 -1
  46. package/lib/tester/cliFormat.js.map +1 -1
  47. package/package.json +4 -4
  48. package/src/linter/attributeSchema.ts +11 -9
  49. package/src/linter/checkPercentageExceedingSlot.ts +41 -0
  50. package/src/linter/conditionSchema.ts +120 -97
  51. package/src/linter/featureSchema.ts +241 -177
  52. package/src/linter/groupSchema.ts +38 -54
  53. package/src/linter/lintProject.ts +233 -110
  54. package/src/linter/printError.ts +21 -0
  55. package/src/linter/segmentSchema.ts +10 -8
  56. package/src/linter/testSchema.ts +67 -50
  57. package/src/tester/cliFormat.ts +1 -0
  58. package/lib/linter/printJoiError.d.ts +0 -2
  59. package/lib/linter/printJoiError.js +0 -14
  60. package/lib/linter/printJoiError.js.map +0 -1
  61. package/src/linter/printJoiError.ts +0 -11
@@ -1,142 +1,248 @@
1
1
  // for use in node only
2
- import * as Joi from "joi";
2
+ import * as path from "path";
3
3
 
4
- import { getAttributeJoiSchema } from "./attributeSchema";
5
- import { getConditionsJoiSchema } from "./conditionSchema";
6
- import { getSegmentJoiSchema } from "./segmentSchema";
7
- import { getGroupJoiSchema } from "./groupSchema";
8
- import { getFeatureJoiSchema } from "./featureSchema";
9
- import { getTestsJoiSchema } from "./testSchema";
4
+ import { getAttributeZodSchema } from "./attributeSchema";
5
+ import { getConditionsZodSchema } from "./conditionSchema";
6
+ import { getSegmentZodSchema } from "./segmentSchema";
7
+ import { getGroupZodSchema } from "./groupSchema";
8
+ import { getFeatureZodSchema } from "./featureSchema";
9
+ import { getTestsZodSchema } from "./testSchema";
10
10
 
11
11
  import { checkForCircularDependencyInRequired } from "./checkCircularDependency";
12
- import { printJoiError } from "./printJoiError";
12
+ import { checkForFeatureExceedingGroupSlotPercentage } from "./checkPercentageExceedingSlot";
13
+ import { printZodError } from "./printError";
13
14
  import { Dependencies } from "../dependencies";
15
+ import { CLI_FORMAT_RED, CLI_FORMAT_UNDERLINE } from "../tester/cliFormat";
14
16
 
15
- export async function lintProject(deps: Dependencies): Promise<boolean> {
17
+ export interface LintProjectOptions {
18
+ keyPattern?: string;
19
+ entityType?: string;
20
+ }
21
+
22
+ export async function lintProject(
23
+ deps: Dependencies,
24
+ options: LintProjectOptions = {},
25
+ ): Promise<boolean> {
16
26
  const { projectConfig, datasource } = deps;
17
27
 
18
28
  let hasError = false;
19
29
 
20
- const availableAttributeKeys: string[] = [];
21
- const availableSegmentKeys: string[] = [];
22
- const availableFeatureKeys: string[] = [];
30
+ function getFullPathFromKey(type: string, key: string, relative = false) {
31
+ const fileName = `${key}.${datasource.getExtension()}`;
32
+ let fullPath = "";
33
+
34
+ if (type === "attribute") {
35
+ fullPath = path.join(projectConfig.attributesDirectoryPath, fileName);
36
+ } else if (type === "segment") {
37
+ fullPath = path.join(projectConfig.segmentsDirectoryPath, fileName);
38
+ } else if (type === "feature") {
39
+ fullPath = path.join(projectConfig.featuresDirectoryPath, fileName);
40
+ } else if (type === "group") {
41
+ fullPath = path.join(projectConfig.groupsDirectoryPath, fileName);
42
+ } else if (type === "test") {
43
+ fullPath = path.join(projectConfig.testsDirectoryPath, fileName);
44
+ } else {
45
+ throw new Error(`Unknown type: ${type}`);
46
+ }
47
+
48
+ if (relative) {
49
+ fullPath = path.relative(process.cwd(), fullPath);
50
+ }
51
+
52
+ return fullPath;
53
+ }
54
+
55
+ const keyPattern = options.keyPattern ? new RegExp(options.keyPattern) : null;
56
+
57
+ if (keyPattern) {
58
+ console.log("");
59
+ console.log(`Linting only keys matching pattern: ${keyPattern}`);
60
+ console.log("");
61
+ }
23
62
 
24
63
  // lint attributes
25
64
  const attributes = await datasource.listAttributes();
26
- console.log(`Linting ${attributes.length} attributes...\n`);
27
-
28
- const attributeJoiSchema = getAttributeJoiSchema();
29
-
30
- for (const key of attributes) {
31
- try {
32
- const parsed = await datasource.readAttribute(key);
33
- availableAttributeKeys.push(key);
34
- await attributeJoiSchema.validateAsync(parsed);
35
- } catch (e) {
36
- console.log(" =>", key);
37
- console.log("");
38
-
39
- if (e instanceof Joi.ValidationError) {
40
- printJoiError(e);
41
- } else {
65
+ const attributeZodSchema = getAttributeZodSchema();
66
+
67
+ if (!options.entityType || options.entityType === "attribute") {
68
+ const filteredKeys = !keyPattern
69
+ ? attributes
70
+ : attributes.filter((key) => keyPattern.test(key));
71
+
72
+ if (filteredKeys.length > 0) {
73
+ console.log(`Linting ${filteredKeys.length} attributes...\n`);
74
+ }
75
+
76
+ for (const key of filteredKeys) {
77
+ const fullPath = getFullPathFromKey("attribute", key);
78
+
79
+ try {
80
+ const parsed = await datasource.readAttribute(key);
81
+
82
+ const result = attributeZodSchema.safeParse(parsed);
83
+
84
+ if (!result.success) {
85
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
86
+
87
+ if ("error" in result) {
88
+ printZodError(result.error);
89
+ }
90
+
91
+ hasError = true;
92
+ }
93
+ } catch (e) {
94
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
95
+ console.log("");
42
96
  console.log(e);
43
- }
44
97
 
45
- hasError = true;
98
+ hasError = true;
99
+ }
46
100
  }
47
101
  }
48
102
 
49
103
  // lint segments
50
104
  const segments = await datasource.listSegments();
51
- console.log(`\nLinting ${segments.length} segments...\n`);
52
-
53
- const conditionsJoiSchema = getConditionsJoiSchema(projectConfig, availableAttributeKeys);
54
- const segmentJoiSchema = getSegmentJoiSchema(projectConfig, conditionsJoiSchema);
55
-
56
- for (const key of segments) {
57
- try {
58
- const parsed = await datasource.readSegment(key);
59
- availableSegmentKeys.push(key);
60
- await segmentJoiSchema.validateAsync(parsed);
61
- } catch (e) {
62
- console.log(" =>", key);
63
- console.log("");
64
-
65
- if (e instanceof Joi.ValidationError) {
66
- printJoiError(e);
67
- } else {
105
+ const conditionsZodSchema = getConditionsZodSchema(
106
+ projectConfig,
107
+ attributes as [string, ...string[]],
108
+ );
109
+ const segmentZodSchema = getSegmentZodSchema(projectConfig, conditionsZodSchema);
110
+
111
+ if (!options.entityType || options.entityType === "segment") {
112
+ const filteredKeys = !keyPattern ? segments : segments.filter((key) => keyPattern.test(key));
113
+
114
+ if (filteredKeys.length > 0) {
115
+ console.log(`Linting ${filteredKeys.length} segments...\n`);
116
+ }
117
+
118
+ for (const key of filteredKeys) {
119
+ const fullPath = getFullPathFromKey("segment", key);
120
+
121
+ try {
122
+ const parsed = await datasource.readSegment(key);
123
+
124
+ const result = segmentZodSchema.safeParse(parsed);
125
+
126
+ if (!result.success) {
127
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
128
+
129
+ if ("error" in result) {
130
+ printZodError(result.error);
131
+ }
132
+
133
+ hasError = true;
134
+ }
135
+ } catch (e) {
136
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
137
+ console.log("");
68
138
  console.log(e);
69
- }
70
139
 
71
- hasError = true;
140
+ hasError = true;
141
+ }
72
142
  }
73
143
  }
74
144
 
75
145
  // lint features
76
146
  const features = await datasource.listFeatures();
77
- console.log(`\nLinting ${features.length} features...\n`);
78
-
79
- const featureJoiSchema = getFeatureJoiSchema(
147
+ const featureZodSchema = getFeatureZodSchema(
80
148
  projectConfig,
81
- conditionsJoiSchema,
82
- availableSegmentKeys,
83
- availableFeatureKeys,
149
+ conditionsZodSchema,
150
+ attributes as [string, ...string[]],
151
+ segments as [string, ...string[]],
152
+ features as [string, ...string[]],
84
153
  );
85
154
 
86
- for (const key of features) {
87
- let parsed;
155
+ if (!options.entityType || options.entityType === "feature") {
156
+ const filteredKeys = !keyPattern ? features : features.filter((key) => keyPattern.test(key));
88
157
 
89
- try {
90
- parsed = await datasource.readFeature(key);
91
- availableFeatureKeys.push(key);
158
+ if (filteredKeys.length > 0) {
159
+ console.log(`Linting ${filteredKeys.length} features...\n`);
160
+ }
92
161
 
93
- await featureJoiSchema.validateAsync(parsed);
94
- } catch (e) {
95
- console.log(" =>", key);
96
- console.log("");
162
+ for (const key of filteredKeys) {
163
+ const fullPath = getFullPathFromKey("feature", key);
164
+ let parsed;
97
165
 
98
- if (e instanceof Joi.ValidationError) {
99
- printJoiError(e);
100
- } else {
101
- console.log(e);
102
- }
166
+ try {
167
+ parsed = await datasource.readFeature(key);
103
168
 
104
- hasError = true;
105
- }
169
+ const result = featureZodSchema.safeParse(parsed);
106
170
 
107
- if (parsed && parsed.required) {
108
- try {
109
- await checkForCircularDependencyInRequired(datasource, key, parsed.required);
171
+ if (!result.success) {
172
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
173
+
174
+ if ("error" in result) {
175
+ printZodError(result.error);
176
+ }
177
+
178
+ hasError = true;
179
+ }
110
180
  } catch (e) {
111
- console.log(" =>", key);
112
- console.log(" => Error:", e.message);
181
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
182
+ console.log("");
183
+ console.log(e);
184
+
113
185
  hasError = true;
114
186
  }
187
+
188
+ if (parsed && parsed.required) {
189
+ try {
190
+ await checkForCircularDependencyInRequired(datasource, key, parsed.required);
191
+ } catch (e) {
192
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
193
+ console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`);
194
+ hasError = true;
195
+ }
196
+ }
115
197
  }
116
198
  }
117
199
 
118
200
  // lint groups
119
201
  const groups = await datasource.listGroups();
120
- console.log(`\nLinting ${groups.length} groups...\n`);
121
-
122
- // @TODO: feature it slots can be from availableFeatureKeys only
123
- const groupJoiSchema = getGroupJoiSchema(projectConfig, datasource, availableFeatureKeys);
124
-
125
- for (const key of groups) {
126
- try {
127
- const parsed = await datasource.readGroup(key);
128
- await groupJoiSchema.validateAsync(parsed);
129
- } catch (e) {
130
- console.log(" =>", key);
131
- console.log("");
132
-
133
- if (e instanceof Joi.ValidationError) {
134
- printJoiError(e);
135
- } else {
202
+ const groupZodSchema = getGroupZodSchema(projectConfig, datasource, features);
203
+
204
+ if (!options.entityType || options.entityType === "group") {
205
+ const filteredKeys = !keyPattern ? groups : groups.filter((key) => keyPattern.test(key));
206
+
207
+ if (filteredKeys.length > 0) {
208
+ console.log(`Linting ${filteredKeys.length} groups...\n`);
209
+ }
210
+
211
+ for (const key of filteredKeys) {
212
+ const fullPath = getFullPathFromKey("group", key);
213
+ let parsed;
214
+
215
+ try {
216
+ parsed = await datasource.readGroup(key);
217
+
218
+ const result = groupZodSchema.safeParse(parsed);
219
+
220
+ if (!result.success) {
221
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
222
+
223
+ if ("error" in result) {
224
+ printZodError(result.error);
225
+ }
226
+
227
+ hasError = true;
228
+ }
229
+ } catch (e) {
230
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
231
+ console.log("");
136
232
  console.log(e);
233
+
234
+ hasError = true;
137
235
  }
138
236
 
139
- hasError = true;
237
+ if (parsed) {
238
+ try {
239
+ await checkForFeatureExceedingGroupSlotPercentage(datasource, parsed, features);
240
+ } catch (e) {
241
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
242
+ console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`);
243
+ hasError = true;
244
+ }
245
+ }
140
246
  }
141
247
  }
142
248
 
@@ -144,29 +250,46 @@ export async function lintProject(deps: Dependencies): Promise<boolean> {
144
250
 
145
251
  // lint tests
146
252
  const tests = await datasource.listTests();
147
- console.log(`\nLinting ${tests.length} tests...\n`);
148
253
 
149
- const testsJoiSchema = getTestsJoiSchema(
254
+ const testsZodSchema = getTestsZodSchema(
150
255
  projectConfig,
151
- availableFeatureKeys,
152
- availableSegmentKeys,
256
+ features as [string, ...string[]],
257
+ segments as [string, ...string[]],
153
258
  );
154
259
 
155
- for (const key of tests) {
156
- try {
157
- const parsed = await datasource.readTest(key);
158
- await testsJoiSchema.validateAsync(parsed);
159
- } catch (e) {
160
- console.log(" =>", key);
161
- console.log("");
162
-
163
- if (e instanceof Joi.ValidationError) {
164
- printJoiError(e);
165
- } else {
260
+ if (!options.entityType || options.entityType === "test") {
261
+ const filteredKeys = !keyPattern ? tests : tests.filter((key) => keyPattern.test(key));
262
+
263
+ if (filteredKeys.length > 0) {
264
+ console.log(`Linting ${filteredKeys.length} tests...\n`);
265
+ }
266
+
267
+ for (const key of filteredKeys) {
268
+ const fullPath = getFullPathFromKey("test", key);
269
+
270
+ try {
271
+ const parsed = await datasource.readTest(key);
272
+
273
+ const result = testsZodSchema.safeParse(parsed);
274
+
275
+ if (!result.success) {
276
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
277
+
278
+ if ("error" in result) {
279
+ printZodError(result.error);
280
+
281
+ process.exit(1);
282
+ }
283
+
284
+ hasError = true;
285
+ }
286
+ } catch (e) {
287
+ console.log(CLI_FORMAT_UNDERLINE, fullPath);
288
+ console.log("");
166
289
  console.log(e);
167
- }
168
290
 
169
- hasError = true;
291
+ hasError = true;
292
+ }
170
293
  }
171
294
  }
172
295
 
@@ -0,0 +1,21 @@
1
+ import { ZodError } from "zod";
2
+
3
+ import { CLI_FORMAT_RED } from "../tester/cliFormat";
4
+
5
+ export function printZodError(e: ZodError) {
6
+ const { issues } = e;
7
+
8
+ issues.forEach((issue) => {
9
+ console.error(CLI_FORMAT_RED, ` => Error: ${issue.message}`);
10
+ console.error(" Path:", issue.path.join("."));
11
+
12
+ const receivedValue = (issue as any).received;
13
+ if (typeof receivedValue !== "undefined" && receivedValue !== "undefined") {
14
+ console.error(" Value:", receivedValue);
15
+ }
16
+
17
+ if (issues.length > 1) {
18
+ console.error("");
19
+ }
20
+ });
21
+ }
@@ -1,13 +1,15 @@
1
- import * as Joi from "joi";
1
+ import { z } from "zod";
2
2
 
3
3
  import { ProjectConfig } from "../config";
4
4
 
5
- export function getSegmentJoiSchema(projectConfig: ProjectConfig, conditionsJoiSchema) {
6
- const segmentJoiSchema = Joi.object({
7
- archived: Joi.boolean().optional(),
8
- description: Joi.string().required(),
9
- conditions: conditionsJoiSchema.required(),
10
- });
5
+ export function getSegmentZodSchema(projectConfig: ProjectConfig, conditionsZodSchema) {
6
+ const segmentZodSchema = z
7
+ .object({
8
+ archived: z.boolean().optional(),
9
+ description: z.string(),
10
+ conditions: conditionsZodSchema,
11
+ })
12
+ .strict();
11
13
 
12
- return segmentJoiSchema;
14
+ return segmentZodSchema;
13
15
  }
@@ -1,62 +1,79 @@
1
- import * as Joi from "joi";
1
+ import { z } from "zod";
2
2
 
3
3
  import { ProjectConfig } from "../config";
4
4
 
5
- export function getTestsJoiSchema(
5
+ export function getTestsZodSchema(
6
6
  projectConfig: ProjectConfig,
7
- availableFeatureKeys: string[],
8
- availableSegmentKeys: string[],
7
+ availableFeatureKeys: [string, ...string[]],
8
+ availableSegmentKeys: [string, ...string[]],
9
9
  ) {
10
- const segmentTestJoiSchema = Joi.object({
11
- segment: Joi.string()
12
- .valid(...availableSegmentKeys)
13
- .required(),
14
- assertions: Joi.array().items(
15
- Joi.object({
16
- matrix: Joi.object().optional(), // @TODO: make it stricter
17
- description: Joi.string().optional(),
18
- context: Joi.object(),
19
- expectedToMatch: Joi.boolean(),
20
- }),
21
- ),
22
- });
10
+ const segmentTestZodSchema = z
11
+ .object({
12
+ segment: z.string().refine(
13
+ (value) => availableSegmentKeys.includes(value),
14
+ (value) => ({
15
+ message: `Unknown segment "${value}"`,
16
+ }),
17
+ ),
18
+ assertions: z.array(
19
+ z
20
+ .object({
21
+ matrix: z.record(z.unknown()).optional(), // @TODO: make it stricter
22
+ description: z.string().optional(),
23
+ context: z.record(z.unknown()),
24
+ expectedToMatch: z.boolean(),
25
+ })
26
+ .strict(),
27
+ ),
28
+ })
29
+ .strict();
23
30
 
24
- const featureTestJoiSchema = Joi.object({
25
- feature: Joi.string()
26
- .valid(...availableFeatureKeys)
27
- .required(),
28
- assertions: Joi.array().items(
29
- Joi.object({
30
- matrix: Joi.object().optional(), // @TODO: make it stricter
31
- description: Joi.string().optional(),
32
- at: Joi.alternatives().try(
33
- Joi.number().precision(3).min(0).max(100).required(),
31
+ const featureTestZodSchema = z
32
+ .object({
33
+ feature: z.string().refine(
34
+ (value) => availableFeatureKeys.includes(value),
35
+ (value) => ({
36
+ message: `Unknown feature "${value}"`,
37
+ }),
38
+ ),
39
+ assertions: z.array(
40
+ z
41
+ .object({
42
+ matrix: z.record(z.unknown()).optional(), // @TODO: make it stricter
43
+ description: z.string().optional(),
44
+ at: z.union([
45
+ z.number().min(0).max(100),
34
46
 
35
- // because of supporting matrix
36
- Joi.string().required(),
37
- ),
38
- environment: Joi.string()
39
- .custom((value, helpers) => {
40
- if (value.indexOf("${{") === 0) {
41
- // allow unknown strings for matrix
42
- return value;
43
- }
47
+ // because of supporting matrix
48
+ z.string(),
49
+ ]),
50
+ environment: z.string().refine(
51
+ (value) => {
52
+ if (value.indexOf("${{") === 0) {
53
+ // allow unknown strings for matrix
54
+ return true;
55
+ }
44
56
 
45
- // otherwise only known environments should be passed
46
- if (projectConfig.environments.includes(value)) {
47
- return value;
48
- }
57
+ // otherwise only known environments should be passed
58
+ if (projectConfig.environments.includes(value)) {
59
+ return true;
60
+ }
49
61
 
50
- return helpers.error("any.invalid");
62
+ return false;
63
+ },
64
+ (value) => ({
65
+ message: `Unknown environment "${value}"`,
66
+ }),
67
+ ),
68
+ context: z.record(z.unknown()),
69
+ expectedToBeEnabled: z.boolean(),
70
+ expectedVariation: z.string().optional(),
71
+ expectedVariables: z.record(z.unknown()).optional(),
51
72
  })
52
- .required(),
53
- context: Joi.object().required(),
54
- expectedToBeEnabled: Joi.boolean().required(),
55
- expectedVariation: Joi.alternatives().try(Joi.string(), Joi.number(), Joi.boolean()),
56
- expectedVariables: Joi.object(),
57
- }),
58
- ),
59
- });
73
+ .strict(),
74
+ ),
75
+ })
76
+ .strict();
60
77
 
61
- return Joi.alternatives().try(segmentTestJoiSchema, featureTestJoiSchema);
78
+ return z.union([segmentTestZodSchema, featureTestZodSchema]);
62
79
  }
@@ -2,3 +2,4 @@ export const CLI_FORMAT_RED = "\x1b[31m%s\x1b[0m";
2
2
  export const CLI_FORMAT_GREEN = "\x1b[32m%s\x1b[0m";
3
3
 
4
4
  export const CLI_FORMAT_BOLD = "\x1b[1m%s\x1b[0m";
5
+ export const CLI_FORMAT_UNDERLINE = "\x1b[4m%s\x1b[0m";
@@ -1,2 +0,0 @@
1
- import * as Joi from "joi";
2
- export declare function printJoiError(e: Joi.ValidationError): void;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.printJoiError = void 0;
4
- function printJoiError(e) {
5
- var details = e.details;
6
- details.forEach(function (detail) {
7
- var _a;
8
- console.error(" => Error:", detail.message);
9
- console.error(" => Path:", detail.path.join("."));
10
- console.error(" => Value:", (_a = detail.context) === null || _a === void 0 ? void 0 : _a.value);
11
- });
12
- }
13
- exports.printJoiError = printJoiError;
14
- //# sourceMappingURL=printJoiError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"printJoiError.js","sourceRoot":"","sources":["../../src/linter/printJoiError.ts"],"names":[],"mappings":";;;AAEA,SAAgB,aAAa,CAAC,CAAsB;IAC1C,IAAA,OAAO,GAAK,CAAC,QAAN,CAAO;IAEtB,OAAO,CAAC,OAAO,CAAC,UAAC,MAAM;;QACrB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,MAAA,MAAM,CAAC,OAAO,0CAAE,KAAK,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC;AARD,sCAQC"}
@@ -1,11 +0,0 @@
1
- import * as Joi from "joi";
2
-
3
- export function printJoiError(e: Joi.ValidationError) {
4
- const { details } = e;
5
-
6
- details.forEach((detail) => {
7
- console.error(" => Error:", detail.message);
8
- console.error(" => Path:", detail.path.join("."));
9
- console.error(" => Value:", detail.context?.value);
10
- });
11
- }