krl-stdlib
Version:
Standard library for KRL
310 lines • 8.82 kB
JavaScript
"use strict";
/**
* This krl module is all the core utilities for working with the KRL language at runtime
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.encode = exports.decode = exports.cleanNulls = exports.isEqual = exports.toHexOrNull = exports.toNumberOrNull = exports.toString = exports.typeOf = exports.isPostlude = exports.assertAction = exports.isAction = exports.assertFunction = exports.isFunction = exports.isArrayOrMap = exports.isMap = exports.isArray = exports.isRegExp = exports.isBoolean = exports.isHex = exports.isString = exports.isNumber = exports.isNull = exports.toPairs = exports.Property = exports.ActionFunction = exports.Postlude = exports.Action = exports.Function = exports.aggregateEvent = exports.SelectWhen = void 0;
const _ = require("lodash");
const SelectWhenModule = require("select-when");
const aggregateEvent_1 = require("./aggregateEvent");
exports.SelectWhen = SelectWhenModule; // exposed for the krl-compiler
exports.aggregateEvent = aggregateEvent_1.aggregateEvent; // exposed for the krl-compiler
function krlNamedArgs(paramOrder) {
return function (args) {
const params = [];
if (_.isArray(args)) {
for (let i = 0; i < Math.min(paramOrder.length, args.length); i++) {
params.push(args[i]);
}
}
else {
for (let i = 0; i < paramOrder.length; i++) {
const paramName = paramOrder[i];
if (_.has(args, paramName)) {
while (params.length < i) {
params.push(void 0);
}
params.push(args[paramName]);
}
else if (_.has(args, i)) {
while (params.length < i) {
params.push(void 0);
}
params.push(args[i]);
}
}
}
return params;
};
}
function krlFunctionMaker(krlTypeName) {
return function (paramOrder, fn) {
const fixArgs = krlNamedArgs(paramOrder);
const wrapped = function (ctx, args) {
return fn.apply(ctx, fixArgs(args));
};
// add this for the compiler to know the type
wrapped["$krl_" + krlTypeName] = true;
return wrapped;
};
}
exports.Function = krlFunctionMaker("function");
exports.Action = krlFunctionMaker("action");
exports.Postlude = krlFunctionMaker("postlude");
function ActionFunction(paramOrder, fn) {
const act = (0, exports.Action)(paramOrder, fn);
act["$krl_function"] = true;
return act;
}
exports.ActionFunction = ActionFunction;
function Property(fn) {
const wrapped = function (ctx) {
return fn.apply(ctx);
};
// add this for the compiler to know the type
wrapped["$krl_property"] = true;
return wrapped;
}
exports.Property = Property;
/**
* used by `foreach` in krl
* Array's use index numbers, maps use key strings
*/
function toPairs(v) {
if (isArray(v)) {
var pairs = [];
var i;
for (i = 0; i < v.length; i++) {
pairs.push([i, v[i]]);
}
return pairs;
}
return _.toPairs(v);
}
exports.toPairs = toPairs;
function isNull(val) {
return val === null || val === void 0 || _.isNaN(val);
}
exports.isNull = isNull;
function isNumber(val) {
return _.isFinite(val);
}
exports.isNumber = isNumber;
function isString(val) {
return typeof val === "string";
}
exports.isString = isString;
function isHex(val) {
return typeof val === "string" && /^0x[A-F0-9]+$/i.test(val);
}
exports.isHex = isHex;
function isBoolean(val) {
return val === true || val === false;
}
exports.isBoolean = isBoolean;
function isRegExp(val) {
return _.isRegExp(val);
}
exports.isRegExp = isRegExp;
function isArray(val) {
return _.isArray(val);
}
exports.isArray = isArray;
function isMap(val) {
// Can't use _.isPlainObject b/c it's to restrictive on what is a "plain" object
// especially when accepting values from other libraries outside of KRL
return isArrayOrMap(val) && !_.isArray(val);
}
exports.isMap = isMap;
function isArrayOrMap(val) {
return (_.isObject(val) &&
!_.isFunction(val) &&
!_.isRegExp(val) &&
!_.isString(val) &&
!_.isNumber(val));
}
exports.isArrayOrMap = isArrayOrMap;
function isFunction(val) {
return _.isFunction(val) && val["$krl_function"] === true;
}
exports.isFunction = isFunction;
function assertFunction(val) {
if (isFunction(val)) {
return val;
}
throw new TypeError(toString(val) + " is not a function");
}
exports.assertFunction = assertFunction;
function isAction(val) {
return _.isFunction(val) && val["$krl_action"] === true;
}
exports.isAction = isAction;
function assertAction(val) {
if (isAction(val)) {
return val;
}
throw new TypeError(toString(val) + " is not an action");
}
exports.assertAction = assertAction;
function isPostlude(val) {
return _.isFunction(val) && val["$krl_postlude"] === true;
}
exports.isPostlude = isPostlude;
function typeOf(val) {
if (isNull(val)) {
return "Null";
}
else if (isBoolean(val)) {
return "Boolean";
}
else if (isHex(val)) {
return "Hex";
}
else if (isString(val)) {
return "String";
}
else if (isNumber(val)) {
return "Number";
}
else if (isRegExp(val)) {
return "RegExp";
}
else if (isArray(val)) {
return "Array";
}
else if (isAction(val) && isFunction(val)) {
return "ActionFunction";
}
else if (isFunction(val)) {
return "Function";
}
else if (isAction(val)) {
return "Action";
}
else if (isMap(val)) {
return "Map";
}
return "JSObject";
}
exports.typeOf = typeOf;
function toString(val) {
var valType = typeOf(val);
switch (typeOf(val)) {
case "String":
return val;
case "Hex":
return val;
case "Null":
return "null";
case "Boolean":
return val ? "true" : "false";
case "Number":
return val + "";
case "RegExp":
// NOTE: val.flags doesn't work on old versions of JS
var flags = "";
if (val.global) {
flags += "g";
}
if (val.ignoreCase) {
flags += "i";
}
return "re#" + val.source + "#" + flags;
}
return "[" + valType + "]";
}
exports.toString = toString;
function toNumberOrNull(val) {
switch (typeOf(val)) {
case "Null":
return 0;
case "Boolean":
return val ? 1 : 0;
case "Hex":
return parseInt(val, 16);
case "String":
var n = _.toNumber(val);
return isNumber(n) ? n : null;
case "Number":
return val;
case "Array":
case "Map":
return _.size(val);
case "RegExp":
case "Function":
case "Action":
}
return null;
}
exports.toNumberOrNull = toNumberOrNull;
function toHexOrNull(val) {
switch (typeOf(val)) {
case "Null":
case "Boolean":
case "Hex":
case "String":
case "Number":
return val.toString(16);
case "Array":
case "Map":
case "RegExp":
case "Function":
case "Action":
}
return null;
}
exports.toHexOrNull = toHexOrNull;
function isEqual(left, right) {
left = cleanNulls(left);
right = cleanNulls(right);
return _.isEqual(left, right);
}
exports.isEqual = isEqual;
// returns a clone of val with void 0 and NaN values converted to null
function cleanNulls(val) {
if (isNull(val)) {
return null;
}
if (isArray(val)) {
return deepClean(val, _.map);
}
if (isMap(val)) {
return deepClean(val, _.mapValues);
}
return val;
}
exports.cleanNulls = cleanNulls;
function deepClean(val, mapFn) {
return mapFn(val, function (v) {
return cleanNulls(v);
});
}
function decode(val) {
if (!isString(val)) {
return val;
}
try {
return JSON.parse(val);
}
catch (e) {
return val;
}
}
exports.decode = decode;
function encode(val, indent) {
indent = _.parseInt(indent, 10) || 0; // default to 0 (no indent)
return JSON.stringify(val, function (k, v) {
switch (typeOf(v)) {
case "Null":
return null;
case "JSObject":
case "RegExp":
case "Function":
case "Action":
return toString(v);
}
return v;
}, indent);
}
exports.encode = encode;
//# sourceMappingURL=krl.js.map