Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

machinepack-fs

Package Overview
Dependencies
Maintainers
5
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

machinepack-fs - npm Package Compare versions

Comparing version 2.3.0 to 3.0.0

21

machines/cp.js
module.exports = {
friendlyName: 'Copy file or directory',
friendlyName: 'Copy (cp)',
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`)',
inputs: {
source: {

@@ -12,2 +20,3 @@ example: '/Users/mikermcneil/.tmp/foo',

},
destination: {

@@ -18,10 +27,12 @@ example: '/Users/mikermcneil/.tmp/bar',

}
},
defaultExit: 'success',
catchallExit: 'error',
exits: {
error: {},
success: {}
success: {
description: 'Done.'
}
},

@@ -28,0 +39,0 @@

module.exports = {
friendlyName: 'Ensure directory exists',
friendlyName: 'Ensure directory',

@@ -10,3 +10,3 @@

extendedDescription: '',
idempotent: true,

@@ -26,5 +26,2 @@

defaultExit: 'success',
exits: {

@@ -31,0 +28,0 @@

@@ -13,3 +13,3 @@ module.exports = {

cacheable: true,
idempotent: true,

@@ -16,0 +16,0 @@

module.exports = {
friendlyName: 'Check existence',
friendlyName: 'Exists?',

@@ -5,0 +5,0 @@

module.exports = {
friendlyName: 'List directory contents',
friendlyName: 'List contents (ls)',
description: 'List contents of a directory on the local filesystem.',
cacheable: true,
inputs: {
dir: {
friendlyName: 'Directory path',
example: '/Users/mikermcneil/.tmp/foo',
description: 'Absolute path to the directory whose contents should be listed (if relative path provided, will be resolved from cwd).',
description: 'Path to the directory whose contents should be listed.',
extendedDescription: 'If a relative path is provided, it will be resolved to an absolute path from the context of the current working directory.',
required: true
},
depth: {
description: 'The maximum number of "hops" (i.e. directories deep) to include directory contents from. 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.',
example: 2
friendlyName: 'Depth',
description: 'The maximum number of "hops" (i.e. directories deep) to include directory contents from.',
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.',
example: 1,
defaultsTo: 1
},
types: {
description: 'The types of directory entries to return (defaults to ["all"])',
example: ['file'],
includeFiles: {
friendlyName: 'Files?',
description: 'Whether or not to include files',
example: true,
defaultsTo: true
},
includeDirs: {
friendlyName: 'Directories?',
description: 'Whether or not to include directories',
example: true,
defaultsTo: true
},
includeSymlinks: {
friendlyName: 'Symlinks?',
description: 'Whether or not to include symbolic links',
example: true,
defaultsTo: true
},
includeHidden: {
friendlyName: 'Hidden entries?',
description: 'Whether or not to include hidden files/directories/symlinks',
example: false,
defaultsTo: false
}
},
defaultExit: 'success',
catchallExit: 'error',
exits: {
error: {
description: 'Triggered when a filesystem error occurs'
},
success: {
variableName: 'dirContents',
example: [

@@ -34,77 +70,89 @@ '/Users/mikermcneil/.tmp/foo/.gitignore'

}
},
fn: function (inputs, exits) {
var path = require('path');
var Walker = require('walker');
try {
// Ensure we've got an absolute path.
inputs.dir = path.resolve(inputs.dir);
// Ensure we've got an absolute path
inputs.dir = path.resolve(inputs.dir);
// Determine the depth of the top-level directory we're walking,
// for comparison later on.
var topLvlDirDepth = inputs.dir.split(path.sep).length;
var spinlock;
var results = [];
// Initialize the walker and teach it to skip walking directories
// that are:
// • deeper than requested, or
// • hidden (if the `includeHidden` input is set to false)
var walker = Walker(inputs.dir);
walker.filterDir(function(dir, stat) {
// Too deep
if (dir.split(path.sep).length > (topLvlDirDepth + inputs.depth)) {
return false;
}
// Too hidden
if (path.basename(dir).match(/^\./) && !inputs.includeHidden) {
return false;
}
return true;
});
// Default depth to 0 (infinite recursion)
var depth = inputs.depth || 0;
// Get the depth of the directory we're walking, for comparison
var dirDepth = inputs.dir.split(path.sep).length;
// Default types to "all"
var types = inputs.types || 'all';
// Initialize the walker
var walker = require('walker')(inputs.dir)
// Skip directories that are deeper than requested
.filterDir(function(dir, stat) {
if (depth && dir.split(path.sep).length > (dirDepth + depth)) {
return false;
// Accumulate results array by listing file, directory, and/or symlink
// entries from the specified directory.
var results = [];
if (inputs.includeFiles) {
walker.on('file', function (entry, stat) {
// Add the new entry to our result list unless it is:
// • hidden (and the `includeHidden` input is set to false), or
// • too deep
var tooHidden = path.basename(entry).match(/^\./) && !inputs.includeHidden;
var tooDeep = entry.split(path.sep).length > (topLvlDirDepth + inputs.depth);
if ( !tooHidden && !tooDeep ) {
results.push(entry);
}
return true;
})
// Handle errors
.on('error', function (err){
if (spinlock) return;
spinlock = true;
return exits.error(err);
})
// When walking is done, return the results
.on('end', function (){
if (spinlock) return;
spinlock = true;
return exits.success(results);
});
// Include file entries if requested
if (types == 'all' || types.indexOf('file') > -1) {
walker.on('file', function (entry, stat) {
// Filter out files that are deeper than requested
if (!depth || (entry.split(path.sep).length <= (dirDepth + depth))) {
results.push(entry);
}
});
}
// Include directory entries if requested
if (types == 'all' || types.indexOf('dir') > -1) {
walker.on('dir', function (entry, stat) {
if (entry===inputs.dir) return;
}
if (inputs.includeDirs) {
walker.on('dir', function (entry, stat) {
// If this is the top-level directory, exclude it.
if (entry === inputs.dir) return;
// Add the new entry to our result list unless it is:
// • hidden (and the `includeHidden` input is set to false)
var tooHidden = path.basename(entry).match(/^\./) && !inputs.includeHidden;
if ( !tooHidden ) {
results.push(entry);
});
}
// Include symlink entries if requested
if (types == 'all' || types.indexOf('symlink') > -1) {
walker.on('symlink', function (entry, stat) {
if (entry===inputs.dir) return;
}
results.push(entry);
});
}
if (inputs.includeSymlinks) {
walker.on('symlink', function (entry, stat) {
// If this is the top-level directory, exclude it.
if (entry===inputs.dir) return;
// Add the new entry to our result list unless it is:
// • hidden (and the `includeHidden` input is set to false)
var tooHidden = path.basename(entry).match(/^\./) && !inputs.includeHidden;
if ( !tooHidden ) {
results.push(entry);
});
}
}
results.push(entry);
});
}
catch(e){
return exits.error(e);
}
// When walking is done, because of an error or otherwise,
// return the results.
var spinlock;
walker.on('error', function (err){
if (spinlock) return;
spinlock = true;
return exits.error(err);
});
walker.on('end', function (){
if (spinlock) return;
spinlock = true;
return exits.success(results);
});
}

@@ -111,0 +159,0 @@ };

module.exports = {
friendlyName: 'Create directory',
friendlyName: 'Make directory (mkdir)',
description: 'Create a new directory.',
description: 'Make a new directory.',

@@ -9,0 +9,0 @@

module.exports = {
friendlyName: 'Move file or directory',
friendlyName: 'Move (mv)',
description: 'Move file or directory located at source path to the destination path.',
extendedDescription: '',
inputs: {
source: {

@@ -10,2 +16,3 @@ example: '/Users/mikermcneil/.tmp/foo',

},
destination: {

@@ -15,12 +22,15 @@ example: '/Users/mikermcneil/.tmp/bar',

}
},
defaultExit: 'success',
exits: {
error: {
description: 'Unexpected error occurred.'
},
success: {
description: 'Done.'
}
},
fn: function(inputs, exits) {

@@ -27,0 +37,0 @@ var fsx = require('fs-extra');

module.exports = {
friendlyName: 'Read JSON file',
description: 'Read and parse JSON file located at source path on disk into usable data.',
extendedDescription: 'Assumes file is encoded using utf8.',
cacheable: true,
idempotent: true,
inputs: {
source: {

@@ -14,2 +23,3 @@ description: 'Absolute path to the source file (if relative path is provided, will resolve path from current working directory)',

},
schema: {

@@ -20,16 +30,20 @@ description: 'An example of what the parsed data should look like (used for type-coercion)',

}
},
defaultExit: 'success',
exits: {
error: {},
doesNotExist: {
description: 'No file exists at the provided `source` path'
},
couldNotParse: {
description: 'Could not parse file as JSON.'
},
// TODO: not a file (and return what it ACTUALLY is, e.g. dir or symlink)
success: {
description: 'Returns the data stored in file at `source` path',
description: 'Returns parsed JSON data from the source file.',
getExample: function (inputs){

@@ -39,11 +53,12 @@ return inputs.schema;

}
},
fn: function (inputs, exits) {
var Util = require('machinepack-util');
var MPJSON = require('machinepack-json');
var thisPack = require('../');
var readFile = require('machine').build(require('./read'));
readFile({
thisPack.read({
source: inputs.source

@@ -54,3 +69,3 @@ }).exec({

success: function (contents){
Util.parseJson({
MPJSON.parse({
json: contents,

@@ -68,2 +83,4 @@ schema: inputs.schema

}
};

@@ -16,5 +16,2 @@ module.exports = {

idempotent: true,
inputs: {

@@ -21,0 +18,0 @@

module.exports = {
friendlyName: 'Delete file or directory',
friendlyName: 'Remove (rm)',
description: 'Completely remove a file or directory (like rm -rf).',
extendedDescription: 'If the provided path is a directory, all contents will be removed recursively. If nothing exists at the provided path, the success exit will be triggered, but nothing will be deleted.',
idempotent: true,
inputs: {
dir: {

@@ -13,9 +23,12 @@ example: '/Users/mikermcneil/.tmp/foo',

}
},
defaultExit: 'success',
exits: {
error: {},
success: {}
success: {
description: 'Done.'
}
},

@@ -22,0 +35,0 @@

module.exports = {
friendlyName: 'Template file',
description: 'Read file at source path, replace substrings with provided data, then write to destination path.',
extendedDescription: 'Uses lodash template syntax (e.g. `"Hi there, <%=firstName%>!"`)',
friendlyName: 'Template',
description: 'Read file at source path as a template, render with provided data, then write to destination path.',
extendedDescription: 'Uses Lodash template syntax (e.g. `<%= %>`, `<%- %>`, `<% %>`) Also provides access to the Node.js core utility module (as `util`), as well as Lodash itself (as `_`).',
idempotent: true,
inputs: {
source: {
example: '/Users/mikermcneil/.tmp/foo',
description: 'The path on disk to the template file.',
example: '/Users/mikermcneil/.tmp/foo.tpl',
required: true
},
destination: {
example: '/Users/mikermcneil/.tmp/bar',
description: 'The path on disk where the resulting file should be written',
example: '/Users/mikermcneil/.tmp/bar.md',
required: true
},
data: {
friendlyName: 'Template data',
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.',
typeclass: 'dictionary'

@@ -26,93 +43,78 @@ // e.g. {

},
force: {
description: 'overwrite existing file(s)?',
example: false
},
options: {
description: 'template options (see http://lodash.com/docs#template)',
typeclass: 'dictionary'
// example: {
// interpolate: /{{([\s\S]+?)}}/g
// }
friendlyName: 'Force?',
description: 'Whether or not to overwrite existing file(s).',
example: false,
defaultsTo: false
}
},
defaultExit: 'success',
exits: {
error: {
description: 'Unexpected error occurred.'
},
success: {
description: 'File written successfully.'
},
noTemplate: {
description: 'Source template file not found'
description: 'Source template file not found.'
},
missingData: {
friendlyName: 'missing data',
description: 'One or more variables used in the template were not provided in the template data.',
variableName: 'info',
example: {
status: 500,
exit: 'missingData',
name: 'ReferenceError',
message: '`appname` is used in template "/Users/mikermcneil/.tmp/foo", but no value for `appname` was provided as template data.'
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']
}
}
},
},
fn: function (inputs, exits) {
couldNotRender: {
description: 'Could not render the template due to invalid or unparseable syntax.'
},
var util = require('util');
var fsx = require('fs-extra');
var _ = require('lodash');
var writeFileFromStr = require('machine').build(require('./write'));
alreadyExists: {
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)'
}
fsx.readFile(inputs.source, 'utf8', function(err, contents) {
if (err) {
err = (typeof err === 'object' && err instanceof Error) ? err : new Error(err);
err.message = 'Template error: ' + err.message;
err.path = inputs.source;
if (err.code === 'ENOENT') {
return (exits.noTemplate||exits.error)(err);
}
return exits.error(err);
}
try {
var options = inputs.options || {};
contents = _.template(contents, inputs.data||{}, options);
},
// With lodash teplates, HTML entities are escaped by default.
// Default assumption is we DON'T want that, so we'll reverse it.
if (!inputs.escapeHTMLEntities) {
contents = _.unescape(contents);
}
} catch (e) {
var err = e;
if (!(typeof err === 'object' && err instanceof Error)){
err = new Error(err);
}
// Recognize lodash template error (scope variable not defined)
if (err.name === 'ReferenceError' || err.type === 'not_defined') {
var undefinedScopeVar = err.arguments && err.arguments[0];
err = {
status: 500,
exit: 'missingData',
name: 'ReferenceError',
message: util.format('`%s` is used in template "%s", but no value for `%s` was provided as template data.', undefinedScopeVar, inputs.source, undefinedScopeVar)
};
return (exits.missingData||exits.error)(err);
}
fn: function (inputs, exits) {
var thisPack = require('../');
var MPStrings = require('machinepack-strings');
return exits.error(e);
// Read template from disk
thisPack.read({
source: inputs.source
}).exec({
error: exits.error,
doesNotExist: exits.noTemplate,
success: function (contents) {
MPStrings.template({
templateStr: contents,
data: inputs.data
}).exec({
error: exits.error,
missingData: exits.missingData,
couldNotRender: exits.couldNotRender,
success: function (rendered) {
thisPack.write({
destination: inputs.destination,
string: rendered,
force: inputs.force
}).exec({
error: exits.error,
alreadyExists: exits.alreadyExists,
success: exits.success
});
}
});
}
});
// Finally, write templated string to disk
writeFileFromStr({
force: inputs.force,
string: contents,
destination: inputs.destination
})
.exec(exits);
});
}
};
module.exports = {
friendlyName: 'Write JSON file',
description: 'Write some data to the specified destination path on disk.',
extendedDescription: 'Assumes file is encoded using utf8.',
idempotent: true,
inputs: {
json: {

@@ -12,2 +23,3 @@ typeclass: '*',

},
destination: {

@@ -18,22 +30,25 @@ example: '/Users/mikermcneil/.tmp/bar.json',

},
force: {
description: 'Overwrite existing file(s)?',
example: false
example: false,
defaultsTo: false
}
},
defaultExit: 'success',
exits: {
error: {
description: 'Unexpected error occurred'
},
alreadyExists: {
description: 'A file or folder already exists at the specified `destination`'
description: 'A file or folder already exists at the specified destination'
},
success: {
description: 'JSON file written successfully.'
}
},
fn: function (inputs, exits) {

@@ -56,5 +71,2 @@

// Don't actually write the file if this is a dry run.
if (inputs.dry) return exits.success();
async.series([

@@ -75,2 +87,4 @@ function deleteExistingFileIfNecessary(next) {

}
};
module.exports = {
friendlyName: 'Write file from string',
friendlyName: 'Write file',
description: 'Generate a file on the local filesystem using the specified utf8 string as its contents.',
idempotent: true,
inputs: {
string: {
description: 'Text to write to the file',
description: 'Text to write to the file (if omitted, will create an empty file)',
example: 'lots of words, utf8 things you know',
},
destination: {

@@ -16,19 +25,25 @@ description: 'Path (relative or absolute) to the file to write.',

},
force: {
description: 'overwrite existing file(s)?',
example: false
description: 'Whether to overwrite existing file(s) which might exist at the destination path.',
example: false,
defaultsTo: false
}
},
defaultExit: 'success',
catchallExit: 'error',
exits: {
error: {},
success: {},
alreadyExists: {
description: 'Something already exists at the specified path (overwrite by enabling the `force` input)'
},
success: {
description: 'OK.'
}
},
fn: function (inputs, exits) {

@@ -41,7 +56,2 @@

inputs = _.defaults(inputs, {
force: false,
dry: false
});
// Coerce `string` input into an actual string

@@ -60,5 +70,2 @@ inputs.string = inputs.string || '';

// Don't actually write the file if this is a dry run.
if (inputs.dry) return exits.success();
async.series([

@@ -80,2 +87,4 @@ function deleteExistingFileIfNecessary(exits) {

}
};
{
"name": "machinepack-fs",
"version": "2.3.0",
"version": "3.0.0",
"description": "Work with the local filesystem; list files, write files, etc.",

@@ -20,8 +20,10 @@ "scripts": {

"dependencies": {
"async": "^0.9.0",
"fs-extra": "~0.10.0",
"lodash": "^2.4.1",
"fs-extra": "~0.10.0",
"walker": "~1.0.6",
"machine": "^4.0.0",
"async": "^0.9.0",
"machinepack-util": "^0.7.0"
"machine": "^4.1.1",
"machinepack-json": "^1.0.0",
"machinepack-strings": "^3.1.0",
"machinepack-util": "^0.7.0",
"walker": "~1.0.6"
},

@@ -48,3 +50,2 @@ "repository": {

"ensure-dir",
"get-home-dirpath",
"ensure-json"

@@ -51,0 +52,0 @@ ],

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc