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

noflo-assembly

Package Overview
Dependencies
Maintainers
2
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

noflo-assembly - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

index.d.ts

3

example/components/BuildBodyBase.js

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -10,2 +10,3 @@ class BuildBodyBase extends Component {

}
relay(msg, output) {

@@ -12,0 +13,0 @@ msg.body = {

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -11,2 +11,3 @@ class BuildFrame extends Component {

}
relay(msg, output) {

@@ -13,0 +14,0 @@ msg.chassis = {

@@ -1,5 +0,3 @@

const Component = require('../../index');
const { Component, merge, fail } = require('../../index');
const { merge, fail } = Component;
class CombineAssemblies extends Component {

@@ -12,2 +10,3 @@ constructor() {

}
handle(input, output) {

@@ -14,0 +13,0 @@ if (!input.hasData('b', 'c')) { return null; }

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -24,2 +24,3 @@ class MountBodyParts extends Component {

}
handle(input, output) {

@@ -26,0 +27,0 @@ if (!input.hasData('in', 'partname')) { return null; }

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -21,2 +21,3 @@ class MountEngine extends Component {

}
handle(input, output) {

@@ -23,0 +24,0 @@ if (!input.hasData('in', 'engine')) { return null; }

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -10,2 +10,3 @@ class MountPanels extends Component {

}
relay(msg, output) {

@@ -12,0 +13,0 @@ msg.body.panels = 'Steel Panels';

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -3,0 +3,0 @@ class MountSuspension extends Component {

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -9,2 +9,3 @@ class MountTransmission extends Component {

}
relay(msg, output) {

@@ -11,0 +12,0 @@ msg.chassis.transmission = 'ZF Automatic 6-speed';

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -21,2 +21,3 @@ class MountWheels extends Component {

}
handle(input, output) {

@@ -23,0 +24,0 @@ if (!input.hasData('in', 'count')) { return null; }

const { IP } = require('noflo');
const Component = require('../../index');
const { Component } = require('../../index');

@@ -11,2 +11,3 @@ class Order extends Component {

}
handle(input, output) {

@@ -13,0 +14,0 @@ this.counter += 1;

@@ -1,5 +0,3 @@

const Component = require('../../index');
const { Component, failed } = require('../../index');
const { failed } = Component;
class Release extends Component {

@@ -12,6 +10,7 @@ constructor() {

}
relay(msg, output) {
// Display errors at this point
if (failed(msg)) {
msg.errors.forEach(e => console.error(e));
msg.errors.forEach((e) => console.error(e));
} else {

@@ -18,0 +17,0 @@ if (msg.parts) {

@@ -1,5 +0,3 @@

const Component = require('../../index');
const { Component, fork } = require('../../index');
const { fork } = Component;
class SplitAssemblies extends Component {

@@ -13,2 +11,3 @@ constructor() {

}
handle(input, output) {

@@ -15,0 +14,0 @@ if (!input.hasData('in')) { return null; }

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -44,2 +44,3 @@ class SupplyBodyParts extends Component {

}
handle(input, output) {

@@ -46,0 +47,0 @@ if (!input.hasData('in', 'interior', 'doortype', 'doornum')) { return null; }

@@ -1,2 +0,2 @@

const Component = require('../../index');
const { Component } = require('../../index');

@@ -11,2 +11,3 @@ class WireElectrics extends Component {

}
handle(input, output) {

@@ -13,0 +14,0 @@ if (!input.hasData('main', 'aux')) { return null; }

@@ -1,170 +0,253 @@

const NoFloComponent = require('noflo').Component;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.merge = exports.fork = exports.Component = exports.failed = exports.fail = void 0;
const noflo_1 = require("noflo");
/**
* @typedef {{ errors: Error[], [key: string]: any }} AssemblyMessage
*/
/**
* @typedef {{ [key: string]: string}} AssemblyValidators
*/
/**
* @typedef {{ [key: string]: (val: any) => boolean}} AssemblyValidatorFunctions
*/
/**
* @typedef {{ [key: string]: (key: string, val?: any) => string}} AssemblyErrorMessages
*/
/**
* @callback RelayFunction
* @param {AssemblyMessage} msg
* @param {import("noflo/lib/ProcessOutput").default} output
*/
/** @type {AssemblyValidatorFunctions} */
const validators = {
def: val => val !== undefined,
set: val => (val !== undefined) && (val !== null),
ok: val => !!val,
num: val => typeof val === 'number',
str: val => typeof val === 'string',
obj: val => (typeof val === 'object') && (val !== null),
func: val => typeof val === 'function',
'>0': val => val > 0,
def: (val) => val !== undefined,
set: (val) => (val !== undefined) && (val !== null),
ok: (val) => !!val,
num: (val) => typeof val === 'number',
str: (val) => typeof val === 'string',
obj: (val) => (typeof val === 'object') && (val !== null),
func: (val) => typeof val === 'function',
'>0': (val) => val > 0,
};
/** @type {AssemblyErrorMessages} */
const errorMessages = {
def: key => `${key} is undefined`,
set: key => `${key} is not set`,
ok: key => `${key} is false or empty`,
num: (key, val) => `${key} is not a number: ${val}`,
str: (key, val) => `${key} is not a string: ${val}`,
obj: (key, val) => `${key} is not an object: ${val}`,
func: (key, val) => `${key} is not a function: ${val}`,
'>0': (key, val) => `${key} is not positive: ${val}`,
def: (key) => `${key} is undefined`,
set: (key) => `${key} is not set`,
ok: (key) => `${key} is false or empty`,
num: (key, val) => `${key} is not a number: ${val}`,
str: (key, val) => `${key} is not a string: ${val}`,
obj: (key, val) => `${key} is not an object: ${val}`,
func: (key, val) => `${key} is not a function: ${val}`,
'>0': (key, val) => `${key} is not positive: ${val}`,
};
/**
* @param {AssemblyMessage} msg
* @param {Error|Error[]} err
* @returns {AssemblyMessage}
*/
function fail(msg, err) {
if (!Array.isArray(msg.errors)) {
throw new Error('Message.errors is not an array');
}
const errs = Array.isArray(err) ? err : [err];
errs.forEach(e => msg.errors.push(e));
return msg;
if (!Array.isArray(msg.errors)) {
throw new Error('Message.errors is not an array');
}
const errs = Array.isArray(err) ? err : [err];
errs.forEach((e) => msg.errors.push(e));
return msg;
}
exports.fail = fail;
/**
* @param {AssemblyMessage} msg
* @returns {boolean}
*/
function failed(msg) {
return msg.errors && Array.isArray(msg.errors) > 0 && msg.errors.length > 0;
return msg.errors && Array.isArray(msg.errors) && msg.errors.length > 0;
}
// Converts shortened ports definition to standard NoFlo ports definition
exports.failed = failed;
/**
* Converts shortened ports definition to standard NoFlo ports definition
* @param {Object<key, any>} options
* @param {string} direction
* @returns {Object<key, any>}
*/
function normalizePorts(options, direction) {
const key = `${direction}Ports`;
const result = options;
if (key in options) {
if (Array.isArray(options[key])) {
// Convert array to all-typed ports
const tmp = {};
options[key].forEach((name) => {
tmp[name] = { datatype: 'all' };
});
result[key] = tmp;
} // else is normal NoFlo ports object
} else {
// Default to single port
const dir = direction === 'out' ? 'Outgoing' : 'Incoming';
result[key] = {
[direction]: {
datatype: 'object',
description: `${dir} message`,
required: true,
},
};
}
return result;
const key = `${direction}Ports`;
const result = options;
if (key in options) {
if (Array.isArray(options[key])) {
// Convert array to all-typed ports
/** @type {Object<key, any>} */
const tmp = {};
const portsArray = /** @type {Array<string>} */ (options[key]);
portsArray.forEach((name) => {
tmp[name] = { datatype: 'all' };
});
result[key] = tmp;
} // else is normal NoFlo ports object
}
else {
// Default to single port
const dir = direction === 'out' ? 'Outgoing' : 'Incoming';
result[key] = {
[direction]: {
datatype: 'object',
description: `${dir} message`,
required: true,
},
};
}
return result;
}
/**
* @param {AssemblyValidators|Array<string>} rules
* @returns {AssemblyValidators}
*/
function normalizeValidators(rules) {
if (Array.isArray(rules)) {
// Normalize array to hashmap
const res = {};
rules.forEach((f) => {
res[f] = 'ok';
});
return res;
}
return rules;
if (Array.isArray(rules)) {
// Normalize array to hashmap
/** @type {AssemblyValidators} */
const res = {};
rules.forEach((f) => {
res[f] = 'ok';
});
return res;
}
return rules;
}
class Component extends NoFloComponent {
constructor(options = {}) {
let opts = normalizePorts(options, 'in');
opts = normalizePorts(opts, 'out');
super(opts);
if (options.validates) {
this.validates = normalizeValidators(options.validates);
/**
* @typedef {Object} AssemblyComponentOptions
* @property {AssemblyValidators|Array<string>} [validates]
*/
class Component extends noflo_1.Component {
/**
* @param {import("noflo/lib/Component").ComponentOptions & AssemblyComponentOptions} [options]
*/
constructor(options = {}) {
let opts = normalizePorts(options, 'in');
opts = normalizePorts(opts, 'out');
super(opts);
/** @type {RelayFunction|null} */
this.relay = this.relay || null;
if (options.validates) {
this.validates = normalizeValidators(options.validates);
}
if (typeof this.relay === 'function') {
const func = /** @type {RelayFunction} */ (this.relay);
this.process((input, output) => {
if (!input.hasData('in')) {
return;
}
const msg = input.getData('in');
if (!this.validate(msg)) {
output.sendDone(msg);
return;
}
func(msg, output);
});
}
if (typeof this.handle === 'function') {
this.process(this.handle);
}
}
if (typeof this.relay === 'function') {
this.process((input, output) => {
if (!input.hasData('in')) { return; }
const msg = input.getData('in');
if (!this.validate(msg)) {
output.sendDone(msg);
return;
/**
* @param {AssemblyMessage} msg
* @param {AssemblyValidators} rules
* @returns {Array<Error>}
*/
checkFields(msg, rules) {
/** @type {Array<Error>} */
const errors = [];
/**
* @param {AssemblyMessage|any} obj
* @param {string} objPath
* @param {string[]} path
* @param {string} validator
*/
function checkField(obj, objPath, path, validator) {
if (!obj || (path.length <= 0)) {
return;
}
const key = /** @type {string} */ (path.shift());
const v = path.length === 0 ? validator : 'obj';
if (!validators[v](obj[key])) {
errors.push(new Error(errorMessages[v](`${objPath}.${key}`, obj[key])));
return;
}
if (path.length > 0) {
checkField(obj[key], `${objPath}.${key}`, path, validator);
}
}
this.relay(msg, output);
});
Object.keys(rules).forEach((f) => {
const path = f.indexOf('.') > 0 ? f.split('.') : [f];
let v = rules[f];
if (!(v in validators)) {
v = 'ok';
}
checkField(msg, 'msg', path, v);
});
return errors;
}
if (typeof this.handle === 'function') {
this.process(this.handle);
/**
* @param {AssemblyMessage} msg
* @param {AssemblyValidators|Array<string>} [rules]
*/
validate(msg, rules = this.validates) {
if (failed(msg)) {
return false;
}
if (rules && typeof rules === 'object') {
rules = normalizeValidators(rules);
const errs = this.checkFields(msg, rules);
if (errs.length > 0) {
fail(msg, errs);
return false;
}
}
return true;
}
}
checkFields(msg, rules) {
const errors = [];
function checkField(obj, objPath, path, validator) {
if (!obj || (path.length <= 0)) { return; }
const key = path.shift();
const v = path.length === 0 ? validator : 'obj';
if (!validators[v](obj[key])) {
errors.push(new Error(errorMessages[v](`${objPath}.${key}`, obj[key])));
return;
}
if (path.length > 0) {
checkField(obj[key], `${objPath}.${key}`, path, validator);
}
}
Object.keys(rules).forEach((f) => {
const path = f.indexOf('.') > 0 ? f.split('.') : [f];
let v = rules[f];
if (!(v in validators)) { v = 'ok'; }
checkField(msg, 'msg', path, v);
});
return errors;
}
validate(msg, rules = this.validates) {
if (failed(msg)) {
return false;
}
if (rules && typeof rules === 'object') {
rules = normalizeValidators(rules);
const errs = this.checkFields(msg, rules);
if (errs.length > 0) {
fail(msg, errs);
return false;
}
}
return true;
}
}
exports.Component = Component;
/**
* @param {AssemblyMessage} msg
* @param {Array<string>} [excludeKeys]
* @param {Array<string>} [cloneKeys]
* @returns {AssemblyMessage}
*/
function fork(msg, excludeKeys = [], cloneKeys = []) {
const newMsg = {};
Object.keys(msg).forEach((key) => {
if (excludeKeys.includes(key)) { return; }
if (cloneKeys.includes(key)) {
newMsg[key] = JSON.parse(JSON.stringify(msg[key]));
} else {
newMsg[key] = msg[key];
}
});
return newMsg;
/** @type {AssemblyMessage} */
const newMsg = {
errors: cloneKeys.includes('error') ? msg.errors.slice(0) : msg.errors,
};
Object.keys(msg).forEach((key) => {
if (key === 'errors') {
return;
}
if (excludeKeys.includes(key)) {
return;
}
if (cloneKeys.includes(key)) {
newMsg[key] = JSON.parse(JSON.stringify(msg[key]));
}
else {
newMsg[key] = msg[key];
}
});
return newMsg;
}
exports.fork = fork;
/**
* @param {AssemblyMessage} base
* @param {Object<string, any>} extra
* @returns {AssemblyMessage}
*/
function merge(base, extra) {
const combined = base;
const baseKeys = Object.keys(base);
Object.keys(extra).forEach((key) => {
if ((baseKeys.indexOf(key) === -1 || base[key] === undefined) && extra[key] !== undefined) {
combined[key] = extra[key];
}
});
return combined;
const combined = base;
const baseKeys = Object.keys(base);
Object.keys(extra).forEach((key) => {
if ((baseKeys.indexOf(key) === -1 || base[key] === undefined) && extra[key] !== undefined) {
combined[key] = extra[key];
}
});
return combined;
}
module.exports = Component;
module.exports.default = Component;
module.exports.fail = fail;
module.exports.failed = failed;
module.exports.fork = fork;
module.exports.merge = merge;
exports.merge = merge;
exports.default = Component;
{
"name": "noflo-assembly",
"version": "0.2.0",
"version": "0.3.0",
"description": "Industrial approach to writing NoFlo applications",
"main": "index.js",
"types": "index.d.ts",
"repository": {

@@ -11,7 +12,11 @@ "type": "git",

"scripts": {
"pretest": "eslint index.js example/components/*.js spec/*.js",
"lint": "eslint src/*.js example/components/*.js spec/*.js",
"build": "tsc",
"pretest": "npm run build && npm run lint",
"test": "mocha -R spec spec/*.js"
},
"keywords": [
"noflo"
"noflo",
"ecosystem:noflo",
"ecosystem:noflo-assembly"
],

@@ -23,3 +28,3 @@ "author": "Vladimir Sibirov",

},
"homepage": "https://github.com/noflo/noflo-assembly",
"homepage": "https://github.com/noflo/noflo-assembly/wiki",
"dependencies": {

@@ -29,9 +34,12 @@ "noflo": "^1.0.0"

"devDependencies": {
"@types/node": "^14.14.12",
"chai": "^4.1.2",
"eslint": "^4.12.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.2.0",
"mocha": "^4.0.1",
"noflo-wrapper": "^0.2.1"
"eslint": "^7.7.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-plugin-import": "^2.22.0",
"mocha": "^8.1.3",
"noflo": "^1.4.2",
"noflo-wrapper": "^0.4.1",
"typescript": "^4.1.2"
}
}
# NoFlo Assembly Line
[![Greenkeeper badge](https://badges.greenkeeper.io/noflo/noflo-assembly.svg)](https://greenkeeper.io/) [![Build Status](https://travis-ci.org/noflo/noflo-assembly.svg?branch=master)](https://travis-ci.org/noflo/noflo-assembly)
Industrial approach to writing NoFlo applications

@@ -45,3 +43,3 @@

```javascript
import Component from 'noflo-assembly';
import { Component } from 'noflo-assembly';
```

@@ -48,0 +46,0 @@

/* eslint-env node, mocha */
const { expect } = require('chai');
const Wrapper = require('noflo-wrapper');
const { ComponentLoader } = require('noflo');
const { resolve } = require('path');

@@ -9,22 +8,13 @@

this.timeout(5000);
let loader;
let c;
before((done) => {
// A bit of magic with custom loader for subfolder project to work
loader = new ComponentLoader(resolve(__dirname, '../example'));
loader.listComponents((err) => {
if (err) { done(err); return; }
done();
});
});
describe('A simple pipeline graph', () => {
before((done) => {
c = new Wrapper('', { loader });
c.component = 'example/BuildChassis';
c.start((err) => {
if (err) { done(err); return; }
done();
c = new Wrapper('example/BuildChassis', {
baseDir: resolve(__dirname, '../example'),
debug: true,
});
c.start(done);
});
after(() => c.dumpTrace());

@@ -59,9 +49,9 @@ it('should build a car chassis', (done) => {

before((done) => {
c = new Wrapper('', { loader });
c.component = 'example/BuildBody';
c.start((err) => {
if (err) { done(err); return; }
done();
c = new Wrapper('example/BuildBody', {
baseDir: resolve(__dirname, '../example'),
debug: true,
});
c.start(done);
});
after(() => c.dumpTrace());

@@ -94,9 +84,9 @@ it('should build a car body', (done) => {

before((done) => {
c = new Wrapper('', { loader });
c.component = 'example/BuildCar';
c.start((err) => {
if (err) { done(err); return; }
done();
c = new Wrapper('example/BuildCar', {
baseDir: resolve(__dirname, '../example'),
debug: true,
});
c.start(done);
});
after(() => c.dumpTrace());

@@ -103,0 +93,0 @@ it('should build a car', (done) => {

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