sdc-check
Version:
Small tool to inform you about potential risks in your project dependencies list
169 lines (148 loc) • 4.5 kB
JavaScript
import { constants } from 'node:fs'
import { access, readFile } from 'node:fs/promises'
import { join } from 'node:path'
const PACKAGE_JSON_CONFIG_KEY = 'sdc-check'
const IGNORE_FILE_NAME = '.sdccheckignore'
const defaultOptionsConfig = {
daysBeforeUpgradeToNewVersion: 5,
limitOfDecisionMakers: 7,
monthsOfInactivityAllowed: 10
}
/**
* @typedef {import('../index').Config['errors']} errors
* @type errors
*/
const defaultErrorsConfig = [
'package-is-too-new',
'lockfile-is-not-safe',
'has-os-scripts',
'dangerous-shell-commands'
]
/**
* @typedef {import('./utils.js').resolveMode} resolveMode
* @type resolveMode
*/
export function resolveMode(directory) {
return typeof directory === 'string' && directory.length > 0 ? 'internal' : 'external'
}
/**
* @typedef {import('./utils.js').loadConfig} loadConfig
* @type loadConfig
*/
export async function loadConfig(mode, directory) {
try {
if (mode === 'external') {
return { ...defaultOptionsConfig, errors: defaultErrorsConfig }
}
let PATH_TO_PACKAGE_JSON = join(directory, 'package.json')
let hasPackageJsonInTargetDir = await isFileExist(PATH_TO_PACKAGE_JSON)
if (!hasPackageJsonInTargetDir) {
return { ...defaultOptionsConfig, errors: defaultErrorsConfig }
}
let packageJson = JSON.parse((await readFile(PATH_TO_PACKAGE_JSON, 'utf-8')) || '{}')
let config =
packageJson[PACKAGE_JSON_CONFIG_KEY] &&
Object.keys(packageJson[PACKAGE_JSON_CONFIG_KEY]).length > 0
? {
...defaultOptionsConfig,
...(packageJson[PACKAGE_JSON_CONFIG_KEY].options || {}),
errors: Array.isArray(packageJson[PACKAGE_JSON_CONFIG_KEY].errors)
? packageJson[PACKAGE_JSON_CONFIG_KEY].errors
: defaultErrorsConfig
}
: { ...defaultOptionsConfig, errors: defaultErrorsConfig }
return config
} catch (error) {
/* eslint-disable no-console */
console.error('ERROR: Could not read config from package.json')
throw error
/* eslint-enable no-console */
}
}
/**
* @typedef {import('./utils.js').loadIgnoreFile} loadIgnoreFile
* @type loadIgnoreFile
*/
export async function loadIgnoreFile(directory) {
let PATH_TO_IGNORE_FILE = join(directory, IGNORE_FILE_NAME)
try {
if (!directory || !(await isFileExist(PATH_TO_IGNORE_FILE))) {
return {}
}
let content = await readFile(PATH_TO_IGNORE_FILE, 'utf-8')
return Object.fromEntries(
content
.split('\n')
.map(line => line.trim())
.filter(Boolean)
.map(rule => {
if (rule.includes('|')) {
let [spec, args] = rule.split('|')
spec = spec.trim()
let metrics = args
.split(',')
.map(metric => metric.trim())
.filter(Boolean)
return [spec, metrics.length > 0 ? metrics : true]
}
return [rule.trim(), true]
})
)
} catch (error) {
/* eslint-disable no-console */
console.error(`ERROR: Could not read ignore file from ${PATH_TO_IGNORE_FILE}`)
throw error
/* eslint-enable no-console */
}
}
/**
* @typedef {import('./utils.js').findLockFilePath} findLockFilePath
* @type findLockFilePath
*/
export async function findLockFilePath(mode, directory) {
if (mode === 'external') {
return ''
}
let PATH_TO_PACKAGE_LOCK = join(directory, 'package-lock.json')
let PATH_TO_YARN_LOCK = join(directory, 'yarn.lock')
try {
if (await isFileExist(PATH_TO_PACKAGE_LOCK)) {
return PATH_TO_PACKAGE_LOCK
}
if (await isFileExist(PATH_TO_YARN_LOCK)) {
return PATH_TO_YARN_LOCK
}
return ''
} catch (error) {
/* eslint-disable no-console */
console.error('ERROR: Could not find package lockfile')
throw error
/* eslint-enable no-console */
}
}
/**
* @typedef {import('./utils.js').omit} omit
* @type omit
*/
export function omit(keys, object) {
return Object.fromEntries(Object.entries(object).filter(([k]) => !keys.includes(k)))
}
/**
* @typedef {import('./utils.js').pick} pick
* @type pick
*/
export function pick(keys, object) {
return Object.fromEntries(Object.entries(object).filter(([k]) => keys.includes(k)))
}
/**
* @typedef {import('./utils.js').isFileExist} isFileExist
* @type isFileExist
*/
async function isFileExist(filePath) {
try {
await access(filePath, constants.R_OK)
return true
} catch (error) {
return false
}
}