@dreamhorizonorg/sentinel
Version:
Open-source, zero-dependency tool that blocks compromised packages BEFORE download. Built to counter supply chain and credential theft attacks like Shai-Hulud.
103 lines (88 loc) • 2.5 kB
JavaScript
/**
* File system utilities
* Pure functions for file detection and validation
*/
import fs from 'fs';
import path from 'path';
import { LOCKFILE_NAMES, PACKAGE_JSON_FILENAME } from '../constants/cli.constants.mjs';
/**
* Check if a path exists
*/
export const pathExists = (filePath) => {
return fs.existsSync(filePath);
};
/**
* Check if a path is a directory
*/
export const isDirectory = (filePath) => {
if (!pathExists(filePath)) {
return false;
}
return fs.statSync(filePath).isDirectory();
};
/**
* Check if a path is a file
*/
export const isFile = (filePath) => {
if (!pathExists(filePath)) {
return false;
}
return fs.statSync(filePath).isFile();
};
/**
* Check if a path is a lockfile by name
*/
export const isLockfileByName = (target) => {
return LOCKFILE_NAMES.some(name =>
target === name || target.endsWith(`/${name}`)
);
};
/**
* Check if a path is a lockfile by existence
*/
export const isLockfileByExistence = (resolvedPath) => {
if (!pathExists(resolvedPath)) {
return false;
}
return LOCKFILE_NAMES.some(name =>
path.basename(resolvedPath) === name
);
};
/**
* Check if a path is a lockfile (by name or existence)
*/
export const isLockfile = (target, resolvedPath) => {
return isLockfileByName(target) || isLockfileByExistence(resolvedPath);
};
/**
* Check if a path is package.json
*/
export const isPackageJson = (target, resolvedPath) => {
return target === PACKAGE_JSON_FILENAME ||
target.endsWith(`/${PACKAGE_JSON_FILENAME}`) ||
path.basename(resolvedPath) === PACKAGE_JSON_FILENAME;
};
/**
* Check if a string is a package spec (not a file path)
*/
export const isPackageSpec = (target, existsAsFile) => {
if (existsAsFile) {
return false;
}
// Regular package: package-name or package-name@version
const isRegularPackage = !target.includes('/') &&
!target.includes('\\') &&
(target.includes('@') || /^[a-zA-Z0-9_-]+$/.test(target));
// Scoped package: @scope/package or @scope/package@version
const isScopedPackage = target.startsWith('@') &&
target.includes('/') &&
!target.includes('\\');
return isRegularPackage || isScopedPackage;
};
/**
* Check if a string is an HTTP/HTTPS URL
*/
export const isHttpUrl = (url) => {
return typeof url === 'string' &&
(url.startsWith('http://') || url.startsWith('https://'));
};