@player-ui/player 0.4.0-next.1 → 0.4.0-next.10

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 (42) hide show
  1. package/dist/index.cjs.js +730 -362
  2. package/dist/index.d.ts +220 -81
  3. package/dist/index.esm.js +726 -364
  4. package/dist/player.dev.js +12311 -0
  5. package/dist/player.prod.js +2 -0
  6. package/package.json +14 -5
  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 -54
  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 +37 -33
  23. package/src/expressions/index.ts +1 -0
  24. package/src/expressions/parser.ts +53 -27
  25. package/src/expressions/types.ts +23 -5
  26. package/src/expressions/utils.ts +19 -0
  27. package/src/player.ts +44 -48
  28. package/src/plugins/default-exp-plugin.ts +57 -0
  29. package/src/plugins/flow-exp-plugin.ts +2 -2
  30. package/src/schema/schema.ts +28 -9
  31. package/src/string-resolver/index.ts +25 -9
  32. package/src/types.ts +1 -4
  33. package/src/validator/binding-map-splice.ts +59 -0
  34. package/src/validator/index.ts +1 -0
  35. package/src/validator/types.ts +11 -3
  36. package/src/validator/validation-middleware.ts +38 -4
  37. package/src/view/parser/index.ts +51 -3
  38. package/src/view/plugins/applicability.ts +1 -1
  39. package/src/view/plugins/string-resolver.ts +8 -4
  40. package/src/view/plugins/template-plugin.ts +1 -6
  41. package/src/view/resolver/index.ts +119 -54
  42. 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;
@@ -909,7 +962,9 @@ function isIdentifierPart(ch) {
909
962
  function isModelRefStart(ch0, ch1) {
910
963
  return ch0 === OCURL_CODE && ch1 === OCURL_CODE;
911
964
  }
912
- function parseExpression(expr) {
965
+ function parseExpression(expr, options) {
966
+ var _a;
967
+ const strictMode = (_a = options == null ? void 0 : options.strict) != null ? _a : true;
913
968
  const charAtFunc = expr.charAt;
914
969
  const charCodeAtFunc = expr.charCodeAt;
915
970
  const { length } = expr;
@@ -1303,6 +1358,9 @@ function parseExpression(expr) {
1303
1358
  }
1304
1359
  args.push(node);
1305
1360
  }
1361
+ if (charIndex !== termination) {
1362
+ throwError(`Expected ${String.fromCharCode(termination)}`, index);
1363
+ }
1306
1364
  return args;
1307
1365
  }
1308
1366
  function gobbleVariable() {
@@ -1373,28 +1431,41 @@ function parseExpression(expr) {
1373
1431
  };
1374
1432
  }
1375
1433
  const nodes = [];
1376
- while (index < length) {
1377
- const chIndex = exprICode(index);
1378
- if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1379
- index++;
1380
- continue;
1434
+ try {
1435
+ while (index < length) {
1436
+ const chIndex = exprICode(index);
1437
+ if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1438
+ index++;
1439
+ continue;
1440
+ }
1441
+ const node = gobbleExpression();
1442
+ if (node) {
1443
+ nodes.push(node);
1444
+ } else if (index < length) {
1445
+ throwError(`Unexpected "${exprI(index)}"`, index);
1446
+ }
1381
1447
  }
1382
- const node = gobbleExpression();
1383
- if (node) {
1384
- nodes.push(node);
1385
- } else if (index < length) {
1386
- throwError(`Unexpected "${exprI(index)}"`, index);
1448
+ if (nodes.length === 1) {
1449
+ return nodes[0];
1387
1450
  }
1451
+ return {
1452
+ __id: ExpNodeOpaqueIdentifier,
1453
+ type: "Compound",
1454
+ body: nodes,
1455
+ location: getLocation(0)
1456
+ };
1457
+ } catch (e) {
1458
+ if (strictMode || !(e instanceof Error)) {
1459
+ throw e;
1460
+ }
1461
+ return {
1462
+ __id: ExpNodeOpaqueIdentifier,
1463
+ type: "Compound",
1464
+ body: nodes,
1465
+ location: getLocation(0),
1466
+ error: e
1467
+ };
1388
1468
  }
1389
- if (nodes.length === 1) {
1390
- return nodes[0];
1391
- }
1392
- return {
1393
- __id: ExpNodeOpaqueIdentifier,
1394
- type: "Compound",
1395
- body: nodes,
1396
- location: getLocation(0)
1397
- };
1398
1469
  }
1399
1470
 
1400
1471
  const setDataVal = (_context, binding, value) => {
@@ -1404,16 +1475,108 @@ const getDataVal = (_context, binding) => {
1404
1475
  return _context.model.get(binding);
1405
1476
  };
1406
1477
  const deleteDataVal = (_context, binding) => {
1407
- return _context.model.set([[binding, void 0]]);
1478
+ return _context.model.delete(binding);
1408
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;
1409
1491
 
1410
1492
  var DEFAULT_EXPRESSION_HANDLERS = /*#__PURE__*/Object.freeze({
1411
1493
  __proto__: null,
1412
1494
  setDataVal: setDataVal,
1413
1495
  getDataVal: getDataVal,
1414
- deleteDataVal: deleteDataVal
1496
+ deleteDataVal: deleteDataVal,
1497
+ conditional: conditional
1415
1498
  });
1416
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
+
1417
1580
  var __defProp$c = Object.defineProperty;
1418
1581
  var __defProps$a = Object.defineProperties;
1419
1582
  var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
@@ -1474,6 +1637,8 @@ class ExpressionEvaluator {
1474
1637
  this.vars = {};
1475
1638
  this.hooks = {
1476
1639
  resolve: new tapableTs.SyncWaterfallHook(),
1640
+ resolveOptions: new tapableTs.SyncWaterfallHook(),
1641
+ beforeEvaluate: new tapableTs.SyncWaterfallHook(),
1477
1642
  onError: new tapableTs.SyncBailHook()
1478
1643
  };
1479
1644
  this.expressionsCache = new Map();
@@ -1492,21 +1657,25 @@ class ExpressionEvaluator {
1492
1657
  reset() {
1493
1658
  this.expressionsCache.clear();
1494
1659
  }
1495
- evaluate(expression, options) {
1496
- const opts = __spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1497
- resolveNode: (node) => this._execAST(node, opts)
1498
- });
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
+ }
1499
1669
  if (typeof expression === "number" || typeof expression === "boolean" || expression === void 0 || expression === null) {
1500
1670
  return expression;
1501
1671
  }
1502
1672
  if (isExpressionNode(expression)) {
1503
- return this._execAST(expression, opts);
1673
+ return this._execAST(expression, resolvedOpts);
1504
1674
  }
1505
- if (typeof expression === "object") {
1506
- const values = Array.isArray(expression) ? expression : Object.values(expression);
1507
- 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);
1508
1677
  }
1509
- return this._execString(String(expression), opts);
1678
+ return this._execString(String(expression), resolvedOpts);
1510
1679
  }
1511
1680
  addExpressionFunction(name, handler) {
1512
1681
  this.operators.expressions.set(name, handler);
@@ -1544,7 +1713,7 @@ class ExpressionEvaluator {
1544
1713
  this.expressionsCache.set(matchedExp, expAST);
1545
1714
  return this._execAST(expAST, options);
1546
1715
  } catch (e) {
1547
- if (!this.hooks.onError.call(e)) {
1716
+ if (options.throwErrors || !this.hooks.onError.call(e)) {
1548
1717
  throw e;
1549
1718
  }
1550
1719
  }
@@ -1598,25 +1767,18 @@ class ExpressionEvaluator {
1598
1767
  }
1599
1768
  if (node.type === "CallExpression") {
1600
1769
  const expressionName = node.callTarget.name;
1601
- if (expressionName === "conditional") {
1602
- const condition = resolveNode(node.args[0]);
1603
- if (condition) {
1604
- return resolveNode(node.args[1]);
1605
- }
1606
- if (node.args[2]) {
1607
- return resolveNode(node.args[2]);
1608
- }
1609
- return null;
1610
- }
1611
1770
  const operator = this.operators.expressions.get(expressionName);
1612
1771
  if (!operator) {
1613
1772
  throw new Error(`Unknown expression function: ${expressionName}`);
1614
1773
  }
1774
+ if ("resolveParams" in operator && operator.resolveParams === false) {
1775
+ return operator(expressionContext, ...node.args);
1776
+ }
1615
1777
  const args = node.args.map((n) => resolveNode(n));
1616
1778
  return operator(expressionContext, ...args);
1617
1779
  }
1618
1780
  if (node.type === "ModelRef") {
1619
- return model.get(node.ref);
1781
+ return model.get(node.ref, { context: { model: options.model } });
1620
1782
  }
1621
1783
  if (node.type === "MemberExpression") {
1622
1784
  const obj = resolveNode(node.object);
@@ -1668,80 +1830,6 @@ class ExpressionEvaluator {
1668
1830
  }
1669
1831
  }
1670
1832
 
1671
- function withoutContext(fn) {
1672
- return (_context, ...args) => fn(...args);
1673
- }
1674
- function isInRange(position, location) {
1675
- return position.character >= location.start.character && position.character <= location.end.character;
1676
- }
1677
- function findClosestNodeAtPosition(node, position) {
1678
- var _a, _b, _c, _d, _e;
1679
- switch (node.type) {
1680
- case "Modification":
1681
- case "Assignment":
1682
- case "LogicalExpression":
1683
- case "BinaryExpression": {
1684
- const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1685
- if (check) {
1686
- return check;
1687
- }
1688
- break;
1689
- }
1690
- case "UnaryExpression": {
1691
- const checkArg = findClosestNodeAtPosition(node.argument, position);
1692
- if (checkArg) {
1693
- return checkArg;
1694
- }
1695
- break;
1696
- }
1697
- case "MemberExpression": {
1698
- const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1699
- if (checkObject) {
1700
- return checkObject;
1701
- }
1702
- break;
1703
- }
1704
- case "ConditionalExpression": {
1705
- const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1706
- if (checkObject) {
1707
- return checkObject;
1708
- }
1709
- break;
1710
- }
1711
- case "ArrayExpression":
1712
- case "Compound": {
1713
- const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1714
- const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1715
- if (anyElements) {
1716
- return anyElements;
1717
- }
1718
- break;
1719
- }
1720
- case "Object": {
1721
- const checkObject = node.attributes.reduce((found, next) => {
1722
- var _a2;
1723
- return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1724
- }, void 0);
1725
- if (checkObject) {
1726
- return checkObject;
1727
- }
1728
- break;
1729
- }
1730
- case "CallExpression": {
1731
- const anyArgs = (_e = node.args.find((arg) => {
1732
- return findClosestNodeAtPosition(arg, position);
1733
- })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1734
- if (anyArgs) {
1735
- return anyArgs;
1736
- }
1737
- break;
1738
- }
1739
- }
1740
- if (node.location && isInRange(position, node.location)) {
1741
- return node;
1742
- }
1743
- }
1744
-
1745
1833
  const severities = ["trace", "debug", "info", "warn", "error"];
1746
1834
 
1747
1835
  class ConsoleLogger {
@@ -1898,6 +1986,9 @@ function parse(schema) {
1898
1986
  if (type.isArray) {
1899
1987
  nestedPath.push("[]");
1900
1988
  }
1989
+ if (type.isRecord) {
1990
+ nestedPath.push("{}");
1991
+ }
1901
1992
  if (type.type && schema[type.type]) {
1902
1993
  parseQueue.push({
1903
1994
  path: nestedPath,
@@ -1946,8 +2037,20 @@ class SchemaController {
1946
2037
  if (cached) {
1947
2038
  return cached;
1948
2039
  }
1949
- const normalized = binding.asArray().map((p) => typeof p === "number" ? "[]" : p).join(".");
1950
- this.bindingSchemaNormalizedCache.set(binding, normalized);
2040
+ let bindingArray = binding.asArray();
2041
+ let normalized = bindingArray.map((p) => typeof p === "number" ? "[]" : p).join(".");
2042
+ if (normalized) {
2043
+ this.bindingSchemaNormalizedCache.set(binding, normalized);
2044
+ bindingArray = normalized.split(".");
2045
+ }
2046
+ bindingArray.forEach((item) => {
2047
+ const recordBinding = bindingArray.map((p) => p === item ? "{}" : p).join(".");
2048
+ if (this.schema.get(recordBinding)) {
2049
+ this.bindingSchemaNormalizedCache.set(binding, recordBinding);
2050
+ bindingArray = recordBinding.split(".");
2051
+ normalized = recordBinding;
2052
+ }
2053
+ });
1951
2054
  return normalized;
1952
2055
  }
1953
2056
  getType(binding) {
@@ -2034,6 +2137,9 @@ function findNextExp(str) {
2034
2137
  };
2035
2138
  }
2036
2139
  function resolveExpressionsInString(val, { evaluate }) {
2140
+ if (!evaluate) {
2141
+ return val;
2142
+ }
2037
2143
  const expMatch = /@\[.*?\]@/;
2038
2144
  let newVal = val;
2039
2145
  let match = newVal.match(expMatch);
@@ -2051,9 +2157,9 @@ function resolveExpressionsInString(val, { evaluate }) {
2051
2157
  return newVal;
2052
2158
  }
2053
2159
  function resolveDataRefsInString(val, options) {
2054
- const { model } = options;
2160
+ const { model, formatted = true } = options;
2055
2161
  let workingString = resolveExpressionsInString(val, options);
2056
- if (typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2162
+ if (!model || typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2057
2163
  return workingString;
2058
2164
  }
2059
2165
  while (workingString.indexOf(DOUBLE_OPEN_CURLY) !== -1) {
@@ -2063,7 +2169,7 @@ function resolveDataRefsInString(val, options) {
2063
2169
  }
2064
2170
  const { start, end } = expLocation;
2065
2171
  const binding = workingString.substring(start + DOUBLE_OPEN_CURLY.length, end - DOUBLE_OPEN_CURLY.length).trim();
2066
- const evaledVal = model.get(binding, { formatted: true });
2172
+ const evaledVal = model.get(binding, { formatted });
2067
2173
  if (start === 0 && end === workingString.length && typeof evaledVal !== "string") {
2068
2174
  return evaledVal;
2069
2175
  }
@@ -2082,9 +2188,9 @@ function traverseObject(val, options) {
2082
2188
  const keys = Object.keys(val);
2083
2189
  let newVal = val;
2084
2190
  if (keys.length > 0) {
2085
- for (const key of keys) {
2191
+ keys.forEach((key) => {
2086
2192
  newVal = timm.setIn(newVal, [key], traverseObject(val[key], options));
2087
- }
2193
+ });
2088
2194
  }
2089
2195
  return newVal;
2090
2196
  }
@@ -2096,6 +2202,36 @@ function resolveDataRefs(val, options) {
2096
2202
  return traverseObject(val, options);
2097
2203
  }
2098
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
+
2099
2235
  var __defProp$a = Object.defineProperty;
2100
2236
  var __defProps$8 = Object.defineProperties;
2101
2237
  var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
@@ -2120,12 +2256,15 @@ class ValidationMiddleware {
2120
2256
  this.validator = validator;
2121
2257
  this.shadowModelPaths = new Map();
2122
2258
  this.logger = options == null ? void 0 : options.logger;
2259
+ this.shouldIncludeInvalid = options == null ? void 0 : options.shouldIncludeInvalid;
2123
2260
  }
2124
2261
  set(transaction, options, next) {
2125
2262
  const asModel = toModel(this, __spreadProps$8(__spreadValues$a({}, options), { includeInvalid: true }), next);
2126
2263
  const nextTransaction = [];
2264
+ const includedBindings = new Set();
2127
2265
  transaction.forEach(([binding, value]) => {
2128
2266
  this.shadowModelPaths.set(binding, value);
2267
+ includedBindings.add(binding);
2129
2268
  });
2130
2269
  const invalidBindings = [];
2131
2270
  this.shadowModelPaths.forEach((value, binding) => {
@@ -2136,22 +2275,25 @@ class ValidationMiddleware {
2136
2275
  } else if (validations instanceof Set) {
2137
2276
  validations.forEach((validation) => {
2138
2277
  invalidBindings.push(validation.binding);
2139
- if (!validation.isStrong) {
2278
+ if (!validation.isStrong && validation.binding.asString() === binding.asString()) {
2140
2279
  nextTransaction.push([validation.binding, value]);
2141
2280
  }
2142
2281
  });
2143
- } else {
2282
+ } else if (includedBindings.has(binding)) {
2283
+ invalidBindings.push(binding);
2144
2284
  (_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
2145
2285
  }
2146
2286
  });
2287
+ let validResults = [];
2147
2288
  if (next && nextTransaction.length > 0) {
2148
2289
  nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
2149
2290
  const result = next.set(nextTransaction, options);
2150
2291
  if (invalidBindings.length === 0) {
2151
2292
  return result;
2152
2293
  }
2294
+ validResults = result;
2153
2295
  }
2154
- return invalidBindings.map((binding) => {
2296
+ const invalidResults = invalidBindings.map((binding) => {
2155
2297
  return {
2156
2298
  binding,
2157
2299
  oldValue: asModel.get(binding),
@@ -2159,10 +2301,12 @@ class ValidationMiddleware {
2159
2301
  force: true
2160
2302
  };
2161
2303
  });
2304
+ return [...validResults, ...invalidResults];
2162
2305
  }
2163
2306
  get(binding, options, next) {
2307
+ var _a, _b;
2164
2308
  let val = next == null ? void 0 : next.get(binding, options);
2165
- 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) {
2166
2310
  this.shadowModelPaths.forEach((shadowValue, shadowBinding) => {
2167
2311
  if (shadowBinding === binding) {
2168
2312
  val = shadowValue;
@@ -2175,6 +2319,10 @@ class ValidationMiddleware {
2175
2319
  }
2176
2320
  return val;
2177
2321
  }
2322
+ delete(binding, options, next) {
2323
+ this.shadowModelPaths = removeBindingAndChildrenFromMap(this.shadowModelPaths, binding);
2324
+ return next == null ? void 0 : next.delete(binding, options);
2325
+ }
2178
2326
  }
2179
2327
 
2180
2328
  class ValidatorRegistry {
@@ -2259,6 +2407,9 @@ class Parser {
2259
2407
  }
2260
2408
  return tapped;
2261
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
+ }
2262
2413
  parseObject(obj, type = exports.NodeType.Value, options = { templateDepth: 0 }) {
2263
2414
  var _a;
2264
2415
  const nodeType = this.hooks.determineNodeType.call(obj);
@@ -2276,12 +2427,19 @@ class Parser {
2276
2427
  if (!localObj) {
2277
2428
  return currentValue;
2278
2429
  }
2279
- const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : Object.entries(localObj);
2430
+ const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : [
2431
+ ...Object.entries(localObj),
2432
+ ...Object.getOwnPropertySymbols(localObj).map((s) => [
2433
+ s,
2434
+ localObj[s]
2435
+ ])
2436
+ ];
2280
2437
  const defaultValue = {
2281
2438
  children: [],
2282
2439
  value: currentValue
2283
2440
  };
2284
2441
  const newValue = objEntries.reduce((accumulation, current) => {
2442
+ var _b;
2285
2443
  const _a2 = accumulation, { children: children2 } = _a2, rest = __objRest$1(_a2, ["children"]);
2286
2444
  const [localKey, localValue] = current;
2287
2445
  if (localKey === "asset" && typeof localValue === "object") {
@@ -2299,14 +2457,19 @@ class Parser {
2299
2457
  }
2300
2458
  } else if (this.hooks.determineNodeType.call(localKey) === exports.NodeType.Template && Array.isArray(localValue)) {
2301
2459
  const templateChildren = localValue.map((template) => {
2302
- var _a3, _b;
2460
+ var _a3, _b2;
2303
2461
  const templateAST = this.hooks.onCreateASTNode.call({
2304
2462
  type: exports.NodeType.Template,
2305
2463
  depth: (_a3 = options.templateDepth) != null ? _a3 : 0,
2306
2464
  data: template.data,
2307
2465
  template: template.value,
2308
- dynamic: (_b = template.dynamic) != null ? _b : false
2466
+ dynamic: (_b2 = template.dynamic) != null ? _b2 : false
2309
2467
  }, template);
2468
+ if ((templateAST == null ? void 0 : templateAST.type) === exports.NodeType.MultiNode) {
2469
+ templateAST.values.forEach((v) => {
2470
+ v.parent = templateAST;
2471
+ });
2472
+ }
2310
2473
  if (templateAST) {
2311
2474
  return {
2312
2475
  path: [...path, template.output],
@@ -2320,6 +2483,18 @@ class Parser {
2320
2483
  });
2321
2484
  } else if (localValue && this.hooks.determineNodeType.call(localValue) === exports.NodeType.Switch) {
2322
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
+ }
2323
2498
  if (localSwitch) {
2324
2499
  return __spreadProps$7(__spreadValues$9({}, rest), {
2325
2500
  children: [
@@ -2336,7 +2511,7 @@ class Parser {
2336
2511
  if (childValues.length > 0) {
2337
2512
  const multiNode = this.hooks.onCreateASTNode.call({
2338
2513
  type: exports.NodeType.MultiNode,
2339
- override: true,
2514
+ override: !this.hasTemplateValues(localObj, localKey),
2340
2515
  values: childValues
2341
2516
  }, localValue);
2342
2517
  if ((multiNode == null ? void 0 : multiNode.type) === exports.NodeType.MultiNode) {
@@ -2359,7 +2534,7 @@ class Parser {
2359
2534
  } else if (localValue && typeof localValue === "object") {
2360
2535
  const determineNodeType = this.hooks.determineNodeType.call(localValue);
2361
2536
  if (determineNodeType === exports.NodeType.Applicability) {
2362
- const parsedNode = this.hooks.parseNode.call(localValue, type, options, determineNodeType);
2537
+ const parsedNode = this.hooks.parseNode.call(localValue, exports.NodeType.Value, options, determineNodeType);
2363
2538
  if (parsedNode) {
2364
2539
  return __spreadProps$7(__spreadValues$9({}, rest), {
2365
2540
  children: [
@@ -2481,6 +2656,11 @@ const withContext = (model) => {
2481
2656
  return model.set(transaction, __spreadValues$7({
2482
2657
  context: { model }
2483
2658
  }, options));
2659
+ },
2660
+ delete: (binding, options) => {
2661
+ return model.delete(binding, __spreadValues$7({
2662
+ context: { model }
2663
+ }, options));
2484
2664
  }
2485
2665
  };
2486
2666
  };
@@ -2510,12 +2690,16 @@ class Resolver {
2510
2690
  this.hooks.beforeUpdate.call(changes);
2511
2691
  const resolveCache = new Map();
2512
2692
  this.idCache.clear();
2693
+ const prevASTMap = new Map(this.ASTMap);
2513
2694
  this.ASTMap.clear();
2514
- 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);
2515
2696
  this.resolveCache = resolveCache;
2516
2697
  this.hooks.afterUpdate.call(updated.value);
2517
2698
  return updated.value;
2518
2699
  }
2700
+ getResolveCache() {
2701
+ return new Map(this.resolveCache);
2702
+ }
2519
2703
  getNodeID(node) {
2520
2704
  var _a;
2521
2705
  if (!node) {
@@ -2547,7 +2731,19 @@ class Resolver {
2547
2731
  }
2548
2732
  return this.resolveCache.get(node);
2549
2733
  }
2550
- 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) {
2551
2747
  var _a, _b;
2552
2748
  const dependencyModel = new DependencyModel(options.data.model);
2553
2749
  dependencyModel.trackSubset("core");
@@ -2568,34 +2764,40 @@ class Resolver {
2568
2764
  updated: false
2569
2765
  });
2570
2766
  cacheUpdate.set(node, update2);
2571
- const repopulateASTMapFromCache = (resolvedAST3, AST) => {
2767
+ const repopulateASTMapFromCache = (resolvedNode, AST, ASTParent) => {
2572
2768
  var _a2;
2573
- this.ASTMap.set(resolvedAST3, AST);
2574
- if ("children" in resolvedAST3) {
2575
- (_a2 = resolvedAST3.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => {
2576
- const { node: childResolvedAST } = this.getPreviousResult(childAST) || {};
2577
- if (!childResolvedAST)
2578
- return;
2579
- repopulateASTMapFromCache(childResolvedAST, childAST);
2580
- if (childResolvedAST.type === exports.NodeType.MultiNode) {
2581
- childResolvedAST.values.forEach((mChildAST) => {
2582
- const { node: mChildResolvedAST } = this.getPreviousResult(mChildAST) || {};
2583
- if (!mChildResolvedAST)
2584
- return;
2585
- repopulateASTMapFromCache(mChildResolvedAST, mChildAST);
2586
- });
2587
- }
2588
- });
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);
2589
2787
  }
2788
+ this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate);
2590
2789
  };
2591
- const resolvedAST2 = previousResult.node;
2592
- repopulateASTMapFromCache(resolvedAST2, node);
2593
- this.hooks.afterNodeUpdate.call(node, parent, update2);
2790
+ previousResult.node.parent = parentNode;
2791
+ repopulateASTMapFromCache(previousResult, node, parent);
2594
2792
  return update2;
2595
2793
  }
2596
- 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 : {
2597
2798
  type: exports.NodeType.Empty
2598
2799
  };
2800
+ resolvedAST.parent = parentNode;
2599
2801
  resolveOptions.node = resolvedAST;
2600
2802
  this.ASTMap.set(resolvedAST, node);
2601
2803
  let resolved = this.hooks.resolve.call(void 0, resolvedAST, resolveOptions);
@@ -2606,22 +2808,15 @@ class Resolver {
2606
2808
  const childDependencies = new Set();
2607
2809
  dependencyModel.trackSubset("children");
2608
2810
  if ("children" in resolvedAST) {
2609
- (_b = resolvedAST.children) == null ? void 0 : _b.forEach((child) => {
2610
- const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions);
2611
- let { updated: childUpdated, value: childValue } = computedChildTree;
2612
- 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;
2613
2819
  childTreeDeps.forEach((binding) => childDependencies.add(binding));
2614
- if (childNode.type === exports.NodeType.MultiNode) {
2615
- childValue = [];
2616
- childNode.values.forEach((mValue) => {
2617
- const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions);
2618
- if (mTree.value !== void 0 && mTree.value !== null) {
2619
- childValue.push(mTree.value);
2620
- }
2621
- mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2622
- childUpdated = childUpdated || mTree.updated;
2623
- });
2624
- }
2625
2820
  if (childValue) {
2626
2821
  if (childNode.type === exports.NodeType.MultiNode && !childNode.override) {
2627
2822
  const arr = timm.addLast(get__default["default"](resolved, child.path, []), childValue);
@@ -2631,7 +2826,22 @@ class Resolver {
2631
2826
  }
2632
2827
  }
2633
2828
  updated = updated || childUpdated;
2829
+ return __spreadProps$5(__spreadValues$7({}, child), { value: childNode });
2634
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;
2842
+ });
2843
+ resolvedAST.values = newValues;
2844
+ resolved = childValue;
2635
2845
  }
2636
2846
  childDependencies.forEach((bindingDep) => dependencyModel.addChildReadDep(bindingDep));
2637
2847
  dependencyModel.trackSubset("core");
@@ -2700,13 +2910,10 @@ class TemplatePlugin {
2700
2910
  }
2701
2911
  });
2702
2912
  const result = {
2703
- parent: node.parent,
2704
2913
  type: exports.NodeType.MultiNode,
2914
+ override: false,
2705
2915
  values
2706
2916
  };
2707
- result.values.forEach((innerNode) => {
2708
- innerNode.parent = result;
2709
- });
2710
2917
  return result;
2711
2918
  }
2712
2919
  applyParser(parser) {
@@ -2800,19 +3007,20 @@ function resolveAllRefs(node, resolveOptions, propertiesToSkip) {
2800
3007
  });
2801
3008
  return newNode;
2802
3009
  }
2803
- const findBasePath = (node) => {
3010
+ const findBasePath = (node, resolver) => {
2804
3011
  var _a, _b, _c;
2805
3012
  const parentNode = node.parent;
2806
3013
  if (!parentNode) {
2807
3014
  return [];
2808
3015
  }
2809
3016
  if ("children" in parentNode) {
2810
- 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 : [];
2811
3019
  }
2812
3020
  if (parentNode.type !== exports.NodeType.MultiNode) {
2813
3021
  return [];
2814
3022
  }
2815
- return findBasePath(parentNode);
3023
+ return findBasePath(parentNode, resolver);
2816
3024
  };
2817
3025
  class StringResolverPlugin {
2818
3026
  constructor() {
@@ -2836,7 +3044,7 @@ class StringResolverPlugin {
2836
3044
  } else {
2837
3045
  propsToSkip = new Set(["exp"]);
2838
3046
  }
2839
- const nodePath = findBasePath(node);
3047
+ const nodePath = findBasePath(node, resolver);
2840
3048
  if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
2841
3049
  return node.value;
2842
3050
  }
@@ -2856,7 +3064,7 @@ class ApplicabilityPlugin {
2856
3064
  let newNode = node;
2857
3065
  if ((node == null ? void 0 : node.type) === exports.NodeType.Applicability) {
2858
3066
  const isApplicable = options.evaluate(node.expression);
2859
- if (!isApplicable) {
3067
+ if (isApplicable === false) {
2860
3068
  return null;
2861
3069
  }
2862
3070
  newNode = node.value;
@@ -3162,7 +3370,8 @@ class FlowInstance {
3162
3370
  skipTransition: new tapableTs.SyncBailHook(),
3163
3371
  beforeTransition: new tapableTs.SyncWaterfallHook(),
3164
3372
  resolveTransitionNode: new tapableTs.SyncWaterfallHook(),
3165
- transition: new tapableTs.SyncHook()
3373
+ transition: new tapableTs.SyncHook(),
3374
+ afterTransition: new tapableTs.SyncHook()
3166
3375
  };
3167
3376
  this.id = id;
3168
3377
  this.flow = flow;
@@ -3209,7 +3418,7 @@ class FlowInstance {
3209
3418
  } else {
3210
3419
  const skipTransition = this.hooks.skipTransition.call(this.currentState);
3211
3420
  if (skipTransition) {
3212
- (_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`);
3213
3422
  return;
3214
3423
  }
3215
3424
  }
@@ -3248,6 +3457,7 @@ class FlowInstance {
3248
3457
  this.hooks.onEnd.call(this.flow.onEnd);
3249
3458
  }
3250
3459
  this.hooks.transition.call(prevState, __spreadValues$5({}, newCurrentState));
3460
+ this.hooks.afterTransition.call(this);
3251
3461
  }
3252
3462
  }
3253
3463
 
@@ -3282,6 +3492,7 @@ class FlowController {
3282
3492
  this.start = this.start.bind(this);
3283
3493
  this.run = this.run.bind(this);
3284
3494
  this.transition = this.transition.bind(this);
3495
+ this.addNewFlow = this.addNewFlow.bind(this);
3285
3496
  }
3286
3497
  transition(stateTransition, options) {
3287
3498
  if (this.current === void 0) {
@@ -3290,20 +3501,9 @@ class FlowController {
3290
3501
  this.current.transition(stateTransition, options);
3291
3502
  }
3292
3503
  addNewFlow(flow) {
3293
- return __async$1(this, null, function* () {
3294
- this.navStack.push(flow);
3295
- this.current = flow;
3296
- flow.hooks.transition.tap("flow-controller", (_oldState, newState) => __async$1(this, null, function* () {
3297
- var _a, _b;
3298
- if (newState.value.state_type === "FLOW") {
3299
- (_a = this.log) == null ? void 0 : _a.debug(`Got FLOW state. Loading flow ${newState.value.ref}`);
3300
- const endState = yield this.run(newState.value.ref);
3301
- (_b = this.log) == null ? void 0 : _b.debug(`Flow ended. Using outcome: ${endState.outcome}`);
3302
- flow.transition(endState.outcome);
3303
- }
3304
- }));
3305
- this.hooks.flow.call(flow);
3306
- });
3504
+ this.navStack.push(flow);
3505
+ this.current = flow;
3506
+ this.hooks.flow.call(flow);
3307
3507
  }
3308
3508
  run(startState) {
3309
3509
  return __async$1(this, null, function* () {
@@ -3318,6 +3518,18 @@ class FlowController {
3318
3518
  (_a = this.log) == null ? void 0 : _a.debug(`Starting flow: ${startState}`);
3319
3519
  const flow = new FlowInstance(startState, startFlow, { logger: this.log });
3320
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
+ });
3321
3533
  const end = yield flow.start();
3322
3534
  this.navStack.pop();
3323
3535
  if (this.navStack.length > 0) {
@@ -3370,11 +3582,18 @@ class ValidationBindingTrackerViewPlugin {
3370
3582
  getBindings() {
3371
3583
  return this.trackedBindings;
3372
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
+ }
3373
3593
  applyResolver(resolver) {
3374
3594
  this.trackedBindings.clear();
3375
3595
  const tracked = new Map();
3376
3596
  const sections = new Map();
3377
- const seenBindings = new Set();
3378
3597
  let lastViewUpdateChangeSet;
3379
3598
  const nodeTree = new Map();
3380
3599
  let lastComputedBindingTree = new Map();
@@ -3421,31 +3640,34 @@ class ValidationBindingTrackerViewPlugin {
3421
3640
  parent = parent.parent;
3422
3641
  }
3423
3642
  }
3424
- if (!seenBindings.has(parsed)) {
3425
- seenBindings.add(parsed);
3426
- (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3427
- }
3643
+ this.trackedBindings.add(parsed);
3644
+ (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3428
3645
  };
3429
3646
  return __spreadProps$3(__spreadValues$4({}, options), {
3430
3647
  validation: __spreadProps$3(__spreadValues$4({}, options.validation), {
3431
3648
  get: (binding, getOptions) => {
3432
- var _a;
3649
+ var _a, _b;
3433
3650
  if (getOptions == null ? void 0 : getOptions.track) {
3434
3651
  track(binding);
3435
3652
  }
3436
- const eow = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding);
3437
- if ((eow == null ? void 0 : eow.displayTarget) === void 0 || (eow == null ? void 0 : eow.displayTarget) === "field") {
3438
- 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);
3439
3661
  }
3440
- return void 0;
3662
+ return (_c = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions)) != null ? _c : [];
3441
3663
  },
3442
3664
  getChildren: (type) => {
3443
3665
  var _a;
3444
3666
  const validations = new Array();
3445
3667
  (_a = lastComputedBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3446
- var _a2;
3447
- const eow = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding);
3448
- 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)) {
3449
3671
  validations.push(eow);
3450
3672
  }
3451
3673
  });
@@ -3455,8 +3677,8 @@ class ValidationBindingTrackerViewPlugin {
3455
3677
  var _a;
3456
3678
  const validations = new Array();
3457
3679
  (_a = lastSectionBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3458
- var _a2;
3459
- 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();
3460
3682
  if (eow && eow.displayTarget === "section") {
3461
3683
  validations.push(eow);
3462
3684
  }
@@ -3475,7 +3697,7 @@ class ValidationBindingTrackerViewPlugin {
3475
3697
  });
3476
3698
  });
3477
3699
  resolver.hooks.afterNodeUpdate.tap(CONTEXT, (node, parent, update) => {
3478
- var _a, _b, _c;
3700
+ var _a, _b;
3479
3701
  if (parent) {
3480
3702
  addToTree(node, parent);
3481
3703
  }
@@ -3490,7 +3712,7 @@ class ValidationBindingTrackerViewPlugin {
3490
3712
  currentBindingTree.set(node, (_b = lastComputedBindingTree.get(node)) != null ? _b : new Set());
3491
3713
  }
3492
3714
  if (node === resolver.root) {
3493
- this.trackedBindings = (_c = currentBindingTree.get(node)) != null ? _c : new Set();
3715
+ this.trackedBindings = new Set(currentBindingTree.get(node));
3494
3716
  lastComputedBindingTree = currentBindingTree;
3495
3717
  lastSectionBindingTree.clear();
3496
3718
  sections.forEach((nodeSet, sectionNode) => {
@@ -3532,11 +3754,15 @@ var __spreadValues$3 = (a, b) => {
3532
3754
  return a;
3533
3755
  };
3534
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");
3535
3760
  function createStatefulValidationObject(obj) {
3536
3761
  return {
3537
3762
  value: obj,
3538
3763
  type: obj.severity,
3539
- state: "none"
3764
+ state: "none",
3765
+ isBlockingNavigation: false
3540
3766
  };
3541
3767
  }
3542
3768
  class ValidatedBinding {
@@ -3551,20 +3777,45 @@ class ValidatedBinding {
3551
3777
  possibleValidations.forEach((vObj) => {
3552
3778
  const { trigger } = vObj;
3553
3779
  if (this.validationsByState[trigger]) {
3554
- this.validationsByState[trigger].push(createStatefulValidationObject(vObj));
3780
+ const statefulValidationObject = createStatefulValidationObject(vObj);
3781
+ this.validationsByState[trigger].push(statefulValidationObject);
3555
3782
  } else {
3556
3783
  log == null ? void 0 : log.warn(`Unknown validation trigger: ${trigger}`);
3557
3784
  }
3558
3785
  });
3559
3786
  this.weakBindings = weakBindings != null ? weakBindings : new Set();
3560
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
+ }
3561
3811
  get() {
3562
- const firstError = this.applicableValidations.find((statefulObj) => {
3563
- const blocking = this.currentPhase === "navigation" ? statefulObj.value.blocking : true;
3564
- return statefulObj.state === "active" && blocking !== false;
3812
+ const firstInvalid = this.applicableValidations.find((statefulObj) => {
3813
+ return statefulObj.state === "active" && statefulObj.response;
3565
3814
  });
3566
- if ((firstError == null ? void 0 : firstError.state) === "active") {
3567
- 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
+ });
3568
3819
  }
3569
3820
  }
3570
3821
  runApplicableValidations(runner, canDismiss) {
@@ -3573,7 +3824,8 @@ class ValidatedBinding {
3573
3824
  if (obj.state === "dismissed") {
3574
3825
  return obj;
3575
3826
  }
3576
- 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;
3577
3829
  const dismissable = canDismiss && blocking === "once";
3578
3830
  if (this.currentPhase === "navigation" && obj.state === "active" && dismissable) {
3579
3831
  if (obj.value.severity === "warning") {
@@ -3585,17 +3837,13 @@ class ValidatedBinding {
3585
3837
  }
3586
3838
  return obj;
3587
3839
  }
3588
- if (obj.value.severity === "error") {
3589
- const err = obj;
3590
- err.state = "none";
3591
- return obj;
3592
- }
3593
3840
  }
3594
3841
  const response = runner(obj.value);
3595
3842
  const newState = {
3596
3843
  type: obj.type,
3597
3844
  value: obj.value,
3598
3845
  state: response ? "active" : "none",
3846
+ isBlockingNavigation,
3599
3847
  dismissable: obj.value.severity === "warning" && this.currentPhase === "navigation",
3600
3848
  response: response ? __spreadProps$2(__spreadValues$3({}, obj.value), {
3601
3849
  message: (_b = response.message) != null ? _b : "Something is broken",
@@ -3646,20 +3894,34 @@ class ValidationController {
3646
3894
  this.hooks = {
3647
3895
  createValidatorRegistry: new tapableTs.SyncHook(),
3648
3896
  onAddValidation: new tapableTs.SyncWaterfallHook(),
3649
- onRemoveValidation: new tapableTs.SyncWaterfallHook()
3897
+ onRemoveValidation: new tapableTs.SyncWaterfallHook(),
3898
+ resolveValidationProviders: new tapableTs.SyncWaterfallHook(),
3899
+ onTrackBinding: new tapableTs.SyncHook()
3650
3900
  };
3651
3901
  this.validations = new Map();
3652
3902
  this.weakBindingTracker = new Set();
3653
- this.lastActiveBindings = new Set();
3654
3903
  this.schema = schema;
3655
3904
  this.options = options;
3656
- this.providers = [schema];
3905
+ this.reset();
3657
3906
  }
3658
3907
  setOptions(options) {
3659
3908
  this.options = options;
3660
3909
  }
3661
3910
  getDataMiddleware() {
3662
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
+ },
3663
3925
  new ValidationMiddleware((binding) => {
3664
3926
  var _a;
3665
3927
  if (!this.options) {
@@ -3675,13 +3937,17 @@ class ValidationController {
3675
3937
  var _a2;
3676
3938
  if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
3677
3939
  weakValidation == null ? void 0 : weakValidation.weakBindings.forEach((weakBinding) => {
3678
- weakBinding === strongBinding ? newInvalidBindings.add({
3679
- binding: weakBinding,
3680
- isStrong: true
3681
- }) : newInvalidBindings.add({
3682
- binding: weakBinding,
3683
- isStrong: false
3684
- });
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
+ }
3685
3951
  });
3686
3952
  }
3687
3953
  });
@@ -3694,6 +3960,35 @@ class ValidationController {
3694
3960
  }) })
3695
3961
  ];
3696
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
+ }
3697
3992
  onView(view) {
3698
3993
  this.validations.clear();
3699
3994
  if (!this.options) {
@@ -3702,7 +3997,7 @@ class ValidationController {
3702
3997
  const bindingTrackerPlugin = new ValidationBindingTrackerViewPlugin(__spreadProps$2(__spreadValues$3({}, this.options), {
3703
3998
  callbacks: {
3704
3999
  onAdd: (binding) => {
3705
- if (!this.options) {
4000
+ if (!this.options || this.getValidationForBinding(binding) !== void 0) {
3706
4001
  return;
3707
4002
  }
3708
4003
  const originalValue = this.options.model.get(binding);
@@ -3717,21 +4012,28 @@ class ValidationController {
3717
4012
  this.updateValidationsForBinding(binding, "load", this.options, () => {
3718
4013
  view.update(new Set([binding]));
3719
4014
  });
4015
+ this.hooks.onTrackBinding.call(binding);
3720
4016
  }
3721
4017
  }
3722
4018
  }));
3723
4019
  this.tracker = bindingTrackerPlugin;
3724
- this.providers = [this.schema, view];
4020
+ this.viewValidationProvider = view;
3725
4021
  bindingTrackerPlugin.apply(view);
3726
4022
  }
3727
- updateValidationsForBinding(binding, trigger, context, onDismiss) {
4023
+ updateValidationsForBinding(binding, trigger, validationContext, onDismiss) {
3728
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
+ }
3729
4029
  if (trigger === "load") {
3730
- const possibleValidations = this.providers.reduce((vals, provider) => {
3731
- var _a2, _b;
4030
+ const possibleValidations = this.getValidationProviders().reduce((vals, provider) => {
4031
+ var _a2, _b, _c, _d;
3732
4032
  return [
3733
4033
  ...vals,
3734
- ...(_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 : []
3735
4037
  ];
3736
4038
  }, []);
3737
4039
  if (possibleValidations.length === 0) {
@@ -3741,7 +4043,7 @@ class ValidationController {
3741
4043
  }
3742
4044
  const trackedValidations = this.validations.get(binding);
3743
4045
  trackedValidations == null ? void 0 : trackedValidations.update(trigger, true, (validationObj) => {
3744
- const response = this.validationRunner(validationObj, context, binding);
4046
+ const response = this.validationRunner(validationObj, binding, context);
3745
4047
  if (this.weakBindingTracker.size > 0) {
3746
4048
  const t = this.validations.get(binding);
3747
4049
  this.weakBindingTracker.forEach((b) => t.weakBindings.add(b));
@@ -3752,27 +4054,33 @@ class ValidationController {
3752
4054
  this.validations.forEach((validation, vBinding) => {
3753
4055
  if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
3754
4056
  validation.update(trigger, true, (validationObj) => {
3755
- const response = this.validationRunner(validationObj, context, vBinding);
4057
+ const response = this.validationRunner(validationObj, vBinding, context);
3756
4058
  return response ? { message: response.message } : void 0;
3757
4059
  });
3758
4060
  }
3759
4061
  });
3760
4062
  }
3761
4063
  }
3762
- validationRunner(validationObj, context, binding) {
3763
- 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);
3764
4070
  const weakBindings = new Set();
3765
4071
  const model = {
3766
- get(b, options = { includeInvalid: true }) {
4072
+ get(b, options) {
3767
4073
  weakBindings.add(isBinding(b) ? binding : context.parseBinding(b));
3768
- return context.model.get(b, options);
4074
+ return context.model.get(b, __spreadProps$2(__spreadValues$3({}, options), { includeInvalid: true }));
3769
4075
  },
3770
- set: context.model.set
4076
+ set: context.model.set,
4077
+ delete: context.model.delete
3771
4078
  };
3772
4079
  const result = handler == null ? void 0 : handler(__spreadProps$2(__spreadValues$3({}, context), {
3773
4080
  evaluate: (exp, options = { model }) => context.evaluate(exp, options),
3774
4081
  model,
3775
- validation: validationObj
4082
+ validation: validationObj,
4083
+ schemaType: this.schema.getType(binding)
3776
4084
  }), context.model.get(binding, {
3777
4085
  includeInvalid: true,
3778
4086
  formatted: validationObj.dataTarget === "formatted"
@@ -3796,19 +4104,25 @@ class ValidationController {
3796
4104
  }
3797
4105
  }
3798
4106
  updateValidationsForView(trigger) {
3799
- const { activeBindings } = this;
3800
- const canDismiss = trigger !== "navigation" || this.setCompare(this.lastActiveBindings, activeBindings);
3801
- this.getBindings().forEach((binding) => {
3802
- var _a;
3803
- (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, canDismiss, (obj) => {
3804
- if (!this.options) {
3805
- return;
3806
- }
3807
- 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
+ });
3808
4118
  });
3809
- });
3810
- if (trigger === "navigation") {
3811
- this.lastActiveBindings = activeBindings;
4119
+ };
4120
+ updateValidations(!isNavigationTrigger);
4121
+ if (isNavigationTrigger) {
4122
+ const { activeBindings } = this;
4123
+ if (this.setCompare(lastActiveBindings, activeBindings)) {
4124
+ updateValidations(true);
4125
+ }
3812
4126
  }
3813
4127
  }
3814
4128
  setCompare(set1, set2) {
@@ -3838,19 +4152,30 @@ class ValidationController {
3838
4152
  var _a, _b;
3839
4153
  return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
3840
4154
  }
4155
+ trackBinding(binding) {
4156
+ var _a;
4157
+ (_a = this.tracker) == null ? void 0 : _a.trackBinding(binding);
4158
+ }
3841
4159
  validateView(trigger = "navigation") {
3842
4160
  this.updateValidationsForView(trigger);
3843
4161
  const validations = new Map();
4162
+ let canTransition = true;
3844
4163
  this.getBindings().forEach((b) => {
3845
- var _a, _b;
3846
- const invalid = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.get();
3847
- if (invalid) {
3848
- (_b = this.options) == null ? void 0 : _b.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(invalid)}`);
3849
- validations.set(b, invalid);
3850
- }
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
+ });
3851
4176
  });
3852
4177
  return {
3853
- canTransition: validations.size === 0,
4178
+ canTransition,
3854
4179
  validations: validations.size ? validations : void 0
3855
4180
  };
3856
4181
  }
@@ -3860,8 +4185,7 @@ class ValidationController {
3860
4185
  forView(parser) {
3861
4186
  return {
3862
4187
  _getValidationForBinding: (binding) => {
3863
- var _a;
3864
- return (_a = this.getValidationForBinding(isBinding(binding) ? binding : parser(binding))) == null ? void 0 : _a.get();
4188
+ return this.getValidationForBinding(isBinding(binding) ? binding : parser(binding));
3865
4189
  },
3866
4190
  getAll: () => {
3867
4191
  const bindings = this.getBindings();
@@ -3881,6 +4205,9 @@ class ValidationController {
3881
4205
  get() {
3882
4206
  throw new Error("Error Access be provided by the view plugin");
3883
4207
  },
4208
+ getValidationsForBinding() {
4209
+ throw new Error("Error rollup should be provided by the view plugin");
4210
+ },
3884
4211
  getChildren() {
3885
4212
  throw new Error("Error rollup should be provided by the view plugin");
3886
4213
  },
@@ -3891,7 +4218,7 @@ class ValidationController {
3891
4218
  throw new Error("Tracking should be provided by the view plugin");
3892
4219
  },
3893
4220
  register: () => {
3894
- 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");
3895
4222
  },
3896
4223
  type: (binding) => this.schema.getType(isBinding(binding) ? binding : parser(binding))
3897
4224
  };
@@ -4007,10 +4334,11 @@ class AssetTransformCorePlugin {
4007
4334
  };
4008
4335
  };
4009
4336
  resolver.hooks.beforeResolve.tap("asset-transform", (node, options) => {
4337
+ var _a;
4010
4338
  if (node && (node.type === "asset" || node.type === "view")) {
4011
4339
  const transform = this.registry.get(node.value);
4012
4340
  if (transform == null ? void 0 : transform.beforeResolve) {
4013
- const store = getStore(node, this.beforeResolveSymbol);
4341
+ const store = getStore((_a = options.node) != null ? _a : node, this.beforeResolveSymbol);
4014
4342
  return transform.beforeResolve(node, options, store);
4015
4343
  }
4016
4344
  }
@@ -4088,14 +4416,26 @@ class ViewController {
4088
4416
  }
4089
4417
  });
4090
4418
  });
4091
- options.model.hooks.onUpdate.tap("viewController", (updates) => {
4419
+ const update = (updates) => {
4092
4420
  if (this.currentView) {
4093
4421
  if (this.optimizeUpdates) {
4094
- this.queueUpdate(new Set(updates.map((t) => t.binding)));
4422
+ this.queueUpdate(updates);
4095
4423
  } else {
4096
4424
  this.currentView.update();
4097
4425
  }
4098
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
+ }
4099
4439
  });
4100
4440
  }
4101
4441
  queueUpdate(bindings) {
@@ -4196,16 +4536,19 @@ class DataController {
4196
4536
  });
4197
4537
  }
4198
4538
  const setUpdates = normalizedTransaction.reduce((updates, [binding, newVal]) => {
4199
- var _a;
4539
+ var _a, _b;
4200
4540
  const oldVal = this.get(binding, { includeInvalid: true });
4201
- if (!dequal.dequal(oldVal, newVal)) {
4202
- updates.push({
4203
- binding,
4204
- newValue: newVal,
4205
- oldValue: oldVal
4206
- });
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}`);
4207
4551
  }
4208
- (_a = this.logger) == null ? void 0 : _a.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4209
4552
  return updates;
4210
4553
  }, []);
4211
4554
  const result = this.getModel().set(normalizedTransaction, options);
@@ -4218,17 +4561,16 @@ class DataController {
4218
4561
  }
4219
4562
  });
4220
4563
  this.hooks.onSet.call(normalizedTransaction);
4221
- this.hooks.onSet.call(normalizedTransaction);
4222
4564
  if (setUpdates.length > 0) {
4223
4565
  this.hooks.onUpdate.call(setUpdates, options);
4224
4566
  }
4225
4567
  return result;
4226
4568
  }
4227
- resolve(binding) {
4228
- 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;
4229
4571
  }
4230
4572
  get(binding, options) {
4231
- const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding);
4573
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, true);
4232
4574
  let result = this.getModel().get(resolved, options);
4233
4575
  if (result === void 0 && !(options == null ? void 0 : options.ignoreDefaultValue)) {
4234
4576
  const defaultVal = this.hooks.resolveDefaultValue.call(resolved);
@@ -4238,44 +4580,26 @@ class DataController {
4238
4580
  }
4239
4581
  if (options == null ? void 0 : options.formatted) {
4240
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);
4241
4585
  }
4242
4586
  this.hooks.onGet.call(binding, result);
4243
4587
  return result;
4244
4588
  }
4245
- delete(binding) {
4246
- if (binding === void 0 || binding === null) {
4247
- 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)");
4248
4592
  }
4249
- const resolved = this.resolve(binding);
4250
- this.hooks.onDelete.call(resolved);
4251
- this.deleteData(resolved);
4252
- }
4253
- getTrash() {
4254
- return this.trash;
4255
- }
4256
- addToTrash(binding) {
4257
- this.trash.add(binding);
4258
- }
4259
- deleteData(binding) {
4260
- const parentBinding = binding.parent();
4261
- const parentPath = parentBinding.asString();
4262
- const property = binding.key();
4263
- const existedBeforeDelete = Object.prototype.hasOwnProperty.call(this.get(parentBinding), property);
4264
- if (property !== void 0) {
4265
- const parent = parentBinding ? this.get(parentBinding) : void 0;
4266
- if (parentPath && Array.isArray(parent)) {
4267
- if (parent.length > property) {
4268
- this.set([[parentBinding, timm.removeAt(parent, property)]]);
4269
- }
4270
- } else if (parentPath && parent[property]) {
4271
- this.set([[parentBinding, timm.omit(parent, property)]]);
4272
- } else if (!parentPath) {
4273
- this.getModel().reset(timm.omit(this.get(""), property));
4274
- }
4275
- }
4276
- if (existedBeforeDelete && !this.get(binding)) {
4277
- 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);
4278
4601
  }
4602
+ this.hooks.onDelete.call(resolved);
4279
4603
  }
4280
4604
  serialize() {
4281
4605
  return this.hooks.serialize.call(this.get(""));
@@ -4336,10 +4660,15 @@ class ConstantsController {
4336
4660
  this.tempStore.set(namespace, new LocalModel(data));
4337
4661
  }
4338
4662
  }
4339
- clearTemporaryValues() {
4340
- this.tempStore.forEach((value) => {
4341
- value.reset();
4342
- });
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
+ }
4343
4672
  }
4344
4673
  }
4345
4674
 
@@ -4377,6 +4706,39 @@ class FlowExpPlugin {
4377
4706
  }
4378
4707
  }
4379
4708
 
4709
+ const createFormatFunction = (schema) => {
4710
+ const handler = (ctx, value, formatName) => {
4711
+ var _a, _b;
4712
+ return (_b = (_a = schema.getFormatterForType({ type: formatName })) == null ? void 0 : _a.format(value)) != null ? _b : value;
4713
+ };
4714
+ return handler;
4715
+ };
4716
+ class DefaultExpPlugin {
4717
+ constructor() {
4718
+ this.name = "flow-exp-plugin";
4719
+ }
4720
+ apply(player) {
4721
+ let formatFunction;
4722
+ player.hooks.schema.tap(this.name, (schemaController) => {
4723
+ formatFunction = createFormatFunction(schemaController);
4724
+ });
4725
+ player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
4726
+ if (formatFunction) {
4727
+ expEvaluator.addExpressionFunction("format", formatFunction);
4728
+ }
4729
+ expEvaluator.addExpressionFunction("log", (ctx, ...args) => {
4730
+ player.logger.info(...args);
4731
+ });
4732
+ expEvaluator.addExpressionFunction("debug", (ctx, ...args) => {
4733
+ player.logger.debug(...args);
4734
+ });
4735
+ expEvaluator.addExpressionFunction("eval", (ctx, ...args) => {
4736
+ return ctx.evaluate(...args);
4737
+ });
4738
+ });
4739
+ }
4740
+ }
4741
+
4380
4742
  const NOT_STARTED_STATE = {
4381
4743
  ref: Symbol("not-started"),
4382
4744
  status: "not-started"
@@ -4421,8 +4783,8 @@ var __async = (__this, __arguments, generator) => {
4421
4783
  step((generator = generator.apply(__this, __arguments)).next());
4422
4784
  });
4423
4785
  };
4424
- const PLAYER_VERSION = "0.4.0-next.1";
4425
- const COMMIT = "f66def4fd8f14f4898927c9ff6061d6094b7b250";
4786
+ const PLAYER_VERSION = "0.4.0-next.10";
4787
+ const COMMIT = "82270dcbee70fc05ba5b5d68e566b431ff5258ec";
4426
4788
  const _Player = class {
4427
4789
  constructor(config) {
4428
4790
  this.logger = new TapableLogger();
@@ -4443,14 +4805,15 @@ const _Player = class {
4443
4805
  resolveFlowContent: new tapableTs.SyncWaterfallHook()
4444
4806
  };
4445
4807
  var _a;
4446
- const initialPlugins = [];
4447
- const flowExpPlugin = new FlowExpPlugin();
4448
- initialPlugins.push(flowExpPlugin);
4449
4808
  if (config == null ? void 0 : config.logger) {
4450
4809
  this.logger.addHandler(config.logger);
4451
4810
  }
4452
4811
  this.config = config || {};
4453
- this.config.plugins = [...this.config.plugins || [], ...initialPlugins];
4812
+ this.config.plugins = [
4813
+ new DefaultExpPlugin(),
4814
+ ...this.config.plugins || [],
4815
+ new FlowExpPlugin()
4816
+ ];
4454
4817
  (_a = this.config.plugins) == null ? void 0 : _a.forEach((plugin) => {
4455
4818
  plugin.apply(this);
4456
4819
  });
@@ -4541,10 +4904,11 @@ const _Player = class {
4541
4904
  flowResultDeferred.reject(e);
4542
4905
  return true;
4543
4906
  });
4544
- function resolveStrings(val) {
4907
+ function resolveStrings(val, formatted) {
4545
4908
  return resolveDataRefs(val, {
4546
4909
  model: dataController,
4547
- evaluate: expressionEvaluator.evaluate
4910
+ evaluate: expressionEvaluator.evaluate,
4911
+ formatted
4548
4912
  });
4549
4913
  }
4550
4914
  flowController.hooks.flow.tap("player", (flow) => {
@@ -4580,23 +4944,21 @@ const _Player = class {
4580
4944
  newState = timm.setIn(state, ["ref"], resolveStrings(state.ref));
4581
4945
  }
4582
4946
  if ("param" in state) {
4583
- newState = timm.setIn(state, ["param"], resolveStrings(state.param));
4947
+ newState = timm.setIn(state, ["param"], resolveStrings(state.param, false));
4584
4948
  }
4585
4949
  return newState;
4586
4950
  });
4587
4951
  flow.hooks.transition.tap("player", (_oldState, newState) => {
4588
- if (newState.value.state_type === "ACTION") {
4589
- const { exp } = newState.value;
4590
- queueMicrotask__default["default"](() => {
4591
- try {
4592
- flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4593
- } catch (error) {
4594
- const state = this.getState();
4595
- if (error instanceof Error && state.status === "in-progress") {
4596
- state.fail(error);
4597
- }
4598
- }
4599
- });
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)));
4600
4962
  }
4601
4963
  expressionEvaluator.reset();
4602
4964
  });
@@ -4614,6 +4976,11 @@ const _Player = class {
4614
4976
  parseBinding,
4615
4977
  transition: flowController.transition,
4616
4978
  model: dataController,
4979
+ utils: {
4980
+ findPlugin: (pluginSymbol) => {
4981
+ return this.findPlugin(pluginSymbol);
4982
+ }
4983
+ },
4617
4984
  logger: this.logger,
4618
4985
  flowController,
4619
4986
  schema,
@@ -4627,23 +4994,19 @@ const _Player = class {
4627
4994
  },
4628
4995
  validation: __spreadProps(__spreadValues({}, validationController.forView(parseBinding)), {
4629
4996
  type: (b) => schema.getType(parseBinding(b))
4630
- })
4997
+ }),
4998
+ constants: this.constantsController
4631
4999
  });
4632
5000
  viewController.hooks.view.tap("player", (view) => {
4633
5001
  validationController.onView(view);
4634
5002
  this.hooks.view.call(view);
4635
5003
  });
4636
5004
  this.hooks.viewController.call(viewController);
4637
- const formatFunction = (ctx, value, formatName) => {
4638
- var _a, _b;
4639
- return (_b = (_a = schema.getFormatterForType({ type: formatName })) == null ? void 0 : _a.format(value)) != null ? _b : value;
4640
- };
4641
- expressionEvaluator.addExpressionFunction("format", formatFunction);
4642
5005
  return {
4643
5006
  start: () => {
4644
5007
  flowController.start().then((endState) => {
4645
5008
  const flowResult = {
4646
- endState: resolveStrings(endState),
5009
+ endState: resolveStrings(endState, false),
4647
5010
  data: dataController.serialize()
4648
5011
  };
4649
5012
  return flowResult;
@@ -4695,8 +5058,7 @@ const _Player = class {
4695
5058
  const endProps = {
4696
5059
  ref,
4697
5060
  status: "completed",
4698
- flow: state.flow,
4699
- dataModel: state.controllers.data.getModel()
5061
+ flow: state.flow
4700
5062
  };
4701
5063
  return maybeUpdateState(__spreadValues(__spreadValues({}, yield state.flowResult), endProps));
4702
5064
  } catch (error) {
@@ -4747,12 +5109,15 @@ exports.Player = Player;
4747
5109
  exports.ProxyLogger = ProxyLogger;
4748
5110
  exports.ROOT_BINDING = ROOT_BINDING;
4749
5111
  exports.Resolver = Resolver;
5112
+ exports.SCHEMA_VALIDATION_PROVIDER_NAME = SCHEMA_VALIDATION_PROVIDER_NAME;
4750
5113
  exports.SIMPLE_BINDING_REGEX = SIMPLE_BINDING_REGEX;
4751
5114
  exports.SchemaController = SchemaController;
4752
5115
  exports.StringResolverPlugin = StringResolverPlugin;
4753
5116
  exports.SwitchPlugin = SwitchPlugin;
4754
5117
  exports.TapableLogger = TapableLogger;
4755
5118
  exports.TemplatePlugin = TemplatePlugin;
5119
+ exports.VALIDATION_PROVIDER_NAME_SYMBOL = VALIDATION_PROVIDER_NAME_SYMBOL;
5120
+ exports.VIEW_VALIDATION_PROVIDER_NAME = VIEW_VALIDATION_PROVIDER_NAME;
4756
5121
  exports.ValidationBindingTrackerViewPlugin = ValidationBindingTrackerViewPlugin;
4757
5122
  exports.ValidationController = ValidationController;
4758
5123
  exports.ValidationMiddleware = ValidationMiddleware;
@@ -4767,8 +5132,11 @@ exports.findNextExp = findNextExp;
4767
5132
  exports.getBindingSegments = getBindingSegments;
4768
5133
  exports.isBinding = isBinding;
4769
5134
  exports.isExpressionNode = isExpressionNode;
5135
+ exports.isObjectExpression = isObjectExpression;
4770
5136
  exports.maybeConvertToNum = maybeConvertToNum;
4771
5137
  exports.parse = parse;
5138
+ exports.parseExpression = parseExpression;
5139
+ exports.removeBindingAndChildrenFromMap = removeBindingAndChildrenFromMap;
4772
5140
  exports.resolveDataRefs = resolveDataRefs;
4773
5141
  exports.resolveDataRefsInString = resolveDataRefsInString;
4774
5142
  exports.resolveExpressionsInString = resolveExpressionsInString;