diff --git a/src/DependencyFinder.ts b/src/DependencyFinder.ts index 10304c42..c39d5548 100644 --- a/src/DependencyFinder.ts +++ b/src/DependencyFinder.ts @@ -13,7 +13,7 @@ // limitations under the License. import last from 'lodash/last.js'; -import {default as jsonata} from "jsonata"; +import {default as jsonata, ExprNode} from "jsonata"; /* There are cases where we need to generate some AST nodes the JSONata does not generate. Instead of referring to @@ -40,10 +40,19 @@ export default class DependencyFinder { private nodeStack: GeneratedExprNode[]; private readonly dependencies: string[][]; //during tree walking we collect these dependencies like [["a", "b", "c"], ["foo", "bar"]] which means the dependencies are a.b.c and foo.bar + /** + * program can be either a string to be compiled, or an already-compiled AST + * @param program + */ + constructor(program: string | ExprNode) { + if (typeof program === 'string') { + // Handle the case where program is a string + this.compiledExpression = jsonata(program); + this.ast = this.compiledExpression.ast(); + } else { + this.ast = program; + } - constructor(program: string) { - this.compiledExpression = jsonata(program); - this.ast = this.compiledExpression.ast(); this.currentSteps = []; this.dependencies = []; this.nodeStack = []; diff --git a/src/test/TemplateProcessor.test.js b/src/test/TemplateProcessor.test.js index fd7f3c78..5210e24c 100644 --- a/src/test/TemplateProcessor.test.js +++ b/src/test/TemplateProcessor.test.js @@ -19,8 +19,7 @@ import fs from 'fs'; import yaml from 'js-yaml'; import {fileURLToPath} from 'url'; import {dirname} from 'path'; -import MetaInfoProducer from "../../dist/src/MetaInfoProducer.js"; -import jsonata from "jsonata"; +import DependencyFinder from "../../dist/src/DependencyFinder.js"; test("test 1", async () => { @@ -1573,7 +1572,13 @@ test("parallel TemplateProcessors", () => { }); test("function generators",async () => { - let template = { a: "${ $jit() }" }; + let template = { + a: "${ $jit() }", + b: "${ $jit() }", + c: "${ $oops() }", + d:{e:"${ $jit() }"}, + e: "${ $serial([foo,bar,baz])}" + }; let tp = new TemplateProcessor(template); const jit = (metaInf, tp)=>{ @@ -1582,8 +1587,39 @@ test("function generators",async () => { } } tp.functionGenerators.set("jit", jit); + const serial = (metaInf, tp)=>{ + return (input, steps, context)=>{ + const ast = metaInf.compiledExpr__.ast(); + const depFinder = new DependencyFinder(ast); + return depFinder.findDependencies() + } + } + tp.functionGenerators.set('serial', serial); await tp.initialize(); - expect(tp.output.a).toBe("path was: /a"); + expect(tp.output).toStrictEqual({ + "a": "path was: /a", + "b": "path was: /b", + "c": { + "error": { + "message": "Attempted to invoke a non-function", + "name": "JSONata evaluation exception" + } + }, + "d": { + "e": "path was: /d/e" + }, + "e": [ + [ + "foo" + ], + [ + "bar" + ], + [ + "baz" + ] + ] + }); });