@jmespath-community/jmespath
Version:
Typescript implementation of the JMESPath Community specification
924 lines • 35.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Runtime = exports.InputArgument = void 0;
const text_1 = require("./utils/text");
const strings_1 = require("./utils/strings");
var InputArgument;
(function (InputArgument) {
InputArgument[InputArgument["TYPE_NUMBER"] = 0] = "TYPE_NUMBER";
InputArgument[InputArgument["TYPE_ANY"] = 1] = "TYPE_ANY";
InputArgument[InputArgument["TYPE_STRING"] = 2] = "TYPE_STRING";
InputArgument[InputArgument["TYPE_ARRAY"] = 3] = "TYPE_ARRAY";
InputArgument[InputArgument["TYPE_OBJECT"] = 4] = "TYPE_OBJECT";
InputArgument[InputArgument["TYPE_BOOLEAN"] = 5] = "TYPE_BOOLEAN";
InputArgument[InputArgument["TYPE_EXPREF"] = 6] = "TYPE_EXPREF";
InputArgument[InputArgument["TYPE_NULL"] = 7] = "TYPE_NULL";
InputArgument[InputArgument["TYPE_ARRAY_NUMBER"] = 8] = "TYPE_ARRAY_NUMBER";
InputArgument[InputArgument["TYPE_ARRAY_STRING"] = 9] = "TYPE_ARRAY_STRING";
InputArgument[InputArgument["TYPE_ARRAY_OBJECT"] = 10] = "TYPE_ARRAY_OBJECT";
InputArgument[InputArgument["TYPE_ARRAY_ARRAY"] = 11] = "TYPE_ARRAY_ARRAY";
})(InputArgument = exports.InputArgument || (exports.InputArgument = {}));
class Runtime {
constructor(interpreter) {
this.TYPE_NAME_TABLE = {
[InputArgument.TYPE_NUMBER]: 'number',
[InputArgument.TYPE_ANY]: 'any',
[InputArgument.TYPE_STRING]: 'string',
[InputArgument.TYPE_ARRAY]: 'array',
[InputArgument.TYPE_OBJECT]: 'object',
[InputArgument.TYPE_BOOLEAN]: 'boolean',
[InputArgument.TYPE_EXPREF]: 'expression',
[InputArgument.TYPE_NULL]: 'null',
[InputArgument.TYPE_ARRAY_NUMBER]: 'Array<number>',
[InputArgument.TYPE_ARRAY_OBJECT]: 'Array<object>',
[InputArgument.TYPE_ARRAY_STRING]: 'Array<string>',
[InputArgument.TYPE_ARRAY_ARRAY]: 'Array<Array<any>>',
};
this.functionAbs = ([inputValue]) => {
return Math.abs(inputValue);
};
this.functionAvg = ([inputArray]) => {
if (!inputArray || inputArray.length == 0) {
return null;
}
let sum = 0;
for (let i = 0; i < inputArray.length; i += 1) {
sum += inputArray[i];
}
return sum / inputArray.length;
};
this.functionCeil = ([inputValue]) => {
return Math.ceil(inputValue);
};
this.functionContains = ([searchable, searchValue,]) => {
if (Array.isArray(searchable)) {
const array = searchable;
return array.includes(searchValue);
}
if (typeof searchable === 'string') {
const text = searchable;
if (typeof searchValue === 'string') {
return text.includes(searchValue);
}
}
return null;
};
this.functionEndsWith = resolvedArgs => {
const [searchStr, suffix] = resolvedArgs;
return searchStr.includes(suffix, searchStr.length - suffix.length);
};
this.functionFindFirst = resolvedArgs => {
const subject = resolvedArgs[0];
const search = resolvedArgs[1];
const start = (resolvedArgs.length > 2 && resolvedArgs[2]) || undefined;
const end = (resolvedArgs.length > 3 && resolvedArgs[3]) || undefined;
return (0, strings_1.findFirst)(subject, search, start, end);
};
this.functionFindLast = resolvedArgs => {
const subject = resolvedArgs[0];
const search = resolvedArgs[1];
const start = (resolvedArgs.length > 2 && resolvedArgs[2]) || undefined;
const end = (resolvedArgs.length > 3 && resolvedArgs[3]) || undefined;
return (0, strings_1.findLast)(subject, search, start, end);
};
this.functionFloor = ([inputValue]) => {
return Math.floor(inputValue);
};
this.functionFromItems = ([array]) => {
array.map((pair) => {
if (pair.length != 2 || typeof pair[0] !== 'string') {
throw new Error('invalid value, each array must contain two elements, a pair of string and value');
}
});
return Object.fromEntries(array);
};
this.functionGroupBy = ([array, exprefNode]) => {
const keyFunction = this.createKeyFunction(exprefNode, [InputArgument.TYPE_STRING]);
return array.reduce((acc, cur) => {
const k = keyFunction(cur !== null && cur !== void 0 ? cur : {});
const target = (acc[k] = acc[k] || []);
target.push(cur);
return acc;
}, {});
};
this.functionItems = ([inputValue]) => {
return Object.entries(inputValue);
};
this.functionJoin = resolvedArgs => {
const [joinChar, listJoin] = resolvedArgs;
return listJoin.join(joinChar);
};
this.functionKeys = ([inputObject]) => {
return Object.keys(inputObject);
};
this.functionLength = ([inputValue]) => {
if (typeof inputValue === 'string') {
return new text_1.Text(inputValue).length;
}
if (Array.isArray(inputValue)) {
return inputValue.length;
}
return Object.keys(inputValue).length;
};
this.functionLower = ([subject]) => {
return (0, strings_1.lower)(subject);
};
this.functionMap = ([exprefNode, elements]) => {
if (!this._interpreter) {
return [];
}
const mapped = [];
const interpreter = this._interpreter;
for (let i = 0; i < elements.length; i += 1) {
mapped.push(interpreter.visit(exprefNode, elements[i]));
}
return mapped;
};
this.functionMax = ([inputValue]) => {
if (!inputValue.length) {
return null;
}
const typeName = this.getTypeName(inputValue[0]);
if (typeName === InputArgument.TYPE_NUMBER) {
return Math.max(...inputValue);
}
const elements = inputValue;
let maxElement = elements[0];
for (let i = 1; i < elements.length; i += 1) {
if (maxElement.localeCompare(elements[i]) < 0) {
maxElement = elements[i];
}
}
return maxElement;
};
this.functionMaxBy = resolvedArgs => {
const exprefNode = resolvedArgs[1];
const resolvedArray = resolvedArgs[0];
const keyFunction = this.createKeyFunction(exprefNode, [InputArgument.TYPE_NUMBER, InputArgument.TYPE_STRING]);
let maxNumber = -Infinity;
let maxRecord;
let current;
for (let i = 0; i < resolvedArray.length; i += 1) {
current = keyFunction && keyFunction(resolvedArray[i]);
if (current !== undefined && current > maxNumber) {
maxNumber = current;
maxRecord = resolvedArray[i];
}
}
return maxRecord || null;
};
this.functionMerge = resolvedArgs => {
let merged = {};
for (let i = 0; i < resolvedArgs.length; i += 1) {
const current = resolvedArgs[i];
merged = Object.assign(merged, current);
}
return merged;
};
this.functionMin = ([inputValue]) => {
if (!inputValue.length) {
return null;
}
const typeName = this.getTypeName(inputValue[0]);
if (typeName === InputArgument.TYPE_NUMBER) {
return Math.min(...inputValue);
}
const elements = inputValue;
let minElement = elements[0];
for (let i = 1; i < elements.length; i += 1) {
if (elements[i].localeCompare(minElement) < 0) {
minElement = elements[i];
}
}
return minElement;
};
this.functionMinBy = resolvedArgs => {
const exprefNode = resolvedArgs[1];
const resolvedArray = resolvedArgs[0];
const keyFunction = this.createKeyFunction(exprefNode, [InputArgument.TYPE_NUMBER, InputArgument.TYPE_STRING]);
let minNumber = Infinity;
let minRecord;
let current;
for (let i = 0; i < resolvedArray.length; i += 1) {
current = keyFunction && keyFunction(resolvedArray[i]);
if (current !== undefined && current < minNumber) {
minNumber = current;
minRecord = resolvedArray[i];
}
}
return minRecord || null;
};
this.functionNotNull = resolvedArgs => {
for (let i = 0; i < resolvedArgs.length; i += 1) {
if (this.getTypeName(resolvedArgs[i]) !== InputArgument.TYPE_NULL) {
return resolvedArgs[i];
}
}
return null;
};
this.functionPadLeft = resolvedArgs => {
const subject = resolvedArgs[0];
const width = resolvedArgs[1];
const padding = (resolvedArgs.length > 2 && resolvedArgs[2]) || undefined;
return (0, strings_1.padLeft)(subject, width, padding);
};
this.functionPadRight = resolvedArgs => {
const subject = resolvedArgs[0];
const width = resolvedArgs[1];
const padding = (resolvedArgs.length > 2 && resolvedArgs[2]) || undefined;
return (0, strings_1.padRight)(subject, width, padding);
};
this.functionReplace = resolvedArgs => {
const subject = resolvedArgs[0];
const string = resolvedArgs[1];
const by = resolvedArgs[2];
return (0, strings_1.replace)(subject, string, by, resolvedArgs.length > 3 ? resolvedArgs[3] : undefined);
};
this.functionSplit = resolvedArgs => {
const subject = resolvedArgs[0];
const search = resolvedArgs[1];
return (0, strings_1.split)(subject, search, resolvedArgs.length > 2 ? resolvedArgs[2] : undefined);
};
this.functionReverse = ([inputValue]) => {
const typeName = this.getTypeName(inputValue);
if (typeName === InputArgument.TYPE_STRING) {
return new text_1.Text(inputValue).reverse();
}
const reversedArray = inputValue.slice(0);
reversedArray.reverse();
return reversedArray;
};
this.functionSort = ([inputValue]) => {
if (inputValue.length == 0) {
return inputValue;
}
if (typeof inputValue[0] === 'string') {
return [...inputValue].sort(text_1.Text.comparer);
}
return [...inputValue].sort();
};
this.functionSortBy = resolvedArgs => {
const sortedArray = resolvedArgs[0].slice(0);
if (sortedArray.length === 0) {
return sortedArray;
}
const interpreter = this._interpreter;
const exprefNode = resolvedArgs[1];
const requiredType = this.getTypeName(interpreter.visit(exprefNode, sortedArray[0]));
if (requiredType !== undefined && ![InputArgument.TYPE_NUMBER, InputArgument.TYPE_STRING].includes(requiredType)) {
throw new Error(`Invalid type: unexpected type (${this.TYPE_NAME_TABLE[requiredType]})`);
}
function throwInvalidTypeError(rt, item) {
throw new Error(`Invalid type: expected (${rt.TYPE_NAME_TABLE[requiredType]}), received ${rt.TYPE_NAME_TABLE[rt.getTypeName(item)]}`);
}
return sortedArray.sort((a, b) => {
const exprA = interpreter.visit(exprefNode, a);
const exprB = interpreter.visit(exprefNode, b);
if (this.getTypeName(exprA) !== requiredType) {
throwInvalidTypeError(this, exprA);
}
else if (this.getTypeName(exprB) !== requiredType) {
throwInvalidTypeError(this, exprB);
}
if (requiredType === InputArgument.TYPE_STRING) {
return text_1.Text.comparer(exprA, exprB);
}
return exprA - exprB;
});
};
this.functionStartsWith = ([searchable, searchStr]) => {
return searchable.startsWith(searchStr);
};
this.functionSum = ([inputValue]) => {
return inputValue.reduce((x, y) => x + y, 0);
};
this.functionToArray = ([inputValue]) => {
if (this.getTypeName(inputValue) === InputArgument.TYPE_ARRAY) {
return inputValue;
}
return [inputValue];
};
this.functionToNumber = ([inputValue]) => {
const typeName = this.getTypeName(inputValue);
let convertedValue;
if (typeName === InputArgument.TYPE_NUMBER) {
return inputValue;
}
if (typeName === InputArgument.TYPE_STRING) {
convertedValue = +inputValue;
if (!isNaN(convertedValue)) {
return convertedValue;
}
}
return null;
};
this.functionToString = ([inputValue]) => {
if (this.getTypeName(inputValue) === InputArgument.TYPE_STRING) {
return inputValue;
}
return JSON.stringify(inputValue);
};
this.functionTrim = resolvedArgs => {
const subject = resolvedArgs[0];
return (0, strings_1.trim)(subject, resolvedArgs.length > 1 ? resolvedArgs[1] : undefined);
};
this.functionTrimLeft = resolvedArgs => {
const subject = resolvedArgs[0];
return (0, strings_1.trimLeft)(subject, resolvedArgs.length > 1 ? resolvedArgs[1] : undefined);
};
this.functionTrimRight = resolvedArgs => {
const subject = resolvedArgs[0];
return (0, strings_1.trimRight)(subject, resolvedArgs.length > 1 ? resolvedArgs[1] : undefined);
};
this.functionType = ([inputValue]) => {
switch (this.getTypeName(inputValue)) {
case InputArgument.TYPE_NUMBER:
return 'number';
case InputArgument.TYPE_STRING:
return 'string';
case InputArgument.TYPE_ARRAY:
return 'array';
case InputArgument.TYPE_OBJECT:
return 'object';
case InputArgument.TYPE_BOOLEAN:
return 'boolean';
case InputArgument.TYPE_NULL:
return 'null';
default:
throw new Error('invalid-type');
}
};
this.functionUpper = ([subject]) => {
return (0, strings_1.upper)(subject);
};
this.functionValues = ([inputObject]) => {
return Object.values(inputObject);
};
this.functionZip = array => {
const length = Math.min(...array.map(arr => arr.length));
const result = Array(length)
.fill(null)
.map((_, index) => array.map(arr => arr[index]));
return result;
};
this.functionTable = {
abs: {
_func: this.functionAbs,
_signature: [
{
types: [InputArgument.TYPE_NUMBER],
},
],
},
avg: {
_func: this.functionAvg,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_NUMBER],
},
],
},
ceil: {
_func: this.functionCeil,
_signature: [
{
types: [InputArgument.TYPE_NUMBER],
},
],
},
contains: {
_func: this.functionContains,
_signature: [
{
types: [InputArgument.TYPE_STRING, InputArgument.TYPE_ARRAY],
},
{
types: [InputArgument.TYPE_ANY],
},
],
},
ends_with: {
_func: this.functionEndsWith,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
],
},
find_first: {
_func: this.functionFindFirst,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
],
},
find_last: {
_func: this.functionFindLast,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
],
},
floor: {
_func: this.functionFloor,
_signature: [
{
types: [InputArgument.TYPE_NUMBER],
},
],
},
from_items: {
_func: this.functionFromItems,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_ARRAY],
},
],
},
group_by: {
_func: this.functionGroupBy,
_signature: [{ types: [InputArgument.TYPE_ARRAY] }, { types: [InputArgument.TYPE_EXPREF] }],
},
items: {
_func: this.functionItems,
_signature: [
{
types: [InputArgument.TYPE_OBJECT],
},
],
},
join: {
_func: this.functionJoin,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_ARRAY_STRING],
},
],
},
keys: {
_func: this.functionKeys,
_signature: [
{
types: [InputArgument.TYPE_OBJECT],
},
],
},
length: {
_func: this.functionLength,
_signature: [
{
types: [InputArgument.TYPE_STRING, InputArgument.TYPE_ARRAY, InputArgument.TYPE_OBJECT],
},
],
},
lower: {
_func: this.functionLower,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
],
},
map: {
_func: this.functionMap,
_signature: [
{
types: [InputArgument.TYPE_EXPREF],
},
{
types: [InputArgument.TYPE_ARRAY],
},
],
},
max: {
_func: this.functionMax,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_NUMBER, InputArgument.TYPE_ARRAY_STRING],
},
],
},
max_by: {
_func: this.functionMaxBy,
_signature: [
{
types: [InputArgument.TYPE_ARRAY],
},
{
types: [InputArgument.TYPE_EXPREF],
},
],
},
merge: {
_func: this.functionMerge,
_signature: [
{
types: [InputArgument.TYPE_OBJECT],
variadic: true,
},
],
},
min: {
_func: this.functionMin,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_NUMBER, InputArgument.TYPE_ARRAY_STRING],
},
],
},
min_by: {
_func: this.functionMinBy,
_signature: [
{
types: [InputArgument.TYPE_ARRAY],
},
{
types: [InputArgument.TYPE_EXPREF],
},
],
},
not_null: {
_func: this.functionNotNull,
_signature: [
{
types: [InputArgument.TYPE_ANY],
variadic: true,
},
],
},
pad_left: {
_func: this.functionPadLeft,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
},
{
types: [InputArgument.TYPE_STRING],
optional: true,
},
],
},
pad_right: {
_func: this.functionPadRight,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
},
{
types: [InputArgument.TYPE_STRING],
optional: true,
},
],
},
replace: {
_func: this.functionReplace,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
],
},
split: {
_func: this.functionSplit,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_NUMBER],
optional: true,
},
],
},
reverse: {
_func: this.functionReverse,
_signature: [
{
types: [InputArgument.TYPE_STRING, InputArgument.TYPE_ARRAY],
},
],
},
sort: {
_func: this.functionSort,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_STRING, InputArgument.TYPE_ARRAY_NUMBER],
},
],
},
sort_by: {
_func: this.functionSortBy,
_signature: [
{
types: [InputArgument.TYPE_ARRAY],
},
{
types: [InputArgument.TYPE_EXPREF],
},
],
},
starts_with: {
_func: this.functionStartsWith,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
},
],
},
sum: {
_func: this.functionSum,
_signature: [
{
types: [InputArgument.TYPE_ARRAY_NUMBER],
},
],
},
to_array: {
_func: this.functionToArray,
_signature: [
{
types: [InputArgument.TYPE_ANY],
},
],
},
to_number: {
_func: this.functionToNumber,
_signature: [
{
types: [InputArgument.TYPE_ANY],
},
],
},
to_string: {
_func: this.functionToString,
_signature: [
{
types: [InputArgument.TYPE_ANY],
},
],
},
trim: {
_func: this.functionTrim,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
optional: true,
},
],
},
trim_left: {
_func: this.functionTrimLeft,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
optional: true,
},
],
},
trim_right: {
_func: this.functionTrimRight,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
{
types: [InputArgument.TYPE_STRING],
optional: true,
},
],
},
type: {
_func: this.functionType,
_signature: [
{
types: [InputArgument.TYPE_ANY],
},
],
},
upper: {
_func: this.functionUpper,
_signature: [
{
types: [InputArgument.TYPE_STRING],
},
],
},
values: {
_func: this.functionValues,
_signature: [
{
types: [InputArgument.TYPE_OBJECT],
},
],
},
zip: {
_func: this.functionZip,
_signature: [
{
types: [InputArgument.TYPE_ARRAY],
variadic: true,
},
],
},
};
this._interpreter = interpreter;
this._functionTable = this.functionTable;
}
registerFunction(name, customFunction, signature) {
if (name in this._functionTable) {
throw new Error(`Function already defined: ${name}()`);
}
this._functionTable[name] = {
_func: customFunction.bind(this),
_signature: signature,
};
}
callFunction(name, resolvedArgs) {
const functionEntry = this._functionTable[name];
if (functionEntry === undefined) {
throw new Error(`Unknown function: ${name}()`);
}
this.validateArgs(name, resolvedArgs, functionEntry._signature);
return functionEntry._func.call(this, resolvedArgs);
}
validateInputSignatures(name, signature) {
for (let i = 0; i < signature.length; i += 1) {
if ('variadic' in signature[i] && i !== signature.length - 1) {
throw new Error(`Invalid arity: ${name}() 'variadic' argument ${i + 1} must occur last`);
}
}
}
validateArgs(name, args, signature) {
var _a, _b;
let pluralized;
this.validateInputSignatures(name, signature);
const numberOfRequiredArgs = signature.filter(argSignature => { var _a; return !((_a = argSignature.optional) !== null && _a !== void 0 ? _a : false); }).length;
const lastArgIsVariadic = (_b = (_a = signature[signature.length - 1]) === null || _a === void 0 ? void 0 : _a.variadic) !== null && _b !== void 0 ? _b : false;
const tooFewArgs = args.length < numberOfRequiredArgs;
const tooManyArgs = args.length > signature.length;
const tooFewModifier = tooFewArgs && ((!lastArgIsVariadic && numberOfRequiredArgs > 1) || lastArgIsVariadic) ? 'at least ' : '';
if ((lastArgIsVariadic && tooFewArgs) || (!lastArgIsVariadic && (tooFewArgs || tooManyArgs))) {
pluralized = signature.length > 1;
throw new Error(`Invalid arity: ${name}() takes ${tooFewModifier}${numberOfRequiredArgs} argument${(pluralized && 's') || ''} but received ${args.length}`);
}
let currentSpec;
let actualType;
let typeMatched;
for (let i = 0; i < signature.length; i += 1) {
typeMatched = false;
currentSpec = signature[i].types;
actualType = this.getTypeName(args[i]);
let j;
for (j = 0; j < currentSpec.length; j += 1) {
if (actualType !== undefined && this.typeMatches(actualType, currentSpec[j], args[i])) {
typeMatched = true;
break;
}
}
if (!typeMatched && actualType !== undefined) {
const expected = currentSpec
.map((typeIdentifier) => {
return this.TYPE_NAME_TABLE[typeIdentifier];
})
.join(' | ');
throw new Error(`Invalid type: ${name}() expected argument ${i + 1} to be type (${expected}) but received type ${this.TYPE_NAME_TABLE[actualType]} instead.`);
}
}
}
typeMatches(actual, expected, argValue) {
if (expected === InputArgument.TYPE_ANY) {
return true;
}
if (expected === InputArgument.TYPE_ARRAY_STRING ||
expected === InputArgument.TYPE_ARRAY_NUMBER ||
expected === InputArgument.TYPE_ARRAY_OBJECT ||
expected === InputArgument.TYPE_ARRAY_ARRAY ||
expected === InputArgument.TYPE_ARRAY) {
if (expected === InputArgument.TYPE_ARRAY) {
return actual === InputArgument.TYPE_ARRAY;
}
if (actual === InputArgument.TYPE_ARRAY) {
let subtype;
if (expected === InputArgument.TYPE_ARRAY_NUMBER) {
subtype = InputArgument.TYPE_NUMBER;
}
else if (expected === InputArgument.TYPE_ARRAY_OBJECT) {
subtype = InputArgument.TYPE_OBJECT;
}
else if (expected === InputArgument.TYPE_ARRAY_STRING) {
subtype = InputArgument.TYPE_STRING;
}
else if (expected === InputArgument.TYPE_ARRAY_ARRAY) {
subtype = InputArgument.TYPE_ARRAY;
}
const array = argValue;
for (let i = 0; i < array.length; i += 1) {
const typeName = this.getTypeName(array[i]);
if (typeName !== undefined && subtype !== undefined && !this.typeMatches(typeName, subtype, array[i])) {
return false;
}
}
return true;
}
}
else {
return actual === expected;
}
return false;
}
getTypeName(obj) {
switch (Object.prototype.toString.call(obj)) {
case '[object String]':
return InputArgument.TYPE_STRING;
case '[object Number]':
return InputArgument.TYPE_NUMBER;
case '[object Array]':
return InputArgument.TYPE_ARRAY;
case '[object Boolean]':
return InputArgument.TYPE_BOOLEAN;
case '[object Null]':
return InputArgument.TYPE_NULL;
case '[object Object]':
if (obj.expref) {
return InputArgument.TYPE_EXPREF;
}
return InputArgument.TYPE_OBJECT;
default:
return;
}
}
createKeyFunction(exprefNode, allowedTypes) {
const interpreter = this._interpreter;
const keyFunc = (x) => {
const current = interpreter.visit(exprefNode, x);
if (!allowedTypes.includes(this.getTypeName(current))) {
const msg = `Invalid type: expected one of (${allowedTypes
.map(t => this.TYPE_NAME_TABLE[t])
.join(' | ')}), received ${this.TYPE_NAME_TABLE[this.getTypeName(current)]}`;
throw new Error(msg);
}
return current;
};
return keyFunc;
}
}
exports.Runtime = Runtime;
//# sourceMappingURL=Runtime.js.map