Skip to content

Commit

Permalink
Reuse template proessor (#27)
Browse files Browse the repository at this point in the history
* reuse template processort WIP

* reset template only when input was explicitely set to initialize()

* import is broken WIP

* use template or the output to create MetaInfos

* set up context and options if provided

* reset tags and options when reusing existing templateProcessor

---------

Co-authored-by: Sergey Sergeev <[email protected]>
  • Loading branch information
zhirafovod and Sergey Sergeev authored Dec 1, 2023
1 parent 102b07c commit cdeb2ff
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 14 deletions.
18 changes: 14 additions & 4 deletions src/CliCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,18 +120,28 @@ export default class CliCore {
const input = await this.readFileAndParse(filepath, importPath);
const contextData = contextFilePath ? await this.readFileAndParse(contextFilePath, importPath) : {};
options.importPath = importPath; //path is where local imports will be sourced from. We sneak path in with the options
this.templateProcessor = new TemplateProcessor(input, contextData, options);
// if we initialize for the first time, we need to create a new instance of TemplateProcessor
if (!this.templateProcessor) {
this.templateProcessor = new TemplateProcessor(input, contextData, options);
} else { // if we are re-initializing, we need to reset the tagSet and options, if provided
this.templateProcessor.tagSet = new Set();
this.templateProcessor.options = options;
if (contextData) {
this.templateProcessor.setupContext(contextData);
}
}
if(this.replServer){
//make variable called 'template' accessible in REPL
this.replServer.context.template = this.templateProcessor;
}
this.templateProcessor.onInitialize = this.onInit;
tags.forEach(a => this.templateProcessor.tagSet.add(a));
// set options
this.templateProcessor.logger.level = this.logLevel;
this.templateProcessor.logger.debug(`arguments: ${JSON.stringify(parsed)}`);

try {
await this.templateProcessor.initialize();
await this.templateProcessor.initialize(input);
if (oneshot === true) {
return this.templateProcessor.output;
}
Expand Down Expand Up @@ -192,15 +202,15 @@ export default class CliCore {
if (!this.templateProcessor) {
throw new Error('Initialize the template first.');
}
const parsed = CliCore.minimistArgs(replCmdInputStr)
const parsed = CliCore.minimistArgs(replCmdInputStr === undefined ? "" : replCmdInputStr)
let {_:jsonPointer=""} = parsed;
if(Array.isArray(jsonPointer)){
jsonPointer = jsonPointer[0];
if(jsonPointer===undefined){
jsonPointer = "";
}
}
return this.templateProcessor.out(jsonPointer);
return this.templateProcessor.out(jsonPointer);
}

state() {
Expand Down
35 changes: 25 additions & 10 deletions src/TemplateProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,22 +179,27 @@ export default class TemplateProcessor {
this.import = this.import.bind(this); // allows clients to directly call import on this TemplateProcessor
this.logger = new ConsoleLogger("info");
this.setupContext(context);
this.resetTemplate(template);
this.options = options;
this.debugger = new Debugger(this.templateMeta, this.logger);
this.isInitializing = false;
this.changeCallbacks = new Map();
this.functionGenerators = new Map();
this.tagSet = new Set();
}

// resetting template means that we are resetting all data holders and set up new template
private resetTemplate(template) {
this.input = JSON.parse(JSON.stringify(template));
this.output = template; //initial output is input template
this.templateMeta = JSON.parse(JSON.stringify(this.output));// Copy the given template to `initialize the templateMeta
this.templateMeta = JSON.parse(JSON.stringify(template));// Copy the given template to `initialize the templateMeta
this.warnings = [];
this.metaInfoByJsonPointer = {}; //there will be one key "/" for the root and one additional key for each import statement in the template
this.tagSet = new Set();
this.options = options;
this.debugger = new Debugger(this.templateMeta, this.logger);
this.errorReport = {}
this.isInitializing = false;
this.tempVars = [];
this.changeCallbacks = new Map();
this.functionGenerators = new Map();
}

private setupContext(context: {}) {
setupContext(context: {}) {
this.context = merge(
{},
TemplateProcessor.DEFAULT_FUNCTIONS,
Expand All @@ -214,8 +219,18 @@ export default class TemplateProcessor {
}
}

public async initialize(template = this.input, jsonPtr = "/") {
// Template processor initialize can be called from 2 major use cases
// 1. initialize a new template processor template
// 2. initialize a new template for an existing template processor
// in the second case we need to reset the template processor data holders
public async initialize(template: {} = undefined, jsonPtr = "/") {
this.timerManager.clearAll();

// if initialize is called with a template and root json pointer (which is "/" b default)
// we need to reset the template. Otherwise, we rely on the one provided in the constructor
if (template !== undefined && jsonPtr === "/") {
this.resetTemplate(template)
}
this.onInitialize && await this.onInitialize();
if (jsonPtr === "/" && this.isInitializing) {
console.error("-----Initialization '/' is already in progress. Ignoring concurrent call to initialize!!!! Strongly consider checking your JS code for errors.-----");
Expand All @@ -240,7 +255,7 @@ export default class TemplateProcessor {
this.executionPlans = {}; //clear execution plans
let parsedJsonPtr = jp.parse(jsonPtr);
parsedJsonPtr = isEqual(parsedJsonPtr, [""]) ? [] : parsedJsonPtr; //correct [""] to []
const metaInfos = await this.createMetaInfos(template, parsedJsonPtr);
const metaInfos = await this.createMetaInfos(template === undefined ? this.output : template , parsedJsonPtr);
this.metaInfoByJsonPointer[jsonPtr] = metaInfos; //dictionary for template meta info, by import path (jsonPtr)
this.sortMetaInfos(metaInfos);
this.populateTemplateMeta(metaInfos);
Expand Down

0 comments on commit cdeb2ff

Please sign in to comment.