UNPKG

adaptive-expressions

Version:
460 lines 15.6 kB
"use strict"; /** * @module adaptive-expressions */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InternalFunctionUtils = void 0; const constant_1 = require("./constant"); const dayjs_1 = __importDefault(require("dayjs")); const utc_1 = __importDefault(require("dayjs/plugin/utc")); dayjs_1.default.extend(utc_1.default); const expressionType_1 = require("./expressionType"); const memory_1 = require("./memory"); const recognizers_text_data_types_timex_expression_1 = require("@microsoft/recognizers-text-data-types-timex-expression"); const big_integer_1 = __importDefault(require("big-integer")); const util_1 = __importDefault(require("util")); /** * Utility functions only used internal */ class InternalFunctionUtils { /** * Parse timex funcition. * * @param timexExpr String or TimexProperty input. * @returns TimexProperty and error. */ static parseTimexProperty(timexExpr) { let parsed; if (timexExpr instanceof recognizers_text_data_types_timex_expression_1.TimexProperty) { parsed = timexExpr; } else if (typeof timexExpr === 'string') { parsed = new recognizers_text_data_types_timex_expression_1.TimexProperty(timexExpr); } else { parsed = new recognizers_text_data_types_timex_expression_1.TimexProperty(timexExpr); if (parsed === undefined || Object.keys(parsed).length === 0) { return { timexProperty: parsed, error: `${timexExpr} requires a TimexProperty or a string as a argument`, }; } } return { timexProperty: parsed, error: undefined }; } /** * Sort helper function. * * @param isDescending Descending flag. * @returns The sorted array. */ static sortBy(isDescending) { return (expression, state, options) => { let result; const { value: oriArr, error: childrenError } = expression.children[0].tryEvaluate(state, options); let error = childrenError; if (!error) { if (Array.isArray(oriArr)) { // Ensures we don't mutate the array in place. const arr = oriArr.slice(0); if (expression.children.length === 1) { if (isDescending) { result = arr.sort().reverse(); } else { result = arr.sort(); } } else { let propertyName; ({ value: propertyName, error } = expression.children[1].tryEvaluate(state, options)); if (!error) { propertyName = propertyName || ''; } if (isDescending) { result = arr.sort(InternalFunctionUtils.sortByKey(propertyName)).reverse(); } else { result = arr.sort(InternalFunctionUtils.sortByKey(propertyName)); } } } else { error = `${expression.children[0]} is not an array`; } } return { value: result, error }; }; } /** * Lookup a string or number index of an Object. * * @param instance Instance with property. * @param index Property to lookup. * @returns Value and error information if any. */ static accessIndex(instance, index) { // NOTE: This returns undefined rather than an error if instance is not present if (instance == null) { return { value: undefined, error: undefined }; } let value; let error; if (Array.isArray(instance)) { if (index >= 0 && index < instance.length) { value = instance[index]; } else { error = `${index} is out of range for ${instance}`; } } else { error = `${instance} is not a collection.`; } return { value, error }; } /** * Verify a timestamp string is valid timestamp format. * * @param value Timestamp string to check. * @returns Error or undefined if invalid. */ static verifyTimestamp(value) { let error; try { const parsedData = new Date(value); if (Number.isNaN(parsedData.getTime())) { error = `${value} is not a valid datetime string.`; } } catch (_a) { error = `${value} is not a valid datetime string.`; } return error; } /** * Verify a timestamp string is valid ISO timestamp format. * * @param value Timestamp string to check. * @returns Error or undefined if invalid. */ static verifyISOTimestamp(value) { let error; try { const parsedData = new Date(value); if (Number.isNaN(parsedData.getTime())) { error = `${value} is not a valid datetime string.`; } else if (parsedData.toISOString() !== value) { error = `${value} is not a ISO format datetime string.`; } } catch (_a) { error = `${value} is not a valid datetime string.`; } return error; } /** * Convert a string input to ticks number. * * @param timeStamp String timestamp input. * @returns The string converted in ticks. */ static ticks(timeStamp) { let result; const error = this.verifyISOTimestamp(timeStamp); if (!error) { const unixMilliSec = (0, dayjs_1.default)(timeStamp).utc().valueOf(); result = this.UnixMilliSecondToTicksConstant.add((0, big_integer_1.default)(unixMilliSec).times(this.MillisecondToTickConstant)); } return { value: result, error }; } /** * Lookup a property in Map or Object. * * @param instance Instance with property. * @param property Property to lookup. * @returns Value and error information if any. */ static accessProperty(instance, property) { // NOTE: This returns undefined rather than an error if property is not present if (!instance) { return { value: undefined, error: undefined }; } let value; let error; if (instance instanceof Map && instance !== undefined) { const instanceMap = instance; value = instanceMap.get(property); if (value === undefined) { const prop = Array.from(instanceMap.keys()).find((k) => k.toLowerCase() === property.toLowerCase()); if (prop !== undefined) { value = instanceMap.get(prop); } } } else { const prop = Object.keys(instance).find((k) => k.toLowerCase() === property.toLowerCase()); if (prop !== undefined) { value = instance[prop]; } } return { value, error }; } /** * Get the value of a path from a memory. * * @param state Memory. * @param path Path string. * @param options Options. * @returns The value of a path from a memory. */ static wrapGetValue(state, path, options) { const result = state.getValue(path); if (result !== undefined) { return result; } if (options.nullSubstitution !== undefined) { return options.nullSubstitution(path); } return undefined; } /** * Wrap string or undefined into string. Default to empty string. * * @param input Input string * @returns The wrapped string. */ static parseStringOrUndefined(input) { if (typeof input === 'string') { return input; } else { return ''; } } /** * Test result to see if True in logical comparison functions. * * @param instance Computed value. * @returns True if boolean true or non-null. */ static isLogicTrue(instance) { let result = true; if (typeof instance === 'boolean') { result = instance; } else if (instance == null) { result = false; } return result; } /** * Evaluator for foreach and select functions. * * @param expression Expression. * @param state Memory scope. * @param options Options. * @returns The evaluated list. */ static foreach(expression, state, options) { let result; const { value: instance, error: childrenError } = expression.children[0].tryEvaluate(state, options); let error = childrenError; if (!instance) { error = `'${expression.children[0]}' evaluated to null.`; } if (!error) { const list = InternalFunctionUtils.convertToList(instance); if (!list) { error = `${expression.children[0]} is not a collection or structure object to run Foreach`; } else { result = []; InternalFunctionUtils.lambdaEvaluator(expression, state, options, list, (currentItem, r, e) => { if (e) { error = e; return true; } else { result.push(r); return false; } }); } } return { value: result, error }; } /** * Lambda evaluator. * * @param expression expression. * @param state memory state. * @param options options. * @param list item list. * @param callback call back. return the should break flag. */ static lambdaEvaluator(expression, state, options, list, callback) { const firstChild = expression.children[1].children[0]; if (!(firstChild instanceof constant_1.Constant) || typeof firstChild.value !== 'string') { return; } const iteratorName = firstChild.value; const stackedMemory = memory_1.StackedMemory.wrap(state); for (const item of list) { const currentItem = item; const local = new Map([[iteratorName, item]]); // the local iterator is pushed as one memory layer in the memory stack stackedMemory.push(memory_1.SimpleObjectMemory.wrap(local)); const { value: r, error: e } = expression.children[2].tryEvaluate(stackedMemory, options); stackedMemory.pop(); const shouldBreak = callback(currentItem, r, e); if (shouldBreak) { break; } } } /** * Convert an object into array. * If the instance is array, return itself. * If the instance is object, return {key, value} pair list. * Else return undefined. * * @param instance input instance. * @returns The generated list. */ static convertToList(instance) { let arr; if (Array.isArray(instance)) { arr = instance; } else if (typeof instance === 'object') { arr = []; Object.keys(instance).forEach((u) => arr.push({ key: u, value: instance[u] })); } return arr; } /** * Validator for foreach, select, and where functions. * * @param expression The expression to validate. */ static ValidateLambdaExpression(expression) { if (expression.children.length !== 3) { throw new Error(`Lambda expression expect 3 parameters, found ${expression.children.length}`); } const second = expression.children[1]; if (!(second.type === expressionType_1.ExpressionType.Accessor && second.children.length === 1)) { throw new Error(`Second parameter is not an identifier : ${second}`); } } /** * Parse string into URL object. * * @param uri Input string uri. * @returns The parsed URL object. */ static parseUri(uri) { let result; let error; try { result = new URL(uri); } catch (_a) { error = `Invalid URI: ${uri}`; } return { value: result, error }; } /** * Transform C# period and unit into js period and unit. * * @param duration C# duration. * @param cSharpStr C# unit. * @returns The transformed timeUnit. */ static timeUnitTransformer(duration, cSharpStr) { switch (cSharpStr) { case 'Day': return { duration, tsStr: 'day' }; case 'Week': return { duration: duration * 7, tsStr: 'day' }; case 'Second': return { duration, tsStr: 'second' }; case 'Minute': return { duration, tsStr: 'minute' }; case 'Hour': return { duration, tsStr: 'hour' }; case 'Month': return { duration, tsStr: 'month' }; case 'Year': return { duration, tsStr: 'year' }; default: return { duration, tsStr: undefined }; } } /** * TextEncoder helper function. * * @returns The text encoder. */ static getTextEncoder() { if (typeof window !== 'undefined' || typeof self !== 'undefined') { return new TextEncoder(); } return new util_1.default.TextEncoder(); } /** * TextDecoder helper function. * * @param code The encoding format. * @returns The text decoder. */ static getTextDecoder(code = 'utf-8') { if (typeof window !== 'undefined' || typeof self !== 'undefined') { return new TextDecoder(code); } return new util_1.default.TextDecoder(code); } /** * Common Stringify an object. * * @param input input object. * @returns the stringified object. */ static commonStringify(input) { if (input == null) { return ''; } if (typeof input === 'object') { return JSON.stringify(input) .replace(/(^['"]*)/g, '') .replace(/(['"]*$)/g, ''); } else { return input.toString(); } } /** * @private */ static sortByKey(key) { return (a, b) => (a[key] > b[key] ? 1 : b[key] > a[key] ? -1 : 0); } } exports.InternalFunctionUtils = InternalFunctionUtils; /** * Constant for converting unix timestamp to ticks. */ InternalFunctionUtils.UnixMilliSecondToTicksConstant = (0, big_integer_1.default)('621355968000000000'); /** * Constant to convert between ticks and ms. */ InternalFunctionUtils.MillisecondToTickConstant = (0, big_integer_1.default)('10000'); //# sourceMappingURL=functionUtils.internal.js.map