UNPKG

@axway/amplify-utils

Version:

Axway Amplify utility library

220 lines (203 loc) 6.64 kB
import fs from 'fs'; import _path from 'path'; /** * Determines owner of existing parent directory, calls the operation's function, then applies the * owner to the destination and its newly created parent directories. * * @param {String} dest - The destination of the file or directory the operation is targetting. * @param {Object} opts - Various options. * @param {Boolean} [opts.applyOwner=true] - When `true`, determines the owner of the closest * existing parent directory and apply the owner to the file and any newly created directories. * @param {Number} [opts.gid] - The group id to apply to the file when assigning an owner. * @param {Number} [opts.uid] - The user id to apply to the file when assigning an owner. * @param {Function} fn - A function to call to perform the original filesystem operation. */ function execute(dest, opts, fn) { if (opts.applyOwner === false || process.platform === 'win32' || !process.getuid || process.getuid() !== 0) { fn(opts); return; } dest = _path.resolve(dest); let origin = _path.parse(dest).root; if (!opts.uid) { for (origin = dest; true; origin = _path.dirname(origin)) { try { const st = fs.lstatSync(origin); if (st.isDirectory()) { opts = Object.assign({}, opts, { gid: st.gid, uid: st.uid }); break; } } catch (err) { // continue } } } fn(opts); const chownSync = fs.lchownSync || fs.chownSync; let stat = fs.lstatSync(dest); while (dest !== origin && stat.uid !== opts.uid) { try { chownSync(dest, opts.uid, opts.gid); dest = _path.dirname(dest); stat = fs.lstatSync(dest); } catch (e) { break; } } } /** * Determines if a file or directory exists. * * @param {String} file - The full path to check if exists. * @returns {Boolean} */ function existsSync(file) { try { fs.statSync(file); return true; } catch (e) { return false; } } /** * Determines if a directory exists and that it is indeed a directory. * * @param {String} dir - The directory to check. * @returns {Boolean} */ function isDir(dir) { try { return fs.statSync(dir).isDirectory(); } catch (e) { // squelch } return false; } /** * Determines if a file exists and that it is indeed a file. * * @param {String} file - The file to check. * @returns {Boolean} */ function isFile(file) { try { return fs.statSync(file).isFile(); } catch (e) { // squelch } return false; } /** * Scan a directory for a specified file. * * @param {String} dir - The directory to start searching from. * @param {String|RegExp} filename - The name of the file to look for. * @param {Number} depth - Optional search depth, default 1 level. * @returns {String|null} */ function locate(dir, filename, depth) { try { if (fs.statSync(dir).isDirectory()) { for (const name of fs.readdirSync(dir)) { const file = _path.join(dir, name); try { /* eslint-disable max-depth */ if (fs.statSync(file).isDirectory()) { if (typeof depth === 'undefined' || depth > 0) { const result = locate(file, filename, typeof depth === 'undefined' ? undefined : depth - 1); if (result) { return result; } } } else if ((typeof filename === 'string' && name === filename) || (filename instanceof RegExp && filename.test(name))) { return file; } } catch (e) { // probably a permission issue, go to next file } } } } catch (e) { // dir does not exist or permission issue } return null; } /** * Creates a directory and any parent directories if needed. * * @param {String} dest - The directory path to create. * @param {Object} [opts] - Various options plus options to pass into `fs.mkdirSync()`. * @param {Boolean} [opts.applyOwner=true] - When `true`, determines the owner of the closest * existing parent directory and apply the owner to the file and any newly created directories. * @param {Number} [opts.gid] - The group id to apply to the file when assigning an owner. * @param {Number} [opts.uid] - The user id to apply to the file when assigning an owner. */ function mkdirpSync(dest, opts = {}) { execute(dest, opts, opts => { fs.mkdirSync(dest, { mode: 0o777, ...opts, recursive: true }); }); } /** * Moves a file. * * @param {String} src - The file or directory to move. * @param {String} dest - The destination to move the file or directory to. * @param {Object} [opts] - Various options plus options to pass into `fs.mkdirSync()` and * `fs.renameSync()`. * @param {Boolean} [opts.applyOwner=true] - When `true`, determines the owner of the closest * existing parent directory and apply the owner to the file and any newly created directories. * @param {Number} [opts.gid] - The group id to apply to the file when assigning an owner. * @param {Number} [opts.uid] - The user id to apply to the file when assigning an owner. */ function moveSync(src, dest, opts = {}) { execute(dest, opts, opts => { mkdirpSync(_path.dirname(dest), opts); fs.renameSync(src, dest); }); } /** * Read a directory including scoped packages as a single entry in the Array * and filtering out all files. * * @param {String} dir - Directory to read. * @returns {Array} */ function readdirScopedSync(dir) { const children = []; for (const name of fs.readdirSync(dir)) { const childPath = _path.join(dir, name); if (!isDir(childPath)) { continue; } if (name.charAt(0) === '@') { for (const scopedPackage of fs.readdirSync(childPath)) { if (isDir(_path.join(childPath, scopedPackage))) { children.push(`${name}/${scopedPackage}`); } } } else { children.push(name); } } return children; } /** * Writes a file to disk. * * @param {String} dest - The name of the file to write. * @param {String} contents - The contents of the file to write. * @param {Object} [opts] - Various options plus options to pass into `fs.mkdirSync()` and * `fs.writeFileSync()`. * @param {Boolean} [opts.applyOwner=true] - When `true`, determines the owner of the closest * existing parent directory and apply the owner to the file and any newly created directories. * @param {Number} [opts.gid] - The group id to apply to the file when assigning an owner. * @param {Number} [opts.uid] - The user id to apply to the file when assigning an owner. */ function writeFileSync(dest, contents, opts = {}) { execute(dest, opts, opts => { mkdirpSync(_path.dirname(dest), { ...opts, mode: undefined }); fs.writeFileSync(dest, contents, opts); }); } export { existsSync, isDir, isFile, locate, mkdirpSync, moveSync, readdirScopedSync, writeFileSync }; //# sourceMappingURL=fs.js.map