UNPKG

@wrote/ensure-path

Version:

Create all directories on the way to the path.

78 lines (73 loc) 2.11 kB
const { mkdir, mkdirSync } = require('fs'); const makePromise = require('makepromise'); const { dirname } = require('path'); /** * Makes sure that a file can be created by creating all directories to which it belongs to, e.g., `ensurePath('~/path/to/wrote.data')` will attempt to create `~/path/to` directory recursively. * @param {string} path The path to the file. * @throws {Error} When the first folder in the path is non-executable. */ async function ensurePath(path) { const dir = dirname(path) try { await make(dir) return path } catch (err) { if (/EEXIST/.test(err.message) && err.message.indexOf(dir) != -1) { return path } throw err } } /** * Recursive promise-based mkdir. * @param {string} dir Path to the directory to be created */ async function make(dir) { try { await makePromise(mkdir, dir) } catch (err) { if (err.code == 'ENOENT') { const parentDir = dirname(dir) await make(parentDir) await make(dir) } else if (err.code != 'EEXIST') { // created in parallel throw err } } } /** * Makes sure that a file can be created by creating all directories to which it belongs to synchronously, e.g., `ensurePath('~/path/to/wrote.data')` will attempt to create `~/path/to` directory recursively. * @param {string} path The path to the file. * @throws {Error} When the first folder in the path is non-executable. */ function ensurePathSync(path) { const dir = dirname(path) try { makeSync(dir) return path } catch (err) { if (/EEXIST/.test(err.message) && err.message.indexOf(dir) != -1) { return path } throw err } } /** * Recursive promise-based mkdir. * @param {string} dir Path to the directory to be created */ function makeSync(dir) { try { mkdirSync(dir) } catch (err) { if (err.code == 'ENOENT') { const parentDir = dirname(dir) makeSync(parentDir) makeSync(dir) } else if (err.code != 'EEXIST') { // created in parallel throw err } } } module.exports = ensurePath module.exports.ensurePathSync = ensurePathSync