| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | 'use strict';const fs = require('fs');const path = require('path');const {promisify} = require('util');const semver = require('semver');const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0');// https://github.com/nodejs/node/issues/8987// https://github.com/libuv/libuv/pull/1088const checkPath = pth => {	if (process.platform === 'win32') {		const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''));		if (pathHasInvalidWinCharacters) {			const error = new Error(`Path contains invalid characters: ${pth}`);			error.code = 'EINVAL';			throw error;		}	}};const processOptions = options => {	// https://github.com/sindresorhus/make-dir/issues/18	const defaults = {		mode: 0o777,		fs	};	return {		...defaults,		...options	};};const permissionError = pth => {	// This replicates the exception of `fs.mkdir` with native the	// `recusive` option when run on an invalid drive under Windows.	const error = new Error(`operation not permitted, mkdir '${pth}'`);	error.code = 'EPERM';	error.errno = -4048;	error.path = pth;	error.syscall = 'mkdir';	return error;};const makeDir = async (input, options) => {	checkPath(input);	options = processOptions(options);	const mkdir = promisify(options.fs.mkdir);	const stat = promisify(options.fs.stat);	if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) {		const pth = path.resolve(input);		await mkdir(pth, {			mode: options.mode,			recursive: true		});		return pth;	}	const make = async pth => {		try {			await mkdir(pth, options.mode);			return pth;		} catch (error) {			if (error.code === 'EPERM') {				throw error;			}			if (error.code === 'ENOENT') {				if (path.dirname(pth) === pth) {					throw permissionError(pth);				}				if (error.message.includes('null bytes')) {					throw error;				}				await make(path.dirname(pth));				return make(pth);			}			try {				const stats = await stat(pth);				if (!stats.isDirectory()) {					throw new Error('The path is not a directory');				}			} catch (_) {				throw error;			}			return pth;		}	};	return make(path.resolve(input));};module.exports = makeDir;module.exports.sync = (input, options) => {	checkPath(input);	options = processOptions(options);	if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) {		const pth = path.resolve(input);		fs.mkdirSync(pth, {			mode: options.mode,			recursive: true		});		return pth;	}	const make = pth => {		try {			options.fs.mkdirSync(pth, options.mode);		} catch (error) {			if (error.code === 'EPERM') {				throw error;			}			if (error.code === 'ENOENT') {				if (path.dirname(pth) === pth) {					throw permissionError(pth);				}				if (error.message.includes('null bytes')) {					throw error;				}				make(path.dirname(pth));				return make(pth);			}			try {				if (!options.fs.statSync(pth).isDirectory()) {					throw new Error('The path is not a directory');				}			} catch (_) {				throw error;			}		}		return pth;	};	return make(path.resolve(input));};
 |