pico-engine-core
Advanced tools
Comparing version 0.14.2 to 0.14.3
{ | ||
"name": "pico-engine-core", | ||
"version": "0.14.2", | ||
"version": "0.14.3", | ||
"description": "The core javascript api for the pico-engine. (no http, logging, process management etc...)", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -7,44 +7,46 @@ var _ = require("lodash"); | ||
test("DB - write and read", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({dont_register_rulesets: true}, function(err, pe){ | ||
if(err)return t.end(err); | ||
λ.series({ | ||
start_db: λ.curry(pe.db.toObj), | ||
pico0: λ.curry(pe.db.newPico, {}), | ||
chan1: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rule0: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "rs0"}), | ||
chan2: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "two", type: "t"}), | ||
end_db: λ.curry(pe.db.toObj), | ||
rmpico0: λ.curry(pe.db.removePico, "id0"), | ||
post_del_db: λ.curry(pe.db.toObj) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
λ.series({ | ||
start_db: λ.curry(pe.db.toObj), | ||
pico0: λ.curry(pe.db.newPico, {}), | ||
chan1: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rule0: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "rs0"}), | ||
chan2: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "two", type: "t"}), | ||
end_db: λ.curry(pe.db.toObj), | ||
rmpico0: λ.curry(pe.db.removePico, "id0"), | ||
post_del_db: λ.curry(pe.db.toObj) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.start_db, {}); | ||
t.deepEquals(data.start_db, {}); | ||
t.deepEquals(data.end_db, { | ||
pico: { | ||
"id0": { | ||
id: "id0", | ||
channel: { | ||
"id1": { | ||
id: "id1", | ||
name: "one", | ||
type: "t" | ||
t.deepEquals(data.end_db, { | ||
pico: { | ||
"id0": { | ||
id: "id0", | ||
channel: { | ||
"id1": { | ||
id: "id1", | ||
name: "one", | ||
type: "t" | ||
}, | ||
"id2": { | ||
id: "id2", | ||
name: "two", | ||
type: "t" | ||
} | ||
}, | ||
"id2": { | ||
id: "id2", | ||
name: "two", | ||
type: "t" | ||
ruleset: { | ||
"rs0": {on: true} | ||
} | ||
}, | ||
ruleset: { | ||
"rs0": {on: true} | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
t.deepEquals(data.post_del_db, {}); | ||
t.deepEquals(data.post_del_db, {}); | ||
t.end(); | ||
t.end(); | ||
}); | ||
}); | ||
@@ -54,29 +56,31 @@ }); | ||
test("DB - registerRuleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({dont_register_rulesets: true}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var krl_src = "ruleset io.picolabs.cool {}"; | ||
var rid = "io.picolabs.cool"; | ||
var hash = "7d71c05bc934b0d41fdd2055c7644fc4d0d3eabf303d67fb97f604eaab2c0aa1"; | ||
var timestamp = (new Date()).toISOString(); | ||
var krl_src = "ruleset io.picolabs.cool {}"; | ||
var rid = "io.picolabs.cool"; | ||
var hash = "7d71c05bc934b0d41fdd2055c7644fc4d0d3eabf303d67fb97f604eaab2c0aa1"; | ||
var timestamp = (new Date()).toISOString(); | ||
var expected = {}; | ||
_.set(expected, ["rulesets", "krl", hash], { | ||
src: krl_src, | ||
rid: rid, | ||
timestamp: timestamp | ||
}); | ||
_.set(expected, ["rulesets", "versions", rid, timestamp, hash], true); | ||
var expected = {}; | ||
_.set(expected, ["rulesets", "krl", hash], { | ||
src: krl_src, | ||
rid: rid, | ||
timestamp: timestamp | ||
}); | ||
_.set(expected, ["rulesets", "versions", rid, timestamp, hash], true); | ||
λ.series({ | ||
start_db: λ.curry(pe.db.toObj), | ||
install: function(next){ | ||
pe.db.registerRuleset(krl_src, next, timestamp); | ||
}, | ||
end_db: λ.curry(pe.db.toObj) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.start_db, {}); | ||
t.deepEquals(data.install, hash); | ||
t.deepEquals(data.end_db, expected); | ||
t.end(); | ||
λ.series({ | ||
start_db: λ.curry(pe.db.toObj), | ||
install: function(next){ | ||
pe.db.registerRuleset(krl_src, next, timestamp); | ||
}, | ||
end_db: λ.curry(pe.db.toObj) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.start_db, {}); | ||
t.deepEquals(data.install, hash); | ||
t.deepEquals(data.end_db, expected); | ||
t.end(); | ||
}); | ||
}); | ||
@@ -86,60 +90,64 @@ }); | ||
test("DB - enableRuleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var krl_src = "ruleset io.picolabs.cool {}"; | ||
//TODO | ||
λ.waterfall([ | ||
function(callback){ | ||
pe.db.toObj(callback); | ||
}, | ||
function(db, callback){ | ||
t.deepEquals(db, {}); | ||
pe.db.registerRuleset(krl_src, callback); | ||
}, | ||
function(hash, callback){ | ||
pe.db.enableRuleset(hash, function(err){ | ||
callback(err, hash); | ||
}); | ||
}, | ||
function(hash, callback){ | ||
pe.db.toObj(function(err, db){ | ||
callback(err, db, hash); | ||
}); | ||
}, | ||
function(db, hash, callback){ | ||
t.deepEquals(_.get(db, [ | ||
"rulesets", | ||
"enabled", | ||
"io.picolabs.cool", | ||
"hash" | ||
]), hash); | ||
pe.db.getEnableRuleset("io.picolabs.cool", function(err, data){ | ||
if(err) return callback(err); | ||
t.equals(data.src, krl_src); | ||
t.equals(data.hash, hash); | ||
t.equals(data.rid, "io.picolabs.cool"); | ||
t.equals(data.timestamp_enable, _.get(db, [ | ||
var krl_src = "ruleset io.picolabs.cool {}"; | ||
//TODO | ||
λ.waterfall([ | ||
function(callback){ | ||
pe.db.toObj(callback); | ||
}, | ||
function(db, callback){ | ||
t.deepEquals(_.omit(db, "rulesets"), {}); | ||
pe.db.registerRuleset(krl_src, callback); | ||
}, | ||
function(hash, callback){ | ||
pe.db.enableRuleset(hash, function(err){ | ||
callback(err, hash); | ||
}); | ||
}, | ||
function(hash, callback){ | ||
pe.db.toObj(function(err, db){ | ||
callback(err, db, hash); | ||
}); | ||
}, | ||
function(db, hash, callback){ | ||
t.deepEquals(_.get(db, [ | ||
"rulesets", | ||
"enabled", | ||
"io.picolabs.cool", | ||
"timestamp" | ||
])); | ||
callback(); | ||
}); | ||
} | ||
], t.end); | ||
"hash" | ||
]), hash); | ||
pe.db.getEnableRuleset("io.picolabs.cool", function(err, data){ | ||
if(err) return callback(err); | ||
t.equals(data.src, krl_src); | ||
t.equals(data.hash, hash); | ||
t.equals(data.rid, "io.picolabs.cool"); | ||
t.equals(data.timestamp_enable, _.get(db, [ | ||
"rulesets", | ||
"enabled", | ||
"io.picolabs.cool", | ||
"timestamp" | ||
])); | ||
callback(); | ||
}); | ||
} | ||
], t.end); | ||
}); | ||
}); | ||
test("DB - read keys that don't exist", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
λ.series({ | ||
ent: λ.curry(pe.db.getEntVar, "pico0", "rid0", "var that doesn't exisit"), | ||
app: λ.curry(pe.db.getAppVar, "rid0", "var that doesn't exisit") | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.ent, undefined); | ||
t.deepEquals(data.app, undefined); | ||
t.end(); | ||
λ.series({ | ||
ent: λ.curry(pe.db.getEntVar, "pico0", "rid0", "var that doesn't exisit"), | ||
app: λ.curry(pe.db.getAppVar, "rid0", "var that doesn't exisit") | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.ent, undefined); | ||
t.deepEquals(data.app, undefined); | ||
t.end(); | ||
}); | ||
}); | ||
}); |
347
src/index.js
var _ = require("lodash"); | ||
var λ = require("contra"); | ||
var DB = require("./DB"); | ||
@@ -11,93 +12,97 @@ var getArg = require("./getArg"); | ||
var EventEmitter = require("events"); | ||
var evalRuleInFiber = require("./evalRuleInFiber"); | ||
var selectRulesToEvalFuture = Future.wrap(require("./selectRulesToEval")); | ||
var runQueryInFiber = require("./runQueryInFiber"); | ||
var signalEventInFiber = require("./signalEventInFiber"); | ||
var mkCTX = function(ctx){ | ||
ctx.getArg = getArg; | ||
ctx.KRLClosure = KRLClosure; | ||
if(!_.has(ctx, "emit")){ | ||
ctx.emit = function(){ | ||
console.error("WARNING ctx.emit(...) was not defined!"); | ||
};//stdlib expects an "emit" function to be available | ||
} | ||
ctx.callKRLstdlib = function(fn_name){ | ||
var args = _.toArray(arguments); | ||
args[0] = ctx; | ||
return krl_stdlib[fn_name].apply(void 0, args); | ||
module.exports = function(conf, callback){ | ||
var db = Future.wrap(DB(conf.db)); | ||
var compileAndLoadRuleset = conf.compileAndLoadRuleset; | ||
var rulesets = {}; | ||
var salience_graph = {}; | ||
var emitter = new EventEmitter(); | ||
var mkCTX = function(ctx){ | ||
ctx.db = db; | ||
ctx.getArg = getArg; | ||
ctx.engine = engine; | ||
ctx.modules = modules; | ||
ctx.rulesets = rulesets; | ||
ctx.salience_graph = salience_graph; | ||
ctx.KRLClosure = KRLClosure; | ||
ctx.emit = function(type, val, message){//for stdlib | ||
var info = {rid: ctx.rid}; | ||
if(ctx.event){ | ||
info.event = { | ||
eci: ctx.event.eci, | ||
eid: ctx.event.eid, | ||
domain: ctx.event.domain, | ||
type: ctx.event.type, | ||
}; | ||
} | ||
emitter.emit(type, info, val, message); | ||
}; | ||
ctx.callKRLstdlib = function(fn_name){ | ||
var args = _.toArray(arguments); | ||
args[0] = ctx; | ||
return krl_stdlib[fn_name].apply(void 0, args); | ||
}; | ||
return ctx; | ||
}; | ||
return ctx; | ||
}; | ||
var rulesets = {}; | ||
var salience_graph = {}; | ||
var doInstallRuleset = function(rs){ | ||
rs.scope = SymbolTable(); | ||
if(_.isFunction(rs.meta && rs.meta.configure)){ | ||
rs.meta.configure(mkCTX({ | ||
var installRulesetInFiber = function(rs, loadDepRS){ | ||
rs.scope = SymbolTable(); | ||
var ctx = mkCTX({ | ||
scope: rs.scope | ||
})); | ||
} | ||
if(_.isFunction(rs.global)){ | ||
rs.global(mkCTX({ | ||
scope: rs.scope | ||
})); | ||
} | ||
rs.modules_used = {}; | ||
_.each(rs.meta && rs.meta.use, function(use){ | ||
if(use.kind !== "module"){ | ||
throw new Error("Unsupported 'use' kind: " + use.kind); | ||
}); | ||
if(_.isFunction(rs.meta && rs.meta.configure)){ | ||
rs.meta.configure(ctx); | ||
} | ||
if(!_.has(rulesets, use.rid)){ | ||
throw new Error("Dependant module not loaded: " + use.rid); | ||
if(_.isFunction(rs.global)){ | ||
rs.global(ctx); | ||
} | ||
var dep_rs = rulesets[use.rid]; | ||
var ctx = mkCTX({ | ||
scope: SymbolTable()//or dep_rs.scope.push() ??? TODO | ||
rs.modules_used = {}; | ||
_.each(rs.meta && rs.meta.use, function(use){ | ||
if(use.kind !== "module"){ | ||
throw new Error("Unsupported 'use' kind: " + use.kind); | ||
} | ||
var dep_rs = loadDepRS(use.rid); | ||
if(!dep_rs){ | ||
throw new Error("Dependant module not loaded: " + use.rid); | ||
} | ||
var ctx = mkCTX({ | ||
scope: SymbolTable()//or dep_rs.scope.push() ??? TODO | ||
}); | ||
if(_.isFunction(dep_rs.meta && dep_rs.meta.configure)){ | ||
dep_rs.meta.configure(ctx); | ||
} | ||
if(_.isFunction(use["with"])){ | ||
use["with"](ctx); | ||
} | ||
if(_.isFunction(dep_rs.global)){ | ||
dep_rs.global(ctx); | ||
} | ||
rs.modules_used[use.alias] = { | ||
rid: use.rid, | ||
scope: ctx.scope, | ||
provides: dep_rs.meta.provides | ||
}; | ||
}); | ||
if(_.isFunction(dep_rs.meta && dep_rs.meta.configure)){ | ||
dep_rs.meta.configure(ctx); | ||
} | ||
if(_.isFunction(use["with"])){ | ||
use["with"](ctx); | ||
} | ||
if(_.isFunction(dep_rs.global)){ | ||
dep_rs.global(ctx); | ||
} | ||
rs.modules_used[use.alias] = { | ||
rid: use.rid, | ||
scope: ctx.scope, | ||
provides: dep_rs.meta.provides | ||
}; | ||
}); | ||
_.each(rs.rules, function(rule){ | ||
rule.rid = rs.rid; | ||
_.each(rs.rules, function(rule){ | ||
rule.rid = rs.rid; | ||
_.each(rule.select && rule.select.graph, function(g, domain){ | ||
_.each(g, function(exprs, type){ | ||
_.set(salience_graph, [domain, type, rule.rid, rule.name], true); | ||
_.each(rule.select && rule.select.graph, function(g, domain){ | ||
_.each(g, function(exprs, type){ | ||
_.set(salience_graph, [domain, type, rule.rid, rule.name], true); | ||
}); | ||
}); | ||
}); | ||
}); | ||
rulesets[rs.rid] = rs; | ||
}; | ||
rulesets[rs.rid] = rs; | ||
}; | ||
var installRuleset = function(rs, callback){ | ||
applyInFiber(doInstallRuleset, null, [rs], callback); | ||
}; | ||
var installRuleset = function(rs, loadDepRS, callback){ | ||
applyInFiber(installRulesetInFiber, null, [rs, loadDepRS], callback); | ||
}; | ||
module.exports = function(conf){ | ||
var db = Future.wrap(DB(conf.db)); | ||
var compileAndLoadRuleset = conf.compileAndLoadRuleset; | ||
var emitter = new EventEmitter(); | ||
var installRID = function(rid, callback){ | ||
if(conf._dont_check_enabled_before_installing){//for testing | ||
compileAndLoadRuleset({rid: rid}, function(err, rs){ | ||
if(err) return callback(err); | ||
installRuleset(rs, callback); | ||
}); | ||
return; | ||
} | ||
var getRulesetForRID = function(rid, callback){ | ||
db.getEnableRuleset(rid, function(err, data){ | ||
@@ -116,3 +121,3 @@ if(err) return callback(err); | ||
} | ||
installRuleset(rs, callback); | ||
callback(void 0, rs); | ||
}); | ||
@@ -122,93 +127,20 @@ }); | ||
//TODO standard startup-phase | ||
db.getAllEnableRulesets(function(err, rids){ | ||
if(err){ | ||
throw err;//TODO handle this somehow? | ||
} | ||
_.each(rids, function(rid){ | ||
installRID(rid, function(err){ | ||
if(err){ | ||
throw err;//TODO handle this somehow? | ||
} | ||
}); | ||
var installRID = function(rid, callback){ | ||
getRulesetForRID(rid, function(err, rs){ | ||
if(err) return callback(err); | ||
installRuleset(rs, function(rid){ | ||
return rulesets[rid]; | ||
}, callback); | ||
}); | ||
}); | ||
}; | ||
var signalEventInFiber = function(event){ | ||
var signalEvent = function(event, callback){ | ||
event.timestamp = new Date(); | ||
event.getAttr = function(attr_key){ | ||
return event.attrs[attr_key]; | ||
}; | ||
event.getAttrMatches = function(pairs){ | ||
var matches = []; | ||
var i, attr, m, pair; | ||
for(i = 0; i < pairs.length; i++){ | ||
pair = pairs[i]; | ||
attr = event.attrs[pair[0]]; | ||
m = pair[1].exec(attr || ""); | ||
if(!m){ | ||
return undefined; | ||
} | ||
matches.push(m[1]); | ||
} | ||
return matches; | ||
}; | ||
var debug_info = { | ||
event: { | ||
eci: event.eci, | ||
eid: event.eid, | ||
domain: event.domain, | ||
type: event.type, | ||
attrs: _.cloneDeep(event.attrs), | ||
timestamp: event.timestamp.toISOString() | ||
} | ||
}; | ||
emitter.emit("debug", "event", debug_info, "event recieved"); | ||
var pico = db.getPicoByECIFuture(event.eci).wait(); | ||
if(!pico){ | ||
throw new Error("Invalid eci: " + event.eci); | ||
} | ||
debug_info.pico_id = pico.id; | ||
emitter.emit("debug", "event", debug_info, "pico selected"); | ||
var ctx = mkCTX({ | ||
emit: function(type, val, message){//for stdlib | ||
//TODO think this through more | ||
emitter.emit(type, debug_info, val, message); | ||
}, | ||
pico: pico, | ||
db: db, | ||
engine: engine, | ||
modules: modules, | ||
event: event | ||
}); | ||
var rules = selectRulesToEvalFuture(ctx, salience_graph, rulesets).wait(); | ||
var responses = _.map(rules, function(rule){ | ||
ctx.emit("debug", "rule selected: " + rule.rid + " -> " + rule.name); | ||
ctx.rid = rule.rid; | ||
ctx.rule = rule; | ||
ctx.scope = rule.scope; | ||
if(_.has(rulesets, rule.rid)){ | ||
ctx.modules_used = rulesets[rule.rid].modules_used; | ||
} | ||
return evalRuleInFiber(rule, ctx); | ||
}); | ||
var res_by_type = _.groupBy(_.flattenDeep(_.values(responses)), "type"); | ||
//TODO other types | ||
return { | ||
directives: _.map(res_by_type.directive, function(d){ | ||
return _.omit(d, "type"); | ||
}) | ||
}; | ||
var ctx = mkCTX({event: event}); | ||
applyInFiber(signalEventInFiber, void 0, [ctx], callback); | ||
}; | ||
var signalEvent = function(event, callback){ | ||
applyInFiber(signalEventInFiber, void 0, [event], callback); | ||
var runQuery = function(query, callback){ | ||
var ctx = mkCTX({query: query}); | ||
applyInFiber(runQueryInFiber, void 0, [ctx], callback); | ||
}; | ||
@@ -221,59 +153,34 @@ | ||
return { | ||
db: db, | ||
emitter: emitter, | ||
isInstalled: function(rid){ | ||
return _.has(rulesets, rid); | ||
}, | ||
installRID: installRID, | ||
signalEvent: signalEvent, | ||
runQuery: function(query, callback){ | ||
db.getPicoByECI(query.eci, function(err, pico){ | ||
if(err) return callback(err); | ||
if(!pico){ | ||
return callback(new Error("Bad eci")); | ||
} | ||
if(!_.has(pico.ruleset, query.rid)){ | ||
return callback(new Error("Pico does not have that rid")); | ||
} | ||
if(!_.has(rulesets, query.rid)){ | ||
return callback(new Error("Not found: rid")); | ||
} | ||
var rs = rulesets[query.rid]; | ||
var shares = _.get(rs, ["meta", "shares"]); | ||
if(!_.isArray(shares) || !_.includes(shares, query.name)){ | ||
return callback(new Error("Not shared")); | ||
} | ||
if(!rs.scope.has(query.name)){ | ||
//TODO throw -or- nil???? | ||
return callback(new Error("Shared, but not defined: " + query.name)); | ||
} | ||
//////////////////////////////////////////////////////////////////////// | ||
var ctx = mkCTX({ | ||
db: db, | ||
rid: rs.rid, | ||
pico: pico, | ||
emit: function(type, val, message){//for stdlib | ||
//TODO think this through more | ||
emitter.emit(type, {rid: rs.rid}, val, message); | ||
}, | ||
engine: engine, | ||
modules: modules, | ||
modules_used: rs.modules_used, | ||
scope: rs.scope | ||
var installAllEnableRulesets = function(callback){ | ||
db.getAllEnableRulesets(function(err, rids){ | ||
if(err)return callback(err); | ||
λ.map(rids, getRulesetForRID, function(err, rs_list){ | ||
if(err)return callback(err); | ||
var rs_by_rid = {}; | ||
_.each(rs_list, function(rs){ | ||
rs_by_rid[rs.rid] = rs; | ||
}); | ||
var val = ctx.scope.get(query.name); | ||
if(_.isFunction(val)){ | ||
applyInFiber(val, null, [ctx, query.args], function(err, resp){ | ||
if(err) return callback(err); | ||
callback(undefined, resp); | ||
}); | ||
}else{ | ||
callback(undefined, val); | ||
} | ||
var loadDepRS = function(rid){ | ||
return rs_by_rid[rid]; | ||
}; | ||
λ.each(rs_list, function(rs, next){ | ||
installRuleset(rs, loadDepRS, next); | ||
}, callback); | ||
}); | ||
} | ||
}); | ||
}; | ||
installAllEnableRulesets(function(err){ | ||
if(err) return callback(err); | ||
callback(void 0, { | ||
db: db, | ||
emitter: emitter, | ||
isInstalled: function(rid){ | ||
return _.has(rulesets, rid); | ||
}, | ||
installRID: installRID, | ||
signalEvent: signalEvent, | ||
runQuery: runQuery | ||
}); | ||
}); | ||
}; |
@@ -60,45 +60,47 @@ var _ = require("lodash"); | ||
test("PicoEngine - hello_world ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
λ.series({ | ||
npico: λ.curry(pe.db.newPico, {}), | ||
chan0: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid1x: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.hello_world"}), | ||
λ.series({ | ||
npico: λ.curry(pe.db.newPico, {}), | ||
chan0: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid1x: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.hello_world"}), | ||
hello_event: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "1234", | ||
domain: "echo", | ||
type: "hello", | ||
attrs: {} | ||
}), | ||
hello_query: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.hello_world", | ||
name: "hello", | ||
args: {obj: "Bob"} | ||
}) | ||
hello_event: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "1234", | ||
domain: "echo", | ||
type: "hello", | ||
attrs: {} | ||
}), | ||
hello_query: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.hello_world", | ||
name: "hello", | ||
args: {obj: "Bob"} | ||
}) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(data.hello_event, { | ||
directives: [ | ||
{ | ||
name: "say", | ||
options: { | ||
something: "Hello World" | ||
}, | ||
meta: { | ||
eid: "1234", | ||
rid: "io.picolabs.hello_world", | ||
rule_name: "say_hello", | ||
txn_id: "TODO" | ||
t.deepEquals(data.hello_event, { | ||
directives: [ | ||
{ | ||
name: "say", | ||
options: { | ||
something: "Hello World" | ||
}, | ||
meta: { | ||
eid: "1234", | ||
rid: "io.picolabs.hello_world", | ||
rule_name: "say_hello", | ||
txn_id: "TODO" | ||
} | ||
} | ||
} | ||
] | ||
] | ||
}); | ||
t.deepEquals(data.hello_query, "Hello Bob"); | ||
t.end(); | ||
}); | ||
t.deepEquals(data.hello_query, "Hello Bob"); | ||
t.end(); | ||
}); | ||
@@ -108,91 +110,93 @@ }); | ||
test("PicoEngine - persistent ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
λ.series({ | ||
pico0: λ.curry(pe.db.newPico, {}), | ||
chan1: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid_0: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.persistent"}), | ||
λ.series({ | ||
pico0: λ.curry(pe.db.newPico, {}), | ||
chan1: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid_0: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.persistent"}), | ||
pico2: λ.curry(pe.db.newPico, {}), | ||
chan3: λ.curry(pe.db.newChannel, {pico_id: "id2", name: "three", type: "t"}), | ||
rid_1: λ.curry(pe.db.addRuleset, {pico_id: "id2", rid: "io.picolabs.persistent"}), | ||
pico2: λ.curry(pe.db.newPico, {}), | ||
chan3: λ.curry(pe.db.newChannel, {pico_id: "id2", name: "three", type: "t"}), | ||
rid_1: λ.curry(pe.db.addRuleset, {pico_id: "id2", rid: "io.picolabs.persistent"}), | ||
store_bob0: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "1234", | ||
domain: "store", | ||
type: "name", | ||
attrs: {name: "bob"} | ||
}), | ||
store_bob0: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "1234", | ||
domain: "store", | ||
type: "name", | ||
attrs: {name: "bob"} | ||
}), | ||
query0: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
query0: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
store_bob1: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "12345", | ||
domain: "store", | ||
type: "name", | ||
attrs: {name: "jim"} | ||
}), | ||
store_bob1: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "12345", | ||
domain: "store", | ||
type: "name", | ||
attrs: {name: "jim"} | ||
}), | ||
query1: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
query2: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
query1: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
query2: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getName", | ||
args: {} | ||
}), | ||
store_appvar0: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "123456", | ||
domain: "store", | ||
type: "appvar", | ||
attrs: {appvar: "global thing"} | ||
}), | ||
query3: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getAppVar", | ||
args: {} | ||
}), | ||
query4: λ.curry(pe.runQuery, { | ||
eci: "id3", | ||
rid: "io.picolabs.persistent", | ||
name: "getAppVar", | ||
args: {} | ||
}) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
store_appvar0: λ.curry(pe.signalEvent, { | ||
eci: "id1", | ||
eid: "123456", | ||
domain: "store", | ||
type: "appvar", | ||
attrs: {appvar: "global thing"} | ||
}), | ||
query3: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "io.picolabs.persistent", | ||
name: "getAppVar", | ||
args: {} | ||
}), | ||
query4: λ.curry(pe.runQuery, { | ||
eci: "id3", | ||
rid: "io.picolabs.persistent", | ||
name: "getAppVar", | ||
args: {} | ||
}) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.deepEquals(omitMeta(data.store_bob0), [ | ||
{name: "store_name", options: {name: "bob"}} | ||
]); | ||
t.deepEquals(omitMeta(data.store_bob0), [ | ||
{name: "store_name", options: {name: "bob"}} | ||
]); | ||
t.deepEquals(data.query0, "bob"); | ||
t.deepEquals(data.query0, "bob"); | ||
t.deepEquals(omitMeta(data.store_bob1), [ | ||
{name: "store_name", options: {name: "jim"}} | ||
]); | ||
t.deepEquals(omitMeta(data.store_bob1), [ | ||
{name: "store_name", options: {name: "jim"}} | ||
]); | ||
t.deepEquals(data.query1, "jim"); | ||
t.deepEquals(data.query2, "jim"); | ||
t.deepEquals(data.query1, "jim"); | ||
t.deepEquals(data.query2, "jim"); | ||
t.deepEquals(omitMeta(data.store_appvar0), [ | ||
{name: "store_appvar", options: {appvar: "global thing"}} | ||
]); | ||
t.deepEquals(data.query3, "global thing"); | ||
t.deepEquals(data.query4, "global thing"); | ||
t.deepEquals(omitMeta(data.store_appvar0), [ | ||
{name: "store_appvar", options: {appvar: "global thing"}} | ||
]); | ||
t.deepEquals(data.query3, "global thing"); | ||
t.deepEquals(data.query4, "global thing"); | ||
t.end(); | ||
t.end(); | ||
}); | ||
}); | ||
@@ -203,26 +207,28 @@ }); | ||
test("PicoEngine - raw ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
λ.series({ | ||
pico: λ.curry(pe.db.newPico, {}), | ||
chan: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid3: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "rid3x0"}), | ||
λ.series({ | ||
pico: λ.curry(pe.db.newPico, {}), | ||
chan: λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
rid3: λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "rid3x0"}), | ||
signal: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "rid3x0", | ||
name: "sayRawHello", | ||
args: {} | ||
}) | ||
signal: λ.curry(pe.runQuery, { | ||
eci: "id1", | ||
rid: "rid3x0", | ||
name: "sayRawHello", | ||
args: {} | ||
}) | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
}, function(err, data){ | ||
if(err) return t.end(err); | ||
t.ok(_.isFunction(data.signal)); | ||
t.ok(_.isFunction(data.signal)); | ||
data.signal({ | ||
end: function(txt){ | ||
t.equals(txt, "raw hello!"); | ||
t.end(); | ||
} | ||
data.signal({ | ||
end: function(txt){ | ||
t.equals(txt, "raw hello!"); | ||
t.end(); | ||
} | ||
}); | ||
}); | ||
@@ -234,407 +240,423 @@ }); | ||
test("PicoEngine - io.picolabs.events ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.events"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.events"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.events"}), | ||
[ | ||
signal("events", "bind", {name: "blah?!"}), | ||
[{name: "bound", options: {name: "blah?!"}}] | ||
], | ||
[ | ||
signal("events", "get", {thing: "asdf"}), | ||
[{name: "get", options: {thing: "asdf"}}] | ||
], | ||
[ | ||
signal("events", "noop", {}), | ||
[] | ||
], | ||
[ | ||
signal("events", "noop2", {}), | ||
[] | ||
], | ||
[ | ||
signal("events_or", "a"), | ||
[{name: "or", options: {}}] | ||
], | ||
[ | ||
signal("events_or", "b"), | ||
[{name: "or", options: {}}] | ||
], | ||
[ | ||
signal("events_or", "c"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "c"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events", "ifthen", {name: "something"}), | ||
[{name: "ifthen", options: {}}] | ||
], | ||
[ | ||
signal("events", "ifthen", {}), | ||
[] | ||
], | ||
[ | ||
signal("events", "on_fired", {name: "blah"}), | ||
[{name: "on_fired", options: {previous_name: undefined}}] | ||
], | ||
[ | ||
signal("events", "on_fired", {}), | ||
[{name: "on_fired", options: {previous_name: "blah"}}] | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "one"}), | ||
[{name: "on_choose - one", options: {}}] | ||
], | ||
[ | ||
query("getOnChooseFired"), | ||
true | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "two"}), | ||
[{name: "on_choose - two", options: {}}] | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "wat?"}), | ||
[] | ||
], | ||
[ | ||
query("getOnChooseFired"), | ||
false | ||
], | ||
[ | ||
signal("events", "select_where", {something: "wat?"}), | ||
[{name: "select_where", options: {}}] | ||
], | ||
[ | ||
signal("events", "select_where", {something: "ok wat?"}), | ||
[] | ||
], | ||
[signal("events", "no_action", {fired: "no"}), []], | ||
[query("getNoActionFired"), void 0], | ||
[signal("events", "no_action", {fired: "yes"}), []], | ||
[query("getNoActionFired"), true]//fired even though no actions | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.events"}), | ||
[ | ||
signal("events", "bind", {name: "blah?!"}), | ||
[{name: "bound", options: {name: "blah?!"}}] | ||
], | ||
[ | ||
signal("events", "get", {thing: "asdf"}), | ||
[{name: "get", options: {thing: "asdf"}}] | ||
], | ||
[ | ||
signal("events", "noop", {}), | ||
[] | ||
], | ||
[ | ||
signal("events", "noop2", {}), | ||
[] | ||
], | ||
[ | ||
signal("events_or", "a"), | ||
[{name: "or", options: {}}] | ||
], | ||
[ | ||
signal("events_or", "b"), | ||
[{name: "or", options: {}}] | ||
], | ||
[ | ||
signal("events_or", "c"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "c"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "b"), | ||
[] | ||
], | ||
[ | ||
signal("events_and", "a"), | ||
[{name: "and", options: {}}] | ||
], | ||
[ | ||
signal("events", "ifthen", {name: "something"}), | ||
[{name: "ifthen", options: {}}] | ||
], | ||
[ | ||
signal("events", "ifthen", {}), | ||
[] | ||
], | ||
[ | ||
signal("events", "on_fired", {name: "blah"}), | ||
[{name: "on_fired", options: {previous_name: undefined}}] | ||
], | ||
[ | ||
signal("events", "on_fired", {}), | ||
[{name: "on_fired", options: {previous_name: "blah"}}] | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "one"}), | ||
[{name: "on_choose - one", options: {}}] | ||
], | ||
[ | ||
query("getOnChooseFired"), | ||
true | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "two"}), | ||
[{name: "on_choose - two", options: {}}] | ||
], | ||
[ | ||
signal("events", "on_choose", {thing: "wat?"}), | ||
[] | ||
], | ||
[ | ||
query("getOnChooseFired"), | ||
false | ||
], | ||
[ | ||
signal("events", "select_where", {something: "wat?"}), | ||
[{name: "select_where", options: {}}] | ||
], | ||
[ | ||
signal("events", "select_where", {something: "ok wat?"}), | ||
[] | ||
], | ||
[signal("events", "no_action", {fired: "no"}), []], | ||
[query("getNoActionFired"), void 0], | ||
[signal("events", "no_action", {fired: "yes"}), []], | ||
[query("getNoActionFired"), true]//fired even though no actions | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.scope ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.scope"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.scope"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.scope"}), | ||
[ | ||
signal("scope", "event0", {name: "name 0"}), | ||
[{name: "say", options: {name: "name 0"}}] | ||
], | ||
[ | ||
signal("scope", "event1", {name: "name 1"}), | ||
[{name: "say", options: {name: undefined}}] | ||
], | ||
[ | ||
signal("scope", "event0", {}), | ||
[{name: "say", options: {name: ""}}] | ||
], | ||
[ | ||
signal("scope", "prelude", {name: "Bill"}), | ||
[{name: "say", options: { | ||
name: "Bill", | ||
p0: "prelude 0", | ||
p1: "prelude 1", | ||
g0: "global 0" | ||
}}] | ||
], | ||
[ | ||
query("getVals"), | ||
{name: "Bill", p0: "prelude 0", p1: "prelude 1"} | ||
], | ||
[ | ||
query("g0"), | ||
"global 0" | ||
], | ||
[ | ||
query("add", {"a": 10, "b": 2}), | ||
12 | ||
], | ||
[ | ||
signal("scope", "functions"), | ||
[{name: "say", options: { | ||
add_one_two: 3, | ||
inc5_3: 8, | ||
g0: "overrided g0!" | ||
}}] | ||
] | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.scope"}), | ||
[ | ||
signal("scope", "event0", {name: "name 0"}), | ||
[{name: "say", options: {name: "name 0"}}] | ||
], | ||
[ | ||
signal("scope", "event1", {name: "name 1"}), | ||
[{name: "say", options: {name: undefined}}] | ||
], | ||
[ | ||
signal("scope", "event0", {}), | ||
[{name: "say", options: {name: ""}}] | ||
], | ||
[ | ||
signal("scope", "prelude", {name: "Bill"}), | ||
[{name: "say", options: { | ||
name: "Bill", | ||
p0: "prelude 0", | ||
p1: "prelude 1", | ||
g0: "global 0" | ||
}}] | ||
], | ||
[ | ||
query("getVals"), | ||
{name: "Bill", p0: "prelude 0", p1: "prelude 1"} | ||
], | ||
[ | ||
query("g0"), | ||
"global 0" | ||
], | ||
[ | ||
query("add", {"a": 10, "b": 2}), | ||
12 | ||
], | ||
[ | ||
signal("scope", "functions"), | ||
[{name: "say", options: { | ||
add_one_two: 3, | ||
inc5_3: 8, | ||
g0: "overrided g0!" | ||
}}] | ||
] | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.operators ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.operators"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.operators"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.operators"}), | ||
[ | ||
query("results"), | ||
{ | ||
"str_as_num": 100.25, | ||
"num_as_str": "1.05", | ||
"regex_as_str": "blah", | ||
"isnull": [ | ||
false, | ||
false, | ||
true | ||
], | ||
"typeof": [ | ||
"Number", | ||
"String", | ||
"String", | ||
"Array", | ||
"Map", | ||
"RegExp", | ||
"Null", | ||
"Null" | ||
], | ||
"75.chr()": "K", | ||
"0.range(10)": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], | ||
"10.sprintf": "< 10>", | ||
".capitalize()": "Hello World", | ||
".decode()": [3, 4, 5], | ||
".extract": ["s is a st","ring"], | ||
".lc()": "hello world", | ||
".match true": true, | ||
".match false": false, | ||
".ord()": 72, | ||
".replace": "Hello Billiam!", | ||
".split": ["a", "b", "c"], | ||
".sprintf": "Hello Jim!", | ||
".substr(5)": "is a string", | ||
".substr(5, 4)": "is a", | ||
".substr(5, -5)": "is a s", | ||
".substr(25)": undefined, | ||
".uc()": "HELLO WORLD" | ||
} | ||
], | ||
[ | ||
query("returnMapAfterKlog"), | ||
{a: 1} | ||
], | ||
[ | ||
query("returnArrayAfterKlog"), | ||
[1, 2] | ||
] | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.operators"}), | ||
[ | ||
query("results"), | ||
{ | ||
"str_as_num": 100.25, | ||
"num_as_str": "1.05", | ||
"regex_as_str": "blah", | ||
"isnull": [ | ||
false, | ||
false, | ||
true | ||
], | ||
"typeof": [ | ||
"Number", | ||
"String", | ||
"String", | ||
"Array", | ||
"Map", | ||
"RegExp", | ||
"Null", | ||
"Null" | ||
], | ||
"75.chr()": "K", | ||
"0.range(10)": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], | ||
"10.sprintf": "< 10>", | ||
".capitalize()": "Hello World", | ||
".decode()": [3, 4, 5], | ||
".extract": ["s is a st","ring"], | ||
".lc()": "hello world", | ||
".match true": true, | ||
".match false": false, | ||
".ord()": 72, | ||
".replace": "Hello Billiam!", | ||
".split": ["a", "b", "c"], | ||
".sprintf": "Hello Jim!", | ||
".substr(5)": "is a string", | ||
".substr(5, 4)": "is a", | ||
".substr(5, -5)": "is a s", | ||
".substr(25)": undefined, | ||
".uc()": "HELLO WORLD" | ||
} | ||
], | ||
[ | ||
query("returnMapAfterKlog"), | ||
{a: 1} | ||
], | ||
[ | ||
query("returnArrayAfterKlog"), | ||
[1, 2] | ||
] | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.chevron ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.chevron"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.chevron"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.chevron"}), | ||
[ | ||
query("d"), | ||
"\n hi 1 + 2 = 3\n <h1>some<b>html</b></h1>\n " | ||
] | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.chevron"}), | ||
[ | ||
query("d"), | ||
"\n hi 1 + 2 = 3\n <h1>some<b>html</b></h1>\n " | ||
] | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.execution-order ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.execution-order"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.execution-order"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.execution-order"}), | ||
[ | ||
query("getOrder"), | ||
void 0 | ||
], | ||
[ | ||
signal("execution_order", "all"), | ||
[{name: "first", options: {}}, {name: "second", options: {}}] | ||
], | ||
[ | ||
query("getOrder"), | ||
[null, "first-fired", "first-finally", "second-fired", "second-finally"] | ||
] | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.execution-order"}), | ||
[ | ||
query("getOrder"), | ||
void 0 | ||
], | ||
[ | ||
signal("execution_order", "all"), | ||
[{name: "first", options: {}}, {name: "second", options: {}}] | ||
], | ||
[ | ||
query("getOrder"), | ||
[null, "first-fired", "first-finally", "second-fired", "second-finally"] | ||
] | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.engine ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var signal = mkSignalTask(pe, "id1"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.engine"}), | ||
[signal("engine", "newPico"), []], | ||
[ | ||
signal("engine", "newChannel", { | ||
pico_id: "id2", | ||
name: "krl created chan", | ||
type: "some type?" | ||
}), | ||
[] | ||
], | ||
function(done){ | ||
pe.db.toObj(function(err, data){ | ||
if(err)return done(err); | ||
t.deepEquals(data.pico.id2, { | ||
id: "id2", | ||
channel: { | ||
id3: { | ||
id: "id3", | ||
name: "krl created chan", | ||
type: "some type?" | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.engine"}), | ||
[signal("engine", "newPico"), []], | ||
[ | ||
signal("engine", "newChannel", { | ||
pico_id: "id2", | ||
name: "krl created chan", | ||
type: "some type?" | ||
}), | ||
[] | ||
], | ||
function(done){ | ||
pe.db.toObj(function(err, data){ | ||
if(err)return done(err); | ||
t.deepEquals(data.pico.id2, { | ||
id: "id2", | ||
channel: { | ||
id3: { | ||
id: "id3", | ||
name: "krl created chan", | ||
type: "some type?" | ||
} | ||
} | ||
} | ||
}); | ||
done(); | ||
}); | ||
done(); | ||
}); | ||
} | ||
], t.end); | ||
} | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.module-used ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.module-defined"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.module-defined"); | ||
var signal = mkSignalTask(pe, "id1"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.module-used"}), | ||
[ | ||
signal("module_used", "say_hello", { | ||
name: "Bob" | ||
}), | ||
[{name: "say_hello", options: { | ||
something: "Hello Bob", | ||
configured: "Greetings Bob" | ||
}}] | ||
], | ||
[ | ||
signal("module_defined", "hello"), | ||
[] | ||
], | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.module-defined"}), | ||
[ | ||
signal("module_defined", "hello"), | ||
[{name: "module_defined - should_not_handle_events !", options: {}}] | ||
], | ||
[ | ||
query("queryFn", {obj: "Jim"}), | ||
"Query: Private: Hello Jim" | ||
], | ||
//test non-shared fn can't be queried | ||
function(next){ | ||
query("hello", {obj: "Jim"})(function(err, data){ | ||
t.ok(/Error: Not shared/i.test(err + "")); | ||
query("privateFn", {obj: "Jim"})(function(err, data){ | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.module-used"}), | ||
[ | ||
signal("module_used", "say_hello", { | ||
name: "Bob" | ||
}), | ||
[{name: "say_hello", options: { | ||
something: "Hello Bob", | ||
configured: "Greetings Bob" | ||
}}] | ||
], | ||
[ | ||
signal("module_defined", "hello"), | ||
[] | ||
], | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.module-defined"}), | ||
[ | ||
signal("module_defined", "hello"), | ||
[{name: "module_defined - should_not_handle_events !", options: {}}] | ||
], | ||
[ | ||
query("queryFn", {obj: "Jim"}), | ||
"Query: Private: Hello Jim" | ||
], | ||
//test non-shared fn can't be queried | ||
function(next){ | ||
query("hello", {obj: "Jim"})(function(err, data){ | ||
t.ok(/Error: Not shared/i.test(err + "")); | ||
next(); | ||
query("privateFn", {obj: "Jim"})(function(err, data){ | ||
t.ok(/Error: Not shared/i.test(err + "")); | ||
next(); | ||
}); | ||
}); | ||
}); | ||
}, | ||
//test non-provides fn can't be used | ||
function(next){ | ||
signal("module_used", "privateFn")(function(err, data){ | ||
t.ok(/Error: Not defined/i.test(err + "")); | ||
signal("module_used", "queryFn")(function(err, data){ | ||
}, | ||
//test non-provides fn can't be used | ||
function(next){ | ||
signal("module_used", "privateFn")(function(err, data){ | ||
t.ok(/Error: Not defined/i.test(err + "")); | ||
next(); | ||
signal("module_used", "queryFn")(function(err, data){ | ||
t.ok(/Error: Not defined/i.test(err + "")); | ||
next(); | ||
}); | ||
}); | ||
}); | ||
} | ||
], t.end); | ||
} | ||
], t.end); | ||
}); | ||
}); | ||
test("PicoEngine - io.picolabs.expressions ruleset", function(t){ | ||
var pe = mkTestPicoEngine(); | ||
mkTestPicoEngine({}, function(err, pe){ | ||
if(err)return t.end(err); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.expressions"); | ||
var query = mkQueryTask(pe, "id1", "io.picolabs.expressions"); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.expressions"}), | ||
[ | ||
query("obj"), | ||
{ | ||
a: "changed 1", | ||
b: {c: [2, 3, 4, {d: {e: "changed 5"}}, 6, 7]} | ||
} | ||
], | ||
[ | ||
query("path1"), | ||
{e: "changed 5"} | ||
], | ||
[ | ||
query("path2"), | ||
7 | ||
], | ||
[ | ||
query("index1"), | ||
"changed 1" | ||
], | ||
[ | ||
query("index2"), | ||
3 | ||
] | ||
], t.end); | ||
testOutputs(t, [ | ||
λ.curry(pe.db.newPico, {}), | ||
λ.curry(pe.db.newChannel, {pico_id: "id0", name: "one", type: "t"}), | ||
λ.curry(pe.db.addRuleset, {pico_id: "id0", rid: "io.picolabs.expressions"}), | ||
[ | ||
query("obj"), | ||
{ | ||
a: "changed 1", | ||
b: {c: [2, 3, 4, {d: {e: "changed 5"}}, 6, 7]} | ||
} | ||
], | ||
[ | ||
query("path1"), | ||
{e: "changed 5"} | ||
], | ||
[ | ||
query("path2"), | ||
7 | ||
], | ||
[ | ||
query("index1"), | ||
"changed 1" | ||
], | ||
[ | ||
query("index2"), | ||
3 | ||
] | ||
], t.end); | ||
}); | ||
}); |
var _ = require("lodash"); | ||
var λ = require("contra"); | ||
var fs = require("fs"); | ||
@@ -20,5 +21,5 @@ var path = require("path"); | ||
module.exports = function(opts){ | ||
var pe = PicoEngine({ | ||
_dont_check_enabled_before_installing: true, | ||
module.exports = function(opts, callback){ | ||
opts = opts || {}; | ||
PicoEngine({ | ||
compileAndLoadRuleset: function(rs_info, callback){ | ||
@@ -37,7 +38,22 @@ var rs = test_rulesets[rs_info.rid]; | ||
} | ||
}, function(err, pe){ | ||
if(err)return callback(err); | ||
if(opts.dont_register_rulesets){ | ||
callback(void 0, pe); | ||
return; | ||
} | ||
λ.each(_.keys(test_rulesets), function(rid, next){ | ||
//hack since compileAndLoadRuleset doesn't actually compile | ||
var krl_src = "ruleset " + rid + "{}"; | ||
pe.db.registerRuleset(krl_src, function(err, hash){ | ||
if(err)return next(err); | ||
pe.db.enableRuleset(hash, function(err){ | ||
if(err)return next(err); | ||
pe.installRID(rid, next); | ||
}); | ||
}); | ||
}, function(err){ | ||
callback(err, pe); | ||
}); | ||
}); | ||
_.each(test_rulesets, function(rs, rid){ | ||
pe.installRID(rid, function(err){if(err)throw err;}); | ||
}); | ||
return pe; | ||
}; |
@@ -5,5 +5,21 @@ var getArg = require("../getArg"); | ||
var name = getArg(args, "name", 0); | ||
return ctx.event.getAttr(name); | ||
return ctx.event.attrs[name]; | ||
}; | ||
var attrMatches = function(ctx, args){ | ||
var pairs = getArg(args, "pairs", 0); | ||
var matches = []; | ||
var i, attr, m, pair; | ||
for(i = 0; i < pairs.length; i++){ | ||
pair = pairs[i]; | ||
attr = ctx.event.attrs[pair[0]]; | ||
m = pair[1].exec(attr || ""); | ||
if(!m){ | ||
return undefined; | ||
} | ||
matches.push(m[1]); | ||
} | ||
return matches; | ||
}; | ||
module.exports = { | ||
@@ -13,2 +29,4 @@ get: function(ctx, id){ | ||
return eventGetAttr; | ||
}else if(id === "attrMatches"){ | ||
return attrMatches; | ||
} | ||
@@ -15,0 +33,0 @@ }, |
@@ -34,5 +34,5 @@ var _ = require("lodash"); | ||
module.exports = function(ctx, salience_graph, rulesets, callback){ | ||
module.exports = function(ctx, callback){ | ||
var to_run = _.get(salience_graph, [ctx.event.domain, ctx.event.type], {}); | ||
var to_run = _.get(ctx.salience_graph, [ctx.event.domain, ctx.event.type], {}); | ||
@@ -46,7 +46,7 @@ var rules_to_select = []; | ||
if(is_on){ | ||
var rule = _.get(rulesets, [rid, "rules", rule_name]); | ||
var rule = _.get(ctx.rulesets, [rid, "rules", rule_name]); | ||
if(rule){ | ||
//shallow clone with it"s own scope for this run | ||
rules_to_select.push(_.assign({}, rule, { | ||
scope: rulesets[rid].scope.push() | ||
scope: ctx.rulesets[rid].scope.push() | ||
})); | ||
@@ -53,0 +53,0 @@ } |
47246
24
1530