Merge pull request #34361 from m-tomczyk/master

[jexl] Upgrade types for jexl@2.1 by TomFrost
This commit is contained in:
Benjamin Lichtman 2019-04-01 11:32:35 -07:00 committed by GitHub
commit 4358936e71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 65 deletions

36
types/jexl/index.d.ts vendored
View File

@ -1,19 +1,15 @@
// Type definitions for jexl 1.1
// Project: https://github.com/tomfrost/jexl
// Type definitions for jexl 2.1
// Project: https://github.com/TomFrost/Jexl
// Definitions by: Marcin Tomczyk <https://github.com/m-tomczyk>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
// Currently maintained by https://github.com/TomFrost/Jexl
type TransformFunction = (value: any, ...args: any[]) => 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
@ -54,14 +50,14 @@ declare class Jexl {
* @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 at least one argument:
* invoked. It will be provided with at least one argument:
* - {*} value: The value to be transformed
* - {...*} args: The arguments for this transform
*/
addTransform(name: string, fn: TransformFunction): void;
/**
* Syntactic sugar for calling {@link #Jexl:addTransform} repeatedly. This function
* Syntactic sugar for calling {@link #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
*/
@ -75,25 +71,23 @@ declare class Jexl {
getTransform(name: string): TransformFunction;
/**
* Evaluates a Jexl string within an optional context.
* Asynchronously 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
* @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.
* @returns resolves with the result of the evaluation.
*/
eval(expression: string, context?: object, cb?: EvalCallbackFunction): Promise<any>;
eval(expression: string, context?: object): Promise<any>;
/**
* Removes a binary or unary operator from the Jexl grammar.
* @param operator The operator string to be removed
* Synchronously 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
* @returns the result of the evaluation.
* @throws on error
*/
removeOp(operator: string): void;
evalSync(expression: string, context?: object): any;
}
/**

View File

@ -10,74 +10,104 @@ const context = {
age: 36
};
// Filter an array
// Output: Kane
// Dummy console. Comment it out if you want to run this code and see output
class DummyConsole {
log(...args: string[]) {
}
}
const console = new DummyConsole();
// Dummy helper function
function dbSelectByLastName(val: string, stat: string): Promise<any> {
return new Promise(((resolve, reject) => resolve(184)));
}
/* Type testing */
// $ExpectType Promise<any>
jexl.eval('assoc[.first == "Lana"].last', context);
// Do math
// Output: 72
// $ExpectType Promise<any>
jexl.eval('age * (3 - 1)', context, (err, res) => {
});
// $ExpectType any
jexl.evalSync('assoc[.first == "Lana"].last');
// $ExpectType Promise<any>
jexl.eval('age * (3 - 1)', context);
// Concatenate
// Output: Sterling Archer
// $ExpectType Promise<any>
jexl.eval('name.first + " " + name["la" + "st"]', context);
// Compound
// Output: true
// $ExpectType Promise<any>
jexl.eval('assoc[.last == "Figgis"].first == "Cyril" && assoc[.last == "Poovey"].first == "Pam"', context);
// Use array indexes
// Output: Cyril Figgis
// $ExpectType Promise<any>
jexl.eval('assoc[1]', context, (err, res) => {
});
jexl.eval('assoc[1]', context);
// Use conditional logic
// Output: working
// $ExpectType Promise<any>
jexl.eval('age > 62 ? "retired" : "working"', context);
// Transform
// $ExpectType void
jexl.addTransform('upper', (val) => {
return val.toUpperCase();
});
// Output: DUCHESS ARCHER
jexl.addTransform('upper', (val) => val.toUpperCase());
// $ExpectType Promise<any>
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
jexl.addTransform('getStat', async (val, stat) => dbSelectByLastName(val, stat));
// $ExpectType Promise<any>
jexl.eval('name.last|getStat("weight")', context, (err, res) => {
});
jexl.eval('name.last|getStat("weight")', context);
// Transform with multiple arguments
// $ExpectType void
jexl.addTransform('substring', (val: string, start: number, end?: number) => {
return val.substring(start, end);
});
// 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
jexl.addBinaryOp('_=', 20, (left, right) => left.toLowerCase() === right.toLowerCase());
// $ExpectType Promise<any>
jexl.eval('"Guest" _= "gUeSt"');
const newJexlInstance = new jexl.Jexl();
/* Example - runnable code */
(async function testStuff() {
// Filter an array asynchronously...
jexl.eval('assoc[.first == "Lana"].last', context).then(filterArray => {
console.log('1. Filter Array', filterArray); // Output: Kane
});
// $ExpectType Promise<any>
newJexlInstance.eval("true == true");
// Or synchronously!
console.log('2. Filter Array Sync', jexl.evalSync('assoc[.first == "Lana"].last')); // Output: Kane
// Do math
const match = await jexl.eval('age * (3 - 1)', context);
console.log('3. Match', match); // Output: 72
// Concatenate
const concatenate = await jexl.eval('name.first + " " + name["la" + "st"]', context);
console.log('4. Concatenate', concatenate); // "Sterling Archer"
// Compound
const compound = await jexl.eval('assoc[.last == "Figgis"].first == "Cyril" && assoc[.last == "Poovey"].first == "Pam"', context);
console.log('5. Compound', compound); // true
// Use array indexes
const arrayIndex = await jexl.eval('assoc[1]', context);
console.log('6. Array Index', arrayIndex); // { first: 'Cyril', last: 'Figgis' }
// Use conditional logic
const conditional = await jexl.eval('age > 62 ? "retired" : "working"', context);
console.log('7. Conditional', conditional); // "working"
// Transform
jexl.addTransform('upper', (val) => val.toUpperCase());
const transform = await jexl.eval('"duchess"|upper + " " + name.last|upper', context);
console.log('8. Transform', transform); // "DUCHESS ARCHER"
// Transform asynchronously, with arguments
jexl.addTransform('getStat', async (val, stat) => dbSelectByLastName(val, stat));
try {
const asyncTransform = await jexl.eval('name.last|getStat("weight")', context);
console.log('9. Async Transform', asyncTransform); // Output: 184
} catch (e) {
console.log('Database Error', e.stack);
}
// Add your own (a)synchronous operators
// Here's a case-insensitive string equality
jexl.addBinaryOp('_=', 20, (left, right) => left.toLowerCase() === right.toLowerCase());
const binaryOp = await jexl.eval('"Guest" _= "gUeSt"');
console.log('10. Binary Op', binaryOp); // true
})().then(() => console.log('Testing done'));