@featurevisor/core
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [1.7.0](https://github.com/featurevisor/featurevisor/compare/v1.6.0...v1.7.0) (2024-02-14) | ||
### Features | ||
* lint by key pattern and entity type ([#261](https://github.com/featurevisor/featurevisor/issues/261)) ([f4ab707](https://github.com/featurevisor/featurevisor/commit/f4ab707abc32660765d72be64bec7bedf83fa94e)) | ||
# [1.6.0](https://github.com/featurevisor/featurevisor/compare/v1.5.1...v1.6.0) (2024-02-11) | ||
@@ -8,0 +19,0 @@ |
import { Dependencies } from "../dependencies"; | ||
export declare function lintProject(deps: Dependencies): Promise<boolean>; | ||
export interface LintProjectOptions { | ||
keyPattern?: string; | ||
entityType?: string; | ||
} | ||
export declare function lintProject(deps: Dependencies, options?: LintProjectOptions): Promise<boolean>; |
@@ -52,3 +52,4 @@ "use strict"; | ||
var cliFormat_1 = require("../tester/cliFormat"); | ||
function lintProject(deps) { | ||
function lintProject(deps, options) { | ||
if (options === void 0) { options = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -82,3 +83,3 @@ function getFullPathFromKey(type, key, relative) { | ||
} | ||
var projectConfig, datasource, hasError, availableAttributeKeys, availableSegmentKeys, availableFeatureKeys, attributes, attributeZodSchema, _i, attributes_1, key, fullPath, parsed, result, e_1, segments, conditionsZodSchema, segmentZodSchema, _a, segments_1, key, fullPath, parsed, result, e_2, features, featureZodSchema, _b, features_1, key, fullPath, parsed, result, e_3, e_4, groups, groupZodSchema, _c, groups_1, key, fullPath, parsed, result, e_5, e_6, tests, testsZodSchema, _d, tests_1, key, fullPath, parsed, result, e_7; | ||
var projectConfig, datasource, hasError, keyPattern, attributes, attributeZodSchema, filteredKeys, _i, filteredKeys_1, key, fullPath, parsed, result, e_1, segments, conditionsZodSchema, segmentZodSchema, filteredKeys, _a, filteredKeys_2, key, fullPath, parsed, result, e_2, features, featureZodSchema, filteredKeys, _b, filteredKeys_3, key, fullPath, parsed, result, e_3, e_4, groups, groupZodSchema, filteredKeys, _c, filteredKeys_4, key, fullPath, parsed, result, e_5, e_6, tests, testsZodSchema, filteredKeys, _d, filteredKeys_5, key, fullPath, parsed, result, e_7; | ||
return __generator(this, function (_e) { | ||
@@ -89,15 +90,24 @@ switch (_e.label) { | ||
hasError = false; | ||
availableAttributeKeys = []; | ||
availableSegmentKeys = []; | ||
availableFeatureKeys = []; | ||
keyPattern = options.keyPattern ? new RegExp(options.keyPattern) : null; | ||
if (keyPattern) { | ||
console.log(""); | ||
console.log("Linting only keys matching pattern: ".concat(keyPattern)); | ||
console.log(""); | ||
} | ||
return [4 /*yield*/, datasource.listAttributes()]; | ||
case 1: | ||
attributes = _e.sent(); | ||
console.log("Linting ".concat(attributes.length, " attributes...\n")); | ||
attributeZodSchema = (0, attributeSchema_1.getAttributeZodSchema)(); | ||
_i = 0, attributes_1 = attributes; | ||
if (!(!options.entityType || options.entityType === "attribute")) return [3 /*break*/, 7]; | ||
filteredKeys = !keyPattern | ||
? attributes | ||
: attributes.filter(function (key) { return keyPattern.test(key); }); | ||
if (filteredKeys.length > 0) { | ||
console.log("Linting ".concat(filteredKeys.length, " attributes...\n")); | ||
} | ||
_i = 0, filteredKeys_1 = filteredKeys; | ||
_e.label = 2; | ||
case 2: | ||
if (!(_i < attributes_1.length)) return [3 /*break*/, 7]; | ||
key = attributes_1[_i]; | ||
if (!(_i < filteredKeys_1.length)) return [3 /*break*/, 7]; | ||
key = filteredKeys_1[_i]; | ||
fullPath = getFullPathFromKey("attribute", key); | ||
@@ -110,3 +120,2 @@ _e.label = 3; | ||
parsed = _e.sent(); | ||
availableAttributeKeys.push(key); | ||
result = attributeZodSchema.safeParse(parsed); | ||
@@ -134,10 +143,14 @@ if (!result.success) { | ||
segments = _e.sent(); | ||
console.log("\nLinting ".concat(segments.length, " segments...\n")); | ||
conditionsZodSchema = (0, conditionSchema_1.getConditionsZodSchema)(projectConfig, availableAttributeKeys); | ||
conditionsZodSchema = (0, conditionSchema_1.getConditionsZodSchema)(projectConfig, attributes); | ||
segmentZodSchema = (0, segmentSchema_1.getSegmentZodSchema)(projectConfig, conditionsZodSchema); | ||
_a = 0, segments_1 = segments; | ||
if (!(!options.entityType || options.entityType === "segment")) return [3 /*break*/, 14]; | ||
filteredKeys = !keyPattern ? segments : segments.filter(function (key) { return keyPattern.test(key); }); | ||
if (filteredKeys.length > 0) { | ||
console.log("Linting ".concat(filteredKeys.length, " segments...\n")); | ||
} | ||
_a = 0, filteredKeys_2 = filteredKeys; | ||
_e.label = 9; | ||
case 9: | ||
if (!(_a < segments_1.length)) return [3 /*break*/, 14]; | ||
key = segments_1[_a]; | ||
if (!(_a < filteredKeys_2.length)) return [3 /*break*/, 14]; | ||
key = filteredKeys_2[_a]; | ||
fullPath = getFullPathFromKey("segment", key); | ||
@@ -150,3 +163,2 @@ _e.label = 10; | ||
parsed = _e.sent(); | ||
availableSegmentKeys.push(key); | ||
result = segmentZodSchema.safeParse(parsed); | ||
@@ -174,9 +186,13 @@ if (!result.success) { | ||
features = _e.sent(); | ||
console.log("\nLinting ".concat(features.length, " features...\n")); | ||
featureZodSchema = (0, featureSchema_1.getFeatureZodSchema)(projectConfig, conditionsZodSchema, availableAttributeKeys, availableSegmentKeys, features); | ||
_b = 0, features_1 = features; | ||
featureZodSchema = (0, featureSchema_1.getFeatureZodSchema)(projectConfig, conditionsZodSchema, attributes, segments, features); | ||
if (!(!options.entityType || options.entityType === "feature")) return [3 /*break*/, 25]; | ||
filteredKeys = !keyPattern ? features : features.filter(function (key) { return keyPattern.test(key); }); | ||
if (filteredKeys.length > 0) { | ||
console.log("Linting ".concat(filteredKeys.length, " features...\n")); | ||
} | ||
_b = 0, filteredKeys_3 = filteredKeys; | ||
_e.label = 16; | ||
case 16: | ||
if (!(_b < features_1.length)) return [3 /*break*/, 25]; | ||
key = features_1[_b]; | ||
if (!(_b < filteredKeys_3.length)) return [3 /*break*/, 25]; | ||
key = filteredKeys_3[_b]; | ||
fullPath = getFullPathFromKey("feature", key); | ||
@@ -190,3 +206,2 @@ parsed = void 0; | ||
parsed = _e.sent(); | ||
availableFeatureKeys.push(key); | ||
result = featureZodSchema.safeParse(parsed); | ||
@@ -229,9 +244,13 @@ if (!result.success) { | ||
groups = _e.sent(); | ||
console.log("\nLinting ".concat(groups.length, " groups...\n")); | ||
groupZodSchema = (0, groupSchema_1.getGroupZodSchema)(projectConfig, datasource, availableFeatureKeys); | ||
_c = 0, groups_1 = groups; | ||
groupZodSchema = (0, groupSchema_1.getGroupZodSchema)(projectConfig, datasource, features); | ||
if (!(!options.entityType || options.entityType === "group")) return [3 /*break*/, 36]; | ||
filteredKeys = !keyPattern ? groups : groups.filter(function (key) { return keyPattern.test(key); }); | ||
if (filteredKeys.length > 0) { | ||
console.log("Linting ".concat(filteredKeys.length, " groups...\n")); | ||
} | ||
_c = 0, filteredKeys_4 = filteredKeys; | ||
_e.label = 27; | ||
case 27: | ||
if (!(_c < groups_1.length)) return [3 /*break*/, 36]; | ||
key = groups_1[_c]; | ||
if (!(_c < filteredKeys_4.length)) return [3 /*break*/, 36]; | ||
key = filteredKeys_4[_c]; | ||
fullPath = getFullPathFromKey("group", key); | ||
@@ -266,3 +285,3 @@ parsed = void 0; | ||
_e.trys.push([32, 34, , 35]); | ||
return [4 /*yield*/, (0, checkPercentageExceedingSlot_1.checkForFeatureExceedingGroupSlotPercentage)(datasource, parsed, availableFeatureKeys)]; | ||
return [4 /*yield*/, (0, checkPercentageExceedingSlot_1.checkForFeatureExceedingGroupSlotPercentage)(datasource, parsed, features)]; | ||
case 33: | ||
@@ -283,9 +302,13 @@ _e.sent(); | ||
tests = _e.sent(); | ||
console.log("\nLinting ".concat(tests.length, " tests...\n")); | ||
testsZodSchema = (0, testSchema_1.getTestsZodSchema)(projectConfig, availableFeatureKeys, availableSegmentKeys); | ||
_d = 0, tests_1 = tests; | ||
testsZodSchema = (0, testSchema_1.getTestsZodSchema)(projectConfig, features, segments); | ||
if (!(!options.entityType || options.entityType === "test")) return [3 /*break*/, 43]; | ||
filteredKeys = !keyPattern ? tests : tests.filter(function (key) { return keyPattern.test(key); }); | ||
if (filteredKeys.length > 0) { | ||
console.log("Linting ".concat(filteredKeys.length, " tests...\n")); | ||
} | ||
_d = 0, filteredKeys_5 = filteredKeys; | ||
_e.label = 38; | ||
case 38: | ||
if (!(_d < tests_1.length)) return [3 /*break*/, 43]; | ||
key = tests_1[_d]; | ||
if (!(_d < filteredKeys_5.length)) return [3 /*break*/, 43]; | ||
key = filteredKeys_5[_d]; | ||
fullPath = getFullPathFromKey("test", key); | ||
@@ -292,0 +315,0 @@ _e.label = 39; |
{ | ||
"name": "@featurevisor/core", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"description": "Core package of Featurevisor for Node.js usage", | ||
@@ -60,3 +60,3 @@ "main": "lib/index.js", | ||
}, | ||
"gitHead": "9d9a317843b028cc68ec0ff4ce060fe1404368d8" | ||
"gitHead": "c258fe5fd1c1ea78798a37a0866e574f5a29afdc" | ||
} |
@@ -17,3 +17,11 @@ // for use in node only | ||
export async function lintProject(deps: Dependencies): Promise<boolean> { | ||
export interface LintProjectOptions { | ||
keyPattern?: string; | ||
entityType?: string; | ||
} | ||
export async function lintProject( | ||
deps: Dependencies, | ||
options: LintProjectOptions = {}, | ||
): Promise<boolean> { | ||
const { projectConfig, datasource } = deps; | ||
@@ -23,6 +31,2 @@ | ||
const availableAttributeKeys: string[] = []; | ||
const availableSegmentKeys: string[] = []; | ||
const availableFeatureKeys: string[] = []; | ||
function getFullPathFromKey(type: string, key: string, relative = false) { | ||
@@ -53,32 +57,47 @@ const fileName = `${key}.${datasource.getExtension()}`; | ||
const keyPattern = options.keyPattern ? new RegExp(options.keyPattern) : null; | ||
if (keyPattern) { | ||
console.log(""); | ||
console.log(`Linting only keys matching pattern: ${keyPattern}`); | ||
console.log(""); | ||
} | ||
// lint attributes | ||
const attributes = await datasource.listAttributes(); | ||
console.log(`Linting ${attributes.length} attributes...\n`); | ||
const attributeZodSchema = getAttributeZodSchema(); | ||
for (const key of attributes) { | ||
const fullPath = getFullPathFromKey("attribute", key); | ||
if (!options.entityType || options.entityType === "attribute") { | ||
const filteredKeys = !keyPattern | ||
? attributes | ||
: attributes.filter((key) => keyPattern.test(key)); | ||
try { | ||
const parsed = await datasource.readAttribute(key); | ||
availableAttributeKeys.push(key); | ||
if (filteredKeys.length > 0) { | ||
console.log(`Linting ${filteredKeys.length} attributes...\n`); | ||
} | ||
const result = attributeZodSchema.safeParse(parsed); | ||
for (const key of filteredKeys) { | ||
const fullPath = getFullPathFromKey("attribute", key); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
try { | ||
const parsed = await datasource.readAttribute(key); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
const result = attributeZodSchema.safeParse(parsed); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
@@ -89,34 +108,39 @@ } | ||
const segments = await datasource.listSegments(); | ||
console.log(`\nLinting ${segments.length} segments...\n`); | ||
const conditionsZodSchema = getConditionsZodSchema( | ||
projectConfig, | ||
availableAttributeKeys as [string, ...string[]], | ||
attributes as [string, ...string[]], | ||
); | ||
const segmentZodSchema = getSegmentZodSchema(projectConfig, conditionsZodSchema); | ||
for (const key of segments) { | ||
const fullPath = getFullPathFromKey("segment", key); | ||
if (!options.entityType || options.entityType === "segment") { | ||
const filteredKeys = !keyPattern ? segments : segments.filter((key) => keyPattern.test(key)); | ||
try { | ||
const parsed = await datasource.readSegment(key); | ||
availableSegmentKeys.push(key); | ||
if (filteredKeys.length > 0) { | ||
console.log(`Linting ${filteredKeys.length} segments...\n`); | ||
} | ||
const result = segmentZodSchema.safeParse(parsed); | ||
for (const key of filteredKeys) { | ||
const fullPath = getFullPathFromKey("segment", key); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
try { | ||
const parsed = await datasource.readSegment(key); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
const result = segmentZodSchema.safeParse(parsed); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
@@ -127,47 +151,52 @@ } | ||
const features = await datasource.listFeatures(); | ||
console.log(`\nLinting ${features.length} features...\n`); | ||
const featureZodSchema = getFeatureZodSchema( | ||
projectConfig, | ||
conditionsZodSchema, | ||
availableAttributeKeys as [string, ...string[]], | ||
availableSegmentKeys as [string, ...string[]], | ||
attributes as [string, ...string[]], | ||
segments as [string, ...string[]], | ||
features as [string, ...string[]], | ||
); | ||
for (const key of features) { | ||
const fullPath = getFullPathFromKey("feature", key); | ||
let parsed; | ||
if (!options.entityType || options.entityType === "feature") { | ||
const filteredKeys = !keyPattern ? features : features.filter((key) => keyPattern.test(key)); | ||
try { | ||
parsed = await datasource.readFeature(key); | ||
availableFeatureKeys.push(key); | ||
if (filteredKeys.length > 0) { | ||
console.log(`Linting ${filteredKeys.length} features...\n`); | ||
} | ||
const result = featureZodSchema.safeParse(parsed); | ||
for (const key of filteredKeys) { | ||
const fullPath = getFullPathFromKey("feature", key); | ||
let parsed; | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
try { | ||
parsed = await datasource.readFeature(key); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
const result = featureZodSchema.safeParse(parsed); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
hasError = true; | ||
} | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
if (parsed && parsed.required) { | ||
try { | ||
await checkForCircularDependencyInRequired(datasource, key, parsed.required); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
if (parsed && parsed.required) { | ||
try { | ||
await checkForCircularDependencyInRequired(datasource, key, parsed.required); | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`); | ||
hasError = true; | ||
} | ||
} | ||
} | ||
@@ -178,41 +207,46 @@ } | ||
const groups = await datasource.listGroups(); | ||
console.log(`\nLinting ${groups.length} groups...\n`); | ||
const groupZodSchema = getGroupZodSchema(projectConfig, datasource, features); | ||
// @TODO: feature it slots can be from availableFeatureKeys only | ||
const groupZodSchema = getGroupZodSchema(projectConfig, datasource, availableFeatureKeys); | ||
if (!options.entityType || options.entityType === "group") { | ||
const filteredKeys = !keyPattern ? groups : groups.filter((key) => keyPattern.test(key)); | ||
for (const key of groups) { | ||
const fullPath = getFullPathFromKey("group", key); | ||
let parsed; | ||
if (filteredKeys.length > 0) { | ||
console.log(`Linting ${filteredKeys.length} groups...\n`); | ||
} | ||
try { | ||
parsed = await datasource.readGroup(key); | ||
for (const key of filteredKeys) { | ||
const fullPath = getFullPathFromKey("group", key); | ||
let parsed; | ||
const result = groupZodSchema.safeParse(parsed); | ||
try { | ||
parsed = await datasource.readGroup(key); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
const result = groupZodSchema.safeParse(parsed); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
} | ||
hasError = true; | ||
} | ||
if (parsed) { | ||
try { | ||
await checkForFeatureExceedingGroupSlotPercentage(datasource, parsed, availableFeatureKeys); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
if (parsed) { | ||
try { | ||
await checkForFeatureExceedingGroupSlotPercentage(datasource, parsed, features); | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(CLI_FORMAT_RED, ` => Error: ${e.message}`); | ||
hasError = true; | ||
} | ||
} | ||
} | ||
@@ -225,35 +259,42 @@ } | ||
const tests = await datasource.listTests(); | ||
console.log(`\nLinting ${tests.length} tests...\n`); | ||
const testsZodSchema = getTestsZodSchema( | ||
projectConfig, | ||
availableFeatureKeys as [string, ...string[]], | ||
availableSegmentKeys as [string, ...string[]], | ||
features as [string, ...string[]], | ||
segments as [string, ...string[]], | ||
); | ||
for (const key of tests) { | ||
const fullPath = getFullPathFromKey("test", key); | ||
if (!options.entityType || options.entityType === "test") { | ||
const filteredKeys = !keyPattern ? tests : tests.filter((key) => keyPattern.test(key)); | ||
try { | ||
const parsed = await datasource.readTest(key); | ||
if (filteredKeys.length > 0) { | ||
console.log(`Linting ${filteredKeys.length} tests...\n`); | ||
} | ||
const result = testsZodSchema.safeParse(parsed); | ||
for (const key of filteredKeys) { | ||
const fullPath = getFullPathFromKey("test", key); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
try { | ||
const parsed = await datasource.readTest(key); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
const result = testsZodSchema.safeParse(parsed); | ||
process.exit(1); | ||
if (!result.success) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
if ("error" in result) { | ||
printZodError(result.error); | ||
process.exit(1); | ||
} | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
} catch (e) { | ||
console.log(CLI_FORMAT_UNDERLINE, fullPath); | ||
console.log(""); | ||
console.log(e); | ||
hasError = true; | ||
} | ||
@@ -260,0 +301,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
913774
11469