From 2550b11007a6d863184167f38fa67ddb60443fdc Mon Sep 17 00:00:00 2001 From: Marcin Tomczyk Date: Sun, 15 Jul 2018 21:38:16 +0200 Subject: [PATCH] Add types for jexl@1.1 by TechnologyAdvice; new owner TomFrost (#27269) --- types/jexl/index.d.ts | 113 +++++++++++++++++++++++++++++++++++++++ types/jexl/jexl-tests.ts | 77 ++++++++++++++++++++++++++ types/jexl/tsconfig.json | 23 ++++++++ types/jexl/tslint.json | 1 + 4 files changed, 214 insertions(+) create mode 100644 types/jexl/index.d.ts create mode 100644 types/jexl/jexl-tests.ts create mode 100644 types/jexl/tsconfig.json create mode 100644 types/jexl/tslint.json diff --git a/types/jexl/index.d.ts b/types/jexl/index.d.ts new file mode 100644 index 0000000000..953702346c --- /dev/null +++ b/types/jexl/index.d.ts @@ -0,0 +1,113 @@ +// Type definitions for jexl 1.1 +// Project: https://github.com/TechnologyAdvice/jexl +// Definitions by: Marcin Tomczyk +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +// Currently maintained by https://github.com/TomFrost/Jexl + +type TransformFunction = (value: any, args?: object) => any; + +type BinaryOpFunction = (left: any, right: any) => any; + +type UnaryOpFunction = (right: any) => any; + +type EvalCallbackFunction = (err: Error | null, result: any) => void; + +/** + * Jexl is the Javascript Expression Language, capable of parsing and + * evaluating basic to complex expression strings, combined with advanced + * xpath-like drilldown into native Javascript objects. + */ +declare class Jexl { + /** + * Adds a binary operator to Jexl at the specified precedence. The higher the + * precedence, the earlier the operator is applied in the order of operations. + * For example, * has a higher precedence than +, because multiplication comes + * before division. + * + * Please see grammar.js for a listing of all default operators and their + * precedence values in order to choose the appropriate precedence for the + * new operator. + * @param operator The operator string to be added + * @param precedence The operator's precedence + * @param fn A function to run to calculate the result. The function + * will be called with two arguments: left and right, denoting the values + * on either side of the operator. It should return either the resulting + * value, or a Promise that resolves with the resulting value. + */ + addBinaryOp(operator: string, precedence: number, fn: BinaryOpFunction): void; + + /** + * Adds a unary operator to Jexl. Unary operators are currently only supported + * on the left side of the value on which it will operate. + * @param operator The operator string to be added + * @param fn A function to run to calculate the result. The function + * will be called with one argument: the literal value to the right of the + * operator. It should return either the resulting value, or a Promise + * that resolves with the resulting value. + */ + addUnaryOp(operator: string, fn: UnaryOpFunction): void; + + /** + * Adds or replaces a transform function in this Jexl instance. + * @param name The name of the transform function, as it will be used + * within Jexl expressions + * @param fn The function to be executed when this transform is + * invoked. It will be provided with two arguments: + * - {*} value: The value to be transformed + * - {{}} args: The arguments for this transform + * - {function} cb: A callback function to be called with an error + * if the transform fails, or a null first argument and the + * transformed value as the second argument on success. + */ + addTransform(name: string, fn: TransformFunction): void; + + /** + * Syntactic sugar for calling {@link #Jexl:addTransform} repeatedly. This function + * accepts a map of one or more transform names to their transform function. + * @param map A map of transform names to transform functions + */ + addTransforms(map: { [key: string]: TransformFunction }): void; + + /** + * Retrieves a previously set transform function. + * @param name The name of the transform function + * @returns The transform function + */ + getTransform(name: string): TransformFunction; + + /** + * Evaluates a Jexl string within an optional context. + * @param expression The Jexl expression to be evaluated + * @param context A mapping of variables to values, which will be + * made accessible to the Jexl expression when evaluating it + * @param cb An optional callback function to be executed when + * evaluation is complete. It will be supplied with two arguments: + * - err: Present if an error occurred + * - result: The result of the evaluation + * @returns resolves with the result of the evaluation. Note that + * if a callback is supplied, the returned promise will already have + * a '.catch' attached to it in order to pass the error to the callback. + */ + eval(expression: string, context?: object, cb?: EvalCallbackFunction): Promise; + + /** + * Removes a binary or unary operator from the Jexl grammar. + * @param operator The operator string to be removed + */ + removeOp(operator: string): void; +} + +/** + * Jexl is the Javascript Expression Language, capable of parsing and + * evaluating basic to complex expression strings, combined with advanced + * xpath-like drilldown into native Javascript objects. + */ +declare class BuildableJexl extends Jexl { + Jexl: { new(): Jexl }; +} + +declare const exportJexl: BuildableJexl; + +export = exportJexl; diff --git a/types/jexl/jexl-tests.ts b/types/jexl/jexl-tests.ts new file mode 100644 index 0000000000..df55bba69e --- /dev/null +++ b/types/jexl/jexl-tests.ts @@ -0,0 +1,77 @@ +import * as jexl from "jexl"; + +const context = { + name: {first: 'Sterling', last: 'Archer'}, + assoc: [ + {first: 'Lana', last: 'Kane'}, + {first: 'Cyril', last: 'Figgis'}, + {first: 'Pam', last: 'Poovey'} + ], + age: 36 +}; + +// Filter an array +// Output: Kane +// $ExpectType Promise +jexl.eval('assoc[.first == "Lana"].last', context); + +// Do math +// Output: 72 +// $ExpectType Promise +jexl.eval('age * (3 - 1)', context, (err, res) => { +}); + +// Concatenate +// Output: Sterling Archer +// $ExpectType Promise +jexl.eval('name.first + " " + name["la" + "st"]', context); + +// Compound +// Output: true +// $ExpectType Promise +jexl.eval('assoc[.last == "Figgis"].first == "Cyril" && assoc[.last == "Poovey"].first == "Pam"', context); + +// Use array indexes +// Output: Cyril Figgis +// $ExpectType Promise +jexl.eval('assoc[1]', context, (err, res) => { +}); + +// Use conditional logic +// Output: working +// $ExpectType Promise +jexl.eval('age > 62 ? "retired" : "working"', context); + +// Transform +// $ExpectType void +jexl.addTransform('upper', (val) => { + return val.toUpperCase(); +}); +// Output: DUCHESS ARCHER +// $ExpectType Promise +jexl.eval('"duchess"|upper + " " + name.last|upper', context); + +// Transform asynchronously, with arguments +// $ExpectType void +jexl.addTransform('getStat', (val, stat) => { + return Promise.resolve('Test'); // Returns a promise +}); +// Output: 184 +// $ExpectType Promise +jexl.eval('name.last|getStat("weight")', context, (err, res) => { +}); + +// Add your own (a)synchronous operators +// Here's a case-insensitive string equality +// $ExpectType void +jexl.addBinaryOp('_=', 20, (left, right) => { + return left.toLowerCase() === right.toLowerCase(); +}); +// Output: true +// $ExpectType Promise +jexl.eval('"Guest" _= "gUeSt"'); + +const newJexlInstance = new jexl.Jexl(); + +// $ExpectType Promise +newJexlInstance.eval("true == true"); diff --git a/types/jexl/tsconfig.json b/types/jexl/tsconfig.json new file mode 100644 index 0000000000..8db678a16d --- /dev/null +++ b/types/jexl/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "jexl-tests.ts" + ] +} diff --git a/types/jexl/tslint.json b/types/jexl/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/jexl/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }