Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/make-dir
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1c36213da8b2e13306ab4704ea861742bbbe7a40
Choose a base ref
...
head repository: sindresorhus/make-dir
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 54612e856661a0c2c61b8414f066ca43e407fe77
Choose a head ref

Commits on Apr 1, 2019

  1. Copy the full SHA
    379001f View commit details
  2. Copy the full SHA
    f04481d View commit details
  3. Meta tweaks

    sindresorhus committed Apr 1, 2019
    Copy the full SHA
    765c9b3 View commit details
  4. 3.0.0

    sindresorhus committed Apr 1, 2019
    Copy the full SHA
    b13a97d View commit details

Commits on Apr 25, 2019

  1. Add Node.js 12 to testing (#16)

    coreyfarrell authored and sindresorhus committed Apr 25, 2019
    Copy the full SHA
    0efa10f View commit details

Commits on May 27, 2019

  1. Create funding.yml

    sindresorhus authored May 27, 2019
    Copy the full SHA
    f03a4db View commit details

Commits on May 31, 2019

  1. Tidelift tasks

    sindresorhus committed May 31, 2019
    Copy the full SHA
    49b26bd View commit details

Commits on Jun 1, 2019

  1. Copy the full SHA
    9de6474 View commit details

Commits on Feb 12, 2020

  1. Fix tests on Windows and Node.js 12 (#22)

    Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
    RyanZim and sindresorhus authored Feb 12, 2020
    Copy the full SHA
    3354122 View commit details
  2. Fix linting

    sindresorhus committed Feb 12, 2020
    Copy the full SHA
    7201491 View commit details
  3. Upgrade nyc

    sindresorhus committed Feb 12, 2020
    Copy the full SHA
    8632e52 View commit details
  4. Copy the full SHA
    dea15ae View commit details
  5. 3.0.1

    sindresorhus committed Feb 12, 2020
    Copy the full SHA
    cde3270 View commit details
  6. Copy the full SHA
    25231fe View commit details
  7. 3.0.2

    sindresorhus committed Feb 12, 2020
    Copy the full SHA
    66ba0d9 View commit details

Commits on Feb 27, 2020

  1. Fix readme typo (#26)

    papb authored Feb 27, 2020
    Copy the full SHA
    960ecf1 View commit details

Commits on Apr 22, 2020

  1. Copy the full SHA
    b5a98ef View commit details
  2. 3.1.0

    sindresorhus committed Apr 22, 2020
    Copy the full SHA
    6d029fe View commit details

Commits on Apr 25, 2020

  1. Cleanup from #28 (#30)

    RyanZim authored Apr 25, 2020
    Copy the full SHA
    978bee9 View commit details

Commits on Oct 26, 2020

  1. Meta tweaks

    sindresorhus committed Oct 26, 2020
    Copy the full SHA
    5e95e00 View commit details
  2. Fix Travis

    sindresorhus committed Oct 26, 2020
    Copy the full SHA
    4616c03 View commit details

Commits on Nov 5, 2020

  1. Copy the full SHA
    064e92d View commit details
  2. Fix tests

    sindresorhus committed Nov 5, 2020
    Copy the full SHA
    cf02568 View commit details

Commits on Jan 1, 2021

  1. Move to GitHub Actions

    sindresorhus committed Jan 1, 2021
    Copy the full SHA
    397e48e View commit details

Commits on Jan 3, 2021

  1. Fix code coverage

    sindresorhus committed Jan 3, 2021
    Copy the full SHA
    1dd6443 View commit details

Commits on Jan 24, 2021

  1. Copy the full SHA
    55af5b8 View commit details

Commits on Jun 23, 2023

  1. Update dependencies

    sindresorhus committed Jun 23, 2023
    Copy the full SHA
    c419a8a View commit details
  2. 4.0.0

    sindresorhus committed Jun 23, 2023
    Copy the full SHA
    54612e8 View commit details
Showing with 322 additions and 206 deletions.
  1. +4 −0 .github/funding.yml
  2. +3 −0 .github/security.md
  3. +30 −0 .github/workflows/main.yml
  4. +0 −11 .travis.yml
  5. +59 −32 index.d.ts
  6. +54 −38 index.js
  7. +5 −4 index.test-d.ts
  8. +1 −1 license
  9. +21 −17 package.json
  10. +19 −17 readme.md
  11. +14 −2 test/{helpers/util.js → _util.js}
  12. +55 −42 test/async.js
  13. +57 −42 test/sync.js
4 changes: 4 additions & 0 deletions .github/funding.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github: sindresorhus
open_collective: sindresorhus
tidelift: npm/make-dir
custom: https://sindresorhus.com/donate
3 changes: 3 additions & 0 deletions .github/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Security Policy

To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
30 changes: 30 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI
on:
- push
- pull_request
jobs:
test:
name: Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 10
os:
- ubuntu-latest
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- uses: codecov/codecov-action@v1
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 14
with:
fail_ci_if_error: true
11 changes: 0 additions & 11 deletions .travis.yml

This file was deleted.

91 changes: 59 additions & 32 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,66 @@
/// <reference types="node"/>
import * as fs from 'fs';

export interface Options {
declare namespace makeDir {
interface Options {
/**
Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/).
@default 0o777
*/
readonly mode?: number;

/**
Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs).
Using a custom `fs` implementation will block the use of the native `recursive` option if `fs.mkdir` or `fs.mkdirSync` is not the native function.
@default require('fs')
*/
readonly fs?: typeof fs;
}
}

declare const makeDir: {
/**
* Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/).
*
* @default 0o777 & (~process.umask())
*/
readonly mode?: number;
Make a directory and its parents if needed - Think `mkdir -p`.
@param path - Directory to create.
@returns The path to the created directory.
@example
```
import makeDir = require('make-dir');
(async () => {
const path = await makeDir('unicorn/rainbow/cake');
console.log(path);
//=> '/Users/sindresorhus/fun/unicorn/rainbow/cake'
// Multiple directories:
const paths = await Promise.all([
makeDir('unicorn/rainbow'),
makeDir('foo/bar')
]);
console.log(paths);
// [
// '/Users/sindresorhus/fun/unicorn/rainbow',
// '/Users/sindresorhus/fun/foo/bar'
// ]
})();
```
*/
(path: string, options?: makeDir.Options): Promise<string>;

/**
* Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs).
*
* Using a custom `fs` implementation will block the use of the native `recursive` option if `fs.mkdir` or `fs.mkdirSync` is not the native function.
*
* @default require('fs')
*/
readonly fs?: typeof fs;
}
Synchronously make a directory and its parents if needed - Think `mkdir -p`.
@param path - Directory to create.
@returns The path to the created directory.
*/
sync(path: string, options?: makeDir.Options): string;
};

/**
* Make a directory and its parents if needed - Think `mkdir -p`.
*
* @param path - Directory to create.
* @returns A `Promise` for the path to the created directory.
*/
export default function makeDir(
path: string,
options?: Options
): Promise<string>;

/**
* Synchronously make a directory and its parents if needed - Think `mkdir -p`.
*
* @param path - Directory to create.
* @returns The path to the created directory.
*/
export function sync(path: string, options?: Options): string;
export = makeDir;
92 changes: 54 additions & 38 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
'use strict';
const fs = require('fs');
const path = require('path');
const pify = require('pify');
const semver = require('semver');
const {promisify} = require('util');
const semverGte = require('semver/functions/gte');

const defaults = {
mode: 0o777 & (~process.umask()),
fs
};

const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0');
const useNativeRecursiveOption = semverGte(process.version, '10.12.0');

// https://github.com/nodejs/node/issues/8987
// https://github.com/libuv/libuv/pull/1088
@@ -25,6 +20,18 @@ const checkPath = pth => {
}
};

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.
@@ -36,60 +43,69 @@ const permissionError = pth => {
return error;
};

const makeDir = (input, options) => Promise.resolve().then(() => {
const makeDir = async (input, options) => {
checkPath(input);
options = Object.assign({}, defaults, options);
options = processOptions(options);

// TODO: Use util.promisify when targeting Node.js 8
const mkdir = pify(options.fs.mkdir);
const stat = pify(options.fs.stat);
const mkdir = promisify(options.fs.mkdir);
const stat = promisify(options.fs.stat);

if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) {
const pth = path.resolve(input);

return mkdir(pth, {
await mkdir(pth, {
mode: options.mode,
recursive: true
}).then(() => pth);
});

return pth;
}

const make = pth => {
return mkdir(pth, options.mode)
.then(() => pth)
.catch(error => {
if (error.code === 'EPERM') {
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;
}

if (error.code === 'ENOENT') {
if (path.dirname(pth) === pth) {
throw permissionError(pth);
}
await make(path.dirname(pth));

if (error.message.includes('null bytes')) {
throw error;
}
return make(pth);
}

return make(path.dirname(pth)).then(() => make(pth));
try {
const stats = await stat(pth);
if (!stats.isDirectory()) {
throw new Error('The path is not a directory');
}
} catch {
throw error;
}

return stat(pth)
.then(stats => stats.isDirectory() ? pth : Promise.reject())
.catch(() => {
throw error;
});
});
return pth;
}
};

return make(path.resolve(input));
});
};

module.exports = makeDir;
module.exports.default = makeDir;

module.exports.sync = (input, options) => {
checkPath(input);
options = Object.assign({}, defaults, options);
options = processOptions(options);

if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) {
const pth = path.resolve(input);
@@ -127,7 +143,7 @@ module.exports.sync = (input, options) => {
if (!options.fs.statSync(pth).isDirectory()) {
throw new Error('The path is not a directory');
}
} catch (_) {
} catch {
throw error;
}
}
9 changes: 5 additions & 4 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {expectType} from 'tsd-check';
import makeDir, {sync as makeDirSync} from '.';
import {expectType} from 'tsd';
import makeDir = require('.');
import {sync as makeDirSync} from '.';
import * as fs from 'fs';
import * as gfs from 'graceful-fs';

// MakeDir
expectType<Promise<string>>(makeDir('path/to/somewhere'));

expectType<Promise<string>>(
makeDir('path/to/somewhere', {mode: parseInt('777', 8)})
makeDir('path/to/somewhere', {mode: 0o777})
);
expectType<Promise<string>>(makeDir('path/to/somewhere', {fs}));
expectType<Promise<string>>(makeDir('path/to/somewhere', {fs: gfs}));
@@ -16,7 +17,7 @@ expectType<Promise<string>>(makeDir('path/to/somewhere', {fs: gfs}));
expectType<string>(makeDirSync('path/to/somewhere'));

expectType<string>(
makeDirSync('path/to/somewhere', {mode: parseInt('777', 8)})
makeDirSync('path/to/somewhere', {mode: 0o777})
);
expectType<string>(makeDirSync('path/to/somewhere', {fs}));
expectType<string>(makeDirSync('path/to/somewhere', {fs: gfs}));
2 changes: 1 addition & 1 deletion license
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Loading