Skip to content

A tool to filter json objects by describing their (timely) behaviour

License

Notifications You must be signed in to change notification settings

Enteee/FluentFlow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FluentFlow

FluentFlow is a filter language with a simple API which lets you define 'followed by'-relations in a flow of JavaScript objects. You can either use FluentFlow from the command line or as a JavaScript library.

npm version Build Status Coverage Status js-semistandard-style #FluentFlow

Library

Installation

$ npm install --save fluentflow 

Usage

const ff = require('fluentflow');
const $ = ff.RuleBuilder
const _ = require('lodash');

/**
 * Log all numbers greater than 9000.
 */
const ffm = ff.Matcher(
  $(
    // Start matching after 9000
    (o, p, c, pc, match) => match(o === 9000)
  ).followedBy(
    // Is the next object (o) greater than the previous (p)?
    (o, p, c, pc, match) => match(o > p.get(0))
  ).then(
    (objs, next) => next(console.log(objs))
  )
);

_.range(9002).forEach((obj) => ffm(obj));

Sandbox (Matchbox)

FluentFlow supports evaluating string rules in an isolated environment:

const _ = require('lodash');
const ffm = require('fluentflow').Matchbox(`
[
  $(
    // Start matching after 9000
    (o, p, c, pc, match) => match(o === 9000)
  ).followedBy(
    // Is the next object (o) greater than the previous (p)?
    (o, p, c, pc, match) => match(o > p.get(0))
  ).then(
    (objs, next) => next(console.log(objs))
  )
]`);
_.range(9002).forEach((obj) => ffm(obj));
  • new Matchbox() will raise an exception if the chain contains syntax-errors.
  • ffm() will run the chain inside a vm2-instance.
  • runtime exceptions will be reported via the ffm() callback: ffm(obj, (err) => { console.log(err) } );

Command Line

Installation

$ sudo npm install -g fluentflow 

Usage

Usage: fluentflow.js [OPTIONS] rulesFile

rulesFile          : path to the rules file
OPTIONS:
   -j JSONPath     : JSONPath expression
   -t              : test if rules are valid
   -h              : print this help

Getting started

Configure rules.js:

[
  /**
   * Check if somebody forked this repository after submitting an issue.
   * Reverse order because the github api displays events in this order.
   */
  $(
    (o, p, c, pc, match) => {
      match(o.get('type') === 'ForkEvent');
    }
  ).followedBy(
    (o, p, c, pc, match) => match(
        o.get('type') === 'IssuesEvent' &&
        o.get('actor').get('login') === p.get(0).get('actor').get('login')
    )
  ).then((objs, next) => next(
    console.log('User: ' +
      objs.get(1).get('actor').get('login') +
      ' forked after writing issue: ' +
      objs.get(0).get('id')
    )
  ))
];

Run FluentFlow:

$ curl -s https://api.github.com/repos/Enteee/FluentFlow/events | fluentflow rules.js -j '*'

Note: -j '*' splits an array into objects.

Testing

$ npm test

API

Documentation on github-pages

ffm

Matching core. Built using the JavaScript API using a Matcher or from a String in a Matchbox.

Parameters

Matcher

Generates the matcher (ffm) for the given Rule(s).

Parameters

  • rule ...Rule Rule(s) to match against.

Examples

const _ = require('lodash');
const ff = require('fluentflow');
const $ = ff.RuleBuilder;
const ffm = ff.Matcher(
 $(
    (o, p, c, pc, match, f) => match(o == 42)
  ).followedBy(
    (o, p, c, pc, match, f) => match(o == 9000)
  ).then(
    (objs, next) => next(
      console.log(objs)
    )
  )
);
// match some objects
_.range(9001).forEach((obj) => ffm(obj)); // prints [42, 9000]

Returns ffm a new matcher

Matchbox

Generates the isolated matcher (ffm) for the given Rule(s).

Parameters

Examples

const _ = require('lodash');
const ffm = require('fluentflow').Matchbox(`
 [
   $(
     (o, p, c, pc, match, forget) => match(o == 42)
   ).followedBy(
     (o, p, c, pc, match, forget) => match(o == 9000)
   ).then(
     (objs, next) => next(
       console.log(objs)
     )
   )
 ]
`);
// match some objects
_.range(9001).forEach((obj) => ffm(obj)); // prints [42, 9000]

Returns ffm an isolated ffm

Callback Types

checkerCallback

Checks if an Object matches.

Type: Function

Parameters
  • o Object the object to check
  • p Object the previous object
  • c Object the matching context
  • pc Object the matching context from the previous state
  • match match match callback, true if matches false otherwise
  • forget forget forget callback, forget all states including objects passed as arguments

thenCallback

Called each time a sequence of Objects matches a Rule in a ffm

Type: Function

Parameters
  • objs Array the matched objects
  • next next end of callback. Continue matching next object
  • forget forget forget objects.

errorFirstCallback

Standard node.js callback type.

Type: Function

Parameters
  • Error Object Truthy if an error occured
  • data ...Object data

Helper Classes

Rule

Parameters
setThen
Parameters

RuleBuilder

Builds Rule.

Parameters
Examples
const rule = require('fluentflow').RuleBuilder(
 (o, p, c, pc, match, forget) => match(o === 42)
).followedBy(
 (o, p, c, pc, match, forget) => match(o === 9000)
).then(
 (objs, next) => next(
   console.log(objs)
 )
); // prints [42, 9000]

Returns RuleBuilder continue

followedBy

Add a new checker.

Parameters

Returns RuleBuilder continue

then

Finishes and builds the chain.

Parameters

Returns Rule finish

next

Signal the end of a thenCallback.

forget

Signal the intent to forget an object. Must be called before next.

Parameters

  • obj ...Object the object(s) to forget

match

Signal the result of a matching operation.

Parameters

  • matched Boolean? true if matched, false otherwise. Default if omitted: false.