TomFrost / Jexl

Javascript Expression Language: Powerful context-based expression parser and evaluator
MIT License
561 stars 92 forks source link

How to provide top-level document to transform #74

Closed cunneen closed 4 years ago

cunneen commented 4 years ago

Hi, is there an expression to provide the entire top-level document when invoking a transform, rather enforcing specification of a sub-property by name?

TomFrost commented 4 years ago

Hi cunneen, sorry for the late response on this. Could you provide an example of what you're looking to do?

cunneen commented 4 years ago

Thanks @TomFrost. So to specify and perform a transform, the syntax seems to require I specify a data property name as a parameter to perform the transform on.

For example, name in the following example is the input data property:

var jexl = require("jexl");
const context = {
  name: { first: 'Sterling', last: 'Archer' },
  assoc: [
    { first: 'Lana', last: 'Kane' },
    { first: 'Cyril', last: 'Figgis' },
    { first: 'Pam', last: 'Poovey' }
  ],
  age: 36
}

// Transform
jexl.addTransform('upper', val => val.toUpperCase())
await jexl.eval('"duchess"|upper + " " + name.last|upper', context); // note the property 'name' here

So how can I specify and perform if my input data looks like this? :


const context = [
    { first: 'Lana', last: 'Kane' },
    { first: 'Cyril', last: 'Figgis' },
    { first: 'Pam', last: 'Poovey' }
  ]

I need a syntax token that allows me to specify that the transform applies to the entire context document rather than a property of the document e.g. . or * or JEXL_ROOT

TomFrost commented 4 years ago

Ah, understood! This has been discussed before, with various solutions being considered. The two that made it the furthest are in your list -- . and a dedicated keyword to access the root level.

Ultimately, both solutions have pitfalls that negatively outweigh the simple solution: just wrap that context in another variable. So rather than Jexl specifying that ROOT refers to the top-level context, the engineer can just pass { ROOT: originalContext } as the context and keep all that control.

Let me know if you have a use case that's not solved by this pattern!

cunneen commented 4 years ago

Thanks @TomFrost . So simple, I'm embarrassed not to have thought of it. Thanks for the detailed answer to my question.

TomFrost commented 4 years ago

Very welcome! And trust me— for how much debate this topic has seen, this solution is anything but obvious ;-)