chai-latte
Version:
Build expressive & readable fluent interface libraries.
127 lines • 3.91 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Expression = exports.register = void 0;
const ConfigurableCallback_1 = require("./lib/ConfigurableCallback");
;
const register = (...args) => {
const callback = args.pop();
return args.map((createUsePattern) => {
const expression = new Expression(callback);
const buildListener = expression.createBuilderProxy();
createUsePattern(buildListener);
const api = expression.getFluentAPI();
return {
api,
callback,
expression,
};
});
};
exports.register = register;
class Expression {
fluentAPI = {};
pointer;
static callbacks = new WeakSet();
callbacks = new Set();
callback;
args = [];
constructor(callback) {
this.callback = callback;
Expression.callbacks.add(callback);
this.pointer = new BuildPointer(this.fluentAPI);
}
index = 0;
setExpressionIdx(index) {
this.index = index;
this.callbacks.forEach((callback) => {
});
}
static isFinalCallback(cb) {
return Expression.callbacks.has(cb);
}
getFluentAPI() {
return this.fluentAPI;
}
createConfigurableCallback() {
const callback = new ConfigurableCallback_1.ConfigurableCallback(this);
this.callbacks.add(callback);
return callback;
}
isLastPointerCallback() {
const lastPointer = this.pointer.getLastPointer();
const isLastPointerCallback = typeof lastPointer === 'function';
return isLastPointerCallback;
}
debugId = '';
updateDebugProp(prop) {
this.debugId += this.debugId ? '.' + prop : prop;
}
updateDebugFunction(arg) {
if (typeof arg === 'undefined') {
this.debugId += '()';
return;
}
this.debugId += '(' + arg.name + ')';
}
callbackCount = 0;
handleFunctionCalled(arg) {
const fluentFunction = this.createConfigurableCallback();
this.pointer.overrideLastPointer(fluentFunction.callback);
fluentFunction.updateArg(arg);
fluentFunction.setCallIdx(this.callbackCount++);
this.updateDebugFunction(arg);
}
handlePropertyAccess(prop) {
const isAccessingPropAfterCall = this.isLastPointerCallback();
if (isAccessingPropAfterCall) {
const lastPointer = this.pointer.getLastPointer();
const fluentFunction = ConfigurableCallback_1.ConfigurableCallback.getBuilderOf(lastPointer);
const nextReturn = {};
this.pointer = new BuildPointer(nextReturn);
fluentFunction.updateReturn(nextReturn);
}
this.updateDebugProp(prop);
this.pointer.accessProp(prop);
this.pointer.movePointer(prop);
}
createBuilderProxy() {
const attribute = (arg) => {
this.handleFunctionCalled(arg);
return proxyBuilder;
};
const proxyBuilder = new Proxy(attribute, {
get: (target, prop) => {
this.handlePropertyAccess(prop);
return proxyBuilder;
},
});
return proxyBuilder;
}
}
exports.Expression = Expression;
class BuildPointer {
lastWord = null;
lastPointer = null;
pointer = null;
constructor(initialValue) {
this.pointer = initialValue;
}
overrideLastPointer(override) {
return this.lastPointer[this.lastWord] = override;
;
}
getLastPointer() {
return this.lastPointer?.[this.lastWord];
}
movePointer(prop) {
this.lastPointer = this.pointer;
this.lastWord = prop;
this.pointer = this.pointer[prop];
}
accessProp(prop) {
if (!this.pointer[prop]) {
this.pointer[prop] = {};
}
}
}
//# sourceMappingURL=register.js.map