chai-latte
Version:
Build expressive & readable fluent interface libraries.
108 lines • 4.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFluentAPI = exports.createExecutableFluentAPI = exports.buildFluentTree = exports.parse = exports.WordNode = void 0;
const WordNode_1 = require("./WordNode");
const parse_1 = require("./parse");
const template_1 = require("./template");
var WordNode_2 = require("./WordNode");
Object.defineProperty(exports, "WordNode", { enumerable: true, get: function () { return WordNode_2.WordNode; } });
var parse_2 = require("./parse");
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return parse_2.parse; } });
;
const buildFluentTree = (builder) => {
const executables = builder(parse_1.parse).map((parsed) => {
return {
sentence: () => parsed,
execute: () => { },
};
});
const executableRoot = (0, exports.createExecutableFluentAPI)(executables);
return executableRoot.node;
};
exports.buildFluentTree = buildFluentTree;
const createExecutableFluentAPI = (executables) => {
const executableByTemplate = new Map();
const parsed = [];
executables.forEach((executable) => {
executableByTemplate.set(executable.sentence.template, executable.execute);
parsed.push(executable.sentence);
});
const callback = (template) => {
const isfunctionAvailable = executableByTemplate.has(template.template);
if (isfunctionAvailable) {
const execute = executableByTemplate.get(template.template);
execute(...template.variables);
}
};
return (0, exports.createFluentAPI)(parsed, callback);
};
exports.createExecutableFluentAPI = createExecutableFluentAPI;
const createFluentAPI = (sentences, onExecute) => {
const root = {};
root.node = WordNode_1.WordNode.createRootNode({ accessor: root });
let lastFunctionCalled = null;
const template = new template_1.TemplateBuilder(onExecute);
template.disable();
sentences.forEach((parsedSentence) => {
let prev = root;
root.node.addparsedSentence(parsedSentence);
parsedSentence.words.map((parsedChunk, i) => {
const word = parsedChunk.name;
const isImplemented = prev[word]
&& prev[word].node;
if (!isImplemented) {
createWordAccessor(prev, word);
}
const wordNode = prev[word].node;
wordNode.addChunk(parsedChunk);
const previousWordNode = prev.node;
const currentWordNode = prev[word].node;
const previousChunk = parsedSentence.words[i - 1];
previousWordNode.addNextWord(currentWordNode, previousChunk);
prev = prev[word];
});
});
function createWordAccessor(parent, attribute) {
const accessor = function (variable) {
if (!variable) {
return;
}
const isFirstWord = parent === root;
if (isFirstWord) {
template.reset();
template.trace({ word: attribute });
lastFunctionCalled = accessor;
}
template.trace({ variable });
return parent[attribute];
};
accessor.node = new WordNode_1.WordNode({
word: attribute,
accessor: accessor,
});
Object.defineProperty(parent, attribute, {
get() {
tracePropertyAccess(parent, attribute, accessor);
return accessor;
}
});
}
function tracePropertyAccess(parent, attribute, accessor) {
const isAlreadyTraced = lastFunctionCalled === accessor;
if (isAlreadyTraced) {
return;
}
const isFirstWord = parent === root;
const isReAccessed = lastFunctionCalled === parent;
if (!isFirstWord && !isReAccessed) {
template.reset();
template.trace({ word: parent.node.word });
}
template.trace({ word: attribute });
lastFunctionCalled = accessor;
}
template.enable();
return root;
};
exports.createFluentAPI = createFluentAPI;
//# sourceMappingURL=index.js.map