UNPKG

sb-babel-cli

Version:
172 lines (171 loc) 7.34 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadConfigFromRoot = exports.validateConfig = exports.getBabelCore = exports.logError = exports.getCacheDB = exports.getSha1 = exports.posixifyPath = exports.CLIError = void 0; const fs_1 = __importDefault(require("fs")); const lowdb_1 = __importDefault(require("lowdb")); const path_1 = __importDefault(require("path")); const crypto_1 = __importDefault(require("crypto")); const make_dir_1 = __importDefault(require("make-dir")); const debounce_1 = __importDefault(require("lodash/debounce")); const resolve_from_1 = __importDefault(require("resolve-from")); const FileAsync_1 = __importDefault(require("lowdb/adapters/FileAsync")); class CLIError extends Error { } exports.CLIError = CLIError; function posixifyPath(filePath) { return filePath.split(path_1.default.sep).join(path_1.default.posix.sep); } exports.posixifyPath = posixifyPath; function getSha1(contents) { const hash = crypto_1.default.createHash('sha1'); hash.update(contents); return hash.digest('hex'); } exports.getSha1 = getSha1; async function getCacheDB(projectPath, loadState, cacheDirectory) { const configPath = path_1.default.join(cacheDirectory, '.sb-babel-cli', `cache-timestamps-${getSha1(projectPath)}`); await make_dir_1.default(path_1.default.dirname(configPath)); const adapter = new FileAsync_1.default(configPath, { serialize: JSON.stringify, }); adapter.write = debounce_1.default(adapter.write, 1000); const db = await lowdb_1.default(adapter); if (!loadState) { db.setState({}); } return db; } exports.getCacheDB = getCacheDB; function logError(error) { if (error instanceof CLIError) { console.error('ERROR', error.message); } else { console.error(error); } } exports.logError = logError; let babelCore; function getBabelCore(projectPath) { if (babelCore == null) { let resolved = null; try { resolved = resolve_from_1.default(projectPath, '@babel/core'); } catch (_) { /* No Op */ } if (!resolved) { throw new CLIError('Unable to find @babel/core in your project'); } // eslint-disable-next-line global-require,import/no-dynamic-require,@typescript-eslint/no-var-requires babelCore = require(resolved); } return babelCore; } exports.getBabelCore = getBabelCore; const EXCLUDED_CONFIG_KEYS = ['rootDirectory', 'sourceDirectory', 'loadConfig', 'specifiedArgs']; function validateConfig(config, sourceConfig) { const issues = []; if (typeof config !== 'object' || config == null || Array.isArray(config)) { issues.push('Config root is malformed'); } else { const validKeys = Object.keys(sourceConfig); EXCLUDED_CONFIG_KEYS.forEach((item) => { validKeys.splice(validKeys.indexOf(item), 1); }); const receivedKeys = Object.keys(config); const extraKeys = receivedKeys.filter((item) => !validKeys.includes(item)); if (extraKeys.length > 0) { issues.push(`Unknown config items: ${extraKeys.join(', ')}`); } if (config.watch != null && typeof config.watch !== 'boolean') { issues.push('config.watch must be a valid boolean'); } if (config.ignored != null && (!Array.isArray(config.ignored) || !config.ignored.every((item) => typeof item === 'string'))) { issues.push('config.ignored must be a valid array of strings'); } if (config.ignoredForRestart != null && (!Array.isArray(config.ignoredForRestart) || !config.ignoredForRestart.every((item) => typeof item === 'string'))) { issues.push('config.ignoredForRestart must be a valid array of strings'); } if (config.sourceMaps != null && typeof config.sourceMaps !== 'boolean' && config.sourceMaps !== 'inline') { issues.push('config.sourceMaps must either be a boolean or "inline"'); } if (config.resetCache != null && typeof config.resetCache !== 'boolean') { issues.push('config.resetCache must be a valid boolean'); } if (config.keepExtraFiles != null && typeof config.keepExtraFiles !== 'boolean') { issues.push('config.keepExtraFiles must be a valid boolean'); } if (config.execute != null && typeof config.execute !== 'string') { issues.push('config.execute must be a valid string'); } if (config.executeDelay != null && typeof config.executeDelay !== 'number') { issues.push('config.executeDelay must be a valid number'); } if (config.extensions != null && (!Array.isArray(config.extensions) || !config.extensions.every((item) => typeof item === 'string'))) { issues.push('config.extensions must be a valid array of strings'); } if (config.printConfig != null && typeof config.printConfig !== 'boolean') { issues.push('config.printConfig must be a valid boolean'); } if (config.nodeArgs != null && (!Array.isArray(config.nodeArgs) || !config.nodeArgs.every((item) => typeof item === 'string'))) { issues.push('config.nodeArgs must be a valid array of strings'); } if (config.programArgs != null && (!Array.isArray(config.programArgs) || !config.programArgs.every((item) => typeof item === 'string'))) { issues.push('config.programArgs must be a valid array of strings'); } } return issues; } exports.validateConfig = validateConfig; async function loadConfigFromRoot(rootDirectory, config) { const manifestPath = path_1.default.join(rootDirectory, 'package.json'); try { await fs_1.default.promises.access(manifestPath, fs_1.default.constants.R_OK); } catch (_) { // Manifest does not exist return config; } let parsed = {}; try { parsed = JSON.parse(await fs_1.default.promises.readFile(manifestPath, 'utf8')); } catch (_) { // Manifest is not a valid JSON console.warn(`WARNING: Manifest file at ${manifestPath} is malformed`); return config; } if (typeof parsed !== 'object' || parsed == null) { // Malformed manifest structure return config; } const manifestConfig = parsed['sb-babel-cli']; if (manifestConfig != null) { const issues = validateConfig(manifestConfig, config); if (issues.length > 0) { console.warn(`WARNING: Malformed sb-babel-cli config in manifest at ${manifestPath}`); console.log(issues.map((item) => ` - ${item}`).join('\n')); return config; } const newConfig = { ...manifestConfig }; Object.keys(config).forEach((key) => { if (config.specifiedArgs.includes(key) || EXCLUDED_CONFIG_KEYS.includes(key) || !(key in newConfig)) { newConfig[key] = config[key]; } }); return newConfig; } return config; } exports.loadConfigFromRoot = loadConfigFromRoot;