1 | /*!
|
---|
2 | * Tmp
|
---|
3 | *
|
---|
4 | * Copyright (c) 2011-2017 KARASZI Istvan <github@spam.raszi.hu>
|
---|
5 | *
|
---|
6 | * MIT Licensed
|
---|
7 | */
|
---|
8 |
|
---|
9 | /*
|
---|
10 | * Module dependencies.
|
---|
11 | */
|
---|
12 | const fs = require('fs');
|
---|
13 | const path = require('path');
|
---|
14 | const crypto = require('crypto');
|
---|
15 | const osTmpDir = require('os-tmpdir');
|
---|
16 | const _c = process.binding('constants');
|
---|
17 |
|
---|
18 | /*
|
---|
19 | * The working inner variables.
|
---|
20 | */
|
---|
21 | const
|
---|
22 | /**
|
---|
23 | * The temporary directory.
|
---|
24 | * @type {string}
|
---|
25 | */
|
---|
26 | tmpDir = osTmpDir(),
|
---|
27 |
|
---|
28 | // the random characters to choose from
|
---|
29 | RANDOM_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
|
---|
30 |
|
---|
31 | TEMPLATE_PATTERN = /XXXXXX/,
|
---|
32 |
|
---|
33 | DEFAULT_TRIES = 3,
|
---|
34 |
|
---|
35 | CREATE_FLAGS = (_c.O_CREAT || _c.fs.O_CREAT) | (_c.O_EXCL || _c.fs.O_EXCL) | (_c.O_RDWR || _c.fs.O_RDWR),
|
---|
36 |
|
---|
37 | EBADF = _c.EBADF || _c.os.errno.EBADF,
|
---|
38 | ENOENT = _c.ENOENT || _c.os.errno.ENOENT,
|
---|
39 |
|
---|
40 | DIR_MODE = 448 /* 0o700 */,
|
---|
41 | FILE_MODE = 384 /* 0o600 */,
|
---|
42 |
|
---|
43 | // this will hold the objects need to be removed on exit
|
---|
44 | _removeObjects = [];
|
---|
45 |
|
---|
46 | var
|
---|
47 | _gracefulCleanup = false,
|
---|
48 | _uncaughtException = false;
|
---|
49 |
|
---|
50 | /**
|
---|
51 | * Random name generator based on crypto.
|
---|
52 | * Adapted from http://blog.tompawlak.org/how-to-generate-random-values-nodejs-javascript
|
---|
53 | *
|
---|
54 | * @param {number} howMany
|
---|
55 | * @returns {string} the generated random name
|
---|
56 | * @private
|
---|
57 | */
|
---|
58 | function _randomChars(howMany) {
|
---|
59 | var
|
---|
60 | value = [],
|
---|
61 | rnd = null;
|
---|
62 |
|
---|
63 | // make sure that we do not fail because we ran out of entropy
|
---|
64 | try {
|
---|
65 | rnd = crypto.randomBytes(howMany);
|
---|
66 | } catch (e) {
|
---|
67 | rnd = crypto.pseudoRandomBytes(howMany);
|
---|
68 | }
|
---|
69 |
|
---|
70 | for (var i = 0; i < howMany; i++) {
|
---|
71 | value.push(RANDOM_CHARS[rnd[i] % RANDOM_CHARS.length]);
|
---|
72 | }
|
---|
73 |
|
---|
74 | return value.join('');
|
---|
75 | }
|
---|
76 |
|
---|
77 | /**
|
---|
78 | * Checks whether the `obj` parameter is defined or not.
|
---|
79 | *
|
---|
80 | * @param {Object} obj
|
---|
81 | * @returns {boolean} true if the object is undefined
|
---|
82 | * @private
|
---|
83 | */
|
---|
84 | function _isUndefined(obj) {
|
---|
85 | return typeof obj === 'undefined';
|
---|
86 | }
|
---|
87 |
|
---|
88 | /**
|
---|
89 | * Parses the function arguments.
|
---|
90 | *
|
---|
91 | * This function helps to have optional arguments.
|
---|
92 | *
|
---|
93 | * @param {(Options|Function)} options
|
---|
94 | * @param {Function} callback
|
---|
95 | * @returns {Array} parsed arguments
|
---|
96 | * @private
|
---|
97 | */
|
---|
98 | function _parseArguments(options, callback) {
|
---|
99 | if (typeof options == 'function') {
|
---|
100 | return [callback || {}, options];
|
---|
101 | }
|
---|
102 |
|
---|
103 | if (_isUndefined(options)) {
|
---|
104 | return [{}, callback];
|
---|
105 | }
|
---|
106 |
|
---|
107 | return [options, callback];
|
---|
108 | }
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Generates a new temporary name.
|
---|
112 | *
|
---|
113 | * @param {Object} opts
|
---|
114 | * @returns {string} the new random name according to opts
|
---|
115 | * @private
|
---|
116 | */
|
---|
117 | function _generateTmpName(opts) {
|
---|
118 | if (opts.name) {
|
---|
119 | return path.join(opts.dir || tmpDir, opts.name);
|
---|
120 | }
|
---|
121 |
|
---|
122 | // mkstemps like template
|
---|
123 | if (opts.template) {
|
---|
124 | return opts.template.replace(TEMPLATE_PATTERN, _randomChars(6));
|
---|
125 | }
|
---|
126 |
|
---|
127 | // prefix and postfix
|
---|
128 | const name = [
|
---|
129 | opts.prefix || 'tmp-',
|
---|
130 | process.pid,
|
---|
131 | _randomChars(12),
|
---|
132 | opts.postfix || ''
|
---|
133 | ].join('');
|
---|
134 |
|
---|
135 | return path.join(opts.dir || tmpDir, name);
|
---|
136 | }
|
---|
137 |
|
---|
138 | /**
|
---|
139 | * Gets a temporary file name.
|
---|
140 | *
|
---|
141 | * @param {(Options|tmpNameCallback)} options options or callback
|
---|
142 | * @param {?tmpNameCallback} callback the callback function
|
---|
143 | */
|
---|
144 | function tmpName(options, callback) {
|
---|
145 | var
|
---|
146 | args = _parseArguments(options, callback),
|
---|
147 | opts = args[0],
|
---|
148 | cb = args[1],
|
---|
149 | tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
|
---|
150 |
|
---|
151 | if (isNaN(tries) || tries < 0)
|
---|
152 | return cb(new Error('Invalid tries'));
|
---|
153 |
|
---|
154 | if (opts.template && !opts.template.match(TEMPLATE_PATTERN))
|
---|
155 | return cb(new Error('Invalid template provided'));
|
---|
156 |
|
---|
157 | (function _getUniqueName() {
|
---|
158 | const name = _generateTmpName(opts);
|
---|
159 |
|
---|
160 | // check whether the path exists then retry if needed
|
---|
161 | fs.stat(name, function (err) {
|
---|
162 | if (!err) {
|
---|
163 | if (tries-- > 0) return _getUniqueName();
|
---|
164 |
|
---|
165 | return cb(new Error('Could not get a unique tmp filename, max tries reached ' + name));
|
---|
166 | }
|
---|
167 |
|
---|
168 | cb(null, name);
|
---|
169 | });
|
---|
170 | }());
|
---|
171 | }
|
---|
172 |
|
---|
173 | /**
|
---|
174 | * Synchronous version of tmpName.
|
---|
175 | *
|
---|
176 | * @param {Object} options
|
---|
177 | * @returns {string} the generated random name
|
---|
178 | * @throws {Error} if the options are invalid or could not generate a filename
|
---|
179 | */
|
---|
180 | function tmpNameSync(options) {
|
---|
181 | var
|
---|
182 | args = _parseArguments(options),
|
---|
183 | opts = args[0],
|
---|
184 | tries = opts.name ? 1 : opts.tries || DEFAULT_TRIES;
|
---|
185 |
|
---|
186 | if (isNaN(tries) || tries < 0)
|
---|
187 | throw new Error('Invalid tries');
|
---|
188 |
|
---|
189 | if (opts.template && !opts.template.match(TEMPLATE_PATTERN))
|
---|
190 | throw new Error('Invalid template provided');
|
---|
191 |
|
---|
192 | do {
|
---|
193 | const name = _generateTmpName(opts);
|
---|
194 | try {
|
---|
195 | fs.statSync(name);
|
---|
196 | } catch (e) {
|
---|
197 | return name;
|
---|
198 | }
|
---|
199 | } while (tries-- > 0);
|
---|
200 |
|
---|
201 | throw new Error('Could not get a unique tmp filename, max tries reached');
|
---|
202 | }
|
---|
203 |
|
---|
204 | /**
|
---|
205 | * Creates and opens a temporary file.
|
---|
206 | *
|
---|
207 | * @param {(Options|fileCallback)} options the config options or the callback function
|
---|
208 | * @param {?fileCallback} callback
|
---|
209 | */
|
---|
210 | function file(options, callback) {
|
---|
211 | var
|
---|
212 | args = _parseArguments(options, callback),
|
---|
213 | opts = args[0],
|
---|
214 | cb = args[1];
|
---|
215 |
|
---|
216 | opts.postfix = (_isUndefined(opts.postfix)) ? '.tmp' : opts.postfix;
|
---|
217 |
|
---|
218 | // gets a temporary filename
|
---|
219 | tmpName(opts, function _tmpNameCreated(err, name) {
|
---|
220 | if (err) return cb(err);
|
---|
221 |
|
---|
222 | // create and open the file
|
---|
223 | fs.open(name, CREATE_FLAGS, opts.mode || FILE_MODE, function _fileCreated(err, fd) {
|
---|
224 | if (err) return cb(err);
|
---|
225 |
|
---|
226 | if (opts.discardDescriptor) {
|
---|
227 | return fs.close(fd, function _discardCallback(err) {
|
---|
228 | if (err) {
|
---|
229 | // Low probability, and the file exists, so this could be
|
---|
230 | // ignored. If it isn't we certainly need to unlink the
|
---|
231 | // file, and if that fails too its error is more
|
---|
232 | // important.
|
---|
233 | try {
|
---|
234 | fs.unlinkSync(name);
|
---|
235 | } catch (e) {
|
---|
236 | if (!isENOENT(e)) {
|
---|
237 | err = e;
|
---|
238 | }
|
---|
239 | }
|
---|
240 | return cb(err);
|
---|
241 | }
|
---|
242 | cb(null, name, undefined, _prepareTmpFileRemoveCallback(name, -1, opts));
|
---|
243 | });
|
---|
244 | }
|
---|
245 | if (opts.detachDescriptor) {
|
---|
246 | return cb(null, name, fd, _prepareTmpFileRemoveCallback(name, -1, opts));
|
---|
247 | }
|
---|
248 | cb(null, name, fd, _prepareTmpFileRemoveCallback(name, fd, opts));
|
---|
249 | });
|
---|
250 | });
|
---|
251 | }
|
---|
252 |
|
---|
253 | /**
|
---|
254 | * Synchronous version of file.
|
---|
255 | *
|
---|
256 | * @param {Options} options
|
---|
257 | * @returns {FileSyncObject} object consists of name, fd and removeCallback
|
---|
258 | * @throws {Error} if cannot create a file
|
---|
259 | */
|
---|
260 | function fileSync(options) {
|
---|
261 | var
|
---|
262 | args = _parseArguments(options),
|
---|
263 | opts = args[0];
|
---|
264 |
|
---|
265 | opts.postfix = opts.postfix || '.tmp';
|
---|
266 |
|
---|
267 | const discardOrDetachDescriptor = opts.discardDescriptor || opts.detachDescriptor;
|
---|
268 | const name = tmpNameSync(opts);
|
---|
269 | var fd = fs.openSync(name, CREATE_FLAGS, opts.mode || FILE_MODE);
|
---|
270 | if (opts.discardDescriptor) {
|
---|
271 | fs.closeSync(fd);
|
---|
272 | fd = undefined;
|
---|
273 | }
|
---|
274 |
|
---|
275 | return {
|
---|
276 | name: name,
|
---|
277 | fd: fd,
|
---|
278 | removeCallback: _prepareTmpFileRemoveCallback(name, discardOrDetachDescriptor ? -1 : fd, opts)
|
---|
279 | };
|
---|
280 | }
|
---|
281 |
|
---|
282 | /**
|
---|
283 | * Removes files and folders in a directory recursively.
|
---|
284 | *
|
---|
285 | * @param {string} root
|
---|
286 | * @private
|
---|
287 | */
|
---|
288 | function _rmdirRecursiveSync(root) {
|
---|
289 | const dirs = [root];
|
---|
290 |
|
---|
291 | do {
|
---|
292 | var
|
---|
293 | dir = dirs.pop(),
|
---|
294 | deferred = false,
|
---|
295 | files = fs.readdirSync(dir);
|
---|
296 |
|
---|
297 | for (var i = 0, length = files.length; i < length; i++) {
|
---|
298 | var
|
---|
299 | file = path.join(dir, files[i]),
|
---|
300 | stat = fs.lstatSync(file); // lstat so we don't recurse into symlinked directories
|
---|
301 |
|
---|
302 | if (stat.isDirectory()) {
|
---|
303 | if (!deferred) {
|
---|
304 | deferred = true;
|
---|
305 | dirs.push(dir);
|
---|
306 | }
|
---|
307 | dirs.push(file);
|
---|
308 | } else {
|
---|
309 | fs.unlinkSync(file);
|
---|
310 | }
|
---|
311 | }
|
---|
312 |
|
---|
313 | if (!deferred) {
|
---|
314 | fs.rmdirSync(dir);
|
---|
315 | }
|
---|
316 | } while (dirs.length !== 0);
|
---|
317 | }
|
---|
318 |
|
---|
319 | /**
|
---|
320 | * Creates a temporary directory.
|
---|
321 | *
|
---|
322 | * @param {(Options|dirCallback)} options the options or the callback function
|
---|
323 | * @param {?dirCallback} callback
|
---|
324 | */
|
---|
325 | function dir(options, callback) {
|
---|
326 | var
|
---|
327 | args = _parseArguments(options, callback),
|
---|
328 | opts = args[0],
|
---|
329 | cb = args[1];
|
---|
330 |
|
---|
331 | // gets a temporary filename
|
---|
332 | tmpName(opts, function _tmpNameCreated(err, name) {
|
---|
333 | if (err) return cb(err);
|
---|
334 |
|
---|
335 | // create the directory
|
---|
336 | fs.mkdir(name, opts.mode || DIR_MODE, function _dirCreated(err) {
|
---|
337 | if (err) return cb(err);
|
---|
338 |
|
---|
339 | cb(null, name, _prepareTmpDirRemoveCallback(name, opts));
|
---|
340 | });
|
---|
341 | });
|
---|
342 | }
|
---|
343 |
|
---|
344 | /**
|
---|
345 | * Synchronous version of dir.
|
---|
346 | *
|
---|
347 | * @param {Options} options
|
---|
348 | * @returns {DirSyncObject} object consists of name and removeCallback
|
---|
349 | * @throws {Error} if it cannot create a directory
|
---|
350 | */
|
---|
351 | function dirSync(options) {
|
---|
352 | var
|
---|
353 | args = _parseArguments(options),
|
---|
354 | opts = args[0];
|
---|
355 |
|
---|
356 | const name = tmpNameSync(opts);
|
---|
357 | fs.mkdirSync(name, opts.mode || DIR_MODE);
|
---|
358 |
|
---|
359 | return {
|
---|
360 | name: name,
|
---|
361 | removeCallback: _prepareTmpDirRemoveCallback(name, opts)
|
---|
362 | };
|
---|
363 | }
|
---|
364 |
|
---|
365 | /**
|
---|
366 | * Prepares the callback for removal of the temporary file.
|
---|
367 | *
|
---|
368 | * @param {string} name the path of the file
|
---|
369 | * @param {number} fd file descriptor
|
---|
370 | * @param {Object} opts
|
---|
371 | * @returns {fileCallback}
|
---|
372 | * @private
|
---|
373 | */
|
---|
374 | function _prepareTmpFileRemoveCallback(name, fd, opts) {
|
---|
375 | const removeCallback = _prepareRemoveCallback(function _removeCallback(fdPath) {
|
---|
376 | try {
|
---|
377 | if (0 <= fdPath[0]) {
|
---|
378 | fs.closeSync(fdPath[0]);
|
---|
379 | }
|
---|
380 | }
|
---|
381 | catch (e) {
|
---|
382 | // under some node/windows related circumstances, a temporary file
|
---|
383 | // may have not be created as expected or the file was already closed
|
---|
384 | // by the user, in which case we will simply ignore the error
|
---|
385 | if (!isEBADF(e) && !isENOENT(e)) {
|
---|
386 | // reraise any unanticipated error
|
---|
387 | throw e;
|
---|
388 | }
|
---|
389 | }
|
---|
390 | try {
|
---|
391 | fs.unlinkSync(fdPath[1]);
|
---|
392 | }
|
---|
393 | catch (e) {
|
---|
394 | if (!isENOENT(e)) {
|
---|
395 | // reraise any unanticipated error
|
---|
396 | throw e;
|
---|
397 | }
|
---|
398 | }
|
---|
399 | }, [fd, name]);
|
---|
400 |
|
---|
401 | if (!opts.keep) {
|
---|
402 | _removeObjects.unshift(removeCallback);
|
---|
403 | }
|
---|
404 |
|
---|
405 | return removeCallback;
|
---|
406 | }
|
---|
407 |
|
---|
408 | /**
|
---|
409 | * Prepares the callback for removal of the temporary directory.
|
---|
410 | *
|
---|
411 | * @param {string} name
|
---|
412 | * @param {Object} opts
|
---|
413 | * @returns {Function} the callback
|
---|
414 | * @private
|
---|
415 | */
|
---|
416 | function _prepareTmpDirRemoveCallback(name, opts) {
|
---|
417 | const removeFunction = opts.unsafeCleanup ? _rmdirRecursiveSync : fs.rmdirSync.bind(fs);
|
---|
418 | const removeCallback = _prepareRemoveCallback(removeFunction, name);
|
---|
419 |
|
---|
420 | if (!opts.keep) {
|
---|
421 | _removeObjects.unshift(removeCallback);
|
---|
422 | }
|
---|
423 |
|
---|
424 | return removeCallback;
|
---|
425 | }
|
---|
426 |
|
---|
427 | /**
|
---|
428 | * Creates a guarded function wrapping the removeFunction call.
|
---|
429 | *
|
---|
430 | * @param {Function} removeFunction
|
---|
431 | * @param {Object} arg
|
---|
432 | * @returns {Function}
|
---|
433 | * @private
|
---|
434 | */
|
---|
435 | function _prepareRemoveCallback(removeFunction, arg) {
|
---|
436 | var called = false;
|
---|
437 |
|
---|
438 | return function _cleanupCallback(next) {
|
---|
439 | if (!called) {
|
---|
440 | const index = _removeObjects.indexOf(_cleanupCallback);
|
---|
441 | if (index >= 0) {
|
---|
442 | _removeObjects.splice(index, 1);
|
---|
443 | }
|
---|
444 |
|
---|
445 | called = true;
|
---|
446 | removeFunction(arg);
|
---|
447 | }
|
---|
448 |
|
---|
449 | if (next) next(null);
|
---|
450 | };
|
---|
451 | }
|
---|
452 |
|
---|
453 | /**
|
---|
454 | * The garbage collector.
|
---|
455 | *
|
---|
456 | * @private
|
---|
457 | */
|
---|
458 | function _garbageCollector() {
|
---|
459 | if (_uncaughtException && !_gracefulCleanup) {
|
---|
460 | return;
|
---|
461 | }
|
---|
462 |
|
---|
463 | // the function being called removes itself from _removeObjects,
|
---|
464 | // loop until _removeObjects is empty
|
---|
465 | while (_removeObjects.length) {
|
---|
466 | try {
|
---|
467 | _removeObjects[0].call(null);
|
---|
468 | } catch (e) {
|
---|
469 | // already removed?
|
---|
470 | }
|
---|
471 | }
|
---|
472 | }
|
---|
473 |
|
---|
474 | /**
|
---|
475 | * Helper for testing against EBADF to compensate changes made to Node 7.x under Windows.
|
---|
476 | */
|
---|
477 | function isEBADF(error) {
|
---|
478 | return isExpectedError(error, -EBADF, 'EBADF');
|
---|
479 | }
|
---|
480 |
|
---|
481 | /**
|
---|
482 | * Helper for testing against ENOENT to compensate changes made to Node 7.x under Windows.
|
---|
483 | */
|
---|
484 | function isENOENT(error) {
|
---|
485 | return isExpectedError(error, -ENOENT, 'ENOENT');
|
---|
486 | }
|
---|
487 |
|
---|
488 | /**
|
---|
489 | * Helper to determine whether the expected error code matches the actual code and errno,
|
---|
490 | * which will differ between the supported node versions.
|
---|
491 | *
|
---|
492 | * - Node >= 7.0:
|
---|
493 | * error.code {String}
|
---|
494 | * error.errno {String|Number} any numerical value will be negated
|
---|
495 | *
|
---|
496 | * - Node >= 6.0 < 7.0:
|
---|
497 | * error.code {String}
|
---|
498 | * error.errno {Number} negated
|
---|
499 | *
|
---|
500 | * - Node >= 4.0 < 6.0: introduces SystemError
|
---|
501 | * error.code {String}
|
---|
502 | * error.errno {Number} negated
|
---|
503 | *
|
---|
504 | * - Node >= 0.10 < 4.0:
|
---|
505 | * error.code {Number} negated
|
---|
506 | * error.errno n/a
|
---|
507 | */
|
---|
508 | function isExpectedError(error, code, errno) {
|
---|
509 | return error.code == code || error.code == errno;
|
---|
510 | }
|
---|
511 |
|
---|
512 | /**
|
---|
513 | * Sets the graceful cleanup.
|
---|
514 | *
|
---|
515 | * Also removes the created files and directories when an uncaught exception occurs.
|
---|
516 | */
|
---|
517 | function setGracefulCleanup() {
|
---|
518 | _gracefulCleanup = true;
|
---|
519 | }
|
---|
520 |
|
---|
521 | const version = process.versions.node.split('.').map(function (value) {
|
---|
522 | return parseInt(value, 10);
|
---|
523 | });
|
---|
524 |
|
---|
525 | if (version[0] === 0 && (version[1] < 9 || version[1] === 9 && version[2] < 5)) {
|
---|
526 | process.addListener('uncaughtException', function _uncaughtExceptionThrown(err) {
|
---|
527 | _uncaughtException = true;
|
---|
528 | _garbageCollector();
|
---|
529 |
|
---|
530 | throw err;
|
---|
531 | });
|
---|
532 | }
|
---|
533 |
|
---|
534 | process.addListener('exit', function _exit(code) {
|
---|
535 | if (code) _uncaughtException = true;
|
---|
536 | _garbageCollector();
|
---|
537 | });
|
---|
538 |
|
---|
539 | /**
|
---|
540 | * Configuration options.
|
---|
541 | *
|
---|
542 | * @typedef {Object} Options
|
---|
543 | * @property {?number} tries the number of tries before give up the name generation
|
---|
544 | * @property {?string} template the "mkstemp" like filename template
|
---|
545 | * @property {?string} name fix name
|
---|
546 | * @property {?string} dir the tmp directory to use
|
---|
547 | * @property {?string} prefix prefix for the generated name
|
---|
548 | * @property {?string} postfix postfix for the generated name
|
---|
549 | */
|
---|
550 |
|
---|
551 | /**
|
---|
552 | * @typedef {Object} FileSyncObject
|
---|
553 | * @property {string} name the name of the file
|
---|
554 | * @property {string} fd the file descriptor
|
---|
555 | * @property {fileCallback} removeCallback the callback function to remove the file
|
---|
556 | */
|
---|
557 |
|
---|
558 | /**
|
---|
559 | * @typedef {Object} DirSyncObject
|
---|
560 | * @property {string} name the name of the directory
|
---|
561 | * @property {fileCallback} removeCallback the callback function to remove the directory
|
---|
562 | */
|
---|
563 |
|
---|
564 | /**
|
---|
565 | * @callback tmpNameCallback
|
---|
566 | * @param {?Error} err the error object if anything goes wrong
|
---|
567 | * @param {string} name the temporary file name
|
---|
568 | */
|
---|
569 |
|
---|
570 | /**
|
---|
571 | * @callback fileCallback
|
---|
572 | * @param {?Error} err the error object if anything goes wrong
|
---|
573 | * @param {string} name the temporary file name
|
---|
574 | * @param {number} fd the file descriptor
|
---|
575 | * @param {cleanupCallback} fn the cleanup callback function
|
---|
576 | */
|
---|
577 |
|
---|
578 | /**
|
---|
579 | * @callback dirCallback
|
---|
580 | * @param {?Error} err the error object if anything goes wrong
|
---|
581 | * @param {string} name the temporary file name
|
---|
582 | * @param {cleanupCallback} fn the cleanup callback function
|
---|
583 | */
|
---|
584 |
|
---|
585 | /**
|
---|
586 | * Removes the temporary created file or directory.
|
---|
587 | *
|
---|
588 | * @callback cleanupCallback
|
---|
589 | * @param {simpleCallback} [next] function to call after entry was removed
|
---|
590 | */
|
---|
591 |
|
---|
592 | /**
|
---|
593 | * Callback function for function composition.
|
---|
594 | * @see {@link https://github.com/raszi/node-tmp/issues/57|raszi/node-tmp#57}
|
---|
595 | *
|
---|
596 | * @callback simpleCallback
|
---|
597 | */
|
---|
598 |
|
---|
599 | // exporting all the needed methods
|
---|
600 | module.exports.tmpdir = tmpDir;
|
---|
601 |
|
---|
602 | module.exports.dir = dir;
|
---|
603 | module.exports.dirSync = dirSync;
|
---|
604 |
|
---|
605 | module.exports.file = file;
|
---|
606 | module.exports.fileSync = fileSync;
|
---|
607 |
|
---|
608 | module.exports.tmpName = tmpName;
|
---|
609 | module.exports.tmpNameSync = tmpNameSync;
|
---|
610 |
|
---|
611 | module.exports.setGracefulCleanup = setGracefulCleanup;
|
---|