From 19dff46c9b33b680c073003387cde3d812a9b77f Mon Sep 17 00:00:00 2001 From: Geoffrey Hendrey Date: Wed, 30 Oct 2024 19:33:10 -0700 Subject: [PATCH] wip --- src/test/TemplateProcessor.test.js | 60 +++++++++++++++++++++++++++++- src/utils/GeneratorManager.ts | 34 +++++++++++------ 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/test/TemplateProcessor.test.js b/src/test/TemplateProcessor.test.js index ad83e777..942e1519 100644 --- a/src/test/TemplateProcessor.test.js +++ b/src/test/TemplateProcessor.test.js @@ -3110,14 +3110,14 @@ test("test close", async () => { } }); -test("test generate", async () => { +test("test generate array", async () => { const o = { "delayMs": 10, "a":"${[1..10]~>$generate(delayMs)}", "b": "${a}" }; - const callCount = 10; + const callCount = 0; let resolvePromise; const allCallsMade = new Promise((resolve) => { resolvePromise = resolve; @@ -3141,6 +3141,62 @@ test("test generate", async () => { } }); +test("test generate single item", async () => { + const o = { + "a":"${$generate(10)}", + "b": "${a}" + }; + + const callCount = 0; + let resolvePromise; + const allCallsMade = new Promise((resolve) => { + resolvePromise = resolve; + }); + + const changeHandler = jest.fn((data, ptr) => { + expect(ptr).toBe("/b"); // Ensure correct pointer + resolvePromise(); // Resolve the promise when callCount is reached + }); + const tp = new TemplateProcessor(o); + tp.setDataChangeCallback('/b', changeHandler); + try { + await tp.initialize(); + await allCallsMade; + expect(changeHandler).toHaveBeenCalledTimes(1); + expect(tp.output.b).toBe(10); + } finally { + await tp.close(); + } +}); + +test("test generate function result", async () => { + const o = { + "a":"${$generate(function(){10})}", + "b": "${a}" + }; + + let resolvePromise; + const allCallsMade = new Promise((resolve) => { + resolvePromise = resolve; + }); + + const changeHandler = jest.fn((data, ptr) => { + expect(ptr).toBe("/b"); // Ensure correct pointer + resolvePromise(); // Resolve the promise when callCount is reached + }); + + const tp = new TemplateProcessor(o); + tp.setDataChangeCallback('/b', changeHandler); + try { + await tp.initialize(); + await allCallsMade; + expect(changeHandler).toHaveBeenCalledTimes(1); + expect(tp.output.b).toBe(10); + } finally { + await tp.close(); + } +}); + test("test lifecycle manager", async () => { const o = { diff --git a/src/utils/GeneratorManager.ts b/src/utils/GeneratorManager.ts index 586726e8..181e40a5 100644 --- a/src/utils/GeneratorManager.ts +++ b/src/utils/GeneratorManager.ts @@ -9,28 +9,40 @@ export class GeneratorManager{ } /** - * Generates an asynchronous generator that yields items from the provided array, + * Generates an asynchronous generator that yields items from the provided generateMe, * separated by the specified timeout, and automatically registers the generator. * - * @param array The array of items to yield. + * @param generateMe The item or array of items to yield. If generate me is a function, the function is called to + * get a result, and recursively passed to generate() * @param timeout The delay in milliseconds between yields. Defaults to 0. * @returns The registered asynchronous generator. */ - public generate = (array: any[], timeout: number = 0): AsyncGenerator => { + public generate = (generateMe: any[]|any| (() => any), timeout: number = 0): AsyncGenerator => { if (this.templateProcessor.isClosed) { throw new Error("generate() cannot be called on a closed TemplateProcessor"); } const timerManager = this.templateProcessor.timerManager; - - const generator = async function* () { - for (let i = 0; i < array.length; i++) { - yield array[i]; - if (timeout > 0 && i < array.length - 1) { - await new Promise((resolve) => timerManager.setTimeout(resolve, timeout)); + //yield array items separated by timeout + if(Array.isArray(generateMe)) { + return async function* () { + for (let i = 0; i < generateMe.length; i++) { + yield generateMe[i]; + if (timeout > 0 && i < generateMe.length - 1) { + await new Promise((resolve) => timerManager.setTimeout(resolve, timeout)); + } } - } + }(); + } + //call function and return result + if(typeof generateMe === 'function'){ + return async function*(){ + yield (generateMe as ()=>any)(); + }(); + } + //yield individual item + return async function*(){ + yield generateMe; }(); - return generator; };