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 install --save fluentflow 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));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) } ); 
$ sudo npm install -g fluentflow 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
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.
$ npm testMatching core. Built using the JavaScript API using a Matcher or from a String in a Matchbox.
objObject next Object to matchcberrorFirstCallback? callback after matching finishes
Generates the matcher (ffm) for the given Rule(s).
rule...Rule Rule(s) to match against.
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
Generates the isolated matcher (ffm) for the given Rule(s).
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]Checks if an Object matches.
Type: Function
oObject the object to checkpObject the previous objectcObject the matching contextpcObject the matching context from the previous statematchmatch match callback, true if matches false otherwiseforgetforget forget callback, forget all states including objects passed as arguments
Called each time a sequence of Objects matches a Rule in a ffm
Type: Function
objsArray the matched objectsnextnext end of callback. Continue matching next objectforgetforget forget objects.
Standard node.js callback type.
Type: Function
thenthenCallback match callback
Builds Rule.
checkercheckerCallback first checker
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
Add a new checker.
checkercheckerCallback next checker
Returns RuleBuilder continue
Finishes and builds the chain.
thenthenCallback? run if rule matches
Returns Rule finish
Signal the end of a thenCallback.
Signal the intent to forget an object. Must be called before next.
obj...Object the object(s) to forget
Signal the result of a matching operation.
matchedBoolean? true if matched, false otherwise. Default if omitted: false.