@player-ui/player 0.4.0-next.7 → 0.4.0-next.9

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.
Files changed (38) hide show
  1. package/dist/index.cjs.js +622 -325
  2. package/dist/index.d.ts +188 -72
  3. package/dist/index.esm.js +619 -327
  4. package/dist/player.dev.js +623 -326
  5. package/dist/player.prod.js +1 -1
  6. package/package.json +11 -3
  7. package/src/binding/binding.ts +8 -0
  8. package/src/binding/index.ts +1 -1
  9. package/src/controllers/constants/index.ts +9 -5
  10. package/src/controllers/data.ts +49 -52
  11. package/src/controllers/flow/controller.ts +16 -12
  12. package/src/controllers/flow/flow.ts +6 -1
  13. package/src/controllers/validation/binding-tracker.ts +42 -19
  14. package/src/controllers/validation/controller.ts +265 -85
  15. package/src/controllers/view/asset-transform.ts +4 -1
  16. package/src/controllers/view/controller.ts +19 -2
  17. package/src/data/dependency-tracker.ts +14 -0
  18. package/src/data/local-model.ts +25 -1
  19. package/src/data/model.ts +55 -8
  20. package/src/data/noop-model.ts +2 -0
  21. package/src/expressions/evaluator-functions.ts +24 -2
  22. package/src/expressions/evaluator.ts +35 -31
  23. package/src/expressions/types.ts +17 -5
  24. package/src/expressions/utils.ts +19 -0
  25. package/src/player.ts +26 -29
  26. package/src/plugins/flow-exp-plugin.ts +2 -2
  27. package/src/string-resolver/index.ts +7 -2
  28. package/src/types.ts +1 -4
  29. package/src/validator/binding-map-splice.ts +59 -0
  30. package/src/validator/index.ts +1 -0
  31. package/src/validator/types.ts +11 -3
  32. package/src/validator/validation-middleware.ts +34 -3
  33. package/src/view/parser/index.ts +44 -2
  34. package/src/view/plugins/applicability.ts +1 -1
  35. package/src/view/plugins/string-resolver.ts +8 -4
  36. package/src/view/plugins/template-plugin.ts +1 -6
  37. package/src/view/resolver/index.ts +119 -54
  38. package/src/view/resolver/types.ts +48 -7
package/dist/index.cjs.js CHANGED
@@ -555,7 +555,7 @@ class BindingParser {
555
555
  updates = __spreadValues$d(__spreadValues$d({}, updates), normalized.updates);
556
556
  }
557
557
  const updateKeys = Object.keys(updates);
558
- if (updateKeys.length > 0) {
558
+ if (!options.readOnly && updateKeys.length > 0) {
559
559
  const updateTransaction = updateKeys.map((updatedBinding) => [
560
560
  this.parse(updatedBinding),
561
561
  updates[updatedBinding]
@@ -651,6 +651,10 @@ class DependencyMiddleware extends DependencyTracker {
651
651
  this.addReadDep(binding);
652
652
  return next == null ? void 0 : next.get(binding, options);
653
653
  }
654
+ delete(binding, options, next) {
655
+ this.addWriteDep(binding);
656
+ return next == null ? void 0 : next.delete(binding, options);
657
+ }
654
658
  }
655
659
  class DependencyModel extends DependencyTracker {
656
660
  constructor(rootModel) {
@@ -667,6 +671,10 @@ class DependencyModel extends DependencyTracker {
667
671
  this.addReadDep(binding);
668
672
  return this.rootModel.get(binding, options);
669
673
  }
674
+ delete(binding, options) {
675
+ this.addWriteDep(binding);
676
+ return this.rootModel.delete(binding, options);
677
+ }
670
678
  }
671
679
 
672
680
  class NOOPDataModel {
@@ -676,15 +684,18 @@ class NOOPDataModel {
676
684
  set() {
677
685
  return [];
678
686
  }
687
+ delete() {
688
+ }
679
689
  }
680
690
  const NOOP_MODEL = new NOOPDataModel();
681
691
 
682
692
  const ROOT_BINDING = new BindingInstance([]);
683
693
  function withParser(model, parseBinding) {
684
- function maybeParse(binding) {
694
+ function maybeParse(binding, readOnly) {
685
695
  const parsed = isBinding(binding) ? binding : parseBinding(binding, {
686
696
  get: model.get,
687
- set: model.set
697
+ set: model.set,
698
+ readOnly
688
699
  });
689
700
  if (!parsed) {
690
701
  throw new Error("Unable to parse binding");
@@ -693,10 +704,13 @@ function withParser(model, parseBinding) {
693
704
  }
694
705
  return {
695
706
  get(binding, options) {
696
- return model.get(maybeParse(binding), options);
707
+ return model.get(maybeParse(binding, true), options);
697
708
  },
698
709
  set(transaction, options) {
699
- return model.set(transaction.map(([key, val]) => [maybeParse(key), val]), options);
710
+ return model.set(transaction.map(([key, val]) => [maybeParse(key, false), val]), options);
711
+ },
712
+ delete(binding, options) {
713
+ return model.delete(maybeParse(binding, false), options);
700
714
  }
701
715
  };
702
716
  }
@@ -705,8 +719,27 @@ function toModel(middleware, defaultOptions, next) {
705
719
  return middleware;
706
720
  }
707
721
  return {
708
- get: (binding, options) => middleware.get(binding, options != null ? options : defaultOptions, next),
709
- set: (transaction, options) => middleware.set(transaction, options != null ? options : defaultOptions, next)
722
+ get: (binding, options) => {
723
+ const resolvedOptions = options != null ? options : defaultOptions;
724
+ if (middleware.get) {
725
+ return middleware.get(binding, resolvedOptions, next);
726
+ }
727
+ return next == null ? void 0 : next.get(binding, resolvedOptions);
728
+ },
729
+ set: (transaction, options) => {
730
+ const resolvedOptions = options != null ? options : defaultOptions;
731
+ if (middleware.set) {
732
+ return middleware.set(transaction, resolvedOptions, next);
733
+ }
734
+ return next == null ? void 0 : next.set(transaction, resolvedOptions);
735
+ },
736
+ delete: (binding, options) => {
737
+ const resolvedOptions = options != null ? options : defaultOptions;
738
+ if (middleware.delete) {
739
+ return middleware.delete(binding, resolvedOptions, next);
740
+ }
741
+ return next == null ? void 0 : next.delete(binding, resolvedOptions);
742
+ }
710
743
  };
711
744
  }
712
745
  function constructModelForPipeline(pipeline) {
@@ -714,7 +747,7 @@ function constructModelForPipeline(pipeline) {
714
747
  return NOOP_MODEL;
715
748
  }
716
749
  if (pipeline.length === 1) {
717
- return pipeline[0];
750
+ return toModel(pipeline[0]);
718
751
  }
719
752
  function createModelWithOptions(options) {
720
753
  var _a;
@@ -729,6 +762,10 @@ function constructModelForPipeline(pipeline) {
729
762
  set: (transaction, options) => {
730
763
  var _a;
731
764
  return (_a = createModelWithOptions(options)) == null ? void 0 : _a.set(transaction, options);
765
+ },
766
+ delete: (binding, options) => {
767
+ var _a;
768
+ return (_a = createModelWithOptions(options)) == null ? void 0 : _a.delete(binding, options);
732
769
  }
733
770
  };
734
771
  }
@@ -765,6 +802,9 @@ class PipelinedDataModel {
765
802
  get(binding, options) {
766
803
  return this.effectiveDataModel.get(binding, options);
767
804
  }
805
+ delete(binding, options) {
806
+ return this.effectiveDataModel.delete(binding, options);
807
+ }
768
808
  }
769
809
 
770
810
  class LocalModel {
@@ -791,11 +831,24 @@ class LocalModel {
791
831
  });
792
832
  return effectiveOperations;
793
833
  }
834
+ delete(binding) {
835
+ const parentBinding = binding.parent();
836
+ if (parentBinding) {
837
+ const parentValue = this.get(parentBinding);
838
+ if (parentValue !== void 0) {
839
+ if (Array.isArray(parentValue)) {
840
+ this.model = timm.setIn(this.model, parentBinding.asArray(), timm.removeAt(parentValue, binding.key()));
841
+ } else {
842
+ this.model = timm.setIn(this.model, parentBinding.asArray(), timm.omit(parentValue, binding.key()));
843
+ }
844
+ }
845
+ }
846
+ }
794
847
  }
795
848
 
796
849
  const ExpNodeOpaqueIdentifier = Symbol("Expression Node ID");
797
850
  function isExpressionNode(x) {
798
- return typeof x === "object" && x.__id === ExpNodeOpaqueIdentifier;
851
+ return typeof x === "object" && x !== null && !Array.isArray(x) && x.__id === ExpNodeOpaqueIdentifier;
799
852
  }
800
853
 
801
854
  const PERIOD_CODE = 46;
@@ -1422,16 +1475,108 @@ const getDataVal = (_context, binding) => {
1422
1475
  return _context.model.get(binding);
1423
1476
  };
1424
1477
  const deleteDataVal = (_context, binding) => {
1425
- return _context.model.set([[binding, void 0]]);
1478
+ return _context.model.delete(binding);
1426
1479
  };
1480
+ const conditional = (ctx, condition, ifTrue, ifFalse) => {
1481
+ const resolution = ctx.evaluate(condition);
1482
+ if (resolution) {
1483
+ return ctx.evaluate(ifTrue);
1484
+ }
1485
+ if (ifFalse) {
1486
+ return ctx.evaluate(ifFalse);
1487
+ }
1488
+ return null;
1489
+ };
1490
+ conditional.resolveParams = false;
1427
1491
 
1428
1492
  var DEFAULT_EXPRESSION_HANDLERS = /*#__PURE__*/Object.freeze({
1429
1493
  __proto__: null,
1430
1494
  setDataVal: setDataVal,
1431
1495
  getDataVal: getDataVal,
1432
- deleteDataVal: deleteDataVal
1496
+ deleteDataVal: deleteDataVal,
1497
+ conditional: conditional
1433
1498
  });
1434
1499
 
1500
+ function withoutContext(fn) {
1501
+ return (_context, ...args) => fn(...args);
1502
+ }
1503
+ function isInRange(position, location) {
1504
+ return position.character >= location.start.character && position.character <= location.end.character;
1505
+ }
1506
+ function findClosestNodeAtPosition(node, position) {
1507
+ var _a, _b, _c, _d, _e;
1508
+ switch (node.type) {
1509
+ case "Modification":
1510
+ case "Assignment":
1511
+ case "LogicalExpression":
1512
+ case "BinaryExpression": {
1513
+ const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1514
+ if (check) {
1515
+ return check;
1516
+ }
1517
+ break;
1518
+ }
1519
+ case "UnaryExpression": {
1520
+ const checkArg = findClosestNodeAtPosition(node.argument, position);
1521
+ if (checkArg) {
1522
+ return checkArg;
1523
+ }
1524
+ break;
1525
+ }
1526
+ case "MemberExpression": {
1527
+ const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1528
+ if (checkObject) {
1529
+ return checkObject;
1530
+ }
1531
+ break;
1532
+ }
1533
+ case "ConditionalExpression": {
1534
+ const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1535
+ if (checkObject) {
1536
+ return checkObject;
1537
+ }
1538
+ break;
1539
+ }
1540
+ case "ArrayExpression":
1541
+ case "Compound": {
1542
+ const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1543
+ const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1544
+ if (anyElements) {
1545
+ return anyElements;
1546
+ }
1547
+ break;
1548
+ }
1549
+ case "Object": {
1550
+ const checkObject = node.attributes.reduce((found, next) => {
1551
+ var _a2;
1552
+ return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1553
+ }, void 0);
1554
+ if (checkObject) {
1555
+ return checkObject;
1556
+ }
1557
+ break;
1558
+ }
1559
+ case "CallExpression": {
1560
+ const anyArgs = (_e = node.args.find((arg) => {
1561
+ return findClosestNodeAtPosition(arg, position);
1562
+ })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1563
+ if (anyArgs) {
1564
+ return anyArgs;
1565
+ }
1566
+ break;
1567
+ }
1568
+ }
1569
+ if (node.location && isInRange(position, node.location)) {
1570
+ return node;
1571
+ }
1572
+ }
1573
+ function isObjectExpression(expr) {
1574
+ if (isExpressionNode(expr)) {
1575
+ return false;
1576
+ }
1577
+ return typeof expr === "object" && expr !== null && !Array.isArray(expr) && "value" in expr;
1578
+ }
1579
+
1435
1580
  var __defProp$c = Object.defineProperty;
1436
1581
  var __defProps$a = Object.defineProperties;
1437
1582
  var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
@@ -1492,6 +1637,8 @@ class ExpressionEvaluator {
1492
1637
  this.vars = {};
1493
1638
  this.hooks = {
1494
1639
  resolve: new tapableTs.SyncWaterfallHook(),
1640
+ resolveOptions: new tapableTs.SyncWaterfallHook(),
1641
+ beforeEvaluate: new tapableTs.SyncWaterfallHook(),
1495
1642
  onError: new tapableTs.SyncBailHook()
1496
1643
  };
1497
1644
  this.expressionsCache = new Map();
@@ -1510,21 +1657,25 @@ class ExpressionEvaluator {
1510
1657
  reset() {
1511
1658
  this.expressionsCache.clear();
1512
1659
  }
1513
- evaluate(expression, options) {
1514
- const opts = __spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1515
- resolveNode: (node) => this._execAST(node, opts)
1516
- });
1660
+ evaluate(expr, options) {
1661
+ var _a;
1662
+ const resolvedOpts = this.hooks.resolveOptions.call(__spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1663
+ resolveNode: (node) => this._execAST(node, resolvedOpts)
1664
+ }));
1665
+ let expression = (_a = this.hooks.beforeEvaluate.call(expr, resolvedOpts)) != null ? _a : expr;
1666
+ while (isObjectExpression(expression)) {
1667
+ expression = expression.value;
1668
+ }
1517
1669
  if (typeof expression === "number" || typeof expression === "boolean" || expression === void 0 || expression === null) {
1518
1670
  return expression;
1519
1671
  }
1520
1672
  if (isExpressionNode(expression)) {
1521
- return this._execAST(expression, opts);
1673
+ return this._execAST(expression, resolvedOpts);
1522
1674
  }
1523
- if (typeof expression === "object") {
1524
- const values = Array.isArray(expression) ? expression : Object.values(expression);
1525
- return values.reduce((_nothing, exp) => this.evaluate(exp, options), null);
1675
+ if (Array.isArray(expression)) {
1676
+ return expression.reduce((_nothing, exp) => this.evaluate(exp, options), null);
1526
1677
  }
1527
- return this._execString(String(expression), opts);
1678
+ return this._execString(String(expression), resolvedOpts);
1528
1679
  }
1529
1680
  addExpressionFunction(name, handler) {
1530
1681
  this.operators.expressions.set(name, handler);
@@ -1562,7 +1713,7 @@ class ExpressionEvaluator {
1562
1713
  this.expressionsCache.set(matchedExp, expAST);
1563
1714
  return this._execAST(expAST, options);
1564
1715
  } catch (e) {
1565
- if (!this.hooks.onError.call(e)) {
1716
+ if (options.throwErrors || !this.hooks.onError.call(e)) {
1566
1717
  throw e;
1567
1718
  }
1568
1719
  }
@@ -1616,25 +1767,18 @@ class ExpressionEvaluator {
1616
1767
  }
1617
1768
  if (node.type === "CallExpression") {
1618
1769
  const expressionName = node.callTarget.name;
1619
- if (expressionName === "conditional") {
1620
- const condition = resolveNode(node.args[0]);
1621
- if (condition) {
1622
- return resolveNode(node.args[1]);
1623
- }
1624
- if (node.args[2]) {
1625
- return resolveNode(node.args[2]);
1626
- }
1627
- return null;
1628
- }
1629
1770
  const operator = this.operators.expressions.get(expressionName);
1630
1771
  if (!operator) {
1631
1772
  throw new Error(`Unknown expression function: ${expressionName}`);
1632
1773
  }
1774
+ if ("resolveParams" in operator && operator.resolveParams === false) {
1775
+ return operator(expressionContext, ...node.args);
1776
+ }
1633
1777
  const args = node.args.map((n) => resolveNode(n));
1634
1778
  return operator(expressionContext, ...args);
1635
1779
  }
1636
1780
  if (node.type === "ModelRef") {
1637
- return model.get(node.ref);
1781
+ return model.get(node.ref, { context: { model: options.model } });
1638
1782
  }
1639
1783
  if (node.type === "MemberExpression") {
1640
1784
  const obj = resolveNode(node.object);
@@ -1686,80 +1830,6 @@ class ExpressionEvaluator {
1686
1830
  }
1687
1831
  }
1688
1832
 
1689
- function withoutContext(fn) {
1690
- return (_context, ...args) => fn(...args);
1691
- }
1692
- function isInRange(position, location) {
1693
- return position.character >= location.start.character && position.character <= location.end.character;
1694
- }
1695
- function findClosestNodeAtPosition(node, position) {
1696
- var _a, _b, _c, _d, _e;
1697
- switch (node.type) {
1698
- case "Modification":
1699
- case "Assignment":
1700
- case "LogicalExpression":
1701
- case "BinaryExpression": {
1702
- const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1703
- if (check) {
1704
- return check;
1705
- }
1706
- break;
1707
- }
1708
- case "UnaryExpression": {
1709
- const checkArg = findClosestNodeAtPosition(node.argument, position);
1710
- if (checkArg) {
1711
- return checkArg;
1712
- }
1713
- break;
1714
- }
1715
- case "MemberExpression": {
1716
- const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1717
- if (checkObject) {
1718
- return checkObject;
1719
- }
1720
- break;
1721
- }
1722
- case "ConditionalExpression": {
1723
- const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1724
- if (checkObject) {
1725
- return checkObject;
1726
- }
1727
- break;
1728
- }
1729
- case "ArrayExpression":
1730
- case "Compound": {
1731
- const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1732
- const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1733
- if (anyElements) {
1734
- return anyElements;
1735
- }
1736
- break;
1737
- }
1738
- case "Object": {
1739
- const checkObject = node.attributes.reduce((found, next) => {
1740
- var _a2;
1741
- return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1742
- }, void 0);
1743
- if (checkObject) {
1744
- return checkObject;
1745
- }
1746
- break;
1747
- }
1748
- case "CallExpression": {
1749
- const anyArgs = (_e = node.args.find((arg) => {
1750
- return findClosestNodeAtPosition(arg, position);
1751
- })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1752
- if (anyArgs) {
1753
- return anyArgs;
1754
- }
1755
- break;
1756
- }
1757
- }
1758
- if (node.location && isInRange(position, node.location)) {
1759
- return node;
1760
- }
1761
- }
1762
-
1763
1833
  const severities = ["trace", "debug", "info", "warn", "error"];
1764
1834
 
1765
1835
  class ConsoleLogger {
@@ -2087,7 +2157,7 @@ function resolveExpressionsInString(val, { evaluate }) {
2087
2157
  return newVal;
2088
2158
  }
2089
2159
  function resolveDataRefsInString(val, options) {
2090
- const { model } = options;
2160
+ const { model, formatted = true } = options;
2091
2161
  let workingString = resolveExpressionsInString(val, options);
2092
2162
  if (!model || typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2093
2163
  return workingString;
@@ -2099,7 +2169,7 @@ function resolveDataRefsInString(val, options) {
2099
2169
  }
2100
2170
  const { start, end } = expLocation;
2101
2171
  const binding = workingString.substring(start + DOUBLE_OPEN_CURLY.length, end - DOUBLE_OPEN_CURLY.length).trim();
2102
- const evaledVal = model.get(binding, { formatted: true });
2172
+ const evaledVal = model.get(binding, { formatted });
2103
2173
  if (start === 0 && end === workingString.length && typeof evaledVal !== "string") {
2104
2174
  return evaledVal;
2105
2175
  }
@@ -2132,6 +2202,36 @@ function resolveDataRefs(val, options) {
2132
2202
  return traverseObject(val, options);
2133
2203
  }
2134
2204
 
2205
+ function removeBindingAndChildrenFromMap(sourceMap, binding) {
2206
+ const targetMap = new Map(sourceMap);
2207
+ const parentBinding = binding.parent();
2208
+ const property = binding.key();
2209
+ targetMap.forEach((_value, trackedBinding) => {
2210
+ if (binding === trackedBinding || binding.contains(trackedBinding)) {
2211
+ targetMap.delete(trackedBinding);
2212
+ }
2213
+ });
2214
+ if (typeof property === "number") {
2215
+ const bindingsToRewrite = Array.from(sourceMap.keys()).filter((b) => {
2216
+ if (parentBinding.contains(b)) {
2217
+ const [childIndex] = b.relative(parentBinding);
2218
+ return typeof childIndex === "number" && childIndex > property;
2219
+ }
2220
+ return false;
2221
+ }).sort();
2222
+ bindingsToRewrite.forEach((trackedBinding) => {
2223
+ const [childIndex, ...childPath] = trackedBinding.relative(parentBinding);
2224
+ if (typeof childIndex === "number") {
2225
+ const newSegments = [childIndex - 1, ...childPath];
2226
+ const newChildBinding = parentBinding.descendent(newSegments);
2227
+ targetMap.set(newChildBinding, targetMap.get(trackedBinding));
2228
+ targetMap.delete(trackedBinding);
2229
+ }
2230
+ });
2231
+ }
2232
+ return targetMap;
2233
+ }
2234
+
2135
2235
  var __defProp$a = Object.defineProperty;
2136
2236
  var __defProps$8 = Object.defineProperties;
2137
2237
  var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
@@ -2156,12 +2256,15 @@ class ValidationMiddleware {
2156
2256
  this.validator = validator;
2157
2257
  this.shadowModelPaths = new Map();
2158
2258
  this.logger = options == null ? void 0 : options.logger;
2259
+ this.shouldIncludeInvalid = options == null ? void 0 : options.shouldIncludeInvalid;
2159
2260
  }
2160
2261
  set(transaction, options, next) {
2161
2262
  const asModel = toModel(this, __spreadProps$8(__spreadValues$a({}, options), { includeInvalid: true }), next);
2162
2263
  const nextTransaction = [];
2264
+ const includedBindings = new Set();
2163
2265
  transaction.forEach(([binding, value]) => {
2164
2266
  this.shadowModelPaths.set(binding, value);
2267
+ includedBindings.add(binding);
2165
2268
  });
2166
2269
  const invalidBindings = [];
2167
2270
  this.shadowModelPaths.forEach((value, binding) => {
@@ -2176,18 +2279,21 @@ class ValidationMiddleware {
2176
2279
  nextTransaction.push([validation.binding, value]);
2177
2280
  }
2178
2281
  });
2179
- } else {
2282
+ } else if (includedBindings.has(binding)) {
2283
+ invalidBindings.push(binding);
2180
2284
  (_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
2181
2285
  }
2182
2286
  });
2287
+ let validResults = [];
2183
2288
  if (next && nextTransaction.length > 0) {
2184
2289
  nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
2185
2290
  const result = next.set(nextTransaction, options);
2186
2291
  if (invalidBindings.length === 0) {
2187
2292
  return result;
2188
2293
  }
2294
+ validResults = result;
2189
2295
  }
2190
- return invalidBindings.map((binding) => {
2296
+ const invalidResults = invalidBindings.map((binding) => {
2191
2297
  return {
2192
2298
  binding,
2193
2299
  oldValue: asModel.get(binding),
@@ -2195,10 +2301,12 @@ class ValidationMiddleware {
2195
2301
  force: true
2196
2302
  };
2197
2303
  });
2304
+ return [...validResults, ...invalidResults];
2198
2305
  }
2199
2306
  get(binding, options, next) {
2307
+ var _a, _b;
2200
2308
  let val = next == null ? void 0 : next.get(binding, options);
2201
- if ((options == null ? void 0 : options.includeInvalid) === true) {
2309
+ if ((_b = (_a = this.shouldIncludeInvalid) == null ? void 0 : _a.call(this, options)) != null ? _b : (options == null ? void 0 : options.includeInvalid) === true) {
2202
2310
  this.shadowModelPaths.forEach((shadowValue, shadowBinding) => {
2203
2311
  if (shadowBinding === binding) {
2204
2312
  val = shadowValue;
@@ -2211,6 +2319,10 @@ class ValidationMiddleware {
2211
2319
  }
2212
2320
  return val;
2213
2321
  }
2322
+ delete(binding, options, next) {
2323
+ this.shadowModelPaths = removeBindingAndChildrenFromMap(this.shadowModelPaths, binding);
2324
+ return next == null ? void 0 : next.delete(binding, options);
2325
+ }
2214
2326
  }
2215
2327
 
2216
2328
  class ValidatorRegistry {
@@ -2295,6 +2407,9 @@ class Parser {
2295
2407
  }
2296
2408
  return tapped;
2297
2409
  }
2410
+ hasTemplateValues(obj, localKey) {
2411
+ return Object.hasOwnProperty.call(obj, "template") && Array.isArray(obj == null ? void 0 : obj.template) && obj.template.length && obj.template.find((tmpl) => tmpl.output === localKey);
2412
+ }
2298
2413
  parseObject(obj, type = exports.NodeType.Value, options = { templateDepth: 0 }) {
2299
2414
  var _a;
2300
2415
  const nodeType = this.hooks.determineNodeType.call(obj);
@@ -2324,6 +2439,7 @@ class Parser {
2324
2439
  value: currentValue
2325
2440
  };
2326
2441
  const newValue = objEntries.reduce((accumulation, current) => {
2442
+ var _b;
2327
2443
  const _a2 = accumulation, { children: children2 } = _a2, rest = __objRest$1(_a2, ["children"]);
2328
2444
  const [localKey, localValue] = current;
2329
2445
  if (localKey === "asset" && typeof localValue === "object") {
@@ -2341,14 +2457,19 @@ class Parser {
2341
2457
  }
2342
2458
  } else if (this.hooks.determineNodeType.call(localKey) === exports.NodeType.Template && Array.isArray(localValue)) {
2343
2459
  const templateChildren = localValue.map((template) => {
2344
- var _a3, _b;
2460
+ var _a3, _b2;
2345
2461
  const templateAST = this.hooks.onCreateASTNode.call({
2346
2462
  type: exports.NodeType.Template,
2347
2463
  depth: (_a3 = options.templateDepth) != null ? _a3 : 0,
2348
2464
  data: template.data,
2349
2465
  template: template.value,
2350
- dynamic: (_b = template.dynamic) != null ? _b : false
2466
+ dynamic: (_b2 = template.dynamic) != null ? _b2 : false
2351
2467
  }, template);
2468
+ if ((templateAST == null ? void 0 : templateAST.type) === exports.NodeType.MultiNode) {
2469
+ templateAST.values.forEach((v) => {
2470
+ v.parent = templateAST;
2471
+ });
2472
+ }
2352
2473
  if (templateAST) {
2353
2474
  return {
2354
2475
  path: [...path, template.output],
@@ -2362,6 +2483,18 @@ class Parser {
2362
2483
  });
2363
2484
  } else if (localValue && this.hooks.determineNodeType.call(localValue) === exports.NodeType.Switch) {
2364
2485
  const localSwitch = this.hooks.parseNode.call(localValue, exports.NodeType.Value, options, exports.NodeType.Switch);
2486
+ if (localSwitch && localSwitch.type === exports.NodeType.Value && ((_b = localSwitch.children) == null ? void 0 : _b.length) === 1 && localSwitch.value === void 0) {
2487
+ const firstChild = localSwitch.children[0];
2488
+ return __spreadProps$7(__spreadValues$9({}, rest), {
2489
+ children: [
2490
+ ...children2,
2491
+ {
2492
+ path: [...path, localKey, ...firstChild.path],
2493
+ value: firstChild.value
2494
+ }
2495
+ ]
2496
+ });
2497
+ }
2365
2498
  if (localSwitch) {
2366
2499
  return __spreadProps$7(__spreadValues$9({}, rest), {
2367
2500
  children: [
@@ -2378,7 +2511,7 @@ class Parser {
2378
2511
  if (childValues.length > 0) {
2379
2512
  const multiNode = this.hooks.onCreateASTNode.call({
2380
2513
  type: exports.NodeType.MultiNode,
2381
- override: true,
2514
+ override: !this.hasTemplateValues(localObj, localKey),
2382
2515
  values: childValues
2383
2516
  }, localValue);
2384
2517
  if ((multiNode == null ? void 0 : multiNode.type) === exports.NodeType.MultiNode) {
@@ -2401,7 +2534,7 @@ class Parser {
2401
2534
  } else if (localValue && typeof localValue === "object") {
2402
2535
  const determineNodeType = this.hooks.determineNodeType.call(localValue);
2403
2536
  if (determineNodeType === exports.NodeType.Applicability) {
2404
- const parsedNode = this.hooks.parseNode.call(localValue, type, options, determineNodeType);
2537
+ const parsedNode = this.hooks.parseNode.call(localValue, exports.NodeType.Value, options, determineNodeType);
2405
2538
  if (parsedNode) {
2406
2539
  return __spreadProps$7(__spreadValues$9({}, rest), {
2407
2540
  children: [
@@ -2523,6 +2656,11 @@ const withContext = (model) => {
2523
2656
  return model.set(transaction, __spreadValues$7({
2524
2657
  context: { model }
2525
2658
  }, options));
2659
+ },
2660
+ delete: (binding, options) => {
2661
+ return model.delete(binding, __spreadValues$7({
2662
+ context: { model }
2663
+ }, options));
2526
2664
  }
2527
2665
  };
2528
2666
  };
@@ -2552,12 +2690,16 @@ class Resolver {
2552
2690
  this.hooks.beforeUpdate.call(changes);
2553
2691
  const resolveCache = new Map();
2554
2692
  this.idCache.clear();
2693
+ const prevASTMap = new Map(this.ASTMap);
2555
2694
  this.ASTMap.clear();
2556
- const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options));
2695
+ const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options), void 0, prevASTMap);
2557
2696
  this.resolveCache = resolveCache;
2558
2697
  this.hooks.afterUpdate.call(updated.value);
2559
2698
  return updated.value;
2560
2699
  }
2700
+ getResolveCache() {
2701
+ return new Map(this.resolveCache);
2702
+ }
2561
2703
  getNodeID(node) {
2562
2704
  var _a;
2563
2705
  if (!node) {
@@ -2589,7 +2731,19 @@ class Resolver {
2589
2731
  }
2590
2732
  return this.resolveCache.get(node);
2591
2733
  }
2592
- computeTree(node, parent, dataChanges, cacheUpdate, options) {
2734
+ cloneNode(node) {
2735
+ const clonedNode = timm.clone(node);
2736
+ Object.keys(clonedNode).forEach((key) => {
2737
+ if (key === "parent")
2738
+ return;
2739
+ const value = clonedNode[key];
2740
+ if (typeof value === "object" && value !== null) {
2741
+ clonedNode[key] = Array.isArray(value) ? [...value] : __spreadValues$7({}, value);
2742
+ }
2743
+ });
2744
+ return clonedNode;
2745
+ }
2746
+ computeTree(node, parent, dataChanges, cacheUpdate, options, parentNode, prevASTMap) {
2593
2747
  var _a, _b;
2594
2748
  const dependencyModel = new DependencyModel(options.data.model);
2595
2749
  dependencyModel.trackSubset("core");
@@ -2610,34 +2764,40 @@ class Resolver {
2610
2764
  updated: false
2611
2765
  });
2612
2766
  cacheUpdate.set(node, update2);
2613
- const repopulateASTMapFromCache = (resolvedAST3, AST) => {
2767
+ const repopulateASTMapFromCache = (resolvedNode, AST, ASTParent) => {
2614
2768
  var _a2;
2615
- this.ASTMap.set(resolvedAST3, AST);
2616
- if ("children" in resolvedAST3) {
2617
- (_a2 = resolvedAST3.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => {
2618
- const { node: childResolvedAST } = this.getPreviousResult(childAST) || {};
2619
- if (!childResolvedAST)
2620
- return;
2621
- repopulateASTMapFromCache(childResolvedAST, childAST);
2622
- if (childResolvedAST.type === exports.NodeType.MultiNode) {
2623
- childResolvedAST.values.forEach((mChildAST) => {
2624
- const { node: mChildResolvedAST } = this.getPreviousResult(mChildAST) || {};
2625
- if (!mChildResolvedAST)
2626
- return;
2627
- repopulateASTMapFromCache(mChildResolvedAST, mChildAST);
2628
- });
2629
- }
2630
- });
2769
+ const { node: resolvedAST2 } = resolvedNode;
2770
+ this.ASTMap.set(resolvedAST2, AST);
2771
+ const resolvedUpdate = __spreadProps$5(__spreadValues$7({}, resolvedNode), {
2772
+ updated: false
2773
+ });
2774
+ cacheUpdate.set(AST, resolvedUpdate);
2775
+ const handleChildNode = (childNode) => {
2776
+ var _a3;
2777
+ const originalChildNode = (_a3 = prevASTMap.get(childNode)) != null ? _a3 : childNode;
2778
+ const previousChildResult = this.getPreviousResult(originalChildNode);
2779
+ if (!previousChildResult)
2780
+ return;
2781
+ repopulateASTMapFromCache(previousChildResult, originalChildNode, AST);
2782
+ };
2783
+ if ("children" in resolvedAST2) {
2784
+ (_a2 = resolvedAST2.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => handleChildNode(childAST));
2785
+ } else if (resolvedAST2.type === exports.NodeType.MultiNode) {
2786
+ resolvedAST2.values.forEach(handleChildNode);
2631
2787
  }
2788
+ this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate);
2632
2789
  };
2633
- const resolvedAST2 = previousResult.node;
2634
- repopulateASTMapFromCache(resolvedAST2, node);
2635
- this.hooks.afterNodeUpdate.call(node, parent, update2);
2790
+ previousResult.node.parent = parentNode;
2791
+ repopulateASTMapFromCache(previousResult, node, parent);
2636
2792
  return update2;
2637
2793
  }
2638
- const resolvedAST = (_a = this.hooks.beforeResolve.call(node, resolveOptions)) != null ? _a : {
2794
+ const clonedNode = __spreadProps$5(__spreadValues$7({}, this.cloneNode(node)), {
2795
+ parent: parentNode
2796
+ });
2797
+ const resolvedAST = (_a = this.hooks.beforeResolve.call(clonedNode, resolveOptions)) != null ? _a : {
2639
2798
  type: exports.NodeType.Empty
2640
2799
  };
2800
+ resolvedAST.parent = parentNode;
2641
2801
  resolveOptions.node = resolvedAST;
2642
2802
  this.ASTMap.set(resolvedAST, node);
2643
2803
  let resolved = this.hooks.resolve.call(void 0, resolvedAST, resolveOptions);
@@ -2648,22 +2808,15 @@ class Resolver {
2648
2808
  const childDependencies = new Set();
2649
2809
  dependencyModel.trackSubset("children");
2650
2810
  if ("children" in resolvedAST) {
2651
- (_b = resolvedAST.children) == null ? void 0 : _b.forEach((child) => {
2652
- const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions);
2653
- let { updated: childUpdated, value: childValue } = computedChildTree;
2654
- const { node: childNode, dependencies: childTreeDeps } = computedChildTree;
2811
+ const newChildren = (_b = resolvedAST.children) == null ? void 0 : _b.map((child) => {
2812
+ const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2813
+ const {
2814
+ dependencies: childTreeDeps,
2815
+ node: childNode,
2816
+ updated: childUpdated,
2817
+ value: childValue
2818
+ } = computedChildTree;
2655
2819
  childTreeDeps.forEach((binding) => childDependencies.add(binding));
2656
- if (childNode.type === exports.NodeType.MultiNode) {
2657
- childValue = [];
2658
- childNode.values.forEach((mValue) => {
2659
- const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions);
2660
- if (mTree.value !== void 0 && mTree.value !== null) {
2661
- childValue.push(mTree.value);
2662
- }
2663
- mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2664
- childUpdated = childUpdated || mTree.updated;
2665
- });
2666
- }
2667
2820
  if (childValue) {
2668
2821
  if (childNode.type === exports.NodeType.MultiNode && !childNode.override) {
2669
2822
  const arr = timm.addLast(get__default["default"](resolved, child.path, []), childValue);
@@ -2673,7 +2826,22 @@ class Resolver {
2673
2826
  }
2674
2827
  }
2675
2828
  updated = updated || childUpdated;
2829
+ return __spreadProps$5(__spreadValues$7({}, child), { value: childNode });
2830
+ });
2831
+ resolvedAST.children = newChildren;
2832
+ } else if (resolvedAST.type === exports.NodeType.MultiNode) {
2833
+ const childValue = [];
2834
+ const newValues = resolvedAST.values.map((mValue) => {
2835
+ const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2836
+ if (mTree.value !== void 0 && mTree.value !== null) {
2837
+ childValue.push(mTree.value);
2838
+ }
2839
+ mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2840
+ updated = updated || mTree.updated;
2841
+ return mTree.node;
2676
2842
  });
2843
+ resolvedAST.values = newValues;
2844
+ resolved = childValue;
2677
2845
  }
2678
2846
  childDependencies.forEach((bindingDep) => dependencyModel.addChildReadDep(bindingDep));
2679
2847
  dependencyModel.trackSubset("core");
@@ -2742,13 +2910,10 @@ class TemplatePlugin {
2742
2910
  }
2743
2911
  });
2744
2912
  const result = {
2745
- parent: node.parent,
2746
2913
  type: exports.NodeType.MultiNode,
2914
+ override: false,
2747
2915
  values
2748
2916
  };
2749
- result.values.forEach((innerNode) => {
2750
- innerNode.parent = result;
2751
- });
2752
2917
  return result;
2753
2918
  }
2754
2919
  applyParser(parser) {
@@ -2842,19 +3007,20 @@ function resolveAllRefs(node, resolveOptions, propertiesToSkip) {
2842
3007
  });
2843
3008
  return newNode;
2844
3009
  }
2845
- const findBasePath = (node) => {
3010
+ const findBasePath = (node, resolver) => {
2846
3011
  var _a, _b, _c;
2847
3012
  const parentNode = node.parent;
2848
3013
  if (!parentNode) {
2849
3014
  return [];
2850
3015
  }
2851
3016
  if ("children" in parentNode) {
2852
- return (_c = (_b = (_a = parentNode.children) == null ? void 0 : _a.find((child) => child.value === node)) == null ? void 0 : _b.path) != null ? _c : [];
3017
+ const original = resolver.getSourceNode(node);
3018
+ return (_c = (_b = (_a = parentNode.children) == null ? void 0 : _a.find((child) => child.value === original)) == null ? void 0 : _b.path) != null ? _c : [];
2853
3019
  }
2854
3020
  if (parentNode.type !== exports.NodeType.MultiNode) {
2855
3021
  return [];
2856
3022
  }
2857
- return findBasePath(parentNode);
3023
+ return findBasePath(parentNode, resolver);
2858
3024
  };
2859
3025
  class StringResolverPlugin {
2860
3026
  constructor() {
@@ -2878,7 +3044,7 @@ class StringResolverPlugin {
2878
3044
  } else {
2879
3045
  propsToSkip = new Set(["exp"]);
2880
3046
  }
2881
- const nodePath = findBasePath(node);
3047
+ const nodePath = findBasePath(node, resolver);
2882
3048
  if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
2883
3049
  return node.value;
2884
3050
  }
@@ -2898,7 +3064,7 @@ class ApplicabilityPlugin {
2898
3064
  let newNode = node;
2899
3065
  if ((node == null ? void 0 : node.type) === exports.NodeType.Applicability) {
2900
3066
  const isApplicable = options.evaluate(node.expression);
2901
- if (!isApplicable) {
3067
+ if (isApplicable === false) {
2902
3068
  return null;
2903
3069
  }
2904
3070
  newNode = node.value;
@@ -3204,7 +3370,8 @@ class FlowInstance {
3204
3370
  skipTransition: new tapableTs.SyncBailHook(),
3205
3371
  beforeTransition: new tapableTs.SyncWaterfallHook(),
3206
3372
  resolveTransitionNode: new tapableTs.SyncWaterfallHook(),
3207
- transition: new tapableTs.SyncHook()
3373
+ transition: new tapableTs.SyncHook(),
3374
+ afterTransition: new tapableTs.SyncHook()
3208
3375
  };
3209
3376
  this.id = id;
3210
3377
  this.flow = flow;
@@ -3251,7 +3418,7 @@ class FlowInstance {
3251
3418
  } else {
3252
3419
  const skipTransition = this.hooks.skipTransition.call(this.currentState);
3253
3420
  if (skipTransition) {
3254
- (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState} b/c hook told us to`);
3421
+ (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState.name} b/c hook told us to`);
3255
3422
  return;
3256
3423
  }
3257
3424
  }
@@ -3290,6 +3457,7 @@ class FlowInstance {
3290
3457
  this.hooks.onEnd.call(this.flow.onEnd);
3291
3458
  }
3292
3459
  this.hooks.transition.call(prevState, __spreadValues$5({}, newCurrentState));
3460
+ this.hooks.afterTransition.call(this);
3293
3461
  }
3294
3462
  }
3295
3463
 
@@ -3324,6 +3492,7 @@ class FlowController {
3324
3492
  this.start = this.start.bind(this);
3325
3493
  this.run = this.run.bind(this);
3326
3494
  this.transition = this.transition.bind(this);
3495
+ this.addNewFlow = this.addNewFlow.bind(this);
3327
3496
  }
3328
3497
  transition(stateTransition, options) {
3329
3498
  if (this.current === void 0) {
@@ -3332,20 +3501,9 @@ class FlowController {
3332
3501
  this.current.transition(stateTransition, options);
3333
3502
  }
3334
3503
  addNewFlow(flow) {
3335
- return __async$1(this, null, function* () {
3336
- this.navStack.push(flow);
3337
- this.current = flow;
3338
- flow.hooks.transition.tap("flow-controller", (_oldState, newState) => __async$1(this, null, function* () {
3339
- var _a, _b;
3340
- if (newState.value.state_type === "FLOW") {
3341
- (_a = this.log) == null ? void 0 : _a.debug(`Got FLOW state. Loading flow ${newState.value.ref}`);
3342
- const endState = yield this.run(newState.value.ref);
3343
- (_b = this.log) == null ? void 0 : _b.debug(`Flow ended. Using outcome: ${endState.outcome}`);
3344
- flow.transition(endState.outcome);
3345
- }
3346
- }));
3347
- this.hooks.flow.call(flow);
3348
- });
3504
+ this.navStack.push(flow);
3505
+ this.current = flow;
3506
+ this.hooks.flow.call(flow);
3349
3507
  }
3350
3508
  run(startState) {
3351
3509
  return __async$1(this, null, function* () {
@@ -3360,6 +3518,18 @@ class FlowController {
3360
3518
  (_a = this.log) == null ? void 0 : _a.debug(`Starting flow: ${startState}`);
3361
3519
  const flow = new FlowInstance(startState, startFlow, { logger: this.log });
3362
3520
  this.addNewFlow(flow);
3521
+ flow.hooks.afterTransition.tap("flow-controller", (flowInstance) => {
3522
+ var _a2, _b, _c;
3523
+ if (((_a2 = flowInstance.currentState) == null ? void 0 : _a2.value.state_type) === "FLOW") {
3524
+ const subflowId = (_b = flowInstance.currentState) == null ? void 0 : _b.value.ref;
3525
+ (_c = this.log) == null ? void 0 : _c.debug(`Loading subflow ${subflowId}`);
3526
+ this.run(subflowId).then((subFlowEndState) => {
3527
+ var _a3;
3528
+ (_a3 = this.log) == null ? void 0 : _a3.debug(`Subflow ended. Using outcome: ${subFlowEndState.outcome}`);
3529
+ flowInstance.transition(subFlowEndState == null ? void 0 : subFlowEndState.outcome);
3530
+ });
3531
+ }
3532
+ });
3363
3533
  const end = yield flow.start();
3364
3534
  this.navStack.pop();
3365
3535
  if (this.navStack.length > 0) {
@@ -3412,11 +3582,18 @@ class ValidationBindingTrackerViewPlugin {
3412
3582
  getBindings() {
3413
3583
  return this.trackedBindings;
3414
3584
  }
3585
+ trackBinding(binding) {
3586
+ var _a, _b;
3587
+ if (this.trackedBindings.has(binding)) {
3588
+ return;
3589
+ }
3590
+ this.trackedBindings.add(binding);
3591
+ (_b = (_a = this.options.callbacks) == null ? void 0 : _a.onAdd) == null ? void 0 : _b.call(_a, binding);
3592
+ }
3415
3593
  applyResolver(resolver) {
3416
3594
  this.trackedBindings.clear();
3417
3595
  const tracked = new Map();
3418
3596
  const sections = new Map();
3419
- const seenBindings = new Set();
3420
3597
  let lastViewUpdateChangeSet;
3421
3598
  const nodeTree = new Map();
3422
3599
  let lastComputedBindingTree = new Map();
@@ -3463,31 +3640,34 @@ class ValidationBindingTrackerViewPlugin {
3463
3640
  parent = parent.parent;
3464
3641
  }
3465
3642
  }
3466
- if (!seenBindings.has(parsed)) {
3467
- seenBindings.add(parsed);
3468
- (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3469
- }
3643
+ this.trackedBindings.add(parsed);
3644
+ (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3470
3645
  };
3471
3646
  return __spreadProps$3(__spreadValues$4({}, options), {
3472
3647
  validation: __spreadProps$3(__spreadValues$4({}, options.validation), {
3473
3648
  get: (binding, getOptions) => {
3474
- var _a;
3649
+ var _a, _b;
3475
3650
  if (getOptions == null ? void 0 : getOptions.track) {
3476
3651
  track(binding);
3477
3652
  }
3478
- const eow = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding);
3479
- if ((eow == null ? void 0 : eow.displayTarget) === void 0 || (eow == null ? void 0 : eow.displayTarget) === "field") {
3480
- return eow;
3653
+ const eows = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions);
3654
+ const firstFieldEOW = eows == null ? void 0 : eows.find((eow) => eow.displayTarget === "field" || eow.displayTarget === void 0);
3655
+ return firstFieldEOW;
3656
+ },
3657
+ getValidationsForBinding(binding, getOptions) {
3658
+ var _a, _b, _c;
3659
+ if (getOptions == null ? void 0 : getOptions.track) {
3660
+ track(binding);
3481
3661
  }
3482
- return void 0;
3662
+ return (_c = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions)) != null ? _c : [];
3483
3663
  },
3484
3664
  getChildren: (type) => {
3485
3665
  var _a;
3486
3666
  const validations = new Array();
3487
3667
  (_a = lastComputedBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3488
- var _a2;
3489
- const eow = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding);
3490
- if (eow && type === eow.displayTarget) {
3668
+ var _a2, _b;
3669
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3670
+ if (eow && (type === void 0 || type === eow.displayTarget)) {
3491
3671
  validations.push(eow);
3492
3672
  }
3493
3673
  });
@@ -3497,8 +3677,8 @@ class ValidationBindingTrackerViewPlugin {
3497
3677
  var _a;
3498
3678
  const validations = new Array();
3499
3679
  (_a = lastSectionBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3500
- var _a2;
3501
- const eow = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding);
3680
+ var _a2, _b;
3681
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3502
3682
  if (eow && eow.displayTarget === "section") {
3503
3683
  validations.push(eow);
3504
3684
  }
@@ -3517,7 +3697,7 @@ class ValidationBindingTrackerViewPlugin {
3517
3697
  });
3518
3698
  });
3519
3699
  resolver.hooks.afterNodeUpdate.tap(CONTEXT, (node, parent, update) => {
3520
- var _a, _b, _c;
3700
+ var _a, _b;
3521
3701
  if (parent) {
3522
3702
  addToTree(node, parent);
3523
3703
  }
@@ -3532,7 +3712,7 @@ class ValidationBindingTrackerViewPlugin {
3532
3712
  currentBindingTree.set(node, (_b = lastComputedBindingTree.get(node)) != null ? _b : new Set());
3533
3713
  }
3534
3714
  if (node === resolver.root) {
3535
- this.trackedBindings = (_c = currentBindingTree.get(node)) != null ? _c : new Set();
3715
+ this.trackedBindings = new Set(currentBindingTree.get(node));
3536
3716
  lastComputedBindingTree = currentBindingTree;
3537
3717
  lastSectionBindingTree.clear();
3538
3718
  sections.forEach((nodeSet, sectionNode) => {
@@ -3574,11 +3754,15 @@ var __spreadValues$3 = (a, b) => {
3574
3754
  return a;
3575
3755
  };
3576
3756
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
3757
+ const SCHEMA_VALIDATION_PROVIDER_NAME = "schema";
3758
+ const VIEW_VALIDATION_PROVIDER_NAME = "view";
3759
+ const VALIDATION_PROVIDER_NAME_SYMBOL = Symbol.for("validation-provider-name");
3577
3760
  function createStatefulValidationObject(obj) {
3578
3761
  return {
3579
3762
  value: obj,
3580
3763
  type: obj.severity,
3581
- state: "none"
3764
+ state: "none",
3765
+ isBlockingNavigation: false
3582
3766
  };
3583
3767
  }
3584
3768
  class ValidatedBinding {
@@ -3593,20 +3777,45 @@ class ValidatedBinding {
3593
3777
  possibleValidations.forEach((vObj) => {
3594
3778
  const { trigger } = vObj;
3595
3779
  if (this.validationsByState[trigger]) {
3596
- this.validationsByState[trigger].push(createStatefulValidationObject(vObj));
3780
+ const statefulValidationObject = createStatefulValidationObject(vObj);
3781
+ this.validationsByState[trigger].push(statefulValidationObject);
3597
3782
  } else {
3598
3783
  log == null ? void 0 : log.warn(`Unknown validation trigger: ${trigger}`);
3599
3784
  }
3600
3785
  });
3601
3786
  this.weakBindings = weakBindings != null ? weakBindings : new Set();
3602
3787
  }
3788
+ get allValidations() {
3789
+ return Object.values(this.validationsByState).flat();
3790
+ }
3791
+ checkIfBlocking(statefulObj) {
3792
+ if (statefulObj.state === "active") {
3793
+ const { isBlockingNavigation } = statefulObj;
3794
+ return isBlockingNavigation;
3795
+ }
3796
+ return false;
3797
+ }
3798
+ getAll() {
3799
+ return this.applicableValidations.reduce((all, statefulObj) => {
3800
+ if (statefulObj.state === "active" && statefulObj.response) {
3801
+ return [
3802
+ ...all,
3803
+ __spreadProps$2(__spreadValues$3({}, statefulObj.response), {
3804
+ blocking: this.checkIfBlocking(statefulObj)
3805
+ })
3806
+ ];
3807
+ }
3808
+ return all;
3809
+ }, []);
3810
+ }
3603
3811
  get() {
3604
- const firstError = this.applicableValidations.find((statefulObj) => {
3605
- const blocking = this.currentPhase === "navigation" ? statefulObj.value.blocking : true;
3606
- return statefulObj.state === "active" && blocking !== false;
3812
+ const firstInvalid = this.applicableValidations.find((statefulObj) => {
3813
+ return statefulObj.state === "active" && statefulObj.response;
3607
3814
  });
3608
- if ((firstError == null ? void 0 : firstError.state) === "active") {
3609
- return firstError.response;
3815
+ if ((firstInvalid == null ? void 0 : firstInvalid.state) === "active") {
3816
+ return __spreadProps$2(__spreadValues$3({}, firstInvalid.response), {
3817
+ blocking: this.checkIfBlocking(firstInvalid)
3818
+ });
3610
3819
  }
3611
3820
  }
3612
3821
  runApplicableValidations(runner, canDismiss) {
@@ -3615,7 +3824,8 @@ class ValidatedBinding {
3615
3824
  if (obj.state === "dismissed") {
3616
3825
  return obj;
3617
3826
  }
3618
- const blocking = (_a = obj.value.blocking) != null ? _a : obj.value.severity === "warning" && "once" || obj.value.severity === "error" && true;
3827
+ const blocking = (_a = obj.value.blocking) != null ? _a : obj.value.severity === "warning" && "once" || true;
3828
+ const isBlockingNavigation = blocking === true || blocking === "once" && !canDismiss;
3619
3829
  const dismissable = canDismiss && blocking === "once";
3620
3830
  if (this.currentPhase === "navigation" && obj.state === "active" && dismissable) {
3621
3831
  if (obj.value.severity === "warning") {
@@ -3627,17 +3837,13 @@ class ValidatedBinding {
3627
3837
  }
3628
3838
  return obj;
3629
3839
  }
3630
- if (obj.value.severity === "error") {
3631
- const err = obj;
3632
- err.state = "none";
3633
- return obj;
3634
- }
3635
3840
  }
3636
3841
  const response = runner(obj.value);
3637
3842
  const newState = {
3638
3843
  type: obj.type,
3639
3844
  value: obj.value,
3640
3845
  state: response ? "active" : "none",
3846
+ isBlockingNavigation,
3641
3847
  dismissable: obj.value.severity === "warning" && this.currentPhase === "navigation",
3642
3848
  response: response ? __spreadProps$2(__spreadValues$3({}, obj.value), {
3643
3849
  message: (_b = response.message) != null ? _b : "Something is broken",
@@ -3688,20 +3894,34 @@ class ValidationController {
3688
3894
  this.hooks = {
3689
3895
  createValidatorRegistry: new tapableTs.SyncHook(),
3690
3896
  onAddValidation: new tapableTs.SyncWaterfallHook(),
3691
- onRemoveValidation: new tapableTs.SyncWaterfallHook()
3897
+ onRemoveValidation: new tapableTs.SyncWaterfallHook(),
3898
+ resolveValidationProviders: new tapableTs.SyncWaterfallHook(),
3899
+ onTrackBinding: new tapableTs.SyncHook()
3692
3900
  };
3693
3901
  this.validations = new Map();
3694
3902
  this.weakBindingTracker = new Set();
3695
- this.lastActiveBindings = new Set();
3696
3903
  this.schema = schema;
3697
3904
  this.options = options;
3698
- this.providers = [schema];
3905
+ this.reset();
3699
3906
  }
3700
3907
  setOptions(options) {
3701
3908
  this.options = options;
3702
3909
  }
3703
3910
  getDataMiddleware() {
3704
3911
  return [
3912
+ {
3913
+ set: (transaction, options, next) => {
3914
+ var _a;
3915
+ return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
3916
+ },
3917
+ get: (binding, options, next) => {
3918
+ return next == null ? void 0 : next.get(binding, options);
3919
+ },
3920
+ delete: (binding, options, next) => {
3921
+ this.validations = removeBindingAndChildrenFromMap(this.validations, binding);
3922
+ return next == null ? void 0 : next.delete(binding, options);
3923
+ }
3924
+ },
3705
3925
  new ValidationMiddleware((binding) => {
3706
3926
  var _a;
3707
3927
  if (!this.options) {
@@ -3717,13 +3937,17 @@ class ValidationController {
3717
3937
  var _a2;
3718
3938
  if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
3719
3939
  weakValidation == null ? void 0 : weakValidation.weakBindings.forEach((weakBinding) => {
3720
- weakBinding === strongBinding ? newInvalidBindings.add({
3721
- binding: weakBinding,
3722
- isStrong: true
3723
- }) : newInvalidBindings.add({
3724
- binding: weakBinding,
3725
- isStrong: false
3726
- });
3940
+ if (weakBinding === strongBinding) {
3941
+ newInvalidBindings.add({
3942
+ binding: weakBinding,
3943
+ isStrong: true
3944
+ });
3945
+ } else {
3946
+ newInvalidBindings.add({
3947
+ binding: weakBinding,
3948
+ isStrong: false
3949
+ });
3950
+ }
3727
3951
  });
3728
3952
  }
3729
3953
  });
@@ -3736,6 +3960,35 @@ class ValidationController {
3736
3960
  }) })
3737
3961
  ];
3738
3962
  }
3963
+ getValidationProviders() {
3964
+ if (this.providers) {
3965
+ return this.providers;
3966
+ }
3967
+ this.providers = this.hooks.resolveValidationProviders.call([
3968
+ {
3969
+ source: SCHEMA_VALIDATION_PROVIDER_NAME,
3970
+ provider: this.schema
3971
+ },
3972
+ {
3973
+ source: VIEW_VALIDATION_PROVIDER_NAME,
3974
+ provider: {
3975
+ getValidationsForBinding: (binding) => {
3976
+ var _a, _b;
3977
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForBinding) == null ? void 0 : _b.call(_a, binding);
3978
+ },
3979
+ getValidationsForView: () => {
3980
+ var _a, _b;
3981
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForView) == null ? void 0 : _b.call(_a);
3982
+ }
3983
+ }
3984
+ }
3985
+ ]);
3986
+ return this.providers;
3987
+ }
3988
+ reset() {
3989
+ this.validations.clear();
3990
+ this.tracker = void 0;
3991
+ }
3739
3992
  onView(view) {
3740
3993
  this.validations.clear();
3741
3994
  if (!this.options) {
@@ -3744,7 +3997,7 @@ class ValidationController {
3744
3997
  const bindingTrackerPlugin = new ValidationBindingTrackerViewPlugin(__spreadProps$2(__spreadValues$3({}, this.options), {
3745
3998
  callbacks: {
3746
3999
  onAdd: (binding) => {
3747
- if (!this.options) {
4000
+ if (!this.options || this.getValidationForBinding(binding) !== void 0) {
3748
4001
  return;
3749
4002
  }
3750
4003
  const originalValue = this.options.model.get(binding);
@@ -3759,21 +4012,28 @@ class ValidationController {
3759
4012
  this.updateValidationsForBinding(binding, "load", this.options, () => {
3760
4013
  view.update(new Set([binding]));
3761
4014
  });
4015
+ this.hooks.onTrackBinding.call(binding);
3762
4016
  }
3763
4017
  }
3764
4018
  }));
3765
4019
  this.tracker = bindingTrackerPlugin;
3766
- this.providers = [this.schema, view];
4020
+ this.viewValidationProvider = view;
3767
4021
  bindingTrackerPlugin.apply(view);
3768
4022
  }
3769
- updateValidationsForBinding(binding, trigger, context, onDismiss) {
4023
+ updateValidationsForBinding(binding, trigger, validationContext, onDismiss) {
3770
4024
  var _a;
4025
+ const context = validationContext != null ? validationContext : this.options;
4026
+ if (!context) {
4027
+ throw new Error(`Context is required for executing validations`);
4028
+ }
3771
4029
  if (trigger === "load") {
3772
- const possibleValidations = this.providers.reduce((vals, provider) => {
3773
- var _a2, _b;
4030
+ const possibleValidations = this.getValidationProviders().reduce((vals, provider) => {
4031
+ var _a2, _b, _c, _d;
3774
4032
  return [
3775
4033
  ...vals,
3776
- ...(_b = (_a2 = provider.getValidationsForBinding) == null ? void 0 : _a2.call(provider, binding)) != null ? _b : []
4034
+ ...(_d = (_c = (_b = (_a2 = provider.provider).getValidationsForBinding) == null ? void 0 : _b.call(_a2, binding)) == null ? void 0 : _c.map((valObj) => __spreadProps$2(__spreadValues$3({}, valObj), {
4035
+ [VALIDATION_PROVIDER_NAME_SYMBOL]: provider.source
4036
+ }))) != null ? _d : []
3777
4037
  ];
3778
4038
  }, []);
3779
4039
  if (possibleValidations.length === 0) {
@@ -3783,7 +4043,7 @@ class ValidationController {
3783
4043
  }
3784
4044
  const trackedValidations = this.validations.get(binding);
3785
4045
  trackedValidations == null ? void 0 : trackedValidations.update(trigger, true, (validationObj) => {
3786
- const response = this.validationRunner(validationObj, context, binding);
4046
+ const response = this.validationRunner(validationObj, binding, context);
3787
4047
  if (this.weakBindingTracker.size > 0) {
3788
4048
  const t = this.validations.get(binding);
3789
4049
  this.weakBindingTracker.forEach((b) => t.weakBindings.add(b));
@@ -3794,27 +4054,33 @@ class ValidationController {
3794
4054
  this.validations.forEach((validation, vBinding) => {
3795
4055
  if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
3796
4056
  validation.update(trigger, true, (validationObj) => {
3797
- const response = this.validationRunner(validationObj, context, vBinding);
4057
+ const response = this.validationRunner(validationObj, vBinding, context);
3798
4058
  return response ? { message: response.message } : void 0;
3799
4059
  });
3800
4060
  }
3801
4061
  });
3802
4062
  }
3803
4063
  }
3804
- validationRunner(validationObj, context, binding) {
3805
- const handler = this.getValidator(validationObj.type);
4064
+ validationRunner(validationObj, binding, context = this.options) {
4065
+ var _a;
4066
+ if (!context) {
4067
+ throw new Error("No context provided to validation runner");
4068
+ }
4069
+ const handler = (_a = validationObj.handler) != null ? _a : this.getValidator(validationObj.type);
3806
4070
  const weakBindings = new Set();
3807
4071
  const model = {
3808
- get(b, options = { includeInvalid: true }) {
4072
+ get(b, options) {
3809
4073
  weakBindings.add(isBinding(b) ? binding : context.parseBinding(b));
3810
- return context.model.get(b, options);
4074
+ return context.model.get(b, __spreadProps$2(__spreadValues$3({}, options), { includeInvalid: true }));
3811
4075
  },
3812
- set: context.model.set
4076
+ set: context.model.set,
4077
+ delete: context.model.delete
3813
4078
  };
3814
4079
  const result = handler == null ? void 0 : handler(__spreadProps$2(__spreadValues$3({}, context), {
3815
4080
  evaluate: (exp, options = { model }) => context.evaluate(exp, options),
3816
4081
  model,
3817
- validation: validationObj
4082
+ validation: validationObj,
4083
+ schemaType: this.schema.getType(binding)
3818
4084
  }), context.model.get(binding, {
3819
4085
  includeInvalid: true,
3820
4086
  formatted: validationObj.dataTarget === "formatted"
@@ -3838,19 +4104,25 @@ class ValidationController {
3838
4104
  }
3839
4105
  }
3840
4106
  updateValidationsForView(trigger) {
3841
- const { activeBindings } = this;
3842
- const canDismiss = trigger !== "navigation" || this.setCompare(this.lastActiveBindings, activeBindings);
3843
- this.getBindings().forEach((binding) => {
3844
- var _a;
3845
- (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, canDismiss, (obj) => {
3846
- if (!this.options) {
3847
- return;
3848
- }
3849
- return this.validationRunner(obj, this.options, binding);
4107
+ const isNavigationTrigger = trigger === "navigation";
4108
+ const lastActiveBindings = this.activeBindings;
4109
+ const updateValidations = (dismissValidations) => {
4110
+ this.getBindings().forEach((binding) => {
4111
+ var _a;
4112
+ (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, dismissValidations, (obj) => {
4113
+ if (!this.options) {
4114
+ return;
4115
+ }
4116
+ return this.validationRunner(obj, binding, this.options);
4117
+ });
3850
4118
  });
3851
- });
3852
- if (trigger === "navigation") {
3853
- this.lastActiveBindings = activeBindings;
4119
+ };
4120
+ updateValidations(!isNavigationTrigger);
4121
+ if (isNavigationTrigger) {
4122
+ const { activeBindings } = this;
4123
+ if (this.setCompare(lastActiveBindings, activeBindings)) {
4124
+ updateValidations(true);
4125
+ }
3854
4126
  }
3855
4127
  }
3856
4128
  setCompare(set1, set2) {
@@ -3880,19 +4152,30 @@ class ValidationController {
3880
4152
  var _a, _b;
3881
4153
  return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
3882
4154
  }
4155
+ trackBinding(binding) {
4156
+ var _a;
4157
+ (_a = this.tracker) == null ? void 0 : _a.trackBinding(binding);
4158
+ }
3883
4159
  validateView(trigger = "navigation") {
3884
4160
  this.updateValidationsForView(trigger);
3885
4161
  const validations = new Map();
4162
+ let canTransition = true;
3886
4163
  this.getBindings().forEach((b) => {
3887
- var _a, _b;
3888
- const invalid = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.get();
3889
- if (invalid) {
3890
- (_b = this.options) == null ? void 0 : _b.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(invalid)}`);
3891
- validations.set(b, invalid);
3892
- }
4164
+ var _a;
4165
+ const allValidations = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.getAll();
4166
+ allValidations == null ? void 0 : allValidations.forEach((v) => {
4167
+ var _a2;
4168
+ if (trigger === "navigation" && v.blocking) {
4169
+ (_a2 = this.options) == null ? void 0 : _a2.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(v)}`);
4170
+ canTransition = false;
4171
+ }
4172
+ if (!validations.has(b)) {
4173
+ validations.set(b, v);
4174
+ }
4175
+ });
3893
4176
  });
3894
4177
  return {
3895
- canTransition: validations.size === 0,
4178
+ canTransition,
3896
4179
  validations: validations.size ? validations : void 0
3897
4180
  };
3898
4181
  }
@@ -3902,8 +4185,7 @@ class ValidationController {
3902
4185
  forView(parser) {
3903
4186
  return {
3904
4187
  _getValidationForBinding: (binding) => {
3905
- var _a;
3906
- return (_a = this.getValidationForBinding(isBinding(binding) ? binding : parser(binding))) == null ? void 0 : _a.get();
4188
+ return this.getValidationForBinding(isBinding(binding) ? binding : parser(binding));
3907
4189
  },
3908
4190
  getAll: () => {
3909
4191
  const bindings = this.getBindings();
@@ -3923,6 +4205,9 @@ class ValidationController {
3923
4205
  get() {
3924
4206
  throw new Error("Error Access be provided by the view plugin");
3925
4207
  },
4208
+ getValidationsForBinding() {
4209
+ throw new Error("Error rollup should be provided by the view plugin");
4210
+ },
3926
4211
  getChildren() {
3927
4212
  throw new Error("Error rollup should be provided by the view plugin");
3928
4213
  },
@@ -3933,7 +4218,7 @@ class ValidationController {
3933
4218
  throw new Error("Tracking should be provided by the view plugin");
3934
4219
  },
3935
4220
  register: () => {
3936
- throw new Error("Section funcationality hould be provided by the view plugin");
4221
+ throw new Error("Section functionality should be provided by the view plugin");
3937
4222
  },
3938
4223
  type: (binding) => this.schema.getType(isBinding(binding) ? binding : parser(binding))
3939
4224
  };
@@ -4049,10 +4334,11 @@ class AssetTransformCorePlugin {
4049
4334
  };
4050
4335
  };
4051
4336
  resolver.hooks.beforeResolve.tap("asset-transform", (node, options) => {
4337
+ var _a;
4052
4338
  if (node && (node.type === "asset" || node.type === "view")) {
4053
4339
  const transform = this.registry.get(node.value);
4054
4340
  if (transform == null ? void 0 : transform.beforeResolve) {
4055
- const store = getStore(node, this.beforeResolveSymbol);
4341
+ const store = getStore((_a = options.node) != null ? _a : node, this.beforeResolveSymbol);
4056
4342
  return transform.beforeResolve(node, options, store);
4057
4343
  }
4058
4344
  }
@@ -4130,14 +4416,26 @@ class ViewController {
4130
4416
  }
4131
4417
  });
4132
4418
  });
4133
- options.model.hooks.onUpdate.tap("viewController", (updates) => {
4419
+ const update = (updates) => {
4134
4420
  if (this.currentView) {
4135
4421
  if (this.optimizeUpdates) {
4136
- this.queueUpdate(new Set(updates.map((t) => t.binding)));
4422
+ this.queueUpdate(updates);
4137
4423
  } else {
4138
4424
  this.currentView.update();
4139
4425
  }
4140
4426
  }
4427
+ };
4428
+ options.model.hooks.onUpdate.tap("viewController", (updates) => {
4429
+ update(new Set(updates.map((t) => t.binding)));
4430
+ });
4431
+ options.model.hooks.onDelete.tap("viewController", (binding) => {
4432
+ const parentBinding = binding.parent();
4433
+ const property = binding.key();
4434
+ if (typeof property === "number" && parentBinding) {
4435
+ update(new Set([parentBinding]));
4436
+ } else {
4437
+ update(new Set([binding]));
4438
+ }
4141
4439
  });
4142
4440
  }
4143
4441
  queueUpdate(bindings) {
@@ -4238,16 +4536,19 @@ class DataController {
4238
4536
  });
4239
4537
  }
4240
4538
  const setUpdates = normalizedTransaction.reduce((updates, [binding, newVal]) => {
4241
- var _a;
4539
+ var _a, _b;
4242
4540
  const oldVal = this.get(binding, { includeInvalid: true });
4243
- if (!dequal.dequal(oldVal, newVal)) {
4244
- updates.push({
4245
- binding,
4246
- newValue: newVal,
4247
- oldValue: oldVal
4248
- });
4541
+ const update = {
4542
+ binding,
4543
+ newValue: newVal,
4544
+ oldValue: oldVal
4545
+ };
4546
+ if (dequal.dequal(oldVal, newVal)) {
4547
+ (_a = this.logger) == null ? void 0 : _a.debug(`Skipping update for path: ${binding.asString()}. Value was unchanged: ${oldVal}`);
4548
+ } else {
4549
+ updates.push(update);
4550
+ (_b = this.logger) == null ? void 0 : _b.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4249
4551
  }
4250
- (_a = this.logger) == null ? void 0 : _a.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4251
4552
  return updates;
4252
4553
  }, []);
4253
4554
  const result = this.getModel().set(normalizedTransaction, options);
@@ -4265,11 +4566,11 @@ class DataController {
4265
4566
  }
4266
4567
  return result;
4267
4568
  }
4268
- resolve(binding) {
4269
- return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding) : binding;
4569
+ resolve(binding, readOnly) {
4570
+ return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding, { readOnly }) : binding;
4270
4571
  }
4271
4572
  get(binding, options) {
4272
- const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding);
4573
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, true);
4273
4574
  let result = this.getModel().get(resolved, options);
4274
4575
  if (result === void 0 && !(options == null ? void 0 : options.ignoreDefaultValue)) {
4275
4576
  const defaultVal = this.hooks.resolveDefaultValue.call(resolved);
@@ -4279,44 +4580,26 @@ class DataController {
4279
4580
  }
4280
4581
  if (options == null ? void 0 : options.formatted) {
4281
4582
  result = this.hooks.format.call(result, resolved);
4583
+ } else if ((options == null ? void 0 : options.formatted) === false) {
4584
+ result = this.hooks.deformat.call(result, resolved);
4282
4585
  }
4283
4586
  this.hooks.onGet.call(binding, result);
4284
4587
  return result;
4285
4588
  }
4286
- delete(binding) {
4287
- if (binding === void 0 || binding === null) {
4288
- throw new Error(`Invalid arguments: delete expects a data path (string)`);
4589
+ delete(binding, options) {
4590
+ if (typeof binding !== "string" && !Array.isArray(binding) && !(binding instanceof BindingInstance)) {
4591
+ throw new Error("Invalid arguments: delete expects a data path (string)");
4289
4592
  }
4290
- const resolved = this.resolve(binding);
4291
- this.hooks.onDelete.call(resolved);
4292
- this.deleteData(resolved);
4293
- }
4294
- getTrash() {
4295
- return this.trash;
4296
- }
4297
- addToTrash(binding) {
4298
- this.trash.add(binding);
4299
- }
4300
- deleteData(binding) {
4301
- const parentBinding = binding.parent();
4302
- const parentPath = parentBinding.asString();
4303
- const property = binding.key();
4304
- const existedBeforeDelete = Object.prototype.hasOwnProperty.call(this.get(parentBinding), property);
4305
- if (property !== void 0) {
4306
- const parent = parentBinding ? this.get(parentBinding) : void 0;
4307
- if (parentPath && Array.isArray(parent)) {
4308
- if (parent.length > property) {
4309
- this.set([[parentBinding, timm.removeAt(parent, property)]]);
4310
- }
4311
- } else if (parentPath && parent[property]) {
4312
- this.set([[parentBinding, timm.omit(parent, property)]]);
4313
- } else if (!parentPath) {
4314
- this.getModel().reset(timm.omit(this.get(""), property));
4315
- }
4316
- }
4317
- if (existedBeforeDelete && !this.get(binding)) {
4318
- this.addToTrash(binding);
4593
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, false);
4594
+ const parentBinding = resolved.parent();
4595
+ const property = resolved.key();
4596
+ const parentValue = this.get(parentBinding);
4597
+ const existedBeforeDelete = typeof parentValue === "object" && parentValue !== null && Object.prototype.hasOwnProperty.call(parentValue, property);
4598
+ this.getModel().delete(resolved, options);
4599
+ if (existedBeforeDelete && !this.get(resolved)) {
4600
+ this.trash.add(resolved);
4319
4601
  }
4602
+ this.hooks.onDelete.call(resolved);
4320
4603
  }
4321
4604
  serialize() {
4322
4605
  return this.hooks.serialize.call(this.get(""));
@@ -4377,10 +4660,15 @@ class ConstantsController {
4377
4660
  this.tempStore.set(namespace, new LocalModel(data));
4378
4661
  }
4379
4662
  }
4380
- clearTemporaryValues() {
4381
- this.tempStore.forEach((value) => {
4382
- value.reset();
4383
- });
4663
+ clearTemporaryValues(namespace) {
4664
+ var _a;
4665
+ if (namespace) {
4666
+ (_a = this.tempStore.get(namespace)) == null ? void 0 : _a.reset();
4667
+ } else {
4668
+ this.tempStore.forEach((value) => {
4669
+ value.reset();
4670
+ });
4671
+ }
4384
4672
  }
4385
4673
  }
4386
4674
 
@@ -4495,8 +4783,8 @@ var __async = (__this, __arguments, generator) => {
4495
4783
  step((generator = generator.apply(__this, __arguments)).next());
4496
4784
  });
4497
4785
  };
4498
- const PLAYER_VERSION = "0.4.0-next.7";
4499
- const COMMIT = "d187c654ea192038fcd5eb00f88d7244bb2cafff";
4786
+ const PLAYER_VERSION = "0.4.0-next.9";
4787
+ const COMMIT = "e7681a2757fe0ab15d0c0e27c11d0ed33334d63f";
4500
4788
  const _Player = class {
4501
4789
  constructor(config) {
4502
4790
  this.logger = new TapableLogger();
@@ -4616,10 +4904,11 @@ const _Player = class {
4616
4904
  flowResultDeferred.reject(e);
4617
4905
  return true;
4618
4906
  });
4619
- function resolveStrings(val) {
4907
+ function resolveStrings(val, formatted) {
4620
4908
  return resolveDataRefs(val, {
4621
4909
  model: dataController,
4622
- evaluate: expressionEvaluator.evaluate
4910
+ evaluate: expressionEvaluator.evaluate,
4911
+ formatted
4623
4912
  });
4624
4913
  }
4625
4914
  flowController.hooks.flow.tap("player", (flow) => {
@@ -4655,23 +4944,21 @@ const _Player = class {
4655
4944
  newState = timm.setIn(state, ["ref"], resolveStrings(state.ref));
4656
4945
  }
4657
4946
  if ("param" in state) {
4658
- newState = timm.setIn(state, ["param"], resolveStrings(state.param));
4947
+ newState = timm.setIn(state, ["param"], resolveStrings(state.param, false));
4659
4948
  }
4660
4949
  return newState;
4661
4950
  });
4662
4951
  flow.hooks.transition.tap("player", (_oldState, newState) => {
4663
- if (newState.value.state_type === "ACTION") {
4664
- const { exp } = newState.value;
4665
- queueMicrotask__default["default"](() => {
4666
- try {
4667
- flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4668
- } catch (error) {
4669
- const state = this.getState();
4670
- if (error instanceof Error && state.status === "in-progress") {
4671
- state.fail(error);
4672
- }
4673
- }
4674
- });
4952
+ if (newState.value.state_type !== "VIEW") {
4953
+ validationController.reset();
4954
+ }
4955
+ });
4956
+ flow.hooks.afterTransition.tap("player", (flowInstance) => {
4957
+ var _a;
4958
+ const value = (_a = flowInstance.currentState) == null ? void 0 : _a.value;
4959
+ if (value && value.state_type === "ACTION") {
4960
+ const { exp } = value;
4961
+ flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4675
4962
  }
4676
4963
  expressionEvaluator.reset();
4677
4964
  });
@@ -4689,6 +4976,11 @@ const _Player = class {
4689
4976
  parseBinding,
4690
4977
  transition: flowController.transition,
4691
4978
  model: dataController,
4979
+ utils: {
4980
+ findPlugin: (pluginSymbol) => {
4981
+ return this.findPlugin(pluginSymbol);
4982
+ }
4983
+ },
4692
4984
  logger: this.logger,
4693
4985
  flowController,
4694
4986
  schema,
@@ -4702,7 +4994,8 @@ const _Player = class {
4702
4994
  },
4703
4995
  validation: __spreadProps(__spreadValues({}, validationController.forView(parseBinding)), {
4704
4996
  type: (b) => schema.getType(parseBinding(b))
4705
- })
4997
+ }),
4998
+ constants: this.constantsController
4706
4999
  });
4707
5000
  viewController.hooks.view.tap("player", (view) => {
4708
5001
  validationController.onView(view);
@@ -4713,7 +5006,7 @@ const _Player = class {
4713
5006
  start: () => {
4714
5007
  flowController.start().then((endState) => {
4715
5008
  const flowResult = {
4716
- endState: resolveStrings(endState),
5009
+ endState: resolveStrings(endState, false),
4717
5010
  data: dataController.serialize()
4718
5011
  };
4719
5012
  return flowResult;
@@ -4765,8 +5058,7 @@ const _Player = class {
4765
5058
  const endProps = {
4766
5059
  ref,
4767
5060
  status: "completed",
4768
- flow: state.flow,
4769
- dataModel: state.controllers.data.getModel()
5061
+ flow: state.flow
4770
5062
  };
4771
5063
  return maybeUpdateState(__spreadValues(__spreadValues({}, yield state.flowResult), endProps));
4772
5064
  } catch (error) {
@@ -4817,12 +5109,15 @@ exports.Player = Player;
4817
5109
  exports.ProxyLogger = ProxyLogger;
4818
5110
  exports.ROOT_BINDING = ROOT_BINDING;
4819
5111
  exports.Resolver = Resolver;
5112
+ exports.SCHEMA_VALIDATION_PROVIDER_NAME = SCHEMA_VALIDATION_PROVIDER_NAME;
4820
5113
  exports.SIMPLE_BINDING_REGEX = SIMPLE_BINDING_REGEX;
4821
5114
  exports.SchemaController = SchemaController;
4822
5115
  exports.StringResolverPlugin = StringResolverPlugin;
4823
5116
  exports.SwitchPlugin = SwitchPlugin;
4824
5117
  exports.TapableLogger = TapableLogger;
4825
5118
  exports.TemplatePlugin = TemplatePlugin;
5119
+ exports.VALIDATION_PROVIDER_NAME_SYMBOL = VALIDATION_PROVIDER_NAME_SYMBOL;
5120
+ exports.VIEW_VALIDATION_PROVIDER_NAME = VIEW_VALIDATION_PROVIDER_NAME;
4826
5121
  exports.ValidationBindingTrackerViewPlugin = ValidationBindingTrackerViewPlugin;
4827
5122
  exports.ValidationController = ValidationController;
4828
5123
  exports.ValidationMiddleware = ValidationMiddleware;
@@ -4837,9 +5132,11 @@ exports.findNextExp = findNextExp;
4837
5132
  exports.getBindingSegments = getBindingSegments;
4838
5133
  exports.isBinding = isBinding;
4839
5134
  exports.isExpressionNode = isExpressionNode;
5135
+ exports.isObjectExpression = isObjectExpression;
4840
5136
  exports.maybeConvertToNum = maybeConvertToNum;
4841
5137
  exports.parse = parse;
4842
5138
  exports.parseExpression = parseExpression;
5139
+ exports.removeBindingAndChildrenFromMap = removeBindingAndChildrenFromMap;
4843
5140
  exports.resolveDataRefs = resolveDataRefs;
4844
5141
  exports.resolveDataRefsInString = resolveDataRefsInString;
4845
5142
  exports.resolveExpressionsInString = resolveExpressionsInString;