import * as cliArguments from "./cliArguments.js"; import * as configFile from "./configFile.js"; import * as environmentVariables from "./environmentVariables.js"; import { ui } from "../environment/userInteraction.js"; export const LOGGING_SILENT = "silent"; export const LOGGING_NORMAL = "normal"; export const LOGGING_VERBOSE = "verbose"; export function getLoggingLevel() { // Priority 1: CLI argument const cliLevel = cliArguments.getLoggingLevel(); if (cliLevel === LOGGING_SILENT || cliLevel === LOGGING_VERBOSE) { return cliLevel; } if (cliLevel) { // CLI arg was set but invalid, default to normal for backwards compatibility. return LOGGING_NORMAL; } // Priority 2: Environment variable const envLevel = environmentVariables.getLoggingLevel()?.toLowerCase(); if (envLevel === LOGGING_SILENT || envLevel === LOGGING_VERBOSE) { return envLevel; } return LOGGING_NORMAL; } export const ECOSYSTEM_JS = "js"; export const ECOSYSTEM_PY = "py"; // Default to JavaScript ecosystem const ecosystemSettings = { ecoSystem: ECOSYSTEM_JS, }; /** @returns {string} - The current ecosystem setting (ECOSYSTEM_JS or ECOSYSTEM_PY) */ export function getEcoSystem() { return ecosystemSettings.ecoSystem; } /** * @param {string} setting - The ecosystem to set (ECOSYSTEM_JS or ECOSYSTEM_PY) */ export function setEcoSystem(setting) { ecosystemSettings.ecoSystem = setting; } const defaultMinimumPackageAge = 48; /** @returns {number} */ export function getMinimumPackageAgeHours() { // Priority 1: CLI argument const cliValue = validateMinimumPackageAgeHours( cliArguments.getMinimumPackageAgeHours() ); if (cliValue !== undefined) { return cliValue; } // Priority 2: Environment variable const envValue = validateMinimumPackageAgeHours( environmentVariables.getMinimumPackageAgeHours() ); if (envValue !== undefined) { return envValue; } // Priority 3: Config file const configValue = configFile.getMinimumPackageAgeHours(); if (configValue !== undefined) { return configValue; } return defaultMinimumPackageAge; } /** * @param {string | undefined} value * @returns {number | undefined} */ function validateMinimumPackageAgeHours(value) { if (!value) { return undefined; } const numericValue = Number(value); if (Number.isNaN(numericValue)) { return undefined; } if (numericValue >= 0) { return numericValue; } return undefined; } const defaultSkipMinimumPackageAge = false; export function skipMinimumPackageAge() { const cliValue = cliArguments.getSkipMinimumPackageAge(); if (cliValue === true) { return true; } return defaultSkipMinimumPackageAge; } /** * Normalizes a registry URL by removing protocol if present * @param {string} registry * @returns {string} */ function normalizeRegistry(registry) { // Remove protocol (http://, https://) if present return registry.replace(/^https?:\/\//, ""); } /** * Parses comma-separated registries from environment variable * @param {string | undefined} envValue * @returns {string[]} */ function parseRegistriesFromEnv(envValue) { if (!envValue || typeof envValue !== "string") { return []; } // Split by comma and trim whitespace return envValue .split(",") .map((registry) => registry.trim()) .filter((registry) => registry.length > 0); } /** * Gets the custom npm registries from both environment variable and config file (merged) * @returns {string[]} */ export function getNpmCustomRegistries() { const envRegistries = parseRegistriesFromEnv( environmentVariables.getNpmCustomRegistries() ); const configRegistries = configFile.getNpmCustomRegistries(); // Merge both sources and remove duplicates const allRegistries = [...envRegistries, ...configRegistries]; const uniqueRegistries = [...new Set(allRegistries)]; // Normalize each registry (remove protocol if any) return uniqueRegistries.map(normalizeRegistry); } /** * Gets the custom npm registries from both environment variable and config file (merged) * @returns {string[]} */ export function getPipCustomRegistries() { const envRegistries = parseRegistriesFromEnv( environmentVariables.getPipCustomRegistries() ); const configRegistries = configFile.getPipCustomRegistries(); // Merge both sources and remove duplicates const allRegistries = [...envRegistries, ...configRegistries]; const uniqueRegistries = [...new Set(allRegistries)]; // Normalize each registry (remove protocol if any) return uniqueRegistries.map(normalizeRegistry); } /** * Parses comma-separated exclusions from environment variable * @param {string | undefined} envValue * @returns {string[]} */ function parseExclusionsFromEnv(envValue) { if (!envValue || typeof envValue !== "string") { return []; } return envValue .split(",") .map((exclusion) => exclusion.trim()) .filter((exclusion) => exclusion.length > 0); } /** * Gets the minimum package age exclusions from both environment variable and config file (merged) * @returns {string[]} */ export function getMinimumPackageAgeExclusions() { const envExclusions = parseExclusionsFromEnv( environmentVariables.getMinimumPackageAgeExclusions() ); const configExclusions = configFile.getMinimumPackageAgeExclusions(); // Merge both sources and remove duplicates const allExclusions = [...envExclusions, ...configExclusions]; return [...new Set(allExclusions)]; } /** * Gets the malware list base URL with priority: CLI argument > environment variable > config file > default * @returns {string} */ export function getMalwareListBaseUrl() { // Priority 1: CLI argument const cliValue = cliArguments.getMalwareListBaseUrl(); if (cliValue) { const url = removeTrailingSlashes(cliValue); ui.writeVerbose(`Fetching malware lists from ${url} as defined by CLI argument --safe-chain-malware-list-base-url`); return url; } // Priority 2: Environment variable const envValue = environmentVariables.getMalwareListBaseUrl(); if (envValue) { const url = removeTrailingSlashes(envValue); ui.writeVerbose(`Fetching malware lists from ${url} as defined by environment variable SAFE_CHAIN_MALWARE_LIST_BASE_URL`); return url; } // Priority 3: Config file const configValue = configFile.getMalwareListBaseUrl(); if (configValue) { const url = removeTrailingSlashes(configValue); ui.writeVerbose(`Fetching malware lists from ${url} as defined by config file (malwareListBaseUrl)`); return url; } // Default return removeTrailingSlashes("https://malware-list.aikido.dev"); } /** * Removes trailing slashes from a URL-like string. * @param {string} value * @returns {string} */ function removeTrailingSlashes(value) { if (!value || typeof value !== "string") { return value; } return value.replace(/\/+$/, ""); }