@accordproject/template-engine 2.8.0 → 2.9.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
@@ -101,6 +101,16 @@ function integerDrafter(value, format) {
101
101
  }
102
102
  }
103
103
 
104
+ function isDuration(value) {
105
+ return value != null && typeof value === "object" && "amount" in value && "unit" in value && typeof value.amount === "number" && typeof value.unit === "string";
106
+ }
107
+ function durationDrafter(value) {
108
+ if (!isDuration(value)) {
109
+ return "0 unknown";
110
+ }
111
+ return `${value.amount} ${value.unit}`;
112
+ }
113
+
104
114
  function longDrafter(value, format) {
105
115
  if (format) {
106
116
  return draftIntegerFormat(value, format);
@@ -189,6 +199,10 @@ function getDrafter(typeName) {
189
199
  return longDrafter;
190
200
  case "org.accordproject.money@0.3.0.MonetaryAmount":
191
201
  return monetaryAmountDrafter;
202
+ case "org.accordproject.time@0.3.0.Duration":
203
+ return durationDrafter;
204
+ case "org.accordproject.time@0.3.0.Period":
205
+ return durationDrafter;
192
206
  case "String":
193
207
  return stringDrafter;
194
208
  default:
@@ -957,10 +971,45 @@ class TemplateMarkInterpreter {
957
971
  const serializer = new Serializer(factory, modelManager);
958
972
  try {
959
973
  serializer.fromJSON(templateMark);
960
- return templateMark;
961
974
  } catch (err) {
962
975
  throw new Error(`Generated invalid agreement: ${err}: ${JSON.stringify(templateMark, null, 2)}`);
963
976
  }
977
+ const errors = [];
978
+ const templateClass = this.templateClass;
979
+ const guardBlockPaths = /* @__PURE__ */ new Map();
980
+ traverse(templateMark).forEach(function(node) {
981
+ if (!node || typeof node !== "object" || !node.$class) return;
982
+ const currentPath = this.path.join("/");
983
+ if (OPTIONAL_DEFINITION_RE.test(node.$class) || CONDITIONAL_DEFINITION_RE.test(node.$class) || WITH_DEFINITION_RE.test(node.$class)) {
984
+ guardBlockPaths.set(node.name, currentPath);
985
+ }
986
+ if (VARIABLE_DEFINITION_RE.test(node.$class) || ENUM_VARIABLE_DEFINITION_RE.test(node.$class) || FORMATTED_VARIABLE_DEFINITION_RE.test(node.$class)) {
987
+ const propName = node.name;
988
+ if (propName && propName !== "this") {
989
+ try {
990
+ const property = templateClass.getProperty(propName);
991
+ if (property && property.isOptional()) {
992
+ const guardPath = guardBlockPaths.get(propName);
993
+ const isGuarded = guardPath !== void 0 && (currentPath === guardPath || currentPath.startsWith(guardPath + "/"));
994
+ if (!isGuarded) {
995
+ errors.push({
996
+ propertyName: propName,
997
+ message: `Optional property '${propName}' is used without a guard. Wrap it in {{#optional ${propName}}}...{{/optional}} or {{#if ${propName}}}...{{/if}}.`
998
+ });
999
+ }
1000
+ }
1001
+ } catch {
1002
+ }
1003
+ }
1004
+ }
1005
+ });
1006
+ if (errors.length > 0) {
1007
+ const errorMessage = `Optional properties used without guards: ${errors.map((e) => e.propertyName).join(", ")}`;
1008
+ const error = new Error(errorMessage);
1009
+ error.errors = errors;
1010
+ throw error;
1011
+ }
1012
+ return templateMark;
964
1013
  }
965
1014
  /**
966
1015
  * Compiles the code nodes containing TS to code nodes containing JS.