machine-framework
Version:
self-assembling client-side web framework
187 lines (119 loc) • 4.83 kB
JavaScript
const PartBuilder = {};
PartBuilder.buildConfig = function buildConfig(def){
if(!def && !this.parent) // empty root config
def = {};
if(def){
def = def.config || def;
const d = this.scope.demand('config');
if(typeof def === 'string'){
const meow = def + ' > config';
this.scope.bus().meow(meow).pull();
} else {
d.write(def);
}
this.config = def;
}
};
PartBuilder.output = function output(name, value){
const d = this.scope.find(name);
d.write(value);
};
PartBuilder.buildStates = function buildStates(){
const script = this.script;
const scope = this.scope;
const states = script.states;
for(const name in states){
const def = states[name];
const state = scope.demand(name);
if(def.hasValue) {
const value = typeof def.value === 'function'
? def.value.call(script)
: def.value;
state.write(value, true);
}
}
for(const name in states){
const state = scope.grab(name);
state.refresh();
}
};
PartBuilder.buildWires = function buildWires(){
const wires = this.script.wires;
const scope = this.scope;
const script = this.script;
// todo add initial state values
for(const name in wires) {
const def = wires[name];
const state = scope.demand(def.stateName);
const action = scope.demand(def.actionName);
if(def.hasValue) {
const value = typeof def.value === 'function'
? def.value.call(script)
: def.value;
state.write(value, true);
}
const meow = def.actionName + def.transform + ' > ' + def.stateName; // todo assert def has cmd at start
scope.bus().meow(meow);
}
for(const name in wires){
const def = wires[name];
const state = scope.grab(def.stateName);
state.refresh();
}
};
PartBuilder.buildRelays = function buildRelays(){
const scope = this.scope;
const config = this.config;
const relays = this.script.relays;
const len = relays.length;
for(let i = 0; i < len; ++i){
const def = relays[i];
const actionProp = def.action || def.wire;
const stateProp = def.state || def.wire;
let actionName = null;
let stateName = null;
if(actionProp)
actionName = (actionProp[0] !== '$') ? '$' + actionProp : actionProp;
if(stateProp)
stateName = (stateProp[0] === '$') ? stateProp.substr(1) : stateProp;
// todo -- make $ prefix correct on these too, put in separate function
const remoteActionName = actionProp && config[actionProp];
const remoteStateName = stateProp && config[stateProp];
let remoteAction = remoteActionName ? scope._parent.find(remoteActionName, true) : null;
let remoteState = remoteStateName ? scope._parent.find(remoteStateName, true) : null;
let localAction = actionName ? scope.demand(actionName) : null;
let localState = stateName ? scope.demand(stateName) : null;
if(actionName && !stateName && remoteAction){ // only action goes out relay
scope.bus().addSubscribe(actionName, localAction).write(remoteAction);
}
if(stateName && !actionName && remoteState){ // only state comes in relay
scope.bus().addSubscribe(remoteStateName, remoteState).write(localState).pull();
}
if(actionName && stateName){ // defines both
if(remoteAction && remoteState){ // wire action and state (wire together above)
scope.bus().addSubscribe(actionName, localAction).write(remoteAction);
scope.bus().addSubscribe(remoteStateName, remoteState).write(localState).pull();
} else if (remoteAction && !remoteState){
// assert relay has action sans state
} else if (remoteState && !remoteAction){
// assert relay has state sans action
} else { // neither configured, wire locally
// warning -- relay disconnected
scope.bus().addSubscribe(actionName, localAction).write(localState);
}
}
}
};
PartBuilder.buildActions = function buildActions(){
const actions = this.script.actions;
const scope = this.scope;
for(const name in actions){
const def = actions[name]; // name in hash might not have leading $
this.scope.demand(def.name); // name in def always has leading $
if(def.to){
const meow = def.name + def.to; // todo assert def has cmd at start
scope.bus().meow(meow);
}
}
};
export default PartBuilder;