1
1
# mkdirp
2
2
3
- Like ` mkdir -p ` , but in node .js!
3
+ Like ` mkdir -p ` , but in Node .js!
4
4
5
- [ ![ build status] ( https://secure.travis-ci.org/substack/node-mkdirp.png )] ( http://travis-ci.org/substack/node-mkdirp )
5
+ Now with a modern API and no\* bugs!
6
+
7
+ <small >\* may contain some bugs</small >
6
8
7
9
# example
8
10
9
11
## pow.js
10
12
11
13
``` js
12
- var mkdirp = require (' mkdirp' );
13
-
14
- mkdirp (' /tmp/foo/bar/baz' , function (err ) {
15
- if (err) console .error (err)
16
- else console .log (' pow!' )
17
- });
14
+ const mkdirp = require (' mkdirp' )
15
+
16
+ // return value is a Promise resolving to the first directory created
17
+ mkdirp (' /tmp/foo/bar/baz' ).then (made =>
18
+ console .log (` made directories, starting with ${ made} ` ))
18
19
```
19
20
20
- Output
21
+ Output (where ` /tmp/foo ` already exists)
21
22
22
23
```
23
- pow!
24
+ made directories, starting with /tmp/foo/bar
25
+ ```
26
+
27
+ Or, if you don't have time to wait around for promises:
28
+
29
+ ``` js
30
+ const mkdirp = require (' mkdirp' )
31
+
32
+ // return value is the first directory created
33
+ const made = mkdirp .sync (' /tmp/foo/bar/baz' )
34
+ console .log (` made directories, starting with ${ made} ` )
24
35
```
25
36
26
37
And now /tmp/foo/bar/baz exists, huzzah!
27
38
28
39
# methods
29
40
30
41
``` js
31
- var mkdirp = require (' mkdirp' );
42
+ const mkdirp = require (' mkdirp' )
32
43
```
33
44
34
- ## mkdirp(dir, opts, cb)
45
+ ## mkdirp(dir, [ opts] ) -> Promise<String | undefined>
35
46
36
47
Create a new directory and any necessary subdirectories at ` dir ` with octal
37
- permission string ` opts.mode ` . If ` opts ` is a non-object , it will be treated as
38
- the ` opts.mode ` .
48
+ permission string ` opts.mode ` . If ` opts ` is a string or number , it will be
49
+ treated as the ` opts.mode ` .
39
50
40
- If ` opts.mode ` isn't specified, it defaults to ` 0777 & (~process.umask()) ` .
51
+ If ` opts.mode ` isn't specified, it defaults to `0o777 &
52
+ (~ process.umask())`.
41
53
42
- ` cb(err, made) ` fires with the error or the first directory ` made `
43
- that had to be created, if any.
54
+ Promise resolves to first directory ` made ` that had to be created, or
55
+ ` undefined ` if everything already exists. Promise rejects if any errors
56
+ are encountered. Note that, in the case of promise rejection, some
57
+ directories _ may_ have been created, as recursive directory creation is not
58
+ an atomic operation.
44
59
45
60
You can optionally pass in an alternate ` fs ` implementation by passing in
46
- ` opts.fs ` . Your implementation should have ` opts.fs.mkdir(path, mode , cb) ` and
47
- ` opts.fs.stat(path, cb) ` .
61
+ ` opts.fs ` . Your implementation should have ` opts.fs.mkdir(path, opts , cb) `
62
+ and ` opts.fs.stat(path, cb) ` .
48
63
49
- ## mkdirp.sync(dir, opts)
64
+ You can also override just one or the other of ` mkdir ` and ` stat ` by
65
+ passing in ` opts.stat ` or ` opts.mkdir ` , or providing an ` fs ` option that
66
+ only overrides one of these.
50
67
51
- Synchronously create a new directory and any necessary subdirectories at ` dir `
52
- with octal permission string ` opts.mode ` . If ` opts ` is a non-object, it will be
53
- treated as the ` opts.mode ` .
68
+ ## mkdirp.sync(dir, opts) -> String|null
54
69
55
- If ` opts.mode ` isn't specified, it defaults to ` 0777 & (~process.umask()) ` .
70
+ Synchronously create a new directory and any necessary subdirectories at
71
+ ` dir ` with octal permission string ` opts.mode ` . If ` opts ` is a string or
72
+ number, it will be treated as the ` opts.mode ` .
56
73
57
- Returns the first directory that had to be created, if any.
74
+ If ` opts.mode ` isn't specified, it defaults to `0o777 &
75
+ (~ process.umask())`.
76
+
77
+ Returns the first directory that had to be created, or undefined if
78
+ everything already exists.
58
79
59
80
You can optionally pass in an alternate ` fs ` implementation by passing in
60
- ` opts.fs ` . Your implementation should have ` opts.fs.mkdirSync(path, mode) ` and
61
- ` opts.fs.statSync(path) ` .
81
+ ` opts.fs ` . Your implementation should have ` opts.fs.mkdirSync(path, mode) `
82
+ and ` opts.fs.statSync(path) ` .
83
+
84
+ You can also override just one or the other of ` mkdirSync ` and ` statSync `
85
+ by passing in ` opts.statSync ` or ` opts.mkdirSync ` , or providing an ` fs `
86
+ option that only overrides one of these.
62
87
63
- # usage
88
+ ## mkdirp.manual, mkdirp.manualSync
89
+
90
+ Use the manual implementation (not the native one). This is the default
91
+ when the native implementation is not available or the stat/mkdir
92
+ implementation is overridden.
93
+
94
+ ## mkdirp.native, mkdirp.nativeSync
95
+
96
+ Use the native implementation (not the manual one). This is the default
97
+ when the native implementation is available and stat/mkdir are not
98
+ overridden.
99
+
100
+ # implementation
101
+
102
+ On Node.js v10.12.0 and above, use the native `fs.mkdir(p,
103
+ {recursive: true })` option, unless ` fs.mkdir` / ` fs.mkdirSync` has been
104
+ overridden by an option.
105
+
106
+ ## native implementation
107
+
108
+ - If the path is a root directory, then pass it to the underlying
109
+ implementation and return the result/error. (In this case, it'll either
110
+ succeed or fail, but we aren't actually creating any dirs.)
111
+ - Walk up the path statting each directory, to find the first path that
112
+ will be created, ` made ` .
113
+ - Call ` fs.mkdir(path, { recursive: true }) ` (or ` fs.mkdirSync ` )
114
+ - If error, raise it to the caller.
115
+ - Return ` made ` .
116
+
117
+ ## manual implementation
118
+
119
+ - Call underlying ` fs.mkdir ` implementation, with ` recursive: false `
120
+ - If error:
121
+ - If path is a root directory, raise to the caller and do not handle it
122
+ - If ENOENT, mkdirp parent dir, store result as ` made `
123
+ - stat(path)
124
+ - If error, raise original ` mkdir ` error
125
+ - If directory, return ` made `
126
+ - Else, raise original ` mkdir ` error
127
+ - else
128
+ - return ` undefined ` if a root dir, or ` made ` if set, or ` path `
129
+
130
+ ## windows vs unix caveat
131
+
132
+ On Windows file systems, attempts to create a root directory (ie, a drive
133
+ letter or root UNC path) will fail. If the root directory exists, then it
134
+ will fail with ` EPERM ` . If the root directory does not exist, then it will
135
+ fail with ` ENOENT ` .
136
+
137
+ On posix file systems, attempts to create a root directory (in recursive
138
+ mode) will succeed silently, as it is treated like just another directory
139
+ that already exists. (In non-recursive mode, of course, it fails with
140
+ ` EEXIST ` .)
141
+
142
+ In order to preserve this system-specific behavior (and because it's not as
143
+ if we can create the parent of a root directory anyway), attempts to create
144
+ a root directory are passed directly to the ` fs ` implementation, and any
145
+ errors encountered are not handled.
146
+
147
+ ## native error caveat
148
+
149
+ The native implementation (as of at least Node.js v13.4.0) does not provide
150
+ appropriate errors in some cases (see
151
+ [ nodejs/node #31481 ] ( https://github.com/nodejs/node/issues/31481 ) and
152
+ [ nodejs/node #28015 ] ( https://github.com/nodejs/node/issues/28015 ) ).
153
+
154
+ In order to work around this issue, the native implementation will fall
155
+ back to the manual implementation if an ` ENOENT ` error is encountered.
156
+
157
+ # choosing a recursive mkdir implementation
158
+
159
+ There are a few to choose from! Use the one that suits your needs best : D
160
+
161
+ ## use ` fs.mkdir(path, {recursive: true}, cb) ` if:
162
+
163
+ - You wish to optimize performance even at the expense of other factors.
164
+ - You don't need to know the first dir created.
165
+ - You are ok with getting ` ENOENT ` as the error when some other problem is
166
+ the actual cause.
167
+ - You can limit your platforms to Node.js v10.12 and above.
168
+ - You're ok with using callbacks instead of promises.
169
+ - You don't need/want a CLI.
170
+ - You don't need to override the ` fs ` methods in use.
171
+
172
+ ## use this module (mkdirp 1.x) if:
173
+
174
+ - You need to know the first directory that was created.
175
+ - You wish to use the native implementation if available, but fall back
176
+ when it's not.
177
+ - You prefer promise-returning APIs to callback-taking APIs.
178
+ - You want more useful error messages than the native recursive mkdir
179
+ provides (at least as of Node.js v13.4), and are ok with re-trying on
180
+ ` ENOENT ` to achieve this.
181
+ - You need (or at least, are ok with) a CLI.
182
+ - You need to override the ` fs ` methods in use.
183
+
184
+ ## use [ `make-dir] ( http://npm.im/make-dir ) if:
185
+
186
+ - You do not need to know the first dir created (and wish to save a few
187
+ ` stat ` calls when using the native implementation for this reason).
188
+ - You wish to use the native implementation if available, but fall back
189
+ when it's not.
190
+ - You prefer promise-returning APIs to callback-taking APIs.
191
+ - You are ok with occasionally getting ` ENOENT ` errors for failures that
192
+ are actually related to something other than a missing file system entry.
193
+ - You don't need/want a CLI.
194
+ - You need to override the ` fs ` methods in use.
195
+
196
+ ## use mkdirp 0.x if:
197
+
198
+ - You need to know the first directory that was created.
199
+ - You need (or at least, are ok with) a CLI.
200
+ - You need to override the ` fs ` methods in use.
201
+ - You're ok with using callbacks instead of promises.
202
+ - You are not running on Windows, where the root-level ENOENT errors can
203
+ lead to infinite regress.
204
+ - You think vinyl just sounds warmer and richer for some weird reason.
205
+ - You are supporting truly ancient Node.js versions, before even the advent
206
+ of a ` Promise ` language primitive. (Please don't. You deserve better.)
207
+
208
+ # cli
64
209
65
210
This package also ships with a ` mkdirp ` command.
66
211
67
212
```
213
+ $ mkdirp -h
214
+
68
215
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
69
216
70
- Create each supplied directory including any necessary parent directories that
71
- don't yet exist.
72
-
217
+ Create each supplied directory including any necessary parent directories
218
+ that don't yet exist.
219
+
73
220
If the directory already exists, do nothing.
74
221
75
222
OPTIONS are:
76
223
77
- -m, --mode If a directory needs to be created, set the mode as an octal
78
- permission string.
224
+ -m<mode> If a directory needs to be created, set the mode as an octal
225
+ --mode=<mode> permission string.
226
+
227
+ -v --version Print the mkdirp version number
79
228
229
+ -h --help Print this helpful banner
230
+
231
+ -p --print Print the first directories created for each path provided
232
+
233
+ --manual Use manual implementation, even if native is available
80
234
```
81
235
82
236
# install
@@ -87,13 +241,25 @@ With [npm](http://npmjs.org) do:
87
241
npm install mkdirp
88
242
```
89
243
90
- to get the library, or
244
+ to get the library locally , or
91
245
92
246
```
93
247
npm install -g mkdirp
94
248
```
95
249
96
- to get the command.
250
+ to get the command everywhere, or
251
+
252
+ ```
253
+ npx mkdirp ...
254
+ ```
255
+
256
+ to run the command without installing it globally.
257
+
258
+ # platform support
259
+
260
+ This module works on node v8, but only v10 and above are officially
261
+ supported, as Node v8 reached its LTS end of life 2020-01-01, which is in
262
+ the past, as of this writing.
97
263
98
264
# license
99
265
0 commit comments