@accordproject/template-engine 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -508,17 +508,31 @@ class JavaScriptEvaluator {
508
508
  const end = (/* @__PURE__ */ new Date()).getTime();
509
509
  resolve({ result, elapsed: end - start });
510
510
  }).catch((err) => {
511
- console.log(err);
512
- reject({
513
- message: err.message
514
- });
511
+ console.error(err);
512
+ if (err instanceof Error) {
513
+ reject({
514
+ message: err.message,
515
+ stack: err.stack
516
+ });
517
+ } else {
518
+ reject({
519
+ message: String(err)
520
+ });
521
+ }
515
522
  });
516
523
  }
517
524
  } catch (err) {
518
- console.log(err);
519
- reject({
520
- message: err.message
521
- });
525
+ console.error(err);
526
+ if (err instanceof Error) {
527
+ reject({
528
+ message: err.message,
529
+ stack: err.stack
530
+ });
531
+ } else {
532
+ reject({
533
+ message: String(err)
534
+ });
535
+ }
522
536
  }
523
537
  });
524
538
  }
@@ -540,6 +554,7 @@ class JavaScriptEvaluator {
540
554
  };
541
555
  if (this.queue.length >= this.options.maxQueueDepth) {
542
556
  reject({ maxQueueDepthExceeded: true, elapsed: 0 });
557
+ return;
543
558
  }
544
559
  this.queue.push(workItem);
545
560
  this.processQueue(options);
@@ -580,7 +595,7 @@ class JavaScriptEvaluator {
580
595
  }
581
596
  const workerPath = this.getWorkerPath();
582
597
  const worker = child_process.fork(workerPath, { timeout: options.timeout, env: {} });
583
- if (!worker.pid) {
598
+ if (worker.pid === void 0 || worker.pid === null) {
584
599
  throw new Error("Failed to fork child process");
585
600
  }
586
601
  this.workers.push(worker);
@@ -589,7 +604,18 @@ class JavaScriptEvaluator {
589
604
  worker.on("error", (err) => {
590
605
  this.workers = this.workers.filter((w) => w.pid !== worker.pid);
591
606
  const end = (/* @__PURE__ */ new Date()).getTime();
592
- reject({ message: err.message, elapsed: end - start });
607
+ if (err instanceof Error) {
608
+ reject({
609
+ message: err.message,
610
+ stack: err.stack,
611
+ elapsed: end - start
612
+ });
613
+ } else {
614
+ reject({
615
+ message: String(err),
616
+ elapsed: end - start
617
+ });
618
+ }
593
619
  });
594
620
  worker.on("message", (msg) => {
595
621
  result = msg;
@@ -772,13 +798,17 @@ async function generateRecursiveBlocks(modelManager, clauseLibrary, templateMark
772
798
  if (!Array.isArray(arrayData)) {
773
799
  throw new Error(`Values found for path '${path}' in data ${data} is not an array: ${arrayData}.`);
774
800
  } else {
801
+ const firstChild = context.nodes[0];
802
+ const hasListWrapper = firstChild && firstChild.$class === `${CommonMarkModel.NAMESPACE}.List` && Array.isArray(firstChild.nodes) && firstChild.nodes.length > 0;
803
+ const itemTemplate = hasListWrapper ? firstChild.nodes[0] : firstChild;
775
804
  const nodes = [];
776
805
  for (let n2 = 0; n2 < arrayData.length; n2++) {
777
806
  const arrayItem = arrayData[n2];
778
- const subResult = await generateAgreement(modelManager, clauseLibrary, context.nodes[0].nodes[0], arrayItem, options);
807
+ const subResult = await generateAgreement(modelManager, clauseLibrary, itemTemplate, arrayItem, options);
808
+ const childNodes = hasListWrapper ? subResult.nodes ? subResult.nodes : [] : [subResult];
779
809
  nodes.push({
780
810
  $class: childNodeClass,
781
- nodes: subResult.nodes ? subResult.nodes : []
811
+ nodes: childNodes
782
812
  });
783
813
  }
784
814
  result[thisPath.join("/")] = nodes;
@@ -1122,14 +1152,14 @@ class TemplateArchiveProcessor {
1122
1152
  return result;
1123
1153
  }
1124
1154
  /**
1125
- * Trigger the logic of a template
1126
- * @param {object} request - the request to send to the template logic
1127
- * @param {object} state - the current state of the template
1128
- * @param {[string]} currentTime - the current time, defaults to now
1129
- * @param {[number]} utcOffset - the UTC offset, defaults to zero
1130
- * @returns {Promise} the response and any events
1155
+ * Compile the logic of a template
1156
+ * @param {boolean} [enableCompiledLogicCache] - whether to cache the compiled logic for future use
1157
+ * @returns {Promise<Record<string, TwoSlashReturn>>} the compiled code for each typescript file
1131
1158
  */
1132
- async trigger(data, request, state, currentTime, utcOffset) {
1159
+ async compileLogic(enableCompiledLogicCache = false) {
1160
+ if (enableCompiledLogicCache && this.compiledLogicCache) {
1161
+ return this.compiledLogicCache;
1162
+ }
1133
1163
  const logicManager = this.template.getLogicManager();
1134
1164
  if (logicManager.getLanguage() === "typescript") {
1135
1165
  const compiledCode = {};
@@ -1146,69 +1176,70 @@ class TemplateArchiveProcessor {
1146
1176
  const result = compiler.compile(code);
1147
1177
  compiledCode[tsFile.getIdentifier()] = result;
1148
1178
  }
1149
- const resolvedTime = currentTime ?? (/* @__PURE__ */ new Date()).toISOString();
1150
- const resolvedOffset = utcOffset ?? 0;
1151
- const evaluator = new JavaScriptEvaluator();
1152
- const evalResponse = await evaluator.evalDangerously({
1153
- templateLogic: true,
1154
- verbose: false,
1155
- functionName: "trigger",
1156
- code: compiledCode["logic/logic.ts"].code,
1157
- // TODO DCS - how to find the code to run?
1158
- argumentNames: ["data", "request", "state"],
1159
- arguments: [data, request, state, resolvedTime, resolvedOffset]
1160
- });
1161
- if (evalResponse.result) {
1162
- return evalResponse.result;
1163
- } else {
1164
- throw new Error("Trigger failed with message: " + evalResponse.message);
1179
+ if (enableCompiledLogicCache) {
1180
+ this.compiledLogicCache = compiledCode;
1165
1181
  }
1182
+ return compiledCode;
1166
1183
  } else {
1167
1184
  throw new Error("Only TypeScript is supported at this time");
1168
1185
  }
1169
1186
  }
1170
1187
  /**
1171
- * Init the logic of a template
1188
+ * Trigger the logic of a template.
1189
+ * @param {object} data - the data for the template
1190
+ * @param {object} request - the request to send to the template logic
1191
+ * @param {object} state - the current state of the template
1172
1192
  * @param {[string]} currentTime - the current time, defaults to now
1173
1193
  * @param {[number]} utcOffset - the UTC offset, defaults to zero
1194
+ * @param {boolean} [enableCompiledLogicCache] - whether to use the compiled logic cache
1195
+ * @returns {Promise<TriggerResponse>} the response and any events
1196
+ */
1197
+ async trigger(data, request, state, currentTime, utcOffset, enableCompiledLogicCache) {
1198
+ const compiledCode = await this.compileLogic(enableCompiledLogicCache);
1199
+ const resolvedTime = currentTime ?? (/* @__PURE__ */ new Date()).toISOString();
1200
+ const resolvedOffset = utcOffset ?? 0;
1201
+ const evaluator = new JavaScriptEvaluator();
1202
+ const evalResponse = await evaluator.evalDangerously({
1203
+ templateLogic: true,
1204
+ verbose: false,
1205
+ functionName: "trigger",
1206
+ code: compiledCode["logic/logic.ts"].code,
1207
+ // TODO DCS - how to find the code to run?
1208
+ argumentNames: ["data", "request", "state"],
1209
+ arguments: [data, request, state, resolvedTime, resolvedOffset]
1210
+ });
1211
+ if (evalResponse.result) {
1212
+ return evalResponse.result;
1213
+ } else {
1214
+ throw new Error("Trigger failed with message: " + evalResponse.message);
1215
+ }
1216
+ }
1217
+ /**
1218
+ * Init the logic of a template.
1219
+ * @param {object} data - the data for the template
1220
+ * @param {[string]} currentTime - the current time, defaults to now
1221
+ * @param {[number]} utcOffset - the UTC offset, defaults to zero
1222
+ * @param {boolean} [enableCompiledLogicCache] - whether to use the compiled logic cache
1174
1223
  * @returns {Promise<InitResponse>} the new state
1175
1224
  */
1176
- async init(data, currentTime, utcOffset) {
1177
- const logicManager = this.template.getLogicManager();
1178
- if (logicManager.getLanguage() === "typescript") {
1179
- const compiledCode = {};
1180
- const tsFiles = logicManager.getScriptManager().getScriptsForTarget("typescript");
1181
- for (let n = 0; n < tsFiles.length; n++) {
1182
- const tsFile = tsFiles[n];
1183
- const compiler = new TypeScriptToJavaScriptCompiler(
1184
- this.template.getModelManager(),
1185
- this.template.getTemplateModel().getFullyQualifiedName()
1186
- );
1187
- await compiler.initialize();
1188
- const code = `${Buffer.from(SMART_LEGAL_CONTRACT_BASE64, "base64").toString()}
1189
- ${tsFile.getContents()}`;
1190
- const result = compiler.compile(code);
1191
- compiledCode[tsFile.getIdentifier()] = result;
1192
- }
1193
- const resolvedTime = currentTime ?? (/* @__PURE__ */ new Date()).toISOString();
1194
- const resolvedOffset = utcOffset ?? 0;
1195
- const evaluator = new JavaScriptEvaluator();
1196
- const evalResponse = await evaluator.evalDangerously({
1197
- templateLogic: true,
1198
- verbose: false,
1199
- functionName: "init",
1200
- code: compiledCode["logic/logic.ts"].code,
1201
- // TODO DCS - how to find the code to run?
1202
- argumentNames: ["data"],
1203
- arguments: [data, resolvedTime, resolvedOffset]
1204
- });
1205
- if (evalResponse.result) {
1206
- return evalResponse.result;
1207
- } else {
1208
- throw new Error("Init failed with message: " + evalResponse.message);
1209
- }
1225
+ async init(data, currentTime, utcOffset, enableCompiledLogicCache) {
1226
+ const compiledCode = await this.compileLogic(enableCompiledLogicCache);
1227
+ const resolvedTime = currentTime ?? (/* @__PURE__ */ new Date()).toISOString();
1228
+ const resolvedOffset = utcOffset ?? 0;
1229
+ const evaluator = new JavaScriptEvaluator();
1230
+ const evalResponse = await evaluator.evalDangerously({
1231
+ templateLogic: true,
1232
+ verbose: false,
1233
+ functionName: "init",
1234
+ code: compiledCode["logic/logic.ts"].code,
1235
+ // TODO DCS - how to find the code to run?
1236
+ argumentNames: ["data"],
1237
+ arguments: [data, resolvedTime, resolvedOffset]
1238
+ });
1239
+ if (evalResponse.result) {
1240
+ return evalResponse.result;
1210
1241
  } else {
1211
- throw new Error("Only TypeScript is supported at this time");
1242
+ throw new Error("Init failed with message: " + evalResponse.message);
1212
1243
  }
1213
1244
  }
1214
1245
  }