standardlint
Version:
Extensible standards linter and auditor.
319 lines (316 loc) • 9.67 kB
JavaScript
import {
writeResultsToDisk
} from "./chunk-L32Q6UKV.mjs";
import {
InvalidFiletreeError,
MissingChecksError
} from "./chunk-5SV5B36E.mjs";
import {
checkForPresenceLicense
} from "./chunk-362CGRNA.mjs";
import {
checkForPresenceReadme
} from "./chunk-6ZWM5VZF.mjs";
import {
checkForPresenceSecurity
} from "./chunk-J4LRGQSA.mjs";
import {
checkForPresenceServiceMetadata
} from "./chunk-SHYXWNSB.mjs";
import {
checkForPresenceTemplateIssues
} from "./chunk-EBQNDNYD.mjs";
import {
checkForPresenceTemplatePullRequests
} from "./chunk-LSIVFAXG.mjs";
import {
checkForPresenceTests
} from "./chunk-NIDKLSVY.mjs";
import {
checkForThrowingPlainErrors
} from "./chunk-37FSA54G.mjs";
import {
checkForDefinedTags
} from "./chunk-447E4RBH.mjs";
import {
checkForPresenceApiSchema
} from "./chunk-GUTXS3F4.mjs";
import {
checkForPresenceChangelog
} from "./chunk-ZW7NUELL.mjs";
import {
checkForPresenceCiConfig
} from "./chunk-XDCL32SQ.mjs";
import {
checkForPresenceCodeowners
} from "./chunk-V6647XWN.mjs";
import {
checkForPresenceContributing
} from "./chunk-PEDPJZRW.mjs";
import {
checkForPresenceDiagramsFolder
} from "./chunk-ETP4RFGG.mjs";
import {
checkForPresenceIacConfig
} from "./chunk-QBAQ5LU2.mjs";
import {
getStatusCount
} from "./chunk-32NR4PF5.mjs";
import {
checkForConflictingLockfiles
} from "./chunk-4T33K72S.mjs";
import {
checkForConsoleUsage
} from "./chunk-7VY2ZK2D.mjs";
import {
checkForDefinedRelations
} from "./chunk-PL2C7SFI.mjs";
import {
checkForDefinedServiceLevelObjectives
} from "./chunk-CIPMB3MM.mjs";
import {
exists
} from "./chunk-DRBJPZVI.mjs";
// src/domain/StandardLint.ts
function createNewStandardLint(config, filetree) {
return new StandardLint(config, filetree);
}
var StandardLint = class {
defaultBasePathFallback = ".";
defaultSeverityFallback = "error";
defaultIgnorePathsFallback = [];
config;
filetree = [];
constructor(config, filetree) {
this.config = this.makeConfig(config);
if (filetree) {
if (this.validateFiletree(filetree)) this.filetree = filetree;
else throw new InvalidFiletreeError();
}
}
/**
* @description Validate that the filetree is a non-empty array with only strings.
*/
validateFiletree(filetree) {
if (filetree && Array.isArray(filetree) && filetree.length > 0) {
if (filetree.every((path) => typeof path === "string")) return true;
}
return false;
}
/**
* @description Validates and sanitizes user input and returns a valid Configuration.
*/
makeConfig(configInput) {
const basePath = configInput?.basePath && exists(configInput.basePath) ? configInput.basePath : this.defaultBasePathFallback;
const defaultSeverity = configInput?.defaultSeverity ? this.getValidatedSeverityLevel(configInput.defaultSeverity) : this.defaultSeverityFallback;
const ignorePaths = configInput?.ignorePaths ? this.getSanitizedPaths(configInput.ignorePaths) : this.defaultIgnorePathsFallback;
const checkList = Array.isArray(configInput?.checks) ? configInput?.checks : [];
const checks = this.getValidatedChecks(
checkList,
defaultSeverity,
ignorePaths
);
return {
basePath,
checks,
defaultSeverity
};
}
/**
* @description Validates and sanitizes a requested Severity level.
*/
getValidatedSeverityLevel(severity) {
const validSeverityLevels = ["warn", "error"];
if (validSeverityLevels.includes(severity)) return severity;
return this.defaultSeverityFallback;
}
/**
* @description Sanitizes provided paths or return empty array if none is provided.
*/
getSanitizedPaths(ignorePaths) {
if (ignorePaths.length === 0) return [];
return ignorePaths.filter((path) => typeof path === "string");
}
/**
* @description Validates and sanitizes a requested list of checks.
*
* Provide `defaultSeverity` as it's not yet available in the class `config` object
* when running the validation.
*/
getValidatedChecks(checks, defaultSeverity, ignorePaths) {
const validCheckNames = [
"all",
"checkForConflictingLockfiles",
"checkForConsoleUsage",
"checkForDefinedRelations",
"checkForDefinedServiceLevelObjectives",
"checkForDefinedTags",
"checkForPresenceApiSchema",
"checkForPresenceChangelog",
"checkForPresenceCiConfig",
"checkForPresenceCodeowners",
"checkForPresenceContributing",
"checkForPresenceDiagramsFolder",
"checkForPresenceIacConfig",
"checkForPresenceLicense",
"checkForPresenceReadme",
"checkForPresenceSecurity",
"checkForPresenceServiceMetadata",
"checkForPresenceTemplateIssues",
"checkForPresenceTemplatePullRequests",
"checkForPresenceTests",
"checkForThrowingPlainErrors"
];
const isValidCheckName = (name) => validCheckNames.includes(name);
if (checks.includes("all")) {
checks = validCheckNames;
validCheckNames.shift();
}
const validatedChecks = checks.map((check) => {
if (typeof check === "string" && isValidCheckName(check))
return {
name: check,
severity: defaultSeverity,
ignorePaths
};
if (typeof check === "object" && isValidCheckName(check.name))
return {
name: check.name,
path: check.path || "",
severity: this.getValidatedSeverityLevel(
check.severity || defaultSeverity
),
ignorePaths
};
return {
name: ""
};
}).filter((check) => check.name);
return validatedChecks;
}
/**
* @description Orchestrates the running of all checks.
*/
check(writeOutputToDisk = false) {
if (this.config.checks.length === 0) throw new MissingChecksError();
const results = this.config.checks.map(
(check) => this.test(check)
);
const checkResults = {
passes: getStatusCount("pass", results),
warnings: getStatusCount("warn", results),
failures: getStatusCount("fail", results),
results
};
if (writeOutputToDisk) writeResultsToDisk(checkResults);
return checkResults;
}
/**
* @description Run test on an individual Check.
*/
test(check) {
const { name, severity, path, ignorePaths } = check;
const checksList = {
checkForConflictingLockfiles: () => checkForConflictingLockfiles(
severity,
this.config.basePath,
this.filetree
),
checkForConsoleUsage: () => checkForConsoleUsage(severity, this.config.basePath, path, ignorePaths),
checkForDefinedRelations: () => checkForDefinedRelations(severity, this.config.basePath, path),
checkForDefinedServiceLevelObjectives: () => checkForDefinedServiceLevelObjectives(
severity,
this.config.basePath,
path
),
checkForDefinedTags: () => checkForDefinedTags(severity, this.config.basePath, path),
checkForPresenceApiSchema: () => checkForPresenceApiSchema(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceChangelog: () => checkForPresenceChangelog(
severity,
this.config.basePath,
this.filetree
),
checkForPresenceCiConfig: () => checkForPresenceCiConfig(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceCodeowners: () => checkForPresenceCodeowners(
severity,
this.config.basePath,
this.filetree
),
checkForPresenceContributing: () => checkForPresenceContributing(
severity,
this.config.basePath,
this.filetree
),
checkForPresenceDiagramsFolder: () => checkForPresenceDiagramsFolder(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceIacConfig: () => checkForPresenceIacConfig(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceLicense: () => checkForPresenceLicense(severity, this.config.basePath, this.filetree),
checkForPresenceReadme: () => checkForPresenceReadme(severity, this.config.basePath, this.filetree),
checkForPresenceSecurity: () => checkForPresenceSecurity(severity, this.config.basePath, this.filetree),
checkForPresenceServiceMetadata: () => checkForPresenceServiceMetadata(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceTemplateIssues: () => checkForPresenceTemplateIssues(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceTemplatePullRequests: () => checkForPresenceTemplatePullRequests(
severity,
this.config.basePath,
path,
this.filetree
),
checkForPresenceTests: () => checkForPresenceTests(
severity,
this.config.basePath,
path,
ignorePaths
),
checkForThrowingPlainErrors: () => checkForThrowingPlainErrors(
severity,
this.config.basePath,
path,
ignorePaths
)
};
const result = checksList[name]();
this.logResult(result);
return result;
}
/**
* @description Outputs a log with the check result.
*/
logResult(checkResult) {
const { status, name } = checkResult;
if (status === "pass") console.log("\u2705 PASS:", name);
if (status === "warn") console.warn("\u26A0\uFE0F WARN:", name);
if (status === "fail") console.error("\u274C FAIL:", name);
}
};
export {
createNewStandardLint
};