This is the main TemplateProcessor class.

Remarks

The TemplateProcessor class is responsible for processing templates and interfacing with your program that may provide changing inputs over time and react to changes with callbacks. Many examples can be found in src/test/TemplateProcessor.test.js

Example: Initialize a simple template stored in local object 'o'

//initialize a simple template stored in local object 'o'
test("test 6", async () => {
const o = {
"a": 10,
"b": [
"../${a}",
]
};
const tp = new TemplateProcessor(o);
await tp.initialize();
expect(o).toEqual({
"a": 10,
"b": [10]
});
});

Example: Pass the TemplateProcessor a context containing a function named `nozzle` and a variable named `ZOINK`

//Pass the TemplateProcessor a context containing a function named `nozzle` and a variable named `ZOINK`
test("context", async () => {
const nozzle = (something) => "nozzle got some " + something;
const context = {"nozzle": nozzle, "ZOINK": "ZOINK"}
const tp = new TemplateProcessor({
"a": "${$nozzle($ZOINK)}"
}, context);
await tp.initialize();
expect(tp.output).toEqual(
{
"a": "nozzle got some ZOINK",
}
);
});

Example: Parse template from JSON or YAML

    it('should correctly identify and parse JSON string', async () => {
const jsonString = '{"key": "value"}';
const instance = TemplateProcessor.fromString(jsonString);
await instance.initialize();
expect(instance).toBeInstanceOf(TemplateProcessor);
expect(instance.output).toEqual({ key: "value" }); // Assuming parsedObject is publicly accessible
});

it('should correctly identify and parse YAML string using ---', async () => {
const yamlString = `---
key: value`;
const instance = TemplateProcessor.fromString(yamlString);
await instance.initialize();
expect(instance).toBeInstanceOf(TemplateProcessor);
expect(instance.output).toEqual({ key: "value" });
});

Example: React to changes using data change callbacks on various locations in the template

 test("test 1", async () => {
const tp = new TemplateProcessor({
"a": "aaa",
"b": "${a}"
});
await tp.initialize();
const received = [];
tp.setDataChangeCallback("/a", (data, jsonPtr) => {
received.push({data, jsonPtr})
});
tp.setDataChangeCallback("/b", (data, jsonPtr) => {
received.push({data, jsonPtr})
});
tp.setDataChangeCallback("/", (data, jsonPtr) => {
received.push({data, jsonPtr})
});
await tp.setData("/a", 42);
expect(received).toEqual([
{
"data": 42,
"jsonPtr": "/a"
},
{
"data": 42,
"jsonPtr": "/b"
},
{
"data": {
"a": 42,
"b": 42
},
"jsonPtr": [
"/a",
"/b"
]
}
]);
});

Constructors

Properties

Methods

Constructors

Properties

changeCallbacks: Map<string, Set<DataChangeCallback>>

for every json pointer, we have multiple callbacks that are stored in a Set

context: any

Contextual data for the template processing.

debugger: any

Debugger utility for the template processor.

errorReport: {
    [key: JsonPointerString]: any;
} = {}

Contains any errors encountered during template processing.

Type declaration

executionPlans: {
    [key: JsonPointerString]: JsonPointerString[];
} = {}

Execution plans 'from' a given JSON Pointer. So key is JSON Pointer and value is array of JSON pointers (a plan)

Type declaration

executionQueue: (Plan | SnapshotPlan)[] = []

A queue of execution plans awaiting processing.

executionStatus: ExecutionStatus
functionGenerators: Map<string, FunctionGenerator>

function generators can be provided by a caller when functions need to be created in such a way that they are somehow 'responsive' or dependent on their location inside the template. Both the generator function, and the function it generates are asynchronous functions (ie they return a promise). $import is an example of this kind of behavior. When $import('http://mytemplate.com/foo.json') is called, the import function is actually genrated on the fly, using knowledge of the json path that it was called at, to replace the content of the template at that path with the downloaded content.

input: any

Represents the raw input for the template processor.

isInitializing: boolean

Flag indicating if the template processor is currently initializing.

logger: StatedLogger

Represents the logger used within the template processor.

metaInfoByJsonPointer: MetaInfoMap = {}

Maps JSON pointers of import paths to their associated meta information.

onInitialize: Map<string, (() => void | Promise<void>)>

Allows caller to set a callback to propagate initialization into their framework

Type declaration

    • (): void | Promise<void>
    • Returns void | Promise<void>

options: any = {}

Configuration options for the template processor.

output: {} = {}

Contains the processed output after template processing.

Type declaration

    postInitialize: (() => Promise<void>) = ...

    Allows a caller to receive a callback after the template is evaluated, but before any temporary variables are removed. This function is slated to be replaced with a map of functions like onInitialize

    Type declaration

      • (): Promise<void>
      • Allows a caller to receive a callback after the template is evaluated, but before any temporary variables are removed. This function is slated to be replaced with a map of functions like onInitialize

        Returns Promise<void>

        Deprecated

    Deprecated

    tagSet: Set<string>

    A set of tags associated with the template.

    tempVars: string[] = []
    templateMeta: any

    This object mirrors the template output in structure but where the output contains actual data, this object contains MetaInfo nodes that track metadata on the actual nodes

    timerManager: TimerManager
    uniqueId: number

    A unique identifier for the template processor instance.

    warnings: any[] = []

    List of warnings generated during template processing.

    DEFAULT_FUNCTIONS: {
        Date: DateConstructor;
        clearInterval: {
            (id): void;
            (intervalId): void;
        };
        console: Console;
        debounce: (<T>(func, wait?) => T);
        fetch: ((url, opts?) => Promise<Response>);
        rateLimit: (<T>(func, maxWait?) => T);
        setInterval: typeof setInterval;
        setTimeout: typeof setTimeout;
    } = ...

    Default set of functions provided for the template processor.

    Type declaration

    • Date: DateConstructor
    • clearInterval: {
          (id): void;
          (intervalId): void;
      }
        • (id): void
        • Parameters

          • id: undefined | number

          Returns void

        • (intervalId): void
        • Cancels a Timeout object created by setInterval().

          Parameters

          • intervalId: undefined | string | number | Timeout

          Returns void

          Since

          v0.0.1

    • console: Console
    • debounce: (<T>(func, wait?) => T)
        • <T>(func, wait?): T
        • Debounces a function, ensuring that it is only called once after a specified time has elapsed since the last call.

          Type Parameters

          • T extends AnyFunction

          Parameters

          • func: T

            The function to debounce.

          • wait: number = 200

            The number of milliseconds to wait before invoking the function.

          Returns T

          A debounced function with the same type as the original function.

          Example

          // Example usage:
          function myFunction(value: string) {
          console.log('Value:', value);
          }

          const debouncedFunction = debounce(myFunction, 500);

          debouncedFunction('First call');
          debouncedFunction('Second call');
          debouncedFunction('Third call');
    • fetch: ((url, opts?) => Promise<Response>)
        • (url, opts?): Promise<Response>
        • Performs a fetch request and enhances error handling. If the response is not ok, it rejects with a custom error object that includes a .json() method. This .json() method, when called, returns the error object itself, facilitating error handling for scenarios where the caller expects to call .json() on the response.

          Parameters

          • url: string

            The URL to fetch.

          • Optional opts: object

            Optional fetch options.

          Returns Promise<Response>

          A promise that resolves to the fetch response. If the response is not ok, it rejects with a custom error object consistent with Stated template-level error handling e.g. {error:{message:"..."}}.

          Throws

          The custom error object with a .json() method if the response is not ok. The error object structure is: { error: { message: string } }.

    • rateLimit: (<T>(func, maxWait?) => T)
        • <T>(func, maxWait?): T
        • Type Parameters

          • T extends AnyFunction

          Parameters

          • func: T
          • maxWait: number = 1000

          Returns T

    • setInterval: typeof setInterval
    • setTimeout: typeof setTimeout

    Remarks

    These functions are commonly used utilities available for usage within the template processor's context. You can replace set this to determine which functions are available from templates

    Static

    NOOP: symbol = ...
    _isNodeJS: boolean = ...

    Methods

    • Private

      Sometimes we need to import a simple expression string that is not nested in an object. for example if we {"msg":"$import('${'hello ' & to }')"), then we are importing an expression directly into the parent, not nesting in an object. In this case we must slice off the last element of the rootJsonPointer, because to not slice it off would imply that the target of the expression is inside the msg field, but the intention when we import a simple expression is target the parent object which holds the msg field.

      Parameters

      • template: any
      • rootJsonPtr: any[]

      Returns any[]

      either the original rootJsonPointer, or one that has been trimmed to point to the parent of rootJsonPtr

    • Parameters

      • tagSetOnTheExpression: Set<string>

      Returns boolean

    • Parameters

      • data: any
      • jsonPointer: string | string[]
      • removed: boolean = false

      Returns Promise<void>

    • Parameters

      • metaInfo: any

      Returns ((jsonPointer, timeoutMs) => object)

        • (jsonPointer, timeoutMs): object
        • Parameters

          • jsonPointer: string
          • timeoutMs: number

          Returns object

    • Private

      When $forked is called, it must push the current output onto the forkStack so it can be restored on $joined, and it must replace the output with a copy of the output.

      Parameters

      Returns ((jsonPtr, data, op?) => Promise<void>)

        • (jsonPtr, data, op?): Promise<void>
        • Parameters

          • jsonPtr: string
          • data: any
          • op: Op = 'set'

          Returns Promise<void>

    • Private

      The $joined(/foo, data) function pops the forkstack and can return us to ordinary non-forked operation if the pop operation empties the fork stack

      Parameters

      Returns ((jsonPtr, data, op?) => Promise<void>)

        • (jsonPtr, data, op?): Promise<void>
        • Parameters

          • jsonPtr: string
          • data: any
          • op: Op = 'set'

          Returns Promise<void>

    • Private

      The $set(/foo, data) command may be operating inside the context of a $forked. If this is the case then $setData is intercepted here and we use the setDataForked function which applies changes to forked output

      Parameters

      Returns ((jsonPtr, data?, op?) => Promise<string[]>) | ((jsonPtr, data, op?) => Promise<void>)

    • Parameters

      Returns ((templateToImport) => Promise<symbol>)

        • (templateToImport): Promise<symbol>
        • Parameters

          • templateToImport: string

          Returns Promise<symbol>

    • Parameters

      • template: string | object
      • jsonPtrImportPath: string

      Returns Promise<void>

    • Template processor initialize can be called from 2 major use cases

      1. initialize a new importedSubtemplate processor importedSubtemplate
      2. $import a new importedSubtemplate for an existing importedSubtemplate processor in the second case we need to reset the importedSubtemplate processor data holders

      Parameters

      • importedSubtemplate: undefined | {} = undefined

        the object representing the importedSubtemplate

      • jsonPtr: string = "/"

        defaults to "/" which is to say, this importedSubtemplate is the root importedSubtemplate. When we $import a importedSubtemplate inside an existing importedSubtemplate, then we must provide a path other than root to import into. Typically, we would use the json pointer of the expression where the $import function is used.

      • snapshottedOutput: undefined | {} = undefined

        if provided, output is set to this initial value

      Returns Promise<void>

    • Initializes the current TemplateProcessor instance using the output data from a given snapshot object. This method is designed for use with an already constructed TemplateProcessor instance, allowing it to be initialized (or re-initialized) with specific output data from a snapshot. This can be particularly useful for setting or resetting the processor's state based on dynamic conditions or to rehydrate the processor from a previously saved state without constructing a new instance.

      Parameters

      • snapshot: Snapshot

        A snapshot object containing only the output data for initializing the TemplateProcessor.

      Returns Promise<void>

      A promise that resolves once the TemplateProcessor has been initialized with the output data from the snapshot.

      Example

      const snapshot = {"output":{...}, "options":{...}, "template":{...}};
      const tp = TemplateProcessor.constructFromSnapshotObject(snapshot);
      await tp.initializeFromSnapshotObject(snapshot)
      .then(() => console.log('TemplateProcessor initialized from snapshot output.'));
    • Private

      temp vars are in scope if all tags are present OR the expression's fieldname ends in !, which makes it an absolutely temporary variable since.

      Parameters

      Returns boolean

    • Parameters

      • tmpVars: string[]
      • jsonPtrOfTemplate: string

      Returns void

    • Parameters

      • literalTemplateToImport: any
      • metaInfo: MetaInfo

      Returns Promise<void>

    • Sets or deletes data based on the specified operation.

      Parameters

      • jsonPtr: string

        The JSON pointer indicating where to apply the operation.

      • Optional data: any = null

        The data to be used with the set or setDeferred operation.

      • Optional op: Op = "set"

        The operation to perform - setDeferred is for internal use

      Returns Promise<string[]>

      A promise with the list of json pointers touched by the plan

      Async

    • Sets a data change callback function that will be called whenever the value at the json pointer has changed

      Parameters

      • jsonPtr: string
      • cbFn: DataChangeCallback

        of form (data, ptr:JsonPointerString, removed?:boolean)=>void

      Returns void

    • Calling setDataForked allows the mutation and its reaction (fromPlan) to begin executing immediately without queuing/seriealizing/blocking on other plans. This is possible because a forked planStep contains a write-safe copy of this.output (essentially a 'snapshot' in MVCC terminology) and therefore the mutation and propagation of the fromPlan are isolated, just like snapshot isolation levels on Postres or other MVCC databases. So, do not await this method. Just let 'er rip.

      Parameters

      Returns Promise<string[]>

    • allows direct injection of ${expression} into template at given jsonPointer.

      Parameters

      • expression: string
      • jsonPointer: string

      Returns Promise<void>

    • Creates a stringified snapshot of the current state of the TemplateProcessor instance, including its input, output, and options.

      Returns Promise<string>

      A JSON string representing the snapshot of the TemplateProcessor's current state, including template input, processed output, and options.

      Example

      const tp = new TemplateProcessor(template, context, options);
      const snapshotString = await tp.snapshot();
      // snapshotString contains a JSON string with the template, output, and options of the TemplateProcessor
    • Parameters

      • metaInfos: MetaInfo[]
      • exprsOnly: boolean = true
      • fanout: boolean = true

      Returns string[]

    • Type Parameters

      • T extends any[]

      Parameters

      • fn: ((...args) => any)
          • (...args): any
          • Parameters

            • Rest ...args: T

            Returns any

      Returns ((...args) => any)

        • (...args): any
        • Parameters

          • Rest ...args: T

          Returns any

    • Parameters

      • jsonataLambda: any

      Returns {
          _stated_function__: boolean;
          apply(_this, args): any;
          (...args): any;
      }

        • (...args): any
        • Parameters

          • Rest ...args: any[]

          Returns any

      • _stated_function__: boolean
      • apply:function
    • Constructs a new TemplateProcessor instance from a given snapshot object, but does NOT initialize it. This method allows the caller the opportunity to register dataChangeCallbacks and so forth before template evaluation begins, providing more control over the initialization process.

      Parameters

      • snapshot: Snapshot

        A snapshot object containing template, options, and output data for initializing the TemplateProcessor.

      • Optional context: {} = {}

        An optional context object to be used by the TemplateProcessor.

        Returns default

        A new TemplateProcessor instance constructed from the snapshot data, not yet initialized.

        Example

        const snapshot = {"template":"...", "options":{}, "output":"..."};
        const tp = TemplateProcessor.constructFromSnapshot(snapshot);
        // Register callbacks or perform other setup operations here
        await tp.initialize();
      • this function is used to make a deep copy of the output so that when we $fork we are operating on a copy of the output, not co-mutating the original

        Parameters

        • output: object

        Returns any

      • Constructs and initializes a new TemplateProcessor instance from a given snapshot string. This method parses the snapshot string, constructs a new TemplateProcessor with the parsed data, and then initializes it. It is a convenient method for quickly rehydrating and preparing a TemplateProcessor instance from a saved state.

        Parameters

        • snapshot: string

          A JSON string snapshot from which to initialize the TemplateProcessor.

        • Optional context: {} = {}

          An optional context object to be used by the TemplateProcessor.

          Returns Promise<default>

          A promise that resolves with the newly initialized TemplateProcessor instance.

          Example

          const snapshotString = '{"template":"...","options":{},"output":"..."}';
          TemplateProcessor.initializeFromSnapshot(snapshotString, context)
          .then(tp => console.log('TemplateProcessor initialized from snapshot.'));
        • Loads a template and initializes a new template processor instance.

          Parameters

          • template: object

            The template data to be processed.

          • Optional context: {} = {}

            Optional context data for the template.

            Returns Promise<default>

            Returns an initialized instance of TemplateProcessor.

            Static

          • Private

            Parameters

            • snapshot: Snapshot

              this method mutates the Snapshot's template in place to merge accumulated output data into it. It does this by

              1. generating local MetaInfo for the template.
              2. making a Map whose key is jsonPointer, and placing into that the MetaInfo for places in the template whose subtree has expressions (treeHasExpressions__). This tells us that these are parts of the template that cannot be altered, ever, because to alter them would be to remove expressions from the template.
              3. walking the output object recursively. As it walks, it looks up the json pointer in the aformmentioned Map. If it does not see the pointer in the Map, then it means the current piece of output is pure data, and is transferred ino the template

              Net effect is that pure data that had been shoved into the output, at runtime gets transfered into the template. Now it is safe to initialize from this Snapshot and we will not have a situation where there is pure data in the output with no corresponding MetaInfo to mark it as materialized__

            Returns Promise<void>

          Generated using TypeDoc