aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/make-dir/index.js
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/make-dir/index.js
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/make-dir/index.js')
-rw-r--r--vanilla/node_modules/make-dir/index.js155
1 files changed, 155 insertions, 0 deletions
diff --git a/vanilla/node_modules/make-dir/index.js b/vanilla/node_modules/make-dir/index.js
new file mode 100644
index 0000000..2c0814e
--- /dev/null
+++ b/vanilla/node_modules/make-dir/index.js
@@ -0,0 +1,155 @@
+'use strict';
+const fs = require('fs');
+const path = require('path');
+const {promisify} = require('util');
+const semverGte = require('semver/functions/gte');
+
+const useNativeRecursiveOption = semverGte(process.version, '10.12.0');
+
+// https://github.com/nodejs/node/issues/8987
+// https://github.com/libuv/libuv/pull/1088
+const 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 => {
+ 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));
+};