machinepack-fs
Advanced tools
Comparing version 8.0.2 to 9.0.0-0
@@ -7,6 +7,6 @@ module.exports = { | ||
description: 'Copy file or directory located at source path to the destination path (overwriting an existing file at the destination path, if there is one).', | ||
description: 'Copy file or directory located at source path to the destination path.', | ||
extendedDescription: 'Includes all of its descendant files and directories (i.e. `cp -r`).', | ||
extendedDescription: 'Includes all of its descendant files and directories (i.e. `cp -r`). Any existing file at the destination path will be overwritten.', | ||
@@ -24,3 +24,4 @@ | ||
example: '/Users/mikermcneil/.tmp/bar', | ||
description: 'The path (relative or absolute) to the directory in which to place the copied file(s). When copying a single file, a target filename may be specified.', | ||
description: 'The path (relative or absolute) to the directory in which to place the copied file(s).', | ||
extendedDescription: 'When copying a single file, a target filename may be specified.', | ||
required: true | ||
@@ -35,7 +36,3 @@ } | ||
doesNotExist: { | ||
description: 'No file or folder exists at the provided souce path.' | ||
}, | ||
success: { | ||
description: 'Done.' | ||
description: 'No file or folder could be found at the provided source path.' | ||
} | ||
@@ -46,12 +43,21 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
var fsx = require('fs-extra'); | ||
// Attempt to copy the source file or directory to the destination. | ||
fsx.copy(path.resolve(inputs.source), path.resolve(inputs.destination), function (err) { | ||
// If the copy failed... | ||
if (err) { | ||
// If we got an ENOENT error, return out of the `doesNotExist` exit. | ||
if (err.code === 'ENOENT') { | ||
return exits.doesNotExist(); | ||
} | ||
// Otherwise return the unknown error out of our `error` exit. | ||
return exits.error(err); | ||
} | ||
// Otherwise return through the `success` exit. | ||
return exits.success(); | ||
@@ -58,0 +64,0 @@ }); |
@@ -10,3 +10,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'cacheable', | ||
@@ -29,3 +29,3 @@ | ||
success: { | ||
description: 'Either a directory already existed, or it was just created, at the specified path.' | ||
description: 'Either a directory already existed, or was just created, at the specified path.' | ||
} | ||
@@ -37,2 +37,4 @@ | ||
fn: function(inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
@@ -44,6 +46,13 @@ var fsx = require('fs-extra'); | ||
// Attempt to ensure the directory. | ||
fsx.ensureDir(inputs.path, function(err) { | ||
// Forward any errors through our `error` exit. | ||
if (err) {return exits.error(err);} | ||
// Otherwise return through the `success` exit. | ||
return exits.success(); | ||
}); | ||
} | ||
@@ -50,0 +59,0 @@ |
module.exports = { | ||
friendlyName: 'Exists?', | ||
friendlyName: 'Does filepath exist?', | ||
@@ -10,3 +10,3 @@ | ||
cacheable: true, | ||
sideEffects: 'cacheable', | ||
@@ -18,3 +18,4 @@ | ||
example: '/Users/mikermcneil/.tmp/foo', | ||
description: 'The absolute path to the file or directory', | ||
description: 'The path to the file or directory to check.', | ||
extendedDescription: 'If a relative path is given, it will be resolved from the current working directory.', | ||
required: true | ||
@@ -28,10 +29,8 @@ } | ||
doesNotExist: { | ||
description: 'The specified path is empty' | ||
success: { | ||
outputFriendlyName: 'Filepath exists?', | ||
outputDescription: 'Whether or not there is a file or directory at the specified path.', | ||
outputExample: true | ||
}, | ||
success: { | ||
description: 'A file or directory exists at the specified path' | ||
} | ||
}, | ||
@@ -41,8 +40,24 @@ | ||
// Import `path` and `fs-extra`. | ||
var Path = require('path'); | ||
var fsx = require('fs-extra'); | ||
fsx.exists(Path.resolve(process.cwd(),inputs.path), function(exists) { | ||
if (!exists) {return exits.doesNotExist();} | ||
return exits.success(); | ||
// Determine if the directory in question exists. | ||
// Use `stat` instead of the deprecated `exists`. | ||
fsx.stat(Path.resolve(process.cwd(),inputs.path), function(err) { | ||
// If an ENOENT error is returned, the file doesn't exist, | ||
// so we can return `false` through the `success` exit. | ||
if (err && err.code === 'ENOENT') { | ||
return exits.success(false); | ||
} | ||
// If some other error is returned, just forward it through | ||
// our `error` exit. | ||
if (err) { | ||
return exits.error(err); | ||
} | ||
// Otherwise return `true` through the `success` exit. | ||
return exits.success(true); | ||
}); | ||
@@ -49,0 +64,0 @@ } |
@@ -10,3 +10,3 @@ module.exports = { | ||
cacheable: true, | ||
sideEffects: 'cacheable', | ||
@@ -25,3 +25,2 @@ | ||
depth: { | ||
friendlyName: 'Depth', | ||
description: 'The maximum number of "hops" (i.e. directories deep) to include directory contents from.', | ||
@@ -34,4 +33,4 @@ extendedDescription: 'For instance, if you are running `ls` on "foo/" which has a subdirectory "foo/bar/baz/", if `depth` is set to 2, the results will include "foo/bar/baz/", but none of the files/folders contained within.', | ||
includeFiles: { | ||
friendlyName: 'Files?', | ||
description: 'Whether or not to include files', | ||
friendlyName: 'Include files?', | ||
description: 'Whether or not to include files.', | ||
example: true, | ||
@@ -42,4 +41,4 @@ defaultsTo: true | ||
includeDirs: { | ||
friendlyName: 'Directories?', | ||
description: 'Whether or not to include directories', | ||
friendlyName: 'Include directories?', | ||
description: 'Whether or not to include directories.', | ||
example: true, | ||
@@ -50,4 +49,4 @@ defaultsTo: true | ||
includeSymlinks: { | ||
friendlyName: 'Symlinks?', | ||
description: 'Whether or not to include symbolic links', | ||
friendlyName: 'Include symlinks?', | ||
description: 'Whether or not to include symbolic links.', | ||
example: true, | ||
@@ -58,4 +57,4 @@ defaultsTo: true | ||
includeHidden: { | ||
friendlyName: 'Hidden entries?', | ||
description: 'Whether or not to include hidden files/directories/symlinks', | ||
friendlyName: 'Include hidden entries?', | ||
description: 'Whether or not to include hidden files/directories/symlinks.', | ||
example: false, | ||
@@ -70,11 +69,12 @@ defaultsTo: false | ||
doesNotExist: { | ||
description: 'Nothing exists at the specified directory path.' | ||
}, | ||
success: { | ||
variableName: 'dirContents', | ||
example: [ | ||
outputFriendlyName: 'Directory contents', | ||
outputDescription: 'A list of the files and subdirectories contained in the specified directory.', | ||
outputExample: [ | ||
'/Users/mikermcneil/.tmp/foo/.gitignore' | ||
] | ||
}, | ||
doesNotExist: { | ||
description: 'No directory was found at the specified directory path.' | ||
} | ||
@@ -86,2 +86,4 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `walker`. | ||
var path = require('path'); | ||
@@ -100,10 +102,10 @@ var Walker = require('walker'); | ||
// • deeper than requested, or | ||
// • hidden (if the `includeHidden` input is set to false) | ||
// • hidden (if the `includeHidden` input is set to false). | ||
var walker = Walker(inputs.dir); | ||
walker.filterDir(function(dir, stat) { | ||
// Too deep | ||
// Too deep. | ||
if (dir.split(path.sep).length > (topLvlDirDepth + inputs.depth)) { | ||
return false; | ||
} | ||
// Too hidden | ||
// Too hidden. | ||
if (path.basename(dir).match(/^\./) && !inputs.includeHidden) { | ||
@@ -118,2 +120,4 @@ return false; | ||
var results = []; | ||
// If `inputs.includeFiles` is `true`, look for files. | ||
if (inputs.includeFiles) { | ||
@@ -131,2 +135,4 @@ walker.on('file', function (entry, stat) { | ||
} | ||
// If `inputs.includeDirs` is `true`, look for directories. | ||
if (inputs.includeDirs) { | ||
@@ -144,2 +150,4 @@ walker.on('dir', function (entry, stat) { | ||
} | ||
// If `inputs.includeSymlinks` is `true`, look for symbolic links. | ||
if (inputs.includeSymlinks) { | ||
@@ -158,16 +166,27 @@ walker.on('symlink', function (entry, stat) { | ||
// When walking is done, because of an error or otherwise, | ||
// return the results. | ||
// Declare a var to act as a spinlock, so that duplicate events can be ignored. | ||
var spinlock; | ||
// If we receive an `error` event from Walker... | ||
walker.on('error', function (err){ | ||
// If the spinlock is already engaged, do nothing. | ||
if (spinlock) { return; } | ||
// Engage the spinlock. | ||
spinlock = true; | ||
// If the error was ENOENT, it means the requested directory does not exist, | ||
// so we'll return through the `doesNotExist` exit. | ||
if (err.code === 'ENOENT') { | ||
return exits.doesNotExist(); | ||
} | ||
// Otherwise forward the unknown error through the `error` exit. | ||
return exits.error(err); | ||
}); | ||
// If we receive a `done` event from Walker... | ||
walker.on('end', function (){ | ||
// If the spinlock is already engaged, do nothing. | ||
if (spinlock) { return; } | ||
// Engage the spinlock. | ||
spinlock = true; | ||
// Return the accumulated directory contents through the `success` exit. | ||
return exits.success(results); | ||
@@ -174,0 +193,0 @@ }); |
@@ -31,7 +31,7 @@ module.exports = { | ||
success: { | ||
description: 'New directory created successfully.' | ||
description: 'New directory was created successfully.' | ||
}, | ||
alreadyExists: { | ||
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)' | ||
description: 'Something already existed at the specified path (overwrite by enabling the `force` input).' | ||
} | ||
@@ -43,12 +43,23 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
var fsx = require('fs-extra'); | ||
// Import this pack. | ||
var Filesystem = require('../'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.destination = path.resolve(inputs.destination); | ||
// Only override an existing file if `inputs.force` is true | ||
fsx.exists(inputs.destination, function(exists) { | ||
// Determine whether the destination already exists. | ||
Filesystem.exists({path: inputs.destination}).exec(function(err, exists) { | ||
// If an error occurred checking for file existence, forward it through | ||
// our `error` exit. | ||
if (err) {return exits.error(err);} | ||
// If so, and we're `inputs.force` is not specified, return through | ||
// the `alreadyExists` exit. | ||
if (exists && !inputs.force) { | ||
@@ -60,5 +71,7 @@ return exits.alreadyExists(); | ||
(function _deleteExistingFilesAndOrDirsIfNecessary(next) { | ||
// If the directory doesn't already exist, there's nothing to delete. | ||
if (!exists) { | ||
return next(); | ||
} | ||
// Otherwise remove the directory and all its contents before continuing. | ||
else { | ||
@@ -68,9 +81,18 @@ fsx.remove(inputs.destination, next); | ||
})(function nowWriteFileToDisk(err){ | ||
if (err) { return exits(err); } | ||
// If there was any error removing the directory, forward it to our `error` exit. | ||
if (err) { return exits.error(err); } | ||
// Now create the directory on disk. | ||
fsx.mkdirs(inputs.destination, exits); | ||
fsx.mkdirs(inputs.destination, function(err) { | ||
// If there was any error creating the directory, forward it to our `error` exit. | ||
if (err) { return exits.error(err); } | ||
// Return through our `success` exit. | ||
return exits.success(); | ||
}); | ||
});//</after deleting existing file(s)/dir(s) if necessary> | ||
});//</fsx.exists()> | ||
});//</Filesystem.exists()> | ||
} | ||
@@ -77,0 +99,0 @@ |
@@ -32,3 +32,3 @@ module.exports = { | ||
doesNotExist: { | ||
description: 'No file or folder exists at the provided souce path.' | ||
description: 'No file or folder could be found at the provided souce path.' | ||
} | ||
@@ -40,2 +40,4 @@ | ||
fn: function(inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
@@ -48,10 +50,18 @@ var fsx = require('fs-extra'); | ||
// Attempt to move the source file or folder to the destination. | ||
fsx.move(inputs.source, inputs.destination, function (err) { | ||
// If the move failed... | ||
if (err) { | ||
// If we got an ENOENT error, return out of the `doesNotExist` exit. | ||
if (err.code === 'ENOENT') { | ||
return exits.doesNotExist(); | ||
} | ||
// Otherwise return the unknown error out of our `error` exit. | ||
return exits.error(err); | ||
} | ||
// Otherwise return through the `success` exit. | ||
return exits.success(); | ||
}); | ||
@@ -58,0 +68,0 @@ }, |
@@ -13,3 +13,3 @@ module.exports = { | ||
cacheable: true, | ||
sideEffects: 'cacheable', | ||
@@ -20,3 +20,3 @@ | ||
source: { | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory).', | ||
example: '/Users/mikermcneil/.tmp/foo.json', | ||
@@ -27,8 +27,5 @@ required: true | ||
schema: { | ||
description: 'An example schema (in RTTC exemplar syntax) describing what the parsed data should look like (used for type-coercion)', | ||
extendedDescription: 'If file does not exist, a "base value" will be derived from this example schema and used as the contents of the newly created JSON file.', | ||
description: 'An example schema (in RTTC exemplar syntax) describing what the parsed data should look like (used for type-coercion).', | ||
moreInfoUrl: 'https://github.com/node-machine/rttc#types--terminology', | ||
example: '*', | ||
defaultsTo: '*', | ||
constant: true, | ||
isExemplar: true | ||
@@ -42,17 +39,20 @@ } | ||
success: { | ||
outputFriendlyName: 'JSON file data', | ||
outputDescription: 'The parsed JSON data from the source file.', | ||
getExample: function (inputs){ | ||
return inputs.schema; | ||
} | ||
}, | ||
doesNotExist: { | ||
description: 'No file exists at the provided `source` path' | ||
description: 'No file could be found at the provided `source` path.' | ||
}, | ||
couldNotParse: { | ||
description: 'Could not parse file as JSON.' | ||
description: 'Could not parse the file as JSON.' | ||
}, | ||
// TODO: not a file (and return what it ACTUALLY is, e.g. dir or symlink) | ||
success: { | ||
description: 'Returns parsed JSON data from the source file.', | ||
getExample: function (inputs){ | ||
return inputs.schema; | ||
} | ||
isDirectory: { | ||
description: 'The specified path pointed to a directory.' | ||
} | ||
@@ -65,17 +65,27 @@ | ||
var MPJSON = require('machinepack-json'); | ||
var thisPack = require('../'); | ||
// Import `machinepack-json`. | ||
var Json = require('machinepack-json'); | ||
thisPack.read({ | ||
// Import this pack. | ||
var Filesystem = require('../'); | ||
// Attempt to read the file at the specified path. | ||
Filesystem.read({ | ||
source: inputs.source | ||
}).exec({ | ||
// Forward errors through the appropriate exits. | ||
error: exits.error, | ||
doesNotExist: exits.doesNotExist, | ||
isDirectory: exits.isDirectory, | ||
// If the file was successfully read... | ||
success: function (contents){ | ||
MPJSON.parse({ | ||
// Attempt to parse the file contents as JSON. | ||
Json.parse({ | ||
json: contents, | ||
schema: inputs.schema | ||
}).exec({ | ||
// Forward errors through the appropriate exits. | ||
error: exits.error, | ||
couldNotParse: exits.couldNotParse, | ||
// If the data was successfully parsed, push it through our `success` exit. | ||
success: function (parsedData){ | ||
@@ -82,0 +92,0 @@ return exits.success(parsedData); |
@@ -22,3 +22,3 @@ module.exports = { | ||
source: { | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory).', | ||
example: '/Users/mikermcneil/.tmp/foo', | ||
@@ -33,10 +33,2 @@ required: true | ||
doesNotExist: { | ||
description: 'No file exists at the provided `source` path' | ||
}, | ||
isDirectory: { | ||
description: 'A directory (not the file we were expecting) is at the source path.' | ||
}, | ||
success: { | ||
@@ -46,7 +38,15 @@ description: 'The file exists and has been successfully opened. The resulting stream may be read at any time.', | ||
'In other words, it is _paused_. That means you don\'t have to worry about using it immediately (i.e. before even one tick of the event loop elapses).', | ||
variableName: 'Readable stream', | ||
outputFriendlyName: 'Readable stream', | ||
outputDescription: 'A stream of data from the source file.', | ||
example: '===' | ||
outputExample: '===' | ||
}, | ||
doesNotExist: { | ||
description: 'No file could be found at the provided `source` path.' | ||
}, | ||
isDirectory: { | ||
description: 'The specified path pointed to a directory.' | ||
}, | ||
}, | ||
@@ -56,2 +56,4 @@ | ||
fn: function (inputs,exits) { | ||
// Import `path` and `fs`. | ||
var path = require('path'); | ||
@@ -61,3 +63,3 @@ var fs = require('fs'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.source = path.resolve(inputs.source); | ||
@@ -76,3 +78,3 @@ | ||
// Bind a no-op handler for the `error` event to prevent it from crashing the process if it fires. | ||
// (userland code can still bind and use its own error events) | ||
// (userland code can still bind and use its own error events). | ||
file__.on('error', function noop (err) { }); | ||
@@ -96,2 +98,3 @@ // ^ Since event handlers are garbage collected when the event emitter is itself gc()'d, it is safe | ||
// If we get an ENOENT error, set the spinlock and return through the `doesNotExist` exit. | ||
if (err.code === 'ENOENT') { | ||
@@ -102,3 +105,4 @@ alreadyExited = true; | ||
// If any other sort of miscellaneous error occurs... (as long as we haven't exited yet) | ||
// If any other sort of miscellaneous error occurs, set the spinlock and forward it through | ||
// the `error` exit. | ||
alreadyExited = true; | ||
@@ -117,4 +121,8 @@ return exits.error(err); | ||
fs.fstat(fd, function (err, stats) { | ||
// If the spinlock is set, do nothing. | ||
if (alreadyExited) {return;} | ||
// Handle unknown errors by setting the spinlock and forwarding them through | ||
// our `error` exit. | ||
if (err) { | ||
@@ -125,2 +133,3 @@ alreadyExited = true; | ||
// If we determined this path to be a directory, set the spinlock and call the `isDirectory` exit. | ||
if (stats.isDirectory()) { | ||
@@ -131,2 +140,3 @@ alreadyExited = true; | ||
// Otherwise set the spinlock and return the new stream through the `success` exit. | ||
alreadyExited = true; | ||
@@ -133,0 +143,0 @@ return exits.success(file__); |
@@ -16,3 +16,3 @@ module.exports = { | ||
cacheable: true, | ||
sideEffects: 'cacheable', | ||
@@ -23,3 +23,3 @@ | ||
source: { | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory).', | ||
example: '/Users/mikermcneil/.tmp/foo', | ||
@@ -34,9 +34,14 @@ required: true | ||
success: { | ||
outputExample: 'stuff in a file!', | ||
outputFriendlyName: 'File contents', | ||
outputDescription: 'The contents of the file at the `source` path.' | ||
}, | ||
doesNotExist: { | ||
description: 'No file exists at the provided `source` path' | ||
description: 'No file could be found at the provided `source` path.' | ||
}, | ||
success: { | ||
example: 'stuff in a file!', | ||
description: 'Returns the contents of the file at `source` path' | ||
isDirectory: { | ||
description: 'The specified path pointed to a directory.' | ||
} | ||
@@ -48,2 +53,4 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs`. | ||
var path = require('path'); | ||
@@ -53,17 +60,29 @@ var fs = require('fs'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.source = path.resolve(inputs.source); | ||
// Declare a var to contain the contents of the file | ||
// we're trying to read. | ||
var contents; | ||
// Attempt to read the file contents synchronously. | ||
try { | ||
contents = fs.readFileSync(inputs.source, 'utf8'); | ||
// It worked! | ||
// It worked! Return the contents through the `success` exit. | ||
return exits.success(contents); | ||
} | ||
// If there was an error... | ||
catch (e) { | ||
// If it was a "file not found", leave through the `doesNotExist` exit. | ||
if (e.code === 'ENOENT') { | ||
return exits.doesNotExist(); | ||
} | ||
// Some unrecognized error | ||
return exits.error(err); | ||
// If we got an EISDIR error, it means the path points to a directory, so | ||
// we'll leave through the `isDirectory` exit. | ||
if (e.code === 'EISDIR') { | ||
return exits.isDirectory(); | ||
} | ||
// Otherwise output the unrecognized error through the `error` exit. | ||
return exits.error(e); | ||
} | ||
@@ -70,0 +89,0 @@ } |
@@ -13,3 +13,3 @@ module.exports = { | ||
cacheable: true, | ||
sideEffects: 'cacheable', | ||
@@ -20,3 +20,3 @@ | ||
source: { | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory).', | ||
example: '/Users/mikermcneil/.tmp/foo', | ||
@@ -31,9 +31,14 @@ required: true | ||
success: { | ||
outputFriendlyName: 'File contents', | ||
outputExample: 'stuff in a file!', | ||
outputDescription: 'The contents of the file at the specified `source` path.' | ||
}, | ||
doesNotExist: { | ||
description: 'No file exists at the provided `source` path' | ||
description: 'No file could be found at the provided `source` path.' | ||
}, | ||
success: { | ||
example: 'stuff in a file!', | ||
description: 'Returns the contents of the file at `source` path' | ||
isDirectory: { | ||
description: 'The specified path pointed to a directory.' | ||
} | ||
@@ -45,2 +50,4 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs`. | ||
var path = require('path'); | ||
@@ -50,18 +57,31 @@ var fs = require('fs'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.source = path.resolve(inputs.source); | ||
// Attempt to read the file at the specified path. | ||
fs.readFile(inputs.source, 'utf8', function (err, contents) { | ||
// It worked! | ||
// It worked! Return the file contents through the `success` exit. | ||
if (!err) { | ||
return exits.success(contents); | ||
} | ||
// No need for `null` check here because we already know `err` is falsy | ||
if (typeof err === 'object' && err.code === 'ENOENT') { | ||
// If we got an ENOENT error, it means the file does not exits, so we'll | ||
// leave through the `doesNotExist` exit. | ||
if (err.code === 'ENOENT') { | ||
return exits.doesNotExist(); | ||
} | ||
// Some unrecognized error | ||
// If we got an EISDIR error, it means the path points to a directory, so | ||
// we'll leave through the `isDirectory` exit. | ||
if (err.code === 'EISDIR') { | ||
return exits.isDirectory(); | ||
} | ||
// Some unrecognized error occurred, so we'll just forward it through | ||
// our `error` exit. | ||
return exits.error(err); | ||
}); | ||
} | ||
}; |
@@ -13,3 +13,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'idempotent', | ||
@@ -37,2 +37,4 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
@@ -44,4 +46,7 @@ var fsx = require('fs-extra'); | ||
// Attempt to remove the path and all its descendents. | ||
fsx.remove(inputs.path, function(err) { | ||
// Return any errors through the `error` exit. | ||
if (err) {return exits.error(err);} | ||
// If successful, return through the `success` exit. | ||
return exits.success(); | ||
@@ -48,0 +53,0 @@ }); |
@@ -13,3 +13,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'cacheable', | ||
@@ -26,3 +26,3 @@ | ||
destination: { | ||
description: 'The path on disk where the resulting file should be written', | ||
description: 'The path on disk where the resulting file should be written.', | ||
example: '/Users/mikermcneil/.tmp/bar.md', | ||
@@ -34,3 +34,3 @@ required: true | ||
friendlyName: 'Template data', | ||
description: 'The data which will be accessible from the template', | ||
description: 'The data which will be accessible from the template.', | ||
extendedDescription: 'Each key will be a variable accessible in the template. For instance, if you supply an array `[{name:"Chandra"}, {name:"Mary"}]` as the key "friends", then you will be able to access `friends` from the template; i.e. `<ul><% _.each(friends, function (friend){ %><li><%= friend.name %></li> <%}); %></ul>` Use `<%= %>` to inject the contents of a variable as-is, `<%- %>` to HTML-escape them first, or `<% %>` to execute some JavaScript code.', | ||
@@ -65,12 +65,12 @@ example: '===', | ||
noTemplate: { | ||
description: 'Source template file not found.' | ||
description: 'The source template file could not be found.' | ||
}, | ||
missingData: { | ||
friendlyName: 'missing data', | ||
description: 'One or more variables used in the template were not provided in the template data.', | ||
variableName: 'info', | ||
example: { | ||
outputFriendlyName: 'Missing data info', | ||
outputDescription: 'Information about the missing template data.', | ||
outputExample: { | ||
message: 'Some variables (`me`,`friends`) were used in template "/code/machine/docs/.type-table.tpl", but not provided in the template data dictionary.', | ||
missingVariables: ['me', 'friends'] | ||
missingVariables: ['me'] | ||
} | ||
@@ -84,3 +84,3 @@ }, | ||
alreadyExists: { | ||
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)' | ||
description: 'An existing file was found at the specified path (overwrite by enabling the `force` input).' | ||
} | ||
@@ -92,21 +92,36 @@ | ||
fn: function (inputs, exits) { | ||
var thisPack = require('../'); | ||
var MPStrings = require('machinepack-strings'); | ||
// Read template from disk | ||
thisPack.read({ | ||
// Import `machinepack-strings`. | ||
var Strings = require('machinepack-strings'); | ||
// Get a handle to this pack. | ||
var Filesystem = require('../'); | ||
// Read template from disk. | ||
Filesystem.read({ | ||
source: inputs.source | ||
}).exec({ | ||
// If the template could not be found, exit through the `doesNotExist` exit. | ||
doesNotExist: exits.noTemplate, | ||
// If an unknown error occurred trying to read the template file, exit through | ||
// the `error` exit. | ||
error: exits.error, | ||
doesNotExist: exits.noTemplate, | ||
// If the template was read successfully... | ||
success: function (templateStr) { | ||
MPStrings.template({ | ||
// Use the `Strings.template` machine to replace tokens in the template | ||
// with input data. | ||
Strings.template({ | ||
templateStr: templateStr, | ||
data: inputs.data | ||
}).exec({ | ||
error: exits.error, | ||
// If the template contained tokens that were missing from the `inputs.data` | ||
// dictionary, leave through the `missingData` exit. | ||
missingData: exits.missingData, | ||
// If another rendering error occurred, leave through the `couldNotRender` exit. | ||
couldNotRender: exits.couldNotRender, | ||
// If an unknown error occurred, leave through the `error` exit. | ||
error: exits.error, | ||
success: function (renderedStr) { | ||
thisPack.write({ | ||
// Now attempt to write the rendered template to disk. | ||
Filesystem.write({ | ||
destination: inputs.destination, | ||
@@ -116,4 +131,8 @@ string: renderedStr, | ||
}).exec({ | ||
// If a file was found at the destination and `inputs.force` was not set, | ||
// leave through the `alreadyExists` exit. | ||
alreadyExists: exits.alreadyExists, | ||
// If an unknown error occurred, leave through the `error` exit. | ||
error: exits.error, | ||
alreadyExists: exits.alreadyExists, | ||
// The file write was successful, so leave through the `success` exit. | ||
success: exits.success | ||
@@ -120,0 +139,0 @@ }); |
@@ -13,3 +13,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'idempotent', | ||
@@ -21,3 +21,3 @@ | ||
example: '*', | ||
description: 'The data to write to disk as JSON', | ||
description: 'The data to write to disk as JSON.', | ||
required: true | ||
@@ -28,3 +28,3 @@ }, | ||
example: '/Users/mikermcneil/.tmp/bar.json', | ||
description: 'Absolute path for the destination file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path for the destination file (if relative path is provided, will resolve path from current working directory).', | ||
required: true | ||
@@ -49,3 +49,3 @@ }, | ||
alreadyExists: { | ||
description: 'A file or folder already exists at the specified destination' | ||
description: 'An existing file or folder was found at the specified destination. Use `force` to overwrite.' | ||
}, | ||
@@ -57,12 +57,23 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
var fsx = require('fs-extra'); | ||
// Import this pack | ||
var Filesystem = require('../'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.destination = path.resolve(inputs.destination); | ||
// Only override an existing file if `inputs.force` is true | ||
fsx.exists(inputs.destination, function(exists) { | ||
// Determine whether the destination already exists. | ||
Filesystem.exists({path: inputs.destination}).exec(function(err, exists) { | ||
// If an error occurred checking for file existence, forward it through | ||
// our `error` exit. | ||
if (err) {return exits.error(err);} | ||
// If one exists, and the `force` flag is not set, leave | ||
// through the `alreadyExists` exit. | ||
if (exists && !inputs.force) { | ||
@@ -74,5 +85,7 @@ return exits.alreadyExists(); | ||
(function _deleteExistingFilesAndOrDirsIfNecessary(next) { | ||
// If nothing was there, continue. | ||
if (!exists) { | ||
return next(); | ||
} | ||
// Otherwise attempt to remove the existing file / folder. | ||
else { | ||
@@ -82,9 +95,19 @@ fsx.remove(inputs.destination, next); | ||
})(function nowWriteFileToDisk(err){ | ||
if (err) { return exits(err); } | ||
// If there was an error removing the existing file / folder, | ||
// forward it to our `error` exit. | ||
if (err) { return exits.error(err); } | ||
// Now write the JSON file to disk. | ||
fsx.outputJson(inputs.destination, inputs.json, exits); | ||
fsx.outputJson(inputs.destination, inputs.json, function(err) { | ||
// If there was an error writing the file, | ||
// forward it to our `error` exit. | ||
if (err) { return exits.error(err); } | ||
// Writing was successful, so leave through the `success` exit. | ||
return exits.success(); | ||
}); | ||
});//</after deleting existing file(s)/dir(s) if necessary> | ||
});//</fsx.exists()> | ||
});//</Filesystem.exists()> | ||
} | ||
@@ -91,0 +114,0 @@ |
@@ -13,3 +13,2 @@ module.exports = { | ||
sourceStream: { | ||
friendlyName: 'Source stream', | ||
description: 'The source (Readable) stream whose contents will be pumped to disk.', | ||
@@ -23,3 +22,3 @@ extendedDescription: 'Must be a utf8-encoded, modern (streams2 or streams3) Readable stream.', | ||
example: '/Users/mikermcneil/.tmp/bar.json', | ||
description: 'Absolute path for the destination file (if relative path is provided, will resolve path from current working directory)', | ||
description: 'Absolute path for the destination file (if relative path is provided, will resolve path from current working directory).', | ||
required: true | ||
@@ -44,3 +43,3 @@ }, | ||
alreadyExists: { | ||
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)' | ||
description: 'An existing file / folder was found at the specified path (overwrite by enabling the `force` input).' | ||
}, | ||
@@ -66,9 +65,19 @@ | ||
fn: function(inputs, exits) { | ||
// Import `path` | ||
var path = require('path'); | ||
// Import Lodash `isFunction` and `isObject` methods. | ||
var isFunction = require('lodash.isfunction'); | ||
var isObject = require('lodash.isobject'); | ||
// Import `fs-extra`. | ||
var fsx = require('fs-extra'); | ||
// Import this pack | ||
var Filesystem = require('../'); | ||
// Check for the methods we need on the provided Readable source stream. | ||
if (!isObject(inputs.sourceStream) || !isFunction(inputs.sourceStream.pipe) || !isFunction(inputs.sourceStream.on)) { | ||
// If the give `sourceStream` is invalid, leave through the `error` exit. | ||
return exits.error(new Error('Invalid stream provided (has no `.pipe()` and/or `.on()` methods).')); | ||
@@ -80,4 +89,11 @@ } | ||
// Only override an existing file if `inputs.force` is true. | ||
fsx.exists(inputs.destination, function(exists) { | ||
// Determine whether the destination already exists. | ||
Filesystem.exists({path: inputs.destination}).exec(function(err, exists) { | ||
// If an error occurred checking for file existence, forward it through | ||
// our `error` exit. | ||
if (err) {return exits.error(err);} | ||
// If one exists, and the `force` flag is not set, leave | ||
// through the `alreadyExists` exit. | ||
if (exists && !inputs.force) { | ||
@@ -89,5 +105,7 @@ return exits.alreadyExists(); | ||
(function _deleteExistingFilesAndOrDirsIfNecessary(next) { | ||
// If nothing was there, continue. | ||
if (!exists) { | ||
return next(); | ||
} | ||
// Otherwise attempt to remove the existing file / folder. | ||
else { | ||
@@ -101,3 +119,3 @@ fsx.remove(inputs.destination, next); | ||
// This is where the content will go. | ||
var writeDrain = fsx.createOutputStream(inputs.destination); | ||
var writeDrain = fsx.createWriteStream(inputs.destination); | ||
@@ -112,4 +130,6 @@ // Pipe the source stream down the drain. | ||
// Handle write errors. | ||
// (note that errors on the source Readable stream are the | ||
// responsibility of the provider of said stream) | ||
// Note that errors on the source Readable stream are the | ||
// responsibility of the provider of said stream. | ||
// | ||
// Declare a variable to act as a spinlock. | ||
var hasAlreadyCalledExit; | ||
@@ -121,2 +141,3 @@ writeDrain.on('error', function (err){ | ||
if (!hasAlreadyCalledExit) { | ||
// Set the spinlock and leave through the `error` exit. | ||
hasAlreadyCalledExit = true; | ||
@@ -128,4 +149,4 @@ return exits.error(err); | ||
// So we just ignore it. | ||
// (we need to keep this handler bound or an error will be | ||
// thrown, potentially crashing the process) | ||
// We need to keep this handler bound or an error will be | ||
// thrown, potentially crashing the process. | ||
}); | ||
@@ -135,3 +156,5 @@ | ||
writeDrain.once('finish', function (){ | ||
// If the spinlock is set (because we already exited) do nothing. | ||
if (hasAlreadyCalledExit) { return; } | ||
// Otherwise set the spinlock and leave through the `success` exit. | ||
hasAlreadyCalledExit = true; | ||
@@ -141,3 +164,3 @@ return exits.success(); | ||
});//</after _deleteExistingFilesAndOrDirsIfNecessary> | ||
});//</fsx.exists()> | ||
});//</Filesystem.exists()> | ||
}, | ||
@@ -144,0 +167,0 @@ |
@@ -16,3 +16,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'idempotent', | ||
@@ -23,3 +23,3 @@ | ||
string: { | ||
description: 'Text to write to the file (if omitted, will create an empty file)', | ||
description: 'Text to write to the file (if omitted, will create an empty file).', | ||
example: 'lots of words, utf8 things you know', | ||
@@ -51,3 +51,3 @@ defaultsTo: '' | ||
alreadyExists: { | ||
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)' | ||
description: 'An existing file / folder was found at the specified path (overwrite by enabling the `force` input).' | ||
}, | ||
@@ -59,3 +59,7 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path`. | ||
var path = require('path'); | ||
// Import `fs` and `fs-extra`. | ||
var fs = require('fs'); | ||
@@ -65,6 +69,8 @@ var fsx = require('fs-extra'); | ||
// In case we ended up here w/ a relative path, | ||
// resolve it using the process's CWD | ||
// resolve it using the process's CWD. | ||
inputs.destination = path.resolve(inputs.destination); | ||
// Only override an existing file if `inputs.force` is true | ||
// Only override an existing file if `inputs.force` is true. | ||
// Any errors thrown will automatically be caught and forwarded | ||
// through our `error` exit. | ||
if (inputs.force) { | ||
@@ -76,9 +82,19 @@ fsx.outputFileSync(inputs.destination, inputs.string); | ||
// Otherwise don't override existing files. | ||
if (fs.existsSync(inputs.destination)) { | ||
// TODO: Some time before fs.existsSync() is deprecated in | ||
// Node core, switch this to use a different strategy. | ||
// See `https://nodejs.org/api/fs.html#fs_fs_exists_path_callback` | ||
try { | ||
// Try to `stat` the destination. | ||
fs.statSync(inputs.destination); | ||
// If we can do so without error, it means the file already | ||
// exists, so call our `alreadyExists` exit. | ||
return exits.alreadyExists(); | ||
} | ||
catch (e) { | ||
// Otherwise we're okay, so continue. | ||
} | ||
// Attempt to write the file to disc. | ||
// Any errors thrown will automatically be caught and forwarded | ||
// through our `error` exit. | ||
fs.writeFileSync(inputs.destination, inputs.string); | ||
// Return through the `success` exit. | ||
return exits.success(); | ||
@@ -85,0 +101,0 @@ |
@@ -10,3 +10,3 @@ module.exports = { | ||
idempotent: true, | ||
sideEffects: 'idempotent', | ||
@@ -17,3 +17,3 @@ | ||
string: { | ||
description: 'Text to write to the file (if omitted, will create an empty file)', | ||
description: 'Text to write to the file (if omitted, will create an empty file).', | ||
example: 'lots of words, utf8 things you know', | ||
@@ -45,3 +45,3 @@ defaultsTo: '' | ||
alreadyExists: { | ||
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)' | ||
description: 'An existing file / folder was found at the specified path (overwrite by enabling the `force` input).' | ||
}, | ||
@@ -53,5 +53,9 @@ | ||
fn: function (inputs, exits) { | ||
// Import `path` and `fs-extra`. | ||
var path = require('path'); | ||
var fsx = require('fs-extra'); | ||
// Import this pack | ||
var Filesystem = require('../'); | ||
@@ -62,4 +66,11 @@ // In case we ended up here w/ a relative path, | ||
// Only override an existing file if `inputs.force` is true | ||
fsx.exists(inputs.destination, function(exists) { | ||
// Determine whether the destination already exists. | ||
Filesystem.exists({path: inputs.destination}).exec(function(err, exists) { | ||
// If an error occurred checking for file existence, forward it through | ||
// our `error` exit. | ||
if (err) {return exits.error(err);} | ||
// If one exists, and the `force` flag is not set, leave | ||
// through the `alreadyExists` exit. | ||
if (exists && !inputs.force) { | ||
@@ -71,5 +82,7 @@ return exits.alreadyExists(); | ||
(function _deleteExistingFilesAndOrDirsIfNecessary(next) { | ||
// If nothing was there, continue. | ||
if (!exists) { | ||
return next(); | ||
} | ||
// Otherwise attempt to remove the existing file / folder. | ||
else { | ||
@@ -82,6 +95,14 @@ fsx.remove(inputs.destination, next); | ||
// Now write the file to disk. | ||
fsx.outputFile(inputs.destination, inputs.string, exits); | ||
fsx.outputFile(inputs.destination, inputs.string, function(err) { | ||
// If there was an error writing the file, | ||
// forward it to our `error` exit. | ||
if (err) { return exits.error(err); } | ||
// Writing was successful, so leave through the `success` exit. | ||
return exits.success(); | ||
}); | ||
});//</after deleting existing file(s)/dir(s) if necessary> | ||
});//</fsx.exists()> | ||
});//</Filesystem.exists()> | ||
} | ||
@@ -88,0 +109,0 @@ |
{ | ||
"name": "machinepack-fs", | ||
"version": "8.0.2", | ||
"version": "9.0.0-0", | ||
"description": "Work with the local filesystem; list files, write files, etc.", | ||
"scripts": { | ||
"test": "node ./node_modules/test-machinepack-mocha/bin/testmachinepack-mocha.js" | ||
"test": "mocha tests/** -R spec" | ||
}, | ||
@@ -16,6 +16,6 @@ "keywords": [ | ||
"dependencies": { | ||
"fs-extra": "0.26.5", | ||
"fs-extra": "0.30.0", | ||
"lodash.isfunction": "3.0.8", | ||
"lodash.isobject": "3.0.2", | ||
"machine": "~12.1.0", | ||
"machine": "^13.0.0-11", | ||
"machinepack-json": "~2.0.0", | ||
@@ -28,3 +28,4 @@ "machinepack-strings": "~5.0.0", | ||
"devDependencies": { | ||
"mocha": "~1.19.0", | ||
"lodash": "^3.10.1", | ||
"mocha": "3.0.2", | ||
"test-machinepack-mocha": "^2.1.3" | ||
@@ -52,7 +53,7 @@ }, | ||
"ensure-dir", | ||
"ensure-json", | ||
"write-sync", | ||
"read-sync", | ||
"read-stream", | ||
"write-stream" | ||
"write-stream", | ||
"rmrf-sync" | ||
], | ||
@@ -59,0 +60,0 @@ "testsUrl": "https://travis-ci.org/mikermcneil/machinepack-fs" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50828
1176
3
2
15
+ Addedfs-extra@0.30.0(transitive)
+ Addedinclude-all@1.0.8(transitive)
+ Addedmachine@13.0.0-24(transitive)
+ Addedrttc@9.8.2(transitive)
+ Addedswitchback@2.0.5(transitive)
- Removedfs-extra@0.26.5(transitive)
Updatedfs-extra@0.30.0
Updatedmachine@^13.0.0-11