New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

machine

Package Overview
Dependencies
Maintainers
5
Versions
132
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

machine - npm Package Compare versions

Comparing version 13.0.0-1 to 13.0.0-2

231

lib/Machine.pack.js

@@ -8,2 +8,3 @@ /**

var _ = require('lodash');
var includeAll = require('include-all');

@@ -14,7 +15,18 @@

*
* Build a dictionary of machine instances.
* Load modules in the specified directory and expose them as
* a dictionary of set machine instances.
*
* > This method is used by default in the index.js file of generated machinepacks.
*
* - - - - - - - - - - - - - - - - - - - - - - - - -
* @required {Dictionary} pkg
* @optional {Dictionary} dir
* @required {Dictionary} dir
* The absolute path to the location of the modules to load & pack.
* (If a relative path is specified, it will be resolved relative from the `pkg`)
*
* @optional {Dictionary} pkg
* The package dictionary (i.e. what package.json exports).
* Will be used for refining the directory to load modules from.
* If `pkg` is not specified, all `.js` files in `dir` will be loaded
* (with the exception of `index.js`, which is reserved.)
*
* @returns {Dictionary}

@@ -25,75 +37,172 @@ */

// Get the `Machine` constructor
var Machine = this;
// If specified as a string, understand as `options.dir`.
if (_.isString(options)) {
options = { dir: options };
}
else if (_.isUndefined(options)) {
options = {};
}
else if (!_.isObject(options) || _.isFunction(options) || _.isArray(options)) {
throw new Error('Usage error: `.pack()` expects a dictionary of options, but instead got:'+util.inspect(options, {depth:null}));
}
options = options||{};
var machines;
try {
machines = options.pkg.machinepack.machines;
// Validate `dir`
if (_.isUndefined(options.dir)) {
throw new Error('Usage error: `.pack()` should be provided a `dir` option, but it was not provided. Received options:'+util.inspect(options, {depth:null}));
}
catch (e) {
var err = new Error();
err.code = 'E_INVALID_OPTION';
err.message = util.format(
'Failed to instantiate hydrated machinepack using the provided `pkg`.\n'+
'`pkg` should be an object with the following properties:\n'+
' • machinepack.machines\n • machinepack\n\n'+
'But the actual `pkg` option provided was:\n'+
'------------------------------------------------------\n'+
'%s\n'+
'------------------------------------------------------\n',
util.inspect(options.pkg, false, null));
if (!_.isString(options.dir)) {
throw new Error('Usage error: `.pack()` received a `dir` path which is not a string:'+util.inspect(options.dir, {depth:null}));
}
throw err;
// Validate `pkg`
// (if specified, must be a dictionary)
if (!_.isUndefined(options.pkg)) {
if (!_.isObject(options.pkg) || _.isArray(options.pkg) || _.isFunction(options.pkg)) {
throw new Error('Usage error: `.pack()` received an invalid `pkg`. If specified, `pkg` must be a dictionary, but instead got:'+util.inspect(options.pkg, {depth:null}));
}
}
// Build an object of all the machines in this pack
return _.reduce(machines, function (memo, machineID) {
try {
// Require and hydrate each static definition into a callable machine fn
var requirePath = path.resolve(options.dir||process.cwd(), options.pkg.machinepack.machineDir || options.pkg.machinepack.machinedir || '', machineID);
var definition = require(requirePath);
// Attach the string identity as referenced in package.json to
// the machine definition object as its "identity"
// (unless the machine definition already has an "identity" explicitly specified)
definition.identity = definition.identity || machineID;
// Build the machine.
var machineInstance = Machine.build(definition);
// Get the `Machine` constructor
var Machine = this;
if (!_.isFunction(Machine.build)) { throw new Error('Consistency violation: Context (`this`) is wrong in Machine.pack()!'); }
// Expose the machine as a method on our Pack object.
memo[Machine.getMethodName(machineInstance.identity)] = machineInstance;
// Now load & pack the modules.
var PackedModules;
// ┬┌─┐ ╔═╗╦╔═╔═╗ ┬ ┬┌─┐┌─┐ ┌─┐┌─┐┌─┐┌─┐┬┌─┐┬┌─┐┌┬┐
// │├┤ ╠═╝╠╩╗║ ╦ │││├─┤└─┐ └─┐├─┘├┤ │ │├┤ │├┤ ││
// ┴└ ╩ ╩ ╩╚═╝ └┴┘┴ ┴└─┘ └─┘┴ └─┘└─┘┴└ ┴└─┘─┴┘ooo
// If `pkg` was specified...
if (!_.isUndefined(options.pkg)) {
var machines;
try {
machines = options.pkg.machinepack.machines;
}
catch (e) {
var err = new Error('Failed to instantiate hydrated machinepack using the provided `pkg`.');
err.code = 'E_INVALID_OPTION';
err.message = util.format(
'Failed to instantiate hydrated machinepack using the provided `pkg`.\n'+
'`pkg` should be a dictionary with the following properties:\n'+
' • machinepack.machines\n • machinepack\n\n'+
'But the actual `pkg` option provided was:\n'+
'------------------------------------------------------\n'+
'%s\n'+
'------------------------------------------------------\n',
util.inspect(options.pkg, false, null));
// TODO: check and see if this is a MODULE_ERROR-
// if so, then it's a very different scenario and we should show a different
// error message.
throw (function buildError(){
e.originalError = e;
e.code = 'E_INVALID_MACHINE';
e.message = util.format(
'\n'+
'Failed to instantiate machine "%s" (listed in `pkg.machinepack.machines`).\n'+
'`pkg.machinepack.machines` should be an array of strings which correspond \n'+
'to the filenames of machine modules in this machinepack.\n\n'+
'The actual `pkg` option provided was:\n'+
'------------------------------------------------------\n'+
'%s\n'+
'------------------------------------------------------\n\n'+
'Error details:\n',
machineID,
util.inspect(options.pkg, false, null),
e.originalError);
return e;
})();
throw err;
}
return memo;
}, {});
// Build a dictionary of all the machines in this pack
PackedModules = _.reduce(machines, function (memo, machineID) {
try {
// Require and hydrate each static definition into a callable machine fn
var requirePath = path.resolve(options.dir, options.pkg.machinepack.machineDir || options.pkg.machinepack.machinedir || '', machineID);
var definition = require(requirePath);
// Attach the string identity as referenced in package.json to
// the machine definition dictionary as its "identity"
// (unless the machine definition already has an "identity" explicitly specified)
definition.identity = definition.identity || machineID;
// Build the machine.
var machineInstance = Machine.build(definition);
// Expose the machine as a method on our Pack dictionary.
memo[Machine.getMethodName(machineInstance.identity)] = machineInstance;
}
catch (e) {
// Check and see if this is a MODULE_ERROR-
// if so, then it's a very different scenario and we should show a different
// error message.
if (e.code === 'MODULE_NOT_FOUND') {
throw (function _buildModuleNotFoundError(){
e.originalError = e;
e.code = 'E_MACHINE_NOT_FOUND';
e.message = util.format(
'\n'+
'Failed to load machine "%s" (listed in `pkg.machinepack.machines`).\n'+
'`pkg.machinepack.machines` should be an array of strings which correspond \n'+
'to the filenames of machine modules in this machinepack.\n\n'+
'The actual `pkg` option provided was:\n'+
'------------------------------------------------------\n'+
'%s\n'+
'------------------------------------------------------\n\n'+
'Error details:\n',
machineID,
util.inspect(options.pkg, false, null),
e.originalError);
return e;
})();//</throw>
}
// --•
throw (function _buildInvalidMachineError(){
e.originalError = e;
e.code = 'E_INVALID_MACHINE';
e.message = util.format(
'\n'+
'Failed to instantiate machine "%s" (listed in `pkg.machinepack.machines`).\n'+
'`pkg.machinepack.machines` should be an array of strings which correspond \n'+
'to the filenames of machine modules in this machinepack.\n\n'+
'The actual `pkg` option provided was:\n'+
'------------------------------------------------------\n'+
'%s\n'+
'------------------------------------------------------\n\n'+
'Error details:\n',
machineID,
util.inspect(options.pkg, false, null),
e.originalError);
return e;
})();//</throw>
}
return memo;
}, {});
}//</if `pkg` option was specified>
// ┌─┐┬ ┌─┐┌─┐ ┌─┐┬┌─┌─┐ ┬ ┬┌─┐┌─┐ ╔╗╔╔═╗╔╦╗ ┌─┐┌─┐┌─┐┌─┐┬┌─┐┬┌─┐┌┬┐
// ├┤ │ └─┐├┤ ├─┘├┴┐│ ┬ │││├─┤└─┐ ║║║║ ║ ║ └─┐├─┘├┤ │ │├┤ │├┤ ││
// └─┘┴─┘└─┘└─┘ ┴ ┴ ┴└─┘ └┴┘┴ ┴└─┘ ╝╚╝╚═╝ ╩ └─┘┴ └─┘└─┘┴└ ┴└─┘─┴┘
// Otherwise, `pkg` was not specified, so just load all `.js` files in `dir`.
else {
// Ensure we have an absolute path.
options.dir = path.resolve(options.dir);
// Load modules (as dry machine definitions)
var inventory = includeAll({
dirname: options.dir,
filter: /(.+)\.js/,
exclude: [
/^index.js$/
],
flatten: true
});
// Now pack the modules, building each individual machine instance.
PackedModules = _.reduce(inventory, function (memo, rawNMDef, key) {
// Come up with an identity for debugging purposes.
rawNMDef.identity = _.kebabCase(key);
var methodName = Machine.getMethodName(rawNMDef.identity);
memo[methodName] = Machine.build(rawNMDef);
return memo;
}, {});
}//</else (no pkg option specified)>
return PackedModules;
};
{
"name": "machine",
"version": "13.0.0-1",
"version": "13.0.0-2",
"description": "Configure and execute machines",

@@ -34,5 +34,6 @@ "main": "index.js",

"debug": "2.2.0",
"include-all": "1.0.1",
"lodash": "3.10.1",
"object-hash": "0.3.0",
"rttc": "^9.7.2",
"rttc": "^9.8.1",
"switchback": "2.0.0"

@@ -39,0 +40,0 @@ },

@@ -8,3 +8,6 @@ module.exports = {

outputDescription: 'A list of invalid gummy worm flavors.', // >> noun phrase
outputExample: '===' // >> an example schema describing the output (technically, an RTTC exemplar schema). Omit this property to indicate no output.
outputExample: '*', // >> an example of the output, if relevant. Technically, this is an RTTC exemplar schema. Omit this property (as well as `like`, `itemOf`, and `getExample`) to indicate no output.
like: 'foo', // >> *ADVANCED, USE WITH CARE*: The code name of an input to base this data type guarantee off of. The referenced input must exist. The effective data type guarantee will be exactly the same as the input's exemplar (`example`). That is, if the referenced input has `example: [ { age: 49 } ]`, then the effective RTTC exemplar schema will be `[ { age: 49 } ]`. If runtime data is received for the referenced input, it will be exemplified (using `rttc.coerceExemplar()`) and used instead. (This is useful for building custom iterator machines, or machines that parse data with a dynamic schema.)
itemOf: 'bar', // >> *ADVANCED, USE WITH CARE*: The code name of an input to base this data type guarantee off of. The referenced input must exist, and its `example` MUST be an array. The effective data type guarantee will be based off of the *pattern* of the input's exemplar (`example`). That is, if the referenced input has `example: [ { name: 'foo' } ]`, then the effective RTTC exemplar schema for this exit will be `{name: 'foo'}`. If runtime data is received for the referenced input, it will be exemplified (using `rttc.coerceExemplar()`) and used instead. (This is useful for building custom iterator machines, or machines that parse data with a dynamic schema.)
getExample: '->', // >> ***VERY ADVANCED, USE WITH CARE!***: A function which receives runtime input values as its first argument and is expected to return an RTTC exemplar schema describing the data type under these particular conditions. May not return `undefined` or throw. Returning `null` to indicate that the exit is void (has no output) is experimental in the current version of the specification.
};

@@ -12,36 +12,18 @@ module.exports = {

cacheable: false,
moreInfoUrl: 'http://hello.com',
sync: true,
sideEffects: 'idempotent', // either omit or set as "cacheable" or "idempotent"
idempotent: true,
habitat: 'sails', // either omit or set as "request" or "sails"
// The `typesafe` flag is disabled by default. If a machine is `typesafe`,
// that means it will run in "unsafe mode" (unless overridden in userland).
//
// That means:
// 1. Its configured input values will not be cloned before exec()ing the fn.
// 2. Its outputs will not be cloned before being passed back to the user.
//
// So if a machine sets this flag, it is guaranteeing that:
// 1. The machine's `fn` will never throw in a callback, EVEN if a completely wrong
// input value is provided, or a required value is omitted. (TODO: reconsider--
// this is a pretty restrictive requirement. Could do some really cheap,
// surface-level validation of inputs when `typesafe` is enabled. That would
// loosen this up a bit without any significant performance cost)
// 2. The machine's `fn` will output values exactly according to the type schema
// inferred from its exit example.
// 3. The machine does not mutate any of the provided input values inside its `fn`.
// 4. The user has exclusive access to its outputs-- that is, they may be mutated
// by the user without causing any terrible side-effects. That means they are
// either primitive values, or objects that were constructed within the `fn`
// itself, and are used nowhere else.
typesafe: true,
sync: true, // either omit or set as `true`
inputs: {
someInput: require('./input-def.struct')
},

@@ -51,7 +33,48 @@

exits: {
someExit: require('./exit-def.struct')
},
fn: function (inputs, exits) { /* ... */ }
fn: function (inputs, exits) {
var _ = require('lodash');
setTimeout(function (){
try {
var luckyNum = Math.random();
if (luckyNum > 0.5) {
throw new Error('whatever');
}
else if (luckyNum < 0.1) {
// Exit `someExit` with no output.
return exits.someExit();
// > NOTE:
// > To send back output, could have done:
// > ```
// > return exits.someExit(luckyNum);
// > ```
// > (^^but if so, we would need to define an `outputExample` in our `someExit` definition!)
}
} catch (e) { return exits.error(e); }
// --• OK so if we made it here, `luckyNum` must be between 0.1 and 0.5 (exclusive).
// Exit `success` with no output.
return exits.success();
// > NOTE:
// > To send back output, could have done:
// > ```
// > return exits.success(luckyNum);
// > ```
// > (^^but if so, we would need to define `success` exit with an `outputExample`!)
}, 500);//</setTimeout>
}
};

Sorry, the diff of this file is not supported yet

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