``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
135 lines
6.6 KiB
JavaScript
135 lines
6.6 KiB
JavaScript
import { log, LOG_LEVEL } from './utils/log';
|
|
var FeaturePreprocessor = /** @class */ (function () {
|
|
function FeaturePreprocessor() {
|
|
this.featureMap = new Map();
|
|
this.statementList = [];
|
|
}
|
|
FeaturePreprocessor.prototype.process = function (_a) {
|
|
var rootFeatureIds = _a.rootFeatureIds, featureMap = _a.featureMap;
|
|
this.featureMap = featureMap;
|
|
// Add statements from root level features, and their subfeatures.
|
|
for (var _i = 0, rootFeatureIds_1 = rootFeatureIds; _i < rootFeatureIds_1.length; _i++) {
|
|
var featureId = rootFeatureIds_1[_i];
|
|
var feature = featureMap.get(featureId);
|
|
if (feature === undefined) {
|
|
log(LOG_LEVEL.ERROR, "Feature " + featureId + " not found");
|
|
}
|
|
else {
|
|
this.deriveStatements(feature, null, null);
|
|
}
|
|
}
|
|
return this.statementList;
|
|
};
|
|
FeaturePreprocessor.prototype.deriveStatements = function (feature, featureReferenceId, parameters) {
|
|
for (var _i = 0, _a = feature.statements; _i < _a.length; _i++) {
|
|
var statement = _a[_i];
|
|
// Make a deep copy of the statement. The copy gets the featureReferenceId set.
|
|
// Also, the engine will be modifying the expressions in the statements, so a deep copy is needed.
|
|
var statementCopy = JSON.parse(JSON.stringify(statement));
|
|
if (featureReferenceId !== null && parameters !== null) {
|
|
// targets might be parameterized
|
|
statementCopy.target = this.evaluateStatementTarget(statementCopy.target, parameters);
|
|
// then dive into the statement's expressions to evaluate parameterized static and dynamic values
|
|
this.processExpression(statementCopy.operand, parameters);
|
|
}
|
|
this.statementList.push(statementCopy);
|
|
}
|
|
for (var _b = 0, _c = feature.subfeatures; _b < _c.length; _b++) {
|
|
var featureReference = _c[_b];
|
|
// the featureReference might also be parameterized, in order to pass parameters down multiple levels
|
|
var referenceCopy = JSON.parse(JSON.stringify(featureReference)); // copy might not be needed
|
|
if (parameters !== null) {
|
|
this.processReferenceParameters(referenceCopy.parameters, parameters);
|
|
}
|
|
var subfeatureDef = this.featureMap.get(referenceCopy.featureId);
|
|
if (subfeatureDef === undefined) {
|
|
log(LOG_LEVEL.ERROR, "Feature " + referenceCopy.featureId + " not found");
|
|
}
|
|
else {
|
|
this.deriveStatements(subfeatureDef, referenceCopy.featureReferenceId, referenceCopy.parameters);
|
|
}
|
|
}
|
|
};
|
|
FeaturePreprocessor.prototype.evaluateStatementTarget = function (target, parameters) {
|
|
var newTargetList = [];
|
|
for (var i = 0; i < target.length; i++) {
|
|
var part = target[i];
|
|
if (typeof part === 'string' && part.startsWith('$inputs.')) {
|
|
var evaluated = this.lookupInput(part, parameters);
|
|
if (evaluated === null || evaluated.some(function (x) { return typeof x !== 'string'; })) {
|
|
throw new Error('Parameter values for dynamic targets must be strings');
|
|
}
|
|
newTargetList.push.apply(newTargetList, evaluated);
|
|
}
|
|
else {
|
|
newTargetList.push(part);
|
|
}
|
|
}
|
|
return newTargetList;
|
|
};
|
|
// Some duplicated code here. The difference is that targets must be strings,
|
|
// while expression parameters might be numbers.
|
|
FeaturePreprocessor.prototype.evaluateExpressionValues = function (values, parameters) {
|
|
// An array of strings might turn into an array of numbers, if the parameter values are numbers.
|
|
// I don't like this :O
|
|
var evaluatedValues = [];
|
|
for (var i = 0; i < values.length; i++) {
|
|
var part = values[i];
|
|
if (typeof part === 'string' && part.startsWith('$inputs.')) {
|
|
var evaluated = this.lookupInput(part, parameters);
|
|
if (evaluated === null) {
|
|
throw new Error('Parameter values for static or dynamic values cannot be null');
|
|
}
|
|
evaluatedValues.push.apply(evaluatedValues, evaluated);
|
|
}
|
|
else {
|
|
evaluatedValues.push(part);
|
|
}
|
|
}
|
|
if (evaluatedValues.every(function (x) { return typeof x === 'string'; })) {
|
|
return evaluatedValues;
|
|
}
|
|
if (evaluatedValues.every(function (x) { return typeof x === 'number'; })) {
|
|
return evaluatedValues;
|
|
}
|
|
throw new Error('Parameter value type needs to match the type of non-parameterized values');
|
|
};
|
|
FeaturePreprocessor.prototype.lookupInput = function (inputName, parameters) {
|
|
var splits = inputName.split('$inputs.');
|
|
if (splits.length !== 2) {
|
|
throw new Error('Invalid $inputs format');
|
|
}
|
|
var key = splits[1];
|
|
if (!parameters.hasOwnProperty(key)) {
|
|
throw new Error("Parameters is missing key " + key);
|
|
}
|
|
return parameters[key]; // TODO: Check to make sure the parameter is there
|
|
};
|
|
FeaturePreprocessor.prototype.processExpression = function (expression, parameters) {
|
|
// If the expression has values, evaluate any $inputs
|
|
if (expression.values !== null && expression.values.length) {
|
|
expression.values = this.evaluateExpressionValues(expression.values, parameters);
|
|
}
|
|
// If the expression has operands, recurse!
|
|
if (expression.operands !== null && expression.operands.length) {
|
|
for (var _i = 0, _a = expression.operands; _i < _a.length; _i++) {
|
|
var operand = _a[_i];
|
|
this.processExpression(operand, parameters);
|
|
}
|
|
}
|
|
};
|
|
FeaturePreprocessor.prototype.processReferenceParameters = function (childParameters, parentParameters) {
|
|
// FeatureParameters is Record<string, Array<string> | Array<number> | null>
|
|
var parameterKeys = Object.keys(childParameters);
|
|
for (var _i = 0, parameterKeys_1 = parameterKeys; _i < parameterKeys_1.length; _i++) {
|
|
var key = parameterKeys_1[_i];
|
|
var parameterValues = childParameters[key];
|
|
if (parameterValues !== null) {
|
|
childParameters[key] = this.evaluateExpressionValues(parameterValues, parentParameters);
|
|
}
|
|
}
|
|
};
|
|
return FeaturePreprocessor;
|
|
}());
|
|
export { FeaturePreprocessor };
|