UNPKG

@sprucelabs/spruce-skill-utils

Version:

Loosely coupled classes and functions to make skill development faster! 🏎

288 lines (287 loc) 10 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = require("child_process"); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const schema_1 = require("@sprucelabs/schema"); const fs_extra_1 = __importDefault(require("fs-extra")); const constants_1 = require("../constants"); function existsSync(path) { return !!fs_extra_1.default.statSync(path, { throwIfNoEntry: false }); } const diskUtil = { writeFile(destination, contents) { fs_extra_1.default.outputFileSync(destination, contents); }, readDir(destination) { return fs_extra_1.default.readdirSync(destination); }, readFile(source) { if (!existsSync(source)) { throw new Error(`No file to read at ${source}`); } return fs_extra_1.default.readFileSync(source).toString(); }, deleteFile(destination) { if (existsSync(destination)) { fs_extra_1.default.removeSync(destination); } }, createDir(destination) { fs_extra_1.default.ensureDirSync(destination); }, moveDir(source, destination) { fs_extra_1.default.moveSync(source, destination); }, moveFile(source, destination) { fs_extra_1.default.moveSync(source, destination); }, async copyDir(source, destination) { this.createDir(destination); return new Promise((resolve, reject) => { (0, child_process_1.exec)(`cd ${source} && tar cf - . | (cd ${destination}; tar xf -)`, { maxBuffer: 1024 * 1024 * 5 }, (err, stdout) => { if (err) { reject(err); return; } resolve(stdout); }); }); }, deleteDir(target) { const resolved = this.resolvePath(target); if (existsSync(resolved)) { fs_extra_1.default.removeSync(resolved); } }, doesFileExist(target) { const resolved = this.resolvePath(target); return existsSync(resolved); }, isDir(target) { const resolved = this.resolvePath(target); if (this.doesDirExist(resolved)) { return fs_extra_1.default.lstatSync(resolved).isDirectory(); } return false; }, isDirPath(path) { const resolved = this.resolvePath(path); if (this.isDir(resolved)) { return true; } return path_1.default.extname(resolved).length === 0; }, isFile(target) { const resolved = this.resolvePath(target); if (this.doesFileExist(resolved)) { return fs_extra_1.default.lstatSync(resolved).isFile(); } return false; }, doesDirExist(target) { const resolved = this.resolvePath(target); return existsSync(resolved); }, resolveHashSprucePath(cwd, ...filePath) { const parts = cwd.split(path_1.default.sep); do { const path = path_1.default.join('/', ...parts, constants_1.HASH_SPRUCE_DIR); if (this.doesDirExist(path)) { return this.resolvePath(path, ...filePath); } parts.pop(); } while (parts.length > 0); throw new Error(`.spruce directory not found at ${cwd}`); }, doesHashSprucePathExist(cwd, ...filePath) { try { this.resolveHashSprucePath(cwd, ...filePath); return true; } catch { return false; } }, resolveBuiltHashSprucePath(cwd, ...filePath) { const parts = cwd.split(path_1.default.sep); do { const path = path_1.default.join('/', ...parts, constants_1.HASH_SPRUCE_BUILD_DIR); if (this.doesDirExist(path)) { return this.resolvePath(path, ...filePath); } parts.pop(); } while (parts.length > 0); throw new Error(`Built .spruce directory not found at ${cwd}. Try \`spruce build\` and try again.`); }, doesBuiltHashSprucePathExist(cwd, ...filePath) { try { this.resolveBuiltHashSprucePath(cwd, ...filePath); return true; } catch { return false; } }, isFileDifferent(destination, contents) { const currentContents = this.readFile(destination); return currentContents != contents; }, deleteEmptyDirs(dir) { if (!dir) { throw new schema_1.SchemaError({ code: 'MISSING_PARAMETERS', parameters: ['dir'], }); } if (!this.doesDirExist(dir)) { throw new schema_1.SchemaError({ code: 'INVALID_PARAMETERS', parameters: ['dir'], friendlyMessage: `No directory found at ${dir} to clean.`, }); } const dirname = path_1.default.resolve(dir); const remove = (dir, depth = 0) => { const thisDepth = depth + 1; if (!diskUtil.isDir(dir)) { return; } let files = fs_extra_1.default.readdirSync(dir); for (let filepath of files) { remove(path_1.default.join(dir, filepath), thisDepth); } let filesAfter = fs_extra_1.default.readdirSync(dir); if (depth > 0 && filesAfter.length === 0) { diskUtil.deleteDir(dir); } }; return remove(dirname); }, resolvePath(cwd, ...filePath) { let builtPath = path_1.default.join(...filePath); if (builtPath[0] !== '/') { // Relative to the cwd if (builtPath.substr(0, 2) === './') { builtPath = builtPath.substr(1); } builtPath = path_1.default.join(cwd, builtPath); } if (builtPath.search('#') > -1) { builtPath = builtPath.replace('#spruce', constants_1.HASH_SPRUCE_DIR); } return builtPath; }, resolveRelativePath(path1, path2) { const path = path_1.default.relative(path1, path2); if (path[0] !== '.') { return `.${path_1.default.sep}${path}`; } return path; }, resolveFile(...pathItems) { const extensions = ['', '.js', '.ts']; for (const extension of extensions) { const items = [...pathItems]; items[pathItems.length - 1] += extension; //@ts-ignore const resolved = this.resolvePath(...items); if (this.doesFileExist(resolved)) { return resolved; } } return false; }, createTempDir(...files) { const tmpDir = os_1.default.tmpdir(); const targetDir = path_1.default.join(tmpDir, ...files); this.createDir(targetDir); return targetDir; }, createRandomTempDir() { return this.createTempDir(uuid()); }, hasFileChanged(...filePath) { if (!filePath || !(filePath.length > 0)) { throw new schema_1.SchemaError({ code: 'MISSING_PARAMETERS', parameters: ['file'], }); } //@ts-ignore const file = this.resolvePath(...filePath); const cacheFile = this.getFileChangedCacheFile(file); let fileStat; try { fileStat = fs_extra_1.default.statSync(file); } catch (err) { return true; } let cacheFileStat; try { cacheFileStat = fs_extra_1.default.statSync(cacheFile); } catch (err) { //@ts-ignore } if (!cacheFileStat || cacheFileStat.ctimeMs < fileStat.ctimeMs) { this.writeFile(cacheFile, ''); return true; } return false; }, markFileAsUnchanged(...filePath) { const cacheCheckFile = this.getFileChangedCacheFile( //@ts-ignore this.resolvePath(...filePath)); diskUtil.writeFile(cacheCheckFile, ''); }, resolveCacheDirForDir(dir) { return this.resolvePath(dir, '.change_cache'); }, resolveFileInHashSpruceDir(cwd, ...filePath) { const dirs = ['build', 'src']; for (const dir of dirs) { const path = this.resolvePath(cwd, ...[dir, constants_1.HASH_SPRUCE_DIR_NAME, ...filePath]); const file = this.resolveFile(path); if (file) { return file; } } const path = diskUtil.resolvePath( //@ts-ignore ...[cwd, '[build|src]', constants_1.HASH_SPRUCE_DIR_NAME, ...filePath]); throw new Error(`Could not find ${path}.[ts|js] in the hash spruce dir!`); }, getFileChangedCacheFile(file) { if (!file) { throw new schema_1.SchemaError({ code: 'MISSING_PARAMETERS', parameters: ['file'], }); } const dirname = path_1.default.dirname(file); const filename = path_1.default.basename(file); const changeCacheDir = this.resolveCacheDirForDir(dirname); const cacheFile = this.resolvePath(changeCacheDir, filename.replace(/\.\./g, '__')); if (!this.doesDirExist(changeCacheDir)) { fs_extra_1.default.mkdirSync(changeCacheDir, { recursive: true }); } const gitignoreFile = diskUtil.resolvePath(changeCacheDir, '.gitignore'); if (!diskUtil.doesFileExist(gitignoreFile)) { diskUtil.writeFile(gitignoreFile, '*'); } return cacheFile; }, }; exports.default = diskUtil; function uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { let r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); }