@player-ui/player 0.4.0 → 0.4.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/index.cjs.js +795 -390
  2. package/dist/index.d.ts +238 -81
  3. package/dist/index.esm.js +787 -388
  4. package/dist/player.dev.js +4768 -5282
  5. package/dist/player.prod.js +1 -1
  6. package/package.json +12 -3
  7. package/src/binding/binding.ts +8 -0
  8. package/src/binding/index.ts +14 -4
  9. package/src/binding/resolver.ts +1 -1
  10. package/src/binding-grammar/custom/index.ts +17 -9
  11. package/src/controllers/constants/index.ts +9 -5
  12. package/src/controllers/{data.ts → data/controller.ts} +60 -61
  13. package/src/controllers/data/index.ts +1 -0
  14. package/src/controllers/data/utils.ts +42 -0
  15. package/src/controllers/flow/controller.ts +16 -12
  16. package/src/controllers/flow/flow.ts +6 -1
  17. package/src/controllers/index.ts +1 -1
  18. package/src/controllers/validation/binding-tracker.ts +42 -19
  19. package/src/controllers/validation/controller.ts +359 -145
  20. package/src/controllers/view/asset-transform.ts +4 -1
  21. package/src/controllers/view/controller.ts +20 -3
  22. package/src/data/dependency-tracker.ts +14 -0
  23. package/src/data/local-model.ts +25 -1
  24. package/src/data/model.ts +55 -8
  25. package/src/data/noop-model.ts +2 -0
  26. package/src/expressions/evaluator-functions.ts +24 -2
  27. package/src/expressions/evaluator.ts +37 -33
  28. package/src/expressions/index.ts +1 -0
  29. package/src/expressions/parser.ts +53 -27
  30. package/src/expressions/types.ts +23 -5
  31. package/src/expressions/utils.ts +19 -0
  32. package/src/player.ts +47 -48
  33. package/src/plugins/default-exp-plugin.ts +57 -0
  34. package/src/plugins/flow-exp-plugin.ts +2 -2
  35. package/src/schema/schema.ts +28 -9
  36. package/src/string-resolver/index.ts +25 -9
  37. package/src/types.ts +6 -3
  38. package/src/validator/binding-map-splice.ts +59 -0
  39. package/src/validator/index.ts +1 -0
  40. package/src/validator/types.ts +11 -3
  41. package/src/validator/validation-middleware.ts +38 -4
  42. package/src/view/parser/index.ts +51 -3
  43. package/src/view/plugins/applicability.ts +1 -1
  44. package/src/view/plugins/string-resolver.ts +8 -4
  45. package/src/view/plugins/template-plugin.ts +1 -6
  46. package/src/view/resolver/index.ts +119 -54
  47. package/src/view/resolver/types.ts +48 -7
package/dist/index.cjs.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var types = require('@player-ui/types');
6
6
  var tapableTs = require('tapable-ts');
7
- var NestedError = require('nested-error-stacks');
7
+ var tsNestedError = require('ts-nested-error');
8
8
  var flatten$1 = require('arr-flatten');
9
9
  var P = require('parsimmon');
10
10
  var ebnf = require('ebnf');
@@ -17,7 +17,6 @@ var partialMatchRegistry = require('@player-ui/partial-match-registry');
17
17
 
18
18
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
19
19
 
20
- var NestedError__default = /*#__PURE__*/_interopDefaultLegacy(NestedError);
21
20
  var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten$1);
22
21
  var P__default = /*#__PURE__*/_interopDefaultLegacy(P);
23
22
  var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
@@ -106,7 +105,8 @@ const isIdentifierChar = (char) => {
106
105
  return false;
107
106
  }
108
107
  const charCode = char.charCodeAt(0);
109
- return charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122 || charCode === 95 || charCode === 45 || charCode === 64;
108
+ const matches = charCode === 32 || charCode === 34 || charCode === 39 || charCode === 40 || charCode === 41 || charCode === 42 || charCode === 46 || charCode === 61 || charCode === 91 || charCode === 93 || charCode === 96 || charCode === 123 || charCode === 125;
109
+ return !matches;
110
110
  };
111
111
  const parse$1 = (path) => {
112
112
  let index = 1;
@@ -392,7 +392,7 @@ function resolveBindingAST(bindingPathNode, options, hooks) {
392
392
  try {
393
393
  return options.convertToPath(options.getValue(nestedResolvedValue.path));
394
394
  } catch (e) {
395
- throw new NestedError__default["default"](`Unable to resolve path segment: ${nestedResolvedValue.path}`, e);
395
+ throw new tsNestedError.NestedError(`Unable to resolve path segment: ${nestedResolvedValue.path}`, e);
396
396
  }
397
397
  }
398
398
  if (node.name === "Expression") {
@@ -400,7 +400,7 @@ function resolveBindingAST(bindingPathNode, options, hooks) {
400
400
  const actualValue = options.evaluate(node.value);
401
401
  return options.convertToPath(actualValue);
402
402
  } catch (e) {
403
- throw new NestedError__default["default"](`Unable to resolve path: ${node.value}`, e);
403
+ throw new tsNestedError.NestedError(`Unable to resolve path: ${node.value}`, e);
404
404
  }
405
405
  }
406
406
  throw new Error(`Unable to resolve value for node: ${node.name}`);
@@ -470,6 +470,8 @@ var __spreadValues$d = (a, b) => {
470
470
  return a;
471
471
  };
472
472
  const SIMPLE_BINDING_REGEX = /^[\w\-@]+(\.[\w\-@]+)*$/;
473
+ const BINDING_BRACKETS_REGEX = /[\s()*=`{}'"[\]]/;
474
+ const LAZY_BINDING_REGEX = /^[^.]+(\..+)*$/;
473
475
  const DEFAULT_OPTIONS = {
474
476
  get: () => {
475
477
  throw new Error("Not Implemented");
@@ -494,7 +496,7 @@ class BindingParser {
494
496
  }
495
497
  normalizePath(path, resolveOptions) {
496
498
  var _a, _b;
497
- if (path.match(SIMPLE_BINDING_REGEX) && this.hooks.skipOptimization.call(path) !== true) {
499
+ if (!BINDING_BRACKETS_REGEX.test(path) && LAZY_BINDING_REGEX.test(path) && this.hooks.skipOptimization.call(path) !== true) {
498
500
  return { path: path.split("."), updates: void 0 };
499
501
  }
500
502
  const ast = (_a = this.parseCache[path]) != null ? _a : parse$1(path);
@@ -505,7 +507,7 @@ class BindingParser {
505
507
  try {
506
508
  return resolveBindingAST(ast.path, resolveOptions, this.hooks);
507
509
  } catch (e) {
508
- throw new NestedError__default["default"](`Cannot resolve binding: ${path}`, e);
510
+ throw new tsNestedError.NestedError(`Cannot resolve binding: ${path}`, e);
509
511
  }
510
512
  }
511
513
  getBindingForNormalizedResult(normalized) {
@@ -555,7 +557,7 @@ class BindingParser {
555
557
  updates = __spreadValues$d(__spreadValues$d({}, updates), normalized.updates);
556
558
  }
557
559
  const updateKeys = Object.keys(updates);
558
- if (updateKeys.length > 0) {
560
+ if (!options.readOnly && updateKeys.length > 0) {
559
561
  const updateTransaction = updateKeys.map((updatedBinding) => [
560
562
  this.parse(updatedBinding),
561
563
  updates[updatedBinding]
@@ -651,6 +653,10 @@ class DependencyMiddleware extends DependencyTracker {
651
653
  this.addReadDep(binding);
652
654
  return next == null ? void 0 : next.get(binding, options);
653
655
  }
656
+ delete(binding, options, next) {
657
+ this.addWriteDep(binding);
658
+ return next == null ? void 0 : next.delete(binding, options);
659
+ }
654
660
  }
655
661
  class DependencyModel extends DependencyTracker {
656
662
  constructor(rootModel) {
@@ -667,6 +673,10 @@ class DependencyModel extends DependencyTracker {
667
673
  this.addReadDep(binding);
668
674
  return this.rootModel.get(binding, options);
669
675
  }
676
+ delete(binding, options) {
677
+ this.addWriteDep(binding);
678
+ return this.rootModel.delete(binding, options);
679
+ }
670
680
  }
671
681
 
672
682
  class NOOPDataModel {
@@ -676,15 +686,18 @@ class NOOPDataModel {
676
686
  set() {
677
687
  return [];
678
688
  }
689
+ delete() {
690
+ }
679
691
  }
680
692
  const NOOP_MODEL = new NOOPDataModel();
681
693
 
682
694
  const ROOT_BINDING = new BindingInstance([]);
683
695
  function withParser(model, parseBinding) {
684
- function maybeParse(binding) {
696
+ function maybeParse(binding, readOnly) {
685
697
  const parsed = isBinding(binding) ? binding : parseBinding(binding, {
686
698
  get: model.get,
687
- set: model.set
699
+ set: model.set,
700
+ readOnly
688
701
  });
689
702
  if (!parsed) {
690
703
  throw new Error("Unable to parse binding");
@@ -693,10 +706,13 @@ function withParser(model, parseBinding) {
693
706
  }
694
707
  return {
695
708
  get(binding, options) {
696
- return model.get(maybeParse(binding), options);
709
+ return model.get(maybeParse(binding, true), options);
697
710
  },
698
711
  set(transaction, options) {
699
- return model.set(transaction.map(([key, val]) => [maybeParse(key), val]), options);
712
+ return model.set(transaction.map(([key, val]) => [maybeParse(key, false), val]), options);
713
+ },
714
+ delete(binding, options) {
715
+ return model.delete(maybeParse(binding, false), options);
700
716
  }
701
717
  };
702
718
  }
@@ -705,8 +721,27 @@ function toModel(middleware, defaultOptions, next) {
705
721
  return middleware;
706
722
  }
707
723
  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)
724
+ get: (binding, options) => {
725
+ const resolvedOptions = options != null ? options : defaultOptions;
726
+ if (middleware.get) {
727
+ return middleware.get(binding, resolvedOptions, next);
728
+ }
729
+ return next == null ? void 0 : next.get(binding, resolvedOptions);
730
+ },
731
+ set: (transaction, options) => {
732
+ const resolvedOptions = options != null ? options : defaultOptions;
733
+ if (middleware.set) {
734
+ return middleware.set(transaction, resolvedOptions, next);
735
+ }
736
+ return next == null ? void 0 : next.set(transaction, resolvedOptions);
737
+ },
738
+ delete: (binding, options) => {
739
+ const resolvedOptions = options != null ? options : defaultOptions;
740
+ if (middleware.delete) {
741
+ return middleware.delete(binding, resolvedOptions, next);
742
+ }
743
+ return next == null ? void 0 : next.delete(binding, resolvedOptions);
744
+ }
710
745
  };
711
746
  }
712
747
  function constructModelForPipeline(pipeline) {
@@ -714,7 +749,7 @@ function constructModelForPipeline(pipeline) {
714
749
  return NOOP_MODEL;
715
750
  }
716
751
  if (pipeline.length === 1) {
717
- return pipeline[0];
752
+ return toModel(pipeline[0]);
718
753
  }
719
754
  function createModelWithOptions(options) {
720
755
  var _a;
@@ -729,6 +764,10 @@ function constructModelForPipeline(pipeline) {
729
764
  set: (transaction, options) => {
730
765
  var _a;
731
766
  return (_a = createModelWithOptions(options)) == null ? void 0 : _a.set(transaction, options);
767
+ },
768
+ delete: (binding, options) => {
769
+ var _a;
770
+ return (_a = createModelWithOptions(options)) == null ? void 0 : _a.delete(binding, options);
732
771
  }
733
772
  };
734
773
  }
@@ -765,6 +804,9 @@ class PipelinedDataModel {
765
804
  get(binding, options) {
766
805
  return this.effectiveDataModel.get(binding, options);
767
806
  }
807
+ delete(binding, options) {
808
+ return this.effectiveDataModel.delete(binding, options);
809
+ }
768
810
  }
769
811
 
770
812
  class LocalModel {
@@ -791,11 +833,24 @@ class LocalModel {
791
833
  });
792
834
  return effectiveOperations;
793
835
  }
836
+ delete(binding) {
837
+ const parentBinding = binding.parent();
838
+ if (parentBinding) {
839
+ const parentValue = this.get(parentBinding);
840
+ if (parentValue !== void 0) {
841
+ if (Array.isArray(parentValue)) {
842
+ this.model = timm.setIn(this.model, parentBinding.asArray(), timm.removeAt(parentValue, binding.key()));
843
+ } else {
844
+ this.model = timm.setIn(this.model, parentBinding.asArray(), timm.omit(parentValue, binding.key()));
845
+ }
846
+ }
847
+ }
848
+ }
794
849
  }
795
850
 
796
851
  const ExpNodeOpaqueIdentifier = Symbol("Expression Node ID");
797
852
  function isExpressionNode(x) {
798
- return typeof x === "object" && x.__id === ExpNodeOpaqueIdentifier;
853
+ return typeof x === "object" && x !== null && !Array.isArray(x) && x.__id === ExpNodeOpaqueIdentifier;
799
854
  }
800
855
 
801
856
  const PERIOD_CODE = 46;
@@ -909,7 +964,9 @@ function isIdentifierPart(ch) {
909
964
  function isModelRefStart(ch0, ch1) {
910
965
  return ch0 === OCURL_CODE && ch1 === OCURL_CODE;
911
966
  }
912
- function parseExpression(expr) {
967
+ function parseExpression(expr, options) {
968
+ var _a;
969
+ const strictMode = (_a = options == null ? void 0 : options.strict) != null ? _a : true;
913
970
  const charAtFunc = expr.charAt;
914
971
  const charCodeAtFunc = expr.charCodeAt;
915
972
  const { length } = expr;
@@ -1303,6 +1360,9 @@ function parseExpression(expr) {
1303
1360
  }
1304
1361
  args.push(node);
1305
1362
  }
1363
+ if (charIndex !== termination) {
1364
+ throwError(`Expected ${String.fromCharCode(termination)}`, index);
1365
+ }
1306
1366
  return args;
1307
1367
  }
1308
1368
  function gobbleVariable() {
@@ -1373,28 +1433,41 @@ function parseExpression(expr) {
1373
1433
  };
1374
1434
  }
1375
1435
  const nodes = [];
1376
- while (index < length) {
1377
- const chIndex = exprICode(index);
1378
- if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1379
- index++;
1380
- continue;
1436
+ try {
1437
+ while (index < length) {
1438
+ const chIndex = exprICode(index);
1439
+ if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1440
+ index++;
1441
+ continue;
1442
+ }
1443
+ const node = gobbleExpression();
1444
+ if (node) {
1445
+ nodes.push(node);
1446
+ } else if (index < length) {
1447
+ throwError(`Unexpected "${exprI(index)}"`, index);
1448
+ }
1381
1449
  }
1382
- const node = gobbleExpression();
1383
- if (node) {
1384
- nodes.push(node);
1385
- } else if (index < length) {
1386
- throwError(`Unexpected "${exprI(index)}"`, index);
1450
+ if (nodes.length === 1) {
1451
+ return nodes[0];
1387
1452
  }
1453
+ return {
1454
+ __id: ExpNodeOpaqueIdentifier,
1455
+ type: "Compound",
1456
+ body: nodes,
1457
+ location: getLocation(0)
1458
+ };
1459
+ } catch (e) {
1460
+ if (strictMode || !(e instanceof Error)) {
1461
+ throw e;
1462
+ }
1463
+ return {
1464
+ __id: ExpNodeOpaqueIdentifier,
1465
+ type: "Compound",
1466
+ body: nodes,
1467
+ location: getLocation(0),
1468
+ error: e
1469
+ };
1388
1470
  }
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
1471
  }
1399
1472
 
1400
1473
  const setDataVal = (_context, binding, value) => {
@@ -1404,16 +1477,108 @@ const getDataVal = (_context, binding) => {
1404
1477
  return _context.model.get(binding);
1405
1478
  };
1406
1479
  const deleteDataVal = (_context, binding) => {
1407
- return _context.model.set([[binding, void 0]]);
1480
+ return _context.model.delete(binding);
1481
+ };
1482
+ const conditional = (ctx, condition, ifTrue, ifFalse) => {
1483
+ const resolution = ctx.evaluate(condition);
1484
+ if (resolution) {
1485
+ return ctx.evaluate(ifTrue);
1486
+ }
1487
+ if (ifFalse) {
1488
+ return ctx.evaluate(ifFalse);
1489
+ }
1490
+ return null;
1408
1491
  };
1492
+ conditional.resolveParams = false;
1409
1493
 
1410
1494
  var DEFAULT_EXPRESSION_HANDLERS = /*#__PURE__*/Object.freeze({
1411
1495
  __proto__: null,
1412
1496
  setDataVal: setDataVal,
1413
1497
  getDataVal: getDataVal,
1414
- deleteDataVal: deleteDataVal
1498
+ deleteDataVal: deleteDataVal,
1499
+ conditional: conditional
1415
1500
  });
1416
1501
 
1502
+ function withoutContext(fn) {
1503
+ return (_context, ...args) => fn(...args);
1504
+ }
1505
+ function isInRange(position, location) {
1506
+ return position.character >= location.start.character && position.character <= location.end.character;
1507
+ }
1508
+ function findClosestNodeAtPosition(node, position) {
1509
+ var _a, _b, _c, _d, _e;
1510
+ switch (node.type) {
1511
+ case "Modification":
1512
+ case "Assignment":
1513
+ case "LogicalExpression":
1514
+ case "BinaryExpression": {
1515
+ const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1516
+ if (check) {
1517
+ return check;
1518
+ }
1519
+ break;
1520
+ }
1521
+ case "UnaryExpression": {
1522
+ const checkArg = findClosestNodeAtPosition(node.argument, position);
1523
+ if (checkArg) {
1524
+ return checkArg;
1525
+ }
1526
+ break;
1527
+ }
1528
+ case "MemberExpression": {
1529
+ const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1530
+ if (checkObject) {
1531
+ return checkObject;
1532
+ }
1533
+ break;
1534
+ }
1535
+ case "ConditionalExpression": {
1536
+ const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1537
+ if (checkObject) {
1538
+ return checkObject;
1539
+ }
1540
+ break;
1541
+ }
1542
+ case "ArrayExpression":
1543
+ case "Compound": {
1544
+ const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1545
+ const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1546
+ if (anyElements) {
1547
+ return anyElements;
1548
+ }
1549
+ break;
1550
+ }
1551
+ case "Object": {
1552
+ const checkObject = node.attributes.reduce((found, next) => {
1553
+ var _a2;
1554
+ return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1555
+ }, void 0);
1556
+ if (checkObject) {
1557
+ return checkObject;
1558
+ }
1559
+ break;
1560
+ }
1561
+ case "CallExpression": {
1562
+ const anyArgs = (_e = node.args.find((arg) => {
1563
+ return findClosestNodeAtPosition(arg, position);
1564
+ })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1565
+ if (anyArgs) {
1566
+ return anyArgs;
1567
+ }
1568
+ break;
1569
+ }
1570
+ }
1571
+ if (node.location && isInRange(position, node.location)) {
1572
+ return node;
1573
+ }
1574
+ }
1575
+ function isObjectExpression(expr) {
1576
+ if (isExpressionNode(expr)) {
1577
+ return false;
1578
+ }
1579
+ return typeof expr === "object" && expr !== null && !Array.isArray(expr) && "value" in expr;
1580
+ }
1581
+
1417
1582
  var __defProp$c = Object.defineProperty;
1418
1583
  var __defProps$a = Object.defineProperties;
1419
1584
  var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
@@ -1474,6 +1639,8 @@ class ExpressionEvaluator {
1474
1639
  this.vars = {};
1475
1640
  this.hooks = {
1476
1641
  resolve: new tapableTs.SyncWaterfallHook(),
1642
+ resolveOptions: new tapableTs.SyncWaterfallHook(),
1643
+ beforeEvaluate: new tapableTs.SyncWaterfallHook(),
1477
1644
  onError: new tapableTs.SyncBailHook()
1478
1645
  };
1479
1646
  this.expressionsCache = new Map();
@@ -1492,21 +1659,25 @@ class ExpressionEvaluator {
1492
1659
  reset() {
1493
1660
  this.expressionsCache.clear();
1494
1661
  }
1495
- evaluate(expression, options) {
1496
- const opts = __spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1497
- resolveNode: (node) => this._execAST(node, opts)
1498
- });
1662
+ evaluate(expr, options) {
1663
+ var _a;
1664
+ const resolvedOpts = this.hooks.resolveOptions.call(__spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1665
+ resolveNode: (node) => this._execAST(node, resolvedOpts)
1666
+ }));
1667
+ let expression = (_a = this.hooks.beforeEvaluate.call(expr, resolvedOpts)) != null ? _a : expr;
1668
+ while (isObjectExpression(expression)) {
1669
+ expression = expression.value;
1670
+ }
1499
1671
  if (typeof expression === "number" || typeof expression === "boolean" || expression === void 0 || expression === null) {
1500
1672
  return expression;
1501
1673
  }
1502
1674
  if (isExpressionNode(expression)) {
1503
- return this._execAST(expression, opts);
1675
+ return this._execAST(expression, resolvedOpts);
1504
1676
  }
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);
1677
+ if (Array.isArray(expression)) {
1678
+ return expression.reduce((_nothing, exp) => this.evaluate(exp, options), null);
1508
1679
  }
1509
- return this._execString(String(expression), opts);
1680
+ return this._execString(String(expression), resolvedOpts);
1510
1681
  }
1511
1682
  addExpressionFunction(name, handler) {
1512
1683
  this.operators.expressions.set(name, handler);
@@ -1544,7 +1715,7 @@ class ExpressionEvaluator {
1544
1715
  this.expressionsCache.set(matchedExp, expAST);
1545
1716
  return this._execAST(expAST, options);
1546
1717
  } catch (e) {
1547
- if (!this.hooks.onError.call(e)) {
1718
+ if (options.throwErrors || !this.hooks.onError.call(e)) {
1548
1719
  throw e;
1549
1720
  }
1550
1721
  }
@@ -1598,25 +1769,18 @@ class ExpressionEvaluator {
1598
1769
  }
1599
1770
  if (node.type === "CallExpression") {
1600
1771
  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
1772
  const operator = this.operators.expressions.get(expressionName);
1612
1773
  if (!operator) {
1613
1774
  throw new Error(`Unknown expression function: ${expressionName}`);
1614
1775
  }
1776
+ if ("resolveParams" in operator && operator.resolveParams === false) {
1777
+ return operator(expressionContext, ...node.args);
1778
+ }
1615
1779
  const args = node.args.map((n) => resolveNode(n));
1616
1780
  return operator(expressionContext, ...args);
1617
1781
  }
1618
1782
  if (node.type === "ModelRef") {
1619
- return model.get(node.ref);
1783
+ return model.get(node.ref, { context: { model: options.model } });
1620
1784
  }
1621
1785
  if (node.type === "MemberExpression") {
1622
1786
  const obj = resolveNode(node.object);
@@ -1668,80 +1832,6 @@ class ExpressionEvaluator {
1668
1832
  }
1669
1833
  }
1670
1834
 
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
1835
  const severities = ["trace", "debug", "info", "warn", "error"];
1746
1836
 
1747
1837
  class ConsoleLogger {
@@ -1898,6 +1988,9 @@ function parse(schema) {
1898
1988
  if (type.isArray) {
1899
1989
  nestedPath.push("[]");
1900
1990
  }
1991
+ if (type.isRecord) {
1992
+ nestedPath.push("{}");
1993
+ }
1901
1994
  if (type.type && schema[type.type]) {
1902
1995
  parseQueue.push({
1903
1996
  path: nestedPath,
@@ -1946,8 +2039,20 @@ class SchemaController {
1946
2039
  if (cached) {
1947
2040
  return cached;
1948
2041
  }
1949
- const normalized = binding.asArray().map((p) => typeof p === "number" ? "[]" : p).join(".");
1950
- this.bindingSchemaNormalizedCache.set(binding, normalized);
2042
+ let bindingArray = binding.asArray();
2043
+ let normalized = bindingArray.map((p) => typeof p === "number" ? "[]" : p).join(".");
2044
+ if (normalized) {
2045
+ this.bindingSchemaNormalizedCache.set(binding, normalized);
2046
+ bindingArray = normalized.split(".");
2047
+ }
2048
+ bindingArray.forEach((item) => {
2049
+ const recordBinding = bindingArray.map((p) => p === item ? "{}" : p).join(".");
2050
+ if (this.schema.get(recordBinding)) {
2051
+ this.bindingSchemaNormalizedCache.set(binding, recordBinding);
2052
+ bindingArray = recordBinding.split(".");
2053
+ normalized = recordBinding;
2054
+ }
2055
+ });
1951
2056
  return normalized;
1952
2057
  }
1953
2058
  getType(binding) {
@@ -2034,6 +2139,9 @@ function findNextExp(str) {
2034
2139
  };
2035
2140
  }
2036
2141
  function resolveExpressionsInString(val, { evaluate }) {
2142
+ if (!evaluate) {
2143
+ return val;
2144
+ }
2037
2145
  const expMatch = /@\[.*?\]@/;
2038
2146
  let newVal = val;
2039
2147
  let match = newVal.match(expMatch);
@@ -2051,9 +2159,9 @@ function resolveExpressionsInString(val, { evaluate }) {
2051
2159
  return newVal;
2052
2160
  }
2053
2161
  function resolveDataRefsInString(val, options) {
2054
- const { model } = options;
2162
+ const { model, formatted = true } = options;
2055
2163
  let workingString = resolveExpressionsInString(val, options);
2056
- if (typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2164
+ if (!model || typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2057
2165
  return workingString;
2058
2166
  }
2059
2167
  while (workingString.indexOf(DOUBLE_OPEN_CURLY) !== -1) {
@@ -2063,7 +2171,7 @@ function resolveDataRefsInString(val, options) {
2063
2171
  }
2064
2172
  const { start, end } = expLocation;
2065
2173
  const binding = workingString.substring(start + DOUBLE_OPEN_CURLY.length, end - DOUBLE_OPEN_CURLY.length).trim();
2066
- const evaledVal = model.get(binding, { formatted: true });
2174
+ const evaledVal = model.get(binding, { formatted });
2067
2175
  if (start === 0 && end === workingString.length && typeof evaledVal !== "string") {
2068
2176
  return evaledVal;
2069
2177
  }
@@ -2082,9 +2190,9 @@ function traverseObject(val, options) {
2082
2190
  const keys = Object.keys(val);
2083
2191
  let newVal = val;
2084
2192
  if (keys.length > 0) {
2085
- for (const key of keys) {
2193
+ keys.forEach((key) => {
2086
2194
  newVal = timm.setIn(newVal, [key], traverseObject(val[key], options));
2087
- }
2195
+ });
2088
2196
  }
2089
2197
  return newVal;
2090
2198
  }
@@ -2096,6 +2204,36 @@ function resolveDataRefs(val, options) {
2096
2204
  return traverseObject(val, options);
2097
2205
  }
2098
2206
 
2207
+ function removeBindingAndChildrenFromMap(sourceMap, binding) {
2208
+ const targetMap = new Map(sourceMap);
2209
+ const parentBinding = binding.parent();
2210
+ const property = binding.key();
2211
+ targetMap.forEach((_value, trackedBinding) => {
2212
+ if (binding === trackedBinding || binding.contains(trackedBinding)) {
2213
+ targetMap.delete(trackedBinding);
2214
+ }
2215
+ });
2216
+ if (typeof property === "number") {
2217
+ const bindingsToRewrite = Array.from(sourceMap.keys()).filter((b) => {
2218
+ if (parentBinding.contains(b)) {
2219
+ const [childIndex] = b.relative(parentBinding);
2220
+ return typeof childIndex === "number" && childIndex > property;
2221
+ }
2222
+ return false;
2223
+ }).sort();
2224
+ bindingsToRewrite.forEach((trackedBinding) => {
2225
+ const [childIndex, ...childPath] = trackedBinding.relative(parentBinding);
2226
+ if (typeof childIndex === "number") {
2227
+ const newSegments = [childIndex - 1, ...childPath];
2228
+ const newChildBinding = parentBinding.descendent(newSegments);
2229
+ targetMap.set(newChildBinding, targetMap.get(trackedBinding));
2230
+ targetMap.delete(trackedBinding);
2231
+ }
2232
+ });
2233
+ }
2234
+ return targetMap;
2235
+ }
2236
+
2099
2237
  var __defProp$a = Object.defineProperty;
2100
2238
  var __defProps$8 = Object.defineProperties;
2101
2239
  var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
@@ -2120,12 +2258,15 @@ class ValidationMiddleware {
2120
2258
  this.validator = validator;
2121
2259
  this.shadowModelPaths = new Map();
2122
2260
  this.logger = options == null ? void 0 : options.logger;
2261
+ this.shouldIncludeInvalid = options == null ? void 0 : options.shouldIncludeInvalid;
2123
2262
  }
2124
2263
  set(transaction, options, next) {
2125
2264
  const asModel = toModel(this, __spreadProps$8(__spreadValues$a({}, options), { includeInvalid: true }), next);
2126
2265
  const nextTransaction = [];
2266
+ const includedBindings = new Set();
2127
2267
  transaction.forEach(([binding, value]) => {
2128
2268
  this.shadowModelPaths.set(binding, value);
2269
+ includedBindings.add(binding);
2129
2270
  });
2130
2271
  const invalidBindings = [];
2131
2272
  this.shadowModelPaths.forEach((value, binding) => {
@@ -2136,22 +2277,25 @@ class ValidationMiddleware {
2136
2277
  } else if (validations instanceof Set) {
2137
2278
  validations.forEach((validation) => {
2138
2279
  invalidBindings.push(validation.binding);
2139
- if (!validation.isStrong) {
2280
+ if (!validation.isStrong && validation.binding.asString() === binding.asString()) {
2140
2281
  nextTransaction.push([validation.binding, value]);
2141
2282
  }
2142
2283
  });
2143
- } else {
2284
+ } else if (includedBindings.has(binding)) {
2285
+ invalidBindings.push(binding);
2144
2286
  (_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
2145
2287
  }
2146
2288
  });
2289
+ let validResults = [];
2147
2290
  if (next && nextTransaction.length > 0) {
2148
2291
  nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
2149
2292
  const result = next.set(nextTransaction, options);
2150
2293
  if (invalidBindings.length === 0) {
2151
2294
  return result;
2152
2295
  }
2296
+ validResults = result;
2153
2297
  }
2154
- return invalidBindings.map((binding) => {
2298
+ const invalidResults = invalidBindings.map((binding) => {
2155
2299
  return {
2156
2300
  binding,
2157
2301
  oldValue: asModel.get(binding),
@@ -2159,10 +2303,12 @@ class ValidationMiddleware {
2159
2303
  force: true
2160
2304
  };
2161
2305
  });
2306
+ return [...validResults, ...invalidResults];
2162
2307
  }
2163
2308
  get(binding, options, next) {
2309
+ var _a, _b;
2164
2310
  let val = next == null ? void 0 : next.get(binding, options);
2165
- if ((options == null ? void 0 : options.includeInvalid) === true) {
2311
+ if ((_b = (_a = this.shouldIncludeInvalid) == null ? void 0 : _a.call(this, options)) != null ? _b : (options == null ? void 0 : options.includeInvalid) === true) {
2166
2312
  this.shadowModelPaths.forEach((shadowValue, shadowBinding) => {
2167
2313
  if (shadowBinding === binding) {
2168
2314
  val = shadowValue;
@@ -2175,6 +2321,10 @@ class ValidationMiddleware {
2175
2321
  }
2176
2322
  return val;
2177
2323
  }
2324
+ delete(binding, options, next) {
2325
+ this.shadowModelPaths = removeBindingAndChildrenFromMap(this.shadowModelPaths, binding);
2326
+ return next == null ? void 0 : next.delete(binding, options);
2327
+ }
2178
2328
  }
2179
2329
 
2180
2330
  class ValidatorRegistry {
@@ -2259,6 +2409,9 @@ class Parser {
2259
2409
  }
2260
2410
  return tapped;
2261
2411
  }
2412
+ hasTemplateValues(obj, localKey) {
2413
+ return Object.hasOwnProperty.call(obj, "template") && Array.isArray(obj == null ? void 0 : obj.template) && obj.template.length && obj.template.find((tmpl) => tmpl.output === localKey);
2414
+ }
2262
2415
  parseObject(obj, type = exports.NodeType.Value, options = { templateDepth: 0 }) {
2263
2416
  var _a;
2264
2417
  const nodeType = this.hooks.determineNodeType.call(obj);
@@ -2276,12 +2429,19 @@ class Parser {
2276
2429
  if (!localObj) {
2277
2430
  return currentValue;
2278
2431
  }
2279
- const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : Object.entries(localObj);
2432
+ const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : [
2433
+ ...Object.entries(localObj),
2434
+ ...Object.getOwnPropertySymbols(localObj).map((s) => [
2435
+ s,
2436
+ localObj[s]
2437
+ ])
2438
+ ];
2280
2439
  const defaultValue = {
2281
2440
  children: [],
2282
2441
  value: currentValue
2283
2442
  };
2284
2443
  const newValue = objEntries.reduce((accumulation, current) => {
2444
+ var _b;
2285
2445
  const _a2 = accumulation, { children: children2 } = _a2, rest = __objRest$1(_a2, ["children"]);
2286
2446
  const [localKey, localValue] = current;
2287
2447
  if (localKey === "asset" && typeof localValue === "object") {
@@ -2299,14 +2459,19 @@ class Parser {
2299
2459
  }
2300
2460
  } else if (this.hooks.determineNodeType.call(localKey) === exports.NodeType.Template && Array.isArray(localValue)) {
2301
2461
  const templateChildren = localValue.map((template) => {
2302
- var _a3, _b;
2462
+ var _a3, _b2;
2303
2463
  const templateAST = this.hooks.onCreateASTNode.call({
2304
2464
  type: exports.NodeType.Template,
2305
2465
  depth: (_a3 = options.templateDepth) != null ? _a3 : 0,
2306
2466
  data: template.data,
2307
2467
  template: template.value,
2308
- dynamic: (_b = template.dynamic) != null ? _b : false
2468
+ dynamic: (_b2 = template.dynamic) != null ? _b2 : false
2309
2469
  }, template);
2470
+ if ((templateAST == null ? void 0 : templateAST.type) === exports.NodeType.MultiNode) {
2471
+ templateAST.values.forEach((v) => {
2472
+ v.parent = templateAST;
2473
+ });
2474
+ }
2310
2475
  if (templateAST) {
2311
2476
  return {
2312
2477
  path: [...path, template.output],
@@ -2320,6 +2485,18 @@ class Parser {
2320
2485
  });
2321
2486
  } else if (localValue && this.hooks.determineNodeType.call(localValue) === exports.NodeType.Switch) {
2322
2487
  const localSwitch = this.hooks.parseNode.call(localValue, exports.NodeType.Value, options, exports.NodeType.Switch);
2488
+ if (localSwitch && localSwitch.type === exports.NodeType.Value && ((_b = localSwitch.children) == null ? void 0 : _b.length) === 1 && localSwitch.value === void 0) {
2489
+ const firstChild = localSwitch.children[0];
2490
+ return __spreadProps$7(__spreadValues$9({}, rest), {
2491
+ children: [
2492
+ ...children2,
2493
+ {
2494
+ path: [...path, localKey, ...firstChild.path],
2495
+ value: firstChild.value
2496
+ }
2497
+ ]
2498
+ });
2499
+ }
2323
2500
  if (localSwitch) {
2324
2501
  return __spreadProps$7(__spreadValues$9({}, rest), {
2325
2502
  children: [
@@ -2336,7 +2513,7 @@ class Parser {
2336
2513
  if (childValues.length > 0) {
2337
2514
  const multiNode = this.hooks.onCreateASTNode.call({
2338
2515
  type: exports.NodeType.MultiNode,
2339
- override: true,
2516
+ override: !this.hasTemplateValues(localObj, localKey),
2340
2517
  values: childValues
2341
2518
  }, localValue);
2342
2519
  if ((multiNode == null ? void 0 : multiNode.type) === exports.NodeType.MultiNode) {
@@ -2359,7 +2536,7 @@ class Parser {
2359
2536
  } else if (localValue && typeof localValue === "object") {
2360
2537
  const determineNodeType = this.hooks.determineNodeType.call(localValue);
2361
2538
  if (determineNodeType === exports.NodeType.Applicability) {
2362
- const parsedNode = this.hooks.parseNode.call(localValue, type, options, determineNodeType);
2539
+ const parsedNode = this.hooks.parseNode.call(localValue, exports.NodeType.Value, options, determineNodeType);
2363
2540
  if (parsedNode) {
2364
2541
  return __spreadProps$7(__spreadValues$9({}, rest), {
2365
2542
  children: [
@@ -2481,6 +2658,11 @@ const withContext = (model) => {
2481
2658
  return model.set(transaction, __spreadValues$7({
2482
2659
  context: { model }
2483
2660
  }, options));
2661
+ },
2662
+ delete: (binding, options) => {
2663
+ return model.delete(binding, __spreadValues$7({
2664
+ context: { model }
2665
+ }, options));
2484
2666
  }
2485
2667
  };
2486
2668
  };
@@ -2510,12 +2692,16 @@ class Resolver {
2510
2692
  this.hooks.beforeUpdate.call(changes);
2511
2693
  const resolveCache = new Map();
2512
2694
  this.idCache.clear();
2695
+ const prevASTMap = new Map(this.ASTMap);
2513
2696
  this.ASTMap.clear();
2514
- const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options));
2697
+ const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options), void 0, prevASTMap);
2515
2698
  this.resolveCache = resolveCache;
2516
2699
  this.hooks.afterUpdate.call(updated.value);
2517
2700
  return updated.value;
2518
2701
  }
2702
+ getResolveCache() {
2703
+ return new Map(this.resolveCache);
2704
+ }
2519
2705
  getNodeID(node) {
2520
2706
  var _a;
2521
2707
  if (!node) {
@@ -2547,7 +2733,19 @@ class Resolver {
2547
2733
  }
2548
2734
  return this.resolveCache.get(node);
2549
2735
  }
2550
- computeTree(node, parent, dataChanges, cacheUpdate, options) {
2736
+ cloneNode(node) {
2737
+ const clonedNode = timm.clone(node);
2738
+ Object.keys(clonedNode).forEach((key) => {
2739
+ if (key === "parent")
2740
+ return;
2741
+ const value = clonedNode[key];
2742
+ if (typeof value === "object" && value !== null) {
2743
+ clonedNode[key] = Array.isArray(value) ? [...value] : __spreadValues$7({}, value);
2744
+ }
2745
+ });
2746
+ return clonedNode;
2747
+ }
2748
+ computeTree(node, parent, dataChanges, cacheUpdate, options, parentNode, prevASTMap) {
2551
2749
  var _a, _b;
2552
2750
  const dependencyModel = new DependencyModel(options.data.model);
2553
2751
  dependencyModel.trackSubset("core");
@@ -2568,34 +2766,40 @@ class Resolver {
2568
2766
  updated: false
2569
2767
  });
2570
2768
  cacheUpdate.set(node, update2);
2571
- const repopulateASTMapFromCache = (resolvedAST3, AST) => {
2769
+ const repopulateASTMapFromCache = (resolvedNode, AST, ASTParent) => {
2572
2770
  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
- });
2771
+ const { node: resolvedAST2 } = resolvedNode;
2772
+ this.ASTMap.set(resolvedAST2, AST);
2773
+ const resolvedUpdate = __spreadProps$5(__spreadValues$7({}, resolvedNode), {
2774
+ updated: false
2775
+ });
2776
+ cacheUpdate.set(AST, resolvedUpdate);
2777
+ const handleChildNode = (childNode) => {
2778
+ var _a3;
2779
+ const originalChildNode = (_a3 = prevASTMap.get(childNode)) != null ? _a3 : childNode;
2780
+ const previousChildResult = this.getPreviousResult(originalChildNode);
2781
+ if (!previousChildResult)
2782
+ return;
2783
+ repopulateASTMapFromCache(previousChildResult, originalChildNode, AST);
2784
+ };
2785
+ if ("children" in resolvedAST2) {
2786
+ (_a2 = resolvedAST2.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => handleChildNode(childAST));
2787
+ } else if (resolvedAST2.type === exports.NodeType.MultiNode) {
2788
+ resolvedAST2.values.forEach(handleChildNode);
2589
2789
  }
2790
+ this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate);
2590
2791
  };
2591
- const resolvedAST2 = previousResult.node;
2592
- repopulateASTMapFromCache(resolvedAST2, node);
2593
- this.hooks.afterNodeUpdate.call(node, parent, update2);
2792
+ previousResult.node.parent = parentNode;
2793
+ repopulateASTMapFromCache(previousResult, node, parent);
2594
2794
  return update2;
2595
2795
  }
2596
- const resolvedAST = (_a = this.hooks.beforeResolve.call(node, resolveOptions)) != null ? _a : {
2796
+ const clonedNode = __spreadProps$5(__spreadValues$7({}, this.cloneNode(node)), {
2797
+ parent: parentNode
2798
+ });
2799
+ const resolvedAST = (_a = this.hooks.beforeResolve.call(clonedNode, resolveOptions)) != null ? _a : {
2597
2800
  type: exports.NodeType.Empty
2598
2801
  };
2802
+ resolvedAST.parent = parentNode;
2599
2803
  resolveOptions.node = resolvedAST;
2600
2804
  this.ASTMap.set(resolvedAST, node);
2601
2805
  let resolved = this.hooks.resolve.call(void 0, resolvedAST, resolveOptions);
@@ -2606,22 +2810,15 @@ class Resolver {
2606
2810
  const childDependencies = new Set();
2607
2811
  dependencyModel.trackSubset("children");
2608
2812
  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;
2813
+ const newChildren = (_b = resolvedAST.children) == null ? void 0 : _b.map((child) => {
2814
+ const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2815
+ const {
2816
+ dependencies: childTreeDeps,
2817
+ node: childNode,
2818
+ updated: childUpdated,
2819
+ value: childValue
2820
+ } = computedChildTree;
2613
2821
  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
2822
  if (childValue) {
2626
2823
  if (childNode.type === exports.NodeType.MultiNode && !childNode.override) {
2627
2824
  const arr = timm.addLast(get__default["default"](resolved, child.path, []), childValue);
@@ -2631,7 +2828,22 @@ class Resolver {
2631
2828
  }
2632
2829
  }
2633
2830
  updated = updated || childUpdated;
2831
+ return __spreadProps$5(__spreadValues$7({}, child), { value: childNode });
2832
+ });
2833
+ resolvedAST.children = newChildren;
2834
+ } else if (resolvedAST.type === exports.NodeType.MultiNode) {
2835
+ const childValue = [];
2836
+ const newValues = resolvedAST.values.map((mValue) => {
2837
+ const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2838
+ if (mTree.value !== void 0 && mTree.value !== null) {
2839
+ childValue.push(mTree.value);
2840
+ }
2841
+ mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2842
+ updated = updated || mTree.updated;
2843
+ return mTree.node;
2634
2844
  });
2845
+ resolvedAST.values = newValues;
2846
+ resolved = childValue;
2635
2847
  }
2636
2848
  childDependencies.forEach((bindingDep) => dependencyModel.addChildReadDep(bindingDep));
2637
2849
  dependencyModel.trackSubset("core");
@@ -2700,13 +2912,10 @@ class TemplatePlugin {
2700
2912
  }
2701
2913
  });
2702
2914
  const result = {
2703
- parent: node.parent,
2704
2915
  type: exports.NodeType.MultiNode,
2916
+ override: false,
2705
2917
  values
2706
2918
  };
2707
- result.values.forEach((innerNode) => {
2708
- innerNode.parent = result;
2709
- });
2710
2919
  return result;
2711
2920
  }
2712
2921
  applyParser(parser) {
@@ -2800,19 +3009,20 @@ function resolveAllRefs(node, resolveOptions, propertiesToSkip) {
2800
3009
  });
2801
3010
  return newNode;
2802
3011
  }
2803
- const findBasePath = (node) => {
3012
+ const findBasePath = (node, resolver) => {
2804
3013
  var _a, _b, _c;
2805
3014
  const parentNode = node.parent;
2806
3015
  if (!parentNode) {
2807
3016
  return [];
2808
3017
  }
2809
3018
  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 : [];
3019
+ const original = resolver.getSourceNode(node);
3020
+ return (_c = (_b = (_a = parentNode.children) == null ? void 0 : _a.find((child) => child.value === original)) == null ? void 0 : _b.path) != null ? _c : [];
2811
3021
  }
2812
3022
  if (parentNode.type !== exports.NodeType.MultiNode) {
2813
3023
  return [];
2814
3024
  }
2815
- return findBasePath(parentNode);
3025
+ return findBasePath(parentNode, resolver);
2816
3026
  };
2817
3027
  class StringResolverPlugin {
2818
3028
  constructor() {
@@ -2836,7 +3046,7 @@ class StringResolverPlugin {
2836
3046
  } else {
2837
3047
  propsToSkip = new Set(["exp"]);
2838
3048
  }
2839
- const nodePath = findBasePath(node);
3049
+ const nodePath = findBasePath(node, resolver);
2840
3050
  if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
2841
3051
  return node.value;
2842
3052
  }
@@ -2856,7 +3066,7 @@ class ApplicabilityPlugin {
2856
3066
  let newNode = node;
2857
3067
  if ((node == null ? void 0 : node.type) === exports.NodeType.Applicability) {
2858
3068
  const isApplicable = options.evaluate(node.expression);
2859
- if (!isApplicable) {
3069
+ if (isApplicable === false) {
2860
3070
  return null;
2861
3071
  }
2862
3072
  newNode = node.value;
@@ -3162,7 +3372,8 @@ class FlowInstance {
3162
3372
  skipTransition: new tapableTs.SyncBailHook(),
3163
3373
  beforeTransition: new tapableTs.SyncWaterfallHook(),
3164
3374
  resolveTransitionNode: new tapableTs.SyncWaterfallHook(),
3165
- transition: new tapableTs.SyncHook()
3375
+ transition: new tapableTs.SyncHook(),
3376
+ afterTransition: new tapableTs.SyncHook()
3166
3377
  };
3167
3378
  this.id = id;
3168
3379
  this.flow = flow;
@@ -3209,7 +3420,7 @@ class FlowInstance {
3209
3420
  } else {
3210
3421
  const skipTransition = this.hooks.skipTransition.call(this.currentState);
3211
3422
  if (skipTransition) {
3212
- (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState} b/c hook told us to`);
3423
+ (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState.name} b/c hook told us to`);
3213
3424
  return;
3214
3425
  }
3215
3426
  }
@@ -3248,6 +3459,7 @@ class FlowInstance {
3248
3459
  this.hooks.onEnd.call(this.flow.onEnd);
3249
3460
  }
3250
3461
  this.hooks.transition.call(prevState, __spreadValues$5({}, newCurrentState));
3462
+ this.hooks.afterTransition.call(this);
3251
3463
  }
3252
3464
  }
3253
3465
 
@@ -3282,6 +3494,7 @@ class FlowController {
3282
3494
  this.start = this.start.bind(this);
3283
3495
  this.run = this.run.bind(this);
3284
3496
  this.transition = this.transition.bind(this);
3497
+ this.addNewFlow = this.addNewFlow.bind(this);
3285
3498
  }
3286
3499
  transition(stateTransition, options) {
3287
3500
  if (this.current === void 0) {
@@ -3290,20 +3503,9 @@ class FlowController {
3290
3503
  this.current.transition(stateTransition, options);
3291
3504
  }
3292
3505
  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
- });
3506
+ this.navStack.push(flow);
3507
+ this.current = flow;
3508
+ this.hooks.flow.call(flow);
3307
3509
  }
3308
3510
  run(startState) {
3309
3511
  return __async$1(this, null, function* () {
@@ -3318,6 +3520,18 @@ class FlowController {
3318
3520
  (_a = this.log) == null ? void 0 : _a.debug(`Starting flow: ${startState}`);
3319
3521
  const flow = new FlowInstance(startState, startFlow, { logger: this.log });
3320
3522
  this.addNewFlow(flow);
3523
+ flow.hooks.afterTransition.tap("flow-controller", (flowInstance) => {
3524
+ var _a2, _b, _c;
3525
+ if (((_a2 = flowInstance.currentState) == null ? void 0 : _a2.value.state_type) === "FLOW") {
3526
+ const subflowId = (_b = flowInstance.currentState) == null ? void 0 : _b.value.ref;
3527
+ (_c = this.log) == null ? void 0 : _c.debug(`Loading subflow ${subflowId}`);
3528
+ this.run(subflowId).then((subFlowEndState) => {
3529
+ var _a3;
3530
+ (_a3 = this.log) == null ? void 0 : _a3.debug(`Subflow ended. Using outcome: ${subFlowEndState.outcome}`);
3531
+ flowInstance.transition(subFlowEndState == null ? void 0 : subFlowEndState.outcome);
3532
+ });
3533
+ }
3534
+ });
3321
3535
  const end = yield flow.start();
3322
3536
  this.navStack.pop();
3323
3537
  if (this.navStack.length > 0) {
@@ -3370,11 +3584,18 @@ class ValidationBindingTrackerViewPlugin {
3370
3584
  getBindings() {
3371
3585
  return this.trackedBindings;
3372
3586
  }
3587
+ trackBinding(binding) {
3588
+ var _a, _b;
3589
+ if (this.trackedBindings.has(binding)) {
3590
+ return;
3591
+ }
3592
+ this.trackedBindings.add(binding);
3593
+ (_b = (_a = this.options.callbacks) == null ? void 0 : _a.onAdd) == null ? void 0 : _b.call(_a, binding);
3594
+ }
3373
3595
  applyResolver(resolver) {
3374
3596
  this.trackedBindings.clear();
3375
3597
  const tracked = new Map();
3376
3598
  const sections = new Map();
3377
- const seenBindings = new Set();
3378
3599
  let lastViewUpdateChangeSet;
3379
3600
  const nodeTree = new Map();
3380
3601
  let lastComputedBindingTree = new Map();
@@ -3421,31 +3642,34 @@ class ValidationBindingTrackerViewPlugin {
3421
3642
  parent = parent.parent;
3422
3643
  }
3423
3644
  }
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
- }
3645
+ this.trackedBindings.add(parsed);
3646
+ (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3428
3647
  };
3429
3648
  return __spreadProps$3(__spreadValues$4({}, options), {
3430
3649
  validation: __spreadProps$3(__spreadValues$4({}, options.validation), {
3431
3650
  get: (binding, getOptions) => {
3432
- var _a;
3651
+ var _a, _b;
3433
3652
  if (getOptions == null ? void 0 : getOptions.track) {
3434
3653
  track(binding);
3435
3654
  }
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;
3655
+ const eows = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions);
3656
+ const firstFieldEOW = eows == null ? void 0 : eows.find((eow) => eow.displayTarget === "field" || eow.displayTarget === void 0);
3657
+ return firstFieldEOW;
3658
+ },
3659
+ getValidationsForBinding(binding, getOptions) {
3660
+ var _a, _b, _c;
3661
+ if (getOptions == null ? void 0 : getOptions.track) {
3662
+ track(binding);
3439
3663
  }
3440
- return void 0;
3664
+ return (_c = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions)) != null ? _c : [];
3441
3665
  },
3442
3666
  getChildren: (type) => {
3443
3667
  var _a;
3444
3668
  const validations = new Array();
3445
3669
  (_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) {
3670
+ var _a2, _b;
3671
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3672
+ if (eow && (type === void 0 || type === eow.displayTarget)) {
3449
3673
  validations.push(eow);
3450
3674
  }
3451
3675
  });
@@ -3455,8 +3679,8 @@ class ValidationBindingTrackerViewPlugin {
3455
3679
  var _a;
3456
3680
  const validations = new Array();
3457
3681
  (_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);
3682
+ var _a2, _b;
3683
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3460
3684
  if (eow && eow.displayTarget === "section") {
3461
3685
  validations.push(eow);
3462
3686
  }
@@ -3475,7 +3699,7 @@ class ValidationBindingTrackerViewPlugin {
3475
3699
  });
3476
3700
  });
3477
3701
  resolver.hooks.afterNodeUpdate.tap(CONTEXT, (node, parent, update) => {
3478
- var _a, _b, _c;
3702
+ var _a, _b;
3479
3703
  if (parent) {
3480
3704
  addToTree(node, parent);
3481
3705
  }
@@ -3490,7 +3714,7 @@ class ValidationBindingTrackerViewPlugin {
3490
3714
  currentBindingTree.set(node, (_b = lastComputedBindingTree.get(node)) != null ? _b : new Set());
3491
3715
  }
3492
3716
  if (node === resolver.root) {
3493
- this.trackedBindings = (_c = currentBindingTree.get(node)) != null ? _c : new Set();
3717
+ this.trackedBindings = new Set(currentBindingTree.get(node));
3494
3718
  lastComputedBindingTree = currentBindingTree;
3495
3719
  lastSectionBindingTree.clear();
3496
3720
  sections.forEach((nodeSet, sectionNode) => {
@@ -3532,11 +3756,23 @@ var __spreadValues$3 = (a, b) => {
3532
3756
  return a;
3533
3757
  };
3534
3758
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
3759
+ const SCHEMA_VALIDATION_PROVIDER_NAME = "schema";
3760
+ const VIEW_VALIDATION_PROVIDER_NAME = "view";
3761
+ const VALIDATION_PROVIDER_NAME_SYMBOL = Symbol.for("validation-provider-name");
3762
+ function isSubset(subset, containingSet) {
3763
+ if (subset.size > containingSet.size)
3764
+ return false;
3765
+ for (const entry of subset)
3766
+ if (!containingSet.has(entry))
3767
+ return false;
3768
+ return true;
3769
+ }
3535
3770
  function createStatefulValidationObject(obj) {
3536
3771
  return {
3537
3772
  value: obj,
3538
3773
  type: obj.severity,
3539
- state: "none"
3774
+ state: "none",
3775
+ isBlockingNavigation: false
3540
3776
  };
3541
3777
  }
3542
3778
  class ValidatedBinding {
@@ -3551,44 +3787,68 @@ class ValidatedBinding {
3551
3787
  possibleValidations.forEach((vObj) => {
3552
3788
  const { trigger } = vObj;
3553
3789
  if (this.validationsByState[trigger]) {
3554
- this.validationsByState[trigger].push(createStatefulValidationObject(vObj));
3790
+ const statefulValidationObject = createStatefulValidationObject(vObj);
3791
+ this.validationsByState[trigger].push(statefulValidationObject);
3555
3792
  } else {
3556
3793
  log == null ? void 0 : log.warn(`Unknown validation trigger: ${trigger}`);
3557
3794
  }
3558
3795
  });
3559
3796
  this.weakBindings = weakBindings != null ? weakBindings : new Set();
3560
3797
  }
3798
+ get allValidations() {
3799
+ return Object.values(this.validationsByState).flat();
3800
+ }
3801
+ checkIfBlocking(statefulObj) {
3802
+ if (statefulObj.state === "active") {
3803
+ const { isBlockingNavigation } = statefulObj;
3804
+ return isBlockingNavigation;
3805
+ }
3806
+ return false;
3807
+ }
3808
+ getAll() {
3809
+ return this.applicableValidations.reduce((all, statefulObj) => {
3810
+ if (statefulObj.state === "active" && statefulObj.response) {
3811
+ return [
3812
+ ...all,
3813
+ __spreadProps$2(__spreadValues$3({}, statefulObj.response), {
3814
+ blocking: this.checkIfBlocking(statefulObj)
3815
+ })
3816
+ ];
3817
+ }
3818
+ return all;
3819
+ }, []);
3820
+ }
3561
3821
  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;
3822
+ const firstInvalid = this.applicableValidations.find((statefulObj) => {
3823
+ return statefulObj.state === "active" && statefulObj.response;
3565
3824
  });
3566
- if ((firstError == null ? void 0 : firstError.state) === "active") {
3567
- return firstError.response;
3825
+ if ((firstInvalid == null ? void 0 : firstInvalid.state) === "active") {
3826
+ return __spreadProps$2(__spreadValues$3({}, firstInvalid.response), {
3827
+ blocking: this.checkIfBlocking(firstInvalid)
3828
+ });
3568
3829
  }
3569
3830
  }
3570
- runApplicableValidations(runner, canDismiss) {
3571
- this.applicableValidations = this.applicableValidations.map((obj) => {
3831
+ runApplicableValidations(runner, canDismiss, phase) {
3832
+ this.applicableValidations = this.applicableValidations.map((originalValue) => {
3572
3833
  var _a, _b, _c;
3573
- if (obj.state === "dismissed") {
3574
- return obj;
3834
+ if (originalValue.state === "dismissed") {
3835
+ return originalValue;
3575
3836
  }
3576
- const blocking = (_a = obj.value.blocking) != null ? _a : obj.value.severity === "warning" && "once" || obj.value.severity === "error" && true;
3577
- const dismissable = canDismiss && blocking === "once";
3578
- if (this.currentPhase === "navigation" && obj.state === "active" && dismissable) {
3837
+ const blocking = (_a = originalValue.value.blocking) != null ? _a : originalValue.value.severity === "warning" && "once" || true;
3838
+ const obj = timm.setIn(originalValue, ["value", "blocking"], blocking);
3839
+ const isBlockingNavigation = blocking === true || blocking === "once" && !canDismiss;
3840
+ if (phase === "navigation" && obj.state === "active" && obj.value.blocking !== true) {
3579
3841
  if (obj.value.severity === "warning") {
3580
3842
  const warn = obj;
3581
- if (warn.dismissable && warn.response.dismiss) {
3843
+ if (warn.dismissable && warn.response.dismiss && (warn.response.blocking !== "once" || !warn.response.blocking)) {
3582
3844
  warn.response.dismiss();
3583
3845
  } else {
3846
+ if ((warn == null ? void 0 : warn.response.blocking) === "once") {
3847
+ warn.response.blocking = false;
3848
+ }
3584
3849
  warn.dismissable = true;
3585
3850
  }
3586
- return obj;
3587
- }
3588
- if (obj.value.severity === "error") {
3589
- const err = obj;
3590
- err.state = "none";
3591
- return obj;
3851
+ return warn;
3592
3852
  }
3593
3853
  }
3594
3854
  const response = runner(obj.value);
@@ -3596,7 +3856,8 @@ class ValidatedBinding {
3596
3856
  type: obj.type,
3597
3857
  value: obj.value,
3598
3858
  state: response ? "active" : "none",
3599
- dismissable: obj.value.severity === "warning" && this.currentPhase === "navigation",
3859
+ isBlockingNavigation,
3860
+ dismissable: obj.value.severity === "warning" && phase === "navigation",
3600
3861
  response: response ? __spreadProps$2(__spreadValues$3({}, obj.value), {
3601
3862
  message: (_b = response.message) != null ? _b : "Something is broken",
3602
3863
  severity: obj.value.severity,
@@ -3614,11 +3875,12 @@ class ValidatedBinding {
3614
3875
  });
3615
3876
  }
3616
3877
  update(phase, canDismiss, runner) {
3878
+ const newApplicableValidations = [];
3617
3879
  if (phase === "load" && this.currentPhase !== void 0) {
3618
3880
  return;
3619
3881
  }
3620
3882
  if (this.currentPhase === "navigation" || phase === this.currentPhase) {
3621
- this.runApplicableValidations(runner, canDismiss);
3883
+ this.runApplicableValidations(runner, canDismiss, phase);
3622
3884
  return;
3623
3885
  }
3624
3886
  if (phase === "load") {
@@ -3631,14 +3893,19 @@ class ValidatedBinding {
3631
3893
  ...this.validationsByState.change
3632
3894
  ];
3633
3895
  } else if (phase === "navigation" && (this.currentPhase === "load" || this.currentPhase === "change")) {
3896
+ this.applicableValidations.forEach((element) => {
3897
+ if (!(element.type === "error" && element.state === "active" && element.isBlockingNavigation === false)) {
3898
+ newApplicableValidations.push(element);
3899
+ }
3900
+ });
3634
3901
  this.applicableValidations = [
3635
- ...this.applicableValidations,
3636
- ...this.currentPhase === "load" ? this.validationsByState.change : [],
3637
- ...this.validationsByState.navigation
3902
+ ...newApplicableValidations,
3903
+ ...this.validationsByState.navigation,
3904
+ ...this.currentPhase === "load" ? this.validationsByState.change : []
3638
3905
  ];
3639
3906
  this.currentPhase = "navigation";
3640
3907
  }
3641
- this.runApplicableValidations(runner, canDismiss);
3908
+ this.runApplicableValidations(runner, canDismiss, phase);
3642
3909
  }
3643
3910
  }
3644
3911
  class ValidationController {
@@ -3646,20 +3913,34 @@ class ValidationController {
3646
3913
  this.hooks = {
3647
3914
  createValidatorRegistry: new tapableTs.SyncHook(),
3648
3915
  onAddValidation: new tapableTs.SyncWaterfallHook(),
3649
- onRemoveValidation: new tapableTs.SyncWaterfallHook()
3916
+ onRemoveValidation: new tapableTs.SyncWaterfallHook(),
3917
+ resolveValidationProviders: new tapableTs.SyncWaterfallHook(),
3918
+ onTrackBinding: new tapableTs.SyncHook()
3650
3919
  };
3651
3920
  this.validations = new Map();
3652
3921
  this.weakBindingTracker = new Set();
3653
- this.lastActiveBindings = new Set();
3654
3922
  this.schema = schema;
3655
3923
  this.options = options;
3656
- this.providers = [schema];
3924
+ this.reset();
3657
3925
  }
3658
3926
  setOptions(options) {
3659
3927
  this.options = options;
3660
3928
  }
3661
3929
  getDataMiddleware() {
3662
3930
  return [
3931
+ {
3932
+ set: (transaction, options, next) => {
3933
+ var _a;
3934
+ return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
3935
+ },
3936
+ get: (binding, options, next) => {
3937
+ return next == null ? void 0 : next.get(binding, options);
3938
+ },
3939
+ delete: (binding, options, next) => {
3940
+ this.validations = removeBindingAndChildrenFromMap(this.validations, binding);
3941
+ return next == null ? void 0 : next.delete(binding, options);
3942
+ }
3943
+ },
3663
3944
  new ValidationMiddleware((binding) => {
3664
3945
  var _a;
3665
3946
  if (!this.options) {
@@ -3675,13 +3956,17 @@ class ValidationController {
3675
3956
  var _a2;
3676
3957
  if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
3677
3958
  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
- });
3959
+ if (weakBinding === strongBinding) {
3960
+ newInvalidBindings.add({
3961
+ binding: weakBinding,
3962
+ isStrong: true
3963
+ });
3964
+ } else {
3965
+ newInvalidBindings.add({
3966
+ binding: weakBinding,
3967
+ isStrong: false
3968
+ });
3969
+ }
3685
3970
  });
3686
3971
  }
3687
3972
  });
@@ -3694,6 +3979,35 @@ class ValidationController {
3694
3979
  }) })
3695
3980
  ];
3696
3981
  }
3982
+ getValidationProviders() {
3983
+ if (this.providers) {
3984
+ return this.providers;
3985
+ }
3986
+ this.providers = this.hooks.resolveValidationProviders.call([
3987
+ {
3988
+ source: SCHEMA_VALIDATION_PROVIDER_NAME,
3989
+ provider: this.schema
3990
+ },
3991
+ {
3992
+ source: VIEW_VALIDATION_PROVIDER_NAME,
3993
+ provider: {
3994
+ getValidationsForBinding: (binding) => {
3995
+ var _a, _b;
3996
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForBinding) == null ? void 0 : _b.call(_a, binding);
3997
+ },
3998
+ getValidationsForView: () => {
3999
+ var _a, _b;
4000
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForView) == null ? void 0 : _b.call(_a);
4001
+ }
4002
+ }
4003
+ }
4004
+ ]);
4005
+ return this.providers;
4006
+ }
4007
+ reset() {
4008
+ this.validations.clear();
4009
+ this.tracker = void 0;
4010
+ }
3697
4011
  onView(view) {
3698
4012
  this.validations.clear();
3699
4013
  if (!this.options) {
@@ -3702,7 +4016,7 @@ class ValidationController {
3702
4016
  const bindingTrackerPlugin = new ValidationBindingTrackerViewPlugin(__spreadProps$2(__spreadValues$3({}, this.options), {
3703
4017
  callbacks: {
3704
4018
  onAdd: (binding) => {
3705
- if (!this.options) {
4019
+ if (!this.options || this.getValidationForBinding(binding) !== void 0) {
3706
4020
  return;
3707
4021
  }
3708
4022
  const originalValue = this.options.model.get(binding);
@@ -3717,21 +4031,28 @@ class ValidationController {
3717
4031
  this.updateValidationsForBinding(binding, "load", this.options, () => {
3718
4032
  view.update(new Set([binding]));
3719
4033
  });
4034
+ this.hooks.onTrackBinding.call(binding);
3720
4035
  }
3721
4036
  }
3722
4037
  }));
3723
4038
  this.tracker = bindingTrackerPlugin;
3724
- this.providers = [this.schema, view];
4039
+ this.viewValidationProvider = view;
3725
4040
  bindingTrackerPlugin.apply(view);
3726
4041
  }
3727
- updateValidationsForBinding(binding, trigger, context, onDismiss) {
4042
+ updateValidationsForBinding(binding, trigger, validationContext, onDismiss) {
3728
4043
  var _a;
4044
+ const context = validationContext != null ? validationContext : this.options;
4045
+ if (!context) {
4046
+ throw new Error(`Context is required for executing validations`);
4047
+ }
3729
4048
  if (trigger === "load") {
3730
- const possibleValidations = this.providers.reduce((vals, provider) => {
3731
- var _a2, _b;
4049
+ const possibleValidations = this.getValidationProviders().reduce((vals, provider) => {
4050
+ var _a2, _b, _c, _d;
3732
4051
  return [
3733
4052
  ...vals,
3734
- ...(_b = (_a2 = provider.getValidationsForBinding) == null ? void 0 : _a2.call(provider, binding)) != null ? _b : []
4053
+ ...(_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), {
4054
+ [VALIDATION_PROVIDER_NAME_SYMBOL]: provider.source
4055
+ }))) != null ? _d : []
3735
4056
  ];
3736
4057
  }, []);
3737
4058
  if (possibleValidations.length === 0) {
@@ -3741,7 +4062,7 @@ class ValidationController {
3741
4062
  }
3742
4063
  const trackedValidations = this.validations.get(binding);
3743
4064
  trackedValidations == null ? void 0 : trackedValidations.update(trigger, true, (validationObj) => {
3744
- const response = this.validationRunner(validationObj, context, binding);
4065
+ const response = this.validationRunner(validationObj, binding, context);
3745
4066
  if (this.weakBindingTracker.size > 0) {
3746
4067
  const t = this.validations.get(binding);
3747
4068
  this.weakBindingTracker.forEach((b) => t.weakBindings.add(b));
@@ -3752,27 +4073,33 @@ class ValidationController {
3752
4073
  this.validations.forEach((validation, vBinding) => {
3753
4074
  if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
3754
4075
  validation.update(trigger, true, (validationObj) => {
3755
- const response = this.validationRunner(validationObj, context, vBinding);
4076
+ const response = this.validationRunner(validationObj, vBinding, context);
3756
4077
  return response ? { message: response.message } : void 0;
3757
4078
  });
3758
4079
  }
3759
4080
  });
3760
4081
  }
3761
4082
  }
3762
- validationRunner(validationObj, context, binding) {
3763
- const handler = this.getValidator(validationObj.type);
4083
+ validationRunner(validationObj, binding, context = this.options) {
4084
+ var _a;
4085
+ if (!context) {
4086
+ throw new Error("No context provided to validation runner");
4087
+ }
4088
+ const handler = (_a = validationObj.handler) != null ? _a : this.getValidator(validationObj.type);
3764
4089
  const weakBindings = new Set();
3765
4090
  const model = {
3766
- get(b, options = { includeInvalid: true }) {
4091
+ get(b, options) {
3767
4092
  weakBindings.add(isBinding(b) ? binding : context.parseBinding(b));
3768
- return context.model.get(b, options);
4093
+ return context.model.get(b, __spreadProps$2(__spreadValues$3({}, options), { includeInvalid: true }));
3769
4094
  },
3770
- set: context.model.set
4095
+ set: context.model.set,
4096
+ delete: context.model.delete
3771
4097
  };
3772
4098
  const result = handler == null ? void 0 : handler(__spreadProps$2(__spreadValues$3({}, context), {
3773
4099
  evaluate: (exp, options = { model }) => context.evaluate(exp, options),
3774
4100
  model,
3775
- validation: validationObj
4101
+ validation: validationObj,
4102
+ schemaType: this.schema.getType(binding)
3776
4103
  }), context.model.get(binding, {
3777
4104
  includeInvalid: true,
3778
4105
  formatted: validationObj.dataTarget === "formatted"
@@ -3796,29 +4123,27 @@ class ValidationController {
3796
4123
  }
3797
4124
  }
3798
4125
  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);
4126
+ const isNavigationTrigger = trigger === "navigation";
4127
+ const lastActiveBindings = this.activeBindings;
4128
+ const updateValidations = (dismissValidations) => {
4129
+ this.getBindings().forEach((binding) => {
4130
+ var _a;
4131
+ (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, dismissValidations, (obj) => {
4132
+ if (!this.options) {
4133
+ return;
4134
+ }
4135
+ return this.validationRunner(obj, binding, this.options);
4136
+ });
3808
4137
  });
3809
- });
3810
- if (trigger === "navigation") {
3811
- this.lastActiveBindings = activeBindings;
4138
+ };
4139
+ updateValidations(!isNavigationTrigger);
4140
+ if (isNavigationTrigger) {
4141
+ const { activeBindings } = this;
4142
+ if (isSubset(activeBindings, lastActiveBindings)) {
4143
+ updateValidations(true);
4144
+ }
3812
4145
  }
3813
4146
  }
3814
- setCompare(set1, set2) {
3815
- if (set1.size !== set2.size)
3816
- return false;
3817
- for (const entry of set1)
3818
- if (!set2.has(entry))
3819
- return false;
3820
- return true;
3821
- }
3822
4147
  get activeBindings() {
3823
4148
  return new Set(Array.from(this.getBindings()).filter((b) => {
3824
4149
  var _a;
@@ -3838,19 +4163,30 @@ class ValidationController {
3838
4163
  var _a, _b;
3839
4164
  return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
3840
4165
  }
4166
+ trackBinding(binding) {
4167
+ var _a;
4168
+ (_a = this.tracker) == null ? void 0 : _a.trackBinding(binding);
4169
+ }
3841
4170
  validateView(trigger = "navigation") {
3842
4171
  this.updateValidationsForView(trigger);
3843
4172
  const validations = new Map();
4173
+ let canTransition = true;
3844
4174
  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
- }
4175
+ var _a;
4176
+ const allValidations = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.getAll();
4177
+ allValidations == null ? void 0 : allValidations.forEach((v) => {
4178
+ var _a2;
4179
+ if (trigger === "navigation" && v.blocking) {
4180
+ (_a2 = this.options) == null ? void 0 : _a2.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(v)}`);
4181
+ canTransition = false;
4182
+ }
4183
+ if (!validations.has(b)) {
4184
+ validations.set(b, v);
4185
+ }
4186
+ });
3851
4187
  });
3852
4188
  return {
3853
- canTransition: validations.size === 0,
4189
+ canTransition,
3854
4190
  validations: validations.size ? validations : void 0
3855
4191
  };
3856
4192
  }
@@ -3860,8 +4196,7 @@ class ValidationController {
3860
4196
  forView(parser) {
3861
4197
  return {
3862
4198
  _getValidationForBinding: (binding) => {
3863
- var _a;
3864
- return (_a = this.getValidationForBinding(isBinding(binding) ? binding : parser(binding))) == null ? void 0 : _a.get();
4199
+ return this.getValidationForBinding(isBinding(binding) ? binding : parser(binding));
3865
4200
  },
3866
4201
  getAll: () => {
3867
4202
  const bindings = this.getBindings();
@@ -3881,6 +4216,9 @@ class ValidationController {
3881
4216
  get() {
3882
4217
  throw new Error("Error Access be provided by the view plugin");
3883
4218
  },
4219
+ getValidationsForBinding() {
4220
+ throw new Error("Error rollup should be provided by the view plugin");
4221
+ },
3884
4222
  getChildren() {
3885
4223
  throw new Error("Error rollup should be provided by the view plugin");
3886
4224
  },
@@ -3891,7 +4229,7 @@ class ValidationController {
3891
4229
  throw new Error("Tracking should be provided by the view plugin");
3892
4230
  },
3893
4231
  register: () => {
3894
- throw new Error("Section funcationality hould be provided by the view plugin");
4232
+ throw new Error("Section functionality should be provided by the view plugin");
3895
4233
  },
3896
4234
  type: (binding) => this.schema.getType(isBinding(binding) ? binding : parser(binding))
3897
4235
  };
@@ -4007,10 +4345,11 @@ class AssetTransformCorePlugin {
4007
4345
  };
4008
4346
  };
4009
4347
  resolver.hooks.beforeResolve.tap("asset-transform", (node, options) => {
4348
+ var _a;
4010
4349
  if (node && (node.type === "asset" || node.type === "view")) {
4011
4350
  const transform = this.registry.get(node.value);
4012
4351
  if (transform == null ? void 0 : transform.beforeResolve) {
4013
- const store = getStore(node, this.beforeResolveSymbol);
4352
+ const store = getStore((_a = options.node) != null ? _a : node, this.beforeResolveSymbol);
4014
4353
  return transform.beforeResolve(node, options, store);
4015
4354
  }
4016
4355
  }
@@ -4088,14 +4427,26 @@ class ViewController {
4088
4427
  }
4089
4428
  });
4090
4429
  });
4091
- options.model.hooks.onUpdate.tap("viewController", (updates) => {
4430
+ const update = (updates) => {
4092
4431
  if (this.currentView) {
4093
4432
  if (this.optimizeUpdates) {
4094
- this.queueUpdate(new Set(updates.map((t) => t.binding)));
4433
+ this.queueUpdate(updates);
4095
4434
  } else {
4096
4435
  this.currentView.update();
4097
4436
  }
4098
4437
  }
4438
+ };
4439
+ options.model.hooks.onUpdate.tap("viewController", (updates) => {
4440
+ update(new Set(updates.map((t) => t.binding)));
4441
+ });
4442
+ options.model.hooks.onDelete.tap("viewController", (binding) => {
4443
+ const parentBinding = binding.parent();
4444
+ const property = binding.key();
4445
+ if (typeof property === "number" && parentBinding) {
4446
+ update(new Set([parentBinding]));
4447
+ } else {
4448
+ update(new Set([binding]));
4449
+ }
4099
4450
  });
4100
4451
  }
4101
4452
  queueUpdate(bindings) {
@@ -4140,6 +4491,25 @@ class ViewController {
4140
4491
  }
4141
4492
  }
4142
4493
 
4494
+ class ReadOnlyDataController {
4495
+ constructor(controller, logger) {
4496
+ this.controller = controller;
4497
+ this.logger = logger;
4498
+ }
4499
+ get(binding, options) {
4500
+ return this.controller.get(binding, options);
4501
+ }
4502
+ set(transaction, options) {
4503
+ var _a;
4504
+ (_a = this.logger) == null ? void 0 : _a.error("Error: Tried to set in a read only instance of the DataController");
4505
+ return [];
4506
+ }
4507
+ delete(binding, options) {
4508
+ var _a;
4509
+ (_a = this.logger) == null ? void 0 : _a.error("Error: Tried to delete in a read only instance of the DataController");
4510
+ }
4511
+ }
4512
+
4143
4513
  class DataController {
4144
4514
  constructor(model, options) {
4145
4515
  this.hooks = {
@@ -4196,16 +4566,19 @@ class DataController {
4196
4566
  });
4197
4567
  }
4198
4568
  const setUpdates = normalizedTransaction.reduce((updates, [binding, newVal]) => {
4199
- var _a;
4569
+ var _a, _b;
4200
4570
  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
- });
4571
+ const update = {
4572
+ binding,
4573
+ newValue: newVal,
4574
+ oldValue: oldVal
4575
+ };
4576
+ if (dequal.dequal(oldVal, newVal)) {
4577
+ (_a = this.logger) == null ? void 0 : _a.debug(`Skipping update for path: ${binding.asString()}. Value was unchanged: ${oldVal}`);
4578
+ } else {
4579
+ updates.push(update);
4580
+ (_b = this.logger) == null ? void 0 : _b.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4207
4581
  }
4208
- (_a = this.logger) == null ? void 0 : _a.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4209
4582
  return updates;
4210
4583
  }, []);
4211
4584
  const result = this.getModel().set(normalizedTransaction, options);
@@ -4218,17 +4591,16 @@ class DataController {
4218
4591
  }
4219
4592
  });
4220
4593
  this.hooks.onSet.call(normalizedTransaction);
4221
- this.hooks.onSet.call(normalizedTransaction);
4222
4594
  if (setUpdates.length > 0) {
4223
4595
  this.hooks.onUpdate.call(setUpdates, options);
4224
4596
  }
4225
4597
  return result;
4226
4598
  }
4227
- resolve(binding) {
4228
- return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding) : binding;
4599
+ resolve(binding, readOnly) {
4600
+ return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding, { readOnly }) : binding;
4229
4601
  }
4230
4602
  get(binding, options) {
4231
- const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding);
4603
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, true);
4232
4604
  let result = this.getModel().get(resolved, options);
4233
4605
  if (result === void 0 && !(options == null ? void 0 : options.ignoreDefaultValue)) {
4234
4606
  const defaultVal = this.hooks.resolveDefaultValue.call(resolved);
@@ -4238,48 +4610,33 @@ class DataController {
4238
4610
  }
4239
4611
  if (options == null ? void 0 : options.formatted) {
4240
4612
  result = this.hooks.format.call(result, resolved);
4613
+ } else if ((options == null ? void 0 : options.formatted) === false) {
4614
+ result = this.hooks.deformat.call(result, resolved);
4241
4615
  }
4242
4616
  this.hooks.onGet.call(binding, result);
4243
4617
  return result;
4244
4618
  }
4245
- delete(binding) {
4246
- if (binding === void 0 || binding === null) {
4247
- throw new Error(`Invalid arguments: delete expects a data path (string)`);
4248
- }
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
- }
4619
+ delete(binding, options) {
4620
+ if (typeof binding !== "string" && !Array.isArray(binding) && !(binding instanceof BindingInstance)) {
4621
+ throw new Error("Invalid arguments: delete expects a data path (string)");
4275
4622
  }
4276
- if (existedBeforeDelete && !this.get(binding)) {
4277
- this.addToTrash(binding);
4623
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, false);
4624
+ const parentBinding = resolved.parent();
4625
+ const property = resolved.key();
4626
+ const parentValue = this.get(parentBinding);
4627
+ const existedBeforeDelete = typeof parentValue === "object" && parentValue !== null && Object.prototype.hasOwnProperty.call(parentValue, property);
4628
+ this.getModel().delete(resolved, options);
4629
+ if (existedBeforeDelete && !this.get(resolved)) {
4630
+ this.trash.add(resolved);
4278
4631
  }
4632
+ this.hooks.onDelete.call(resolved);
4279
4633
  }
4280
4634
  serialize() {
4281
4635
  return this.hooks.serialize.call(this.get(""));
4282
4636
  }
4637
+ makeReadOnly() {
4638
+ return new ReadOnlyDataController(this, this.logger);
4639
+ }
4283
4640
  }
4284
4641
 
4285
4642
  var __defProp$1 = Object.defineProperty;
@@ -4336,10 +4693,15 @@ class ConstantsController {
4336
4693
  this.tempStore.set(namespace, new LocalModel(data));
4337
4694
  }
4338
4695
  }
4339
- clearTemporaryValues() {
4340
- this.tempStore.forEach((value) => {
4341
- value.reset();
4342
- });
4696
+ clearTemporaryValues(namespace) {
4697
+ var _a;
4698
+ if (namespace) {
4699
+ (_a = this.tempStore.get(namespace)) == null ? void 0 : _a.reset();
4700
+ } else {
4701
+ this.tempStore.forEach((value) => {
4702
+ value.reset();
4703
+ });
4704
+ }
4343
4705
  }
4344
4706
  }
4345
4707
 
@@ -4377,6 +4739,39 @@ class FlowExpPlugin {
4377
4739
  }
4378
4740
  }
4379
4741
 
4742
+ const createFormatFunction = (schema) => {
4743
+ const handler = (ctx, value, formatName) => {
4744
+ var _a, _b;
4745
+ return (_b = (_a = schema.getFormatterForType({ type: formatName })) == null ? void 0 : _a.format(value)) != null ? _b : value;
4746
+ };
4747
+ return handler;
4748
+ };
4749
+ class DefaultExpPlugin {
4750
+ constructor() {
4751
+ this.name = "flow-exp-plugin";
4752
+ }
4753
+ apply(player) {
4754
+ let formatFunction;
4755
+ player.hooks.schema.tap(this.name, (schemaController) => {
4756
+ formatFunction = createFormatFunction(schemaController);
4757
+ });
4758
+ player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
4759
+ if (formatFunction) {
4760
+ expEvaluator.addExpressionFunction("format", formatFunction);
4761
+ }
4762
+ expEvaluator.addExpressionFunction("log", (ctx, ...args) => {
4763
+ player.logger.info(...args);
4764
+ });
4765
+ expEvaluator.addExpressionFunction("debug", (ctx, ...args) => {
4766
+ player.logger.debug(...args);
4767
+ });
4768
+ expEvaluator.addExpressionFunction("eval", (ctx, ...args) => {
4769
+ return ctx.evaluate(...args);
4770
+ });
4771
+ });
4772
+ }
4773
+ }
4774
+
4380
4775
  const NOT_STARTED_STATE = {
4381
4776
  ref: Symbol("not-started"),
4382
4777
  status: "not-started"
@@ -4421,8 +4816,8 @@ var __async = (__this, __arguments, generator) => {
4421
4816
  step((generator = generator.apply(__this, __arguments)).next());
4422
4817
  });
4423
4818
  };
4424
- const PLAYER_VERSION = "0.4.0";
4425
- const COMMIT = "39b851fc45e4903eae2f5b0697dea142c890443c";
4819
+ const PLAYER_VERSION = "0.4.1-next.0";
4820
+ const COMMIT = "3fca14a3bf47195b400f5989a2f3ecbc5f73ac4b";
4426
4821
  const _Player = class {
4427
4822
  constructor(config) {
4428
4823
  this.logger = new TapableLogger();
@@ -4443,14 +4838,15 @@ const _Player = class {
4443
4838
  resolveFlowContent: new tapableTs.SyncWaterfallHook()
4444
4839
  };
4445
4840
  var _a;
4446
- const initialPlugins = [];
4447
- const flowExpPlugin = new FlowExpPlugin();
4448
- initialPlugins.push(flowExpPlugin);
4449
4841
  if (config == null ? void 0 : config.logger) {
4450
4842
  this.logger.addHandler(config.logger);
4451
4843
  }
4452
4844
  this.config = config || {};
4453
- this.config.plugins = [...this.config.plugins || [], ...initialPlugins];
4845
+ this.config.plugins = [
4846
+ new DefaultExpPlugin(),
4847
+ ...this.config.plugins || [],
4848
+ new FlowExpPlugin()
4849
+ ];
4454
4850
  (_a = this.config.plugins) == null ? void 0 : _a.forEach((plugin) => {
4455
4851
  plugin.apply(this);
4456
4852
  });
@@ -4541,10 +4937,11 @@ const _Player = class {
4541
4937
  flowResultDeferred.reject(e);
4542
4938
  return true;
4543
4939
  });
4544
- function resolveStrings(val) {
4940
+ function resolveStrings(val, formatted) {
4545
4941
  return resolveDataRefs(val, {
4546
4942
  model: dataController,
4547
- evaluate: expressionEvaluator.evaluate
4943
+ evaluate: expressionEvaluator.evaluate,
4944
+ formatted
4548
4945
  });
4549
4946
  }
4550
4947
  flowController.hooks.flow.tap("player", (flow) => {
@@ -4580,23 +4977,21 @@ const _Player = class {
4580
4977
  newState = timm.setIn(state, ["ref"], resolveStrings(state.ref));
4581
4978
  }
4582
4979
  if ("param" in state) {
4583
- newState = timm.setIn(state, ["param"], resolveStrings(state.param));
4980
+ newState = timm.setIn(state, ["param"], resolveStrings(state.param, false));
4584
4981
  }
4585
4982
  return newState;
4586
4983
  });
4587
4984
  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
- });
4985
+ if (newState.value.state_type !== "VIEW") {
4986
+ validationController.reset();
4987
+ }
4988
+ });
4989
+ flow.hooks.afterTransition.tap("player", (flowInstance) => {
4990
+ var _a;
4991
+ const value = (_a = flowInstance.currentState) == null ? void 0 : _a.value;
4992
+ if (value && value.state_type === "ACTION") {
4993
+ const { exp } = value;
4994
+ flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4600
4995
  }
4601
4996
  expressionEvaluator.reset();
4602
4997
  });
@@ -4614,6 +5009,11 @@ const _Player = class {
4614
5009
  parseBinding,
4615
5010
  transition: flowController.transition,
4616
5011
  model: dataController,
5012
+ utils: {
5013
+ findPlugin: (pluginSymbol) => {
5014
+ return this.findPlugin(pluginSymbol);
5015
+ }
5016
+ },
4617
5017
  logger: this.logger,
4618
5018
  flowController,
4619
5019
  schema,
@@ -4627,23 +5027,19 @@ const _Player = class {
4627
5027
  },
4628
5028
  validation: __spreadProps(__spreadValues({}, validationController.forView(parseBinding)), {
4629
5029
  type: (b) => schema.getType(parseBinding(b))
4630
- })
5030
+ }),
5031
+ constants: this.constantsController
4631
5032
  });
4632
5033
  viewController.hooks.view.tap("player", (view) => {
4633
5034
  validationController.onView(view);
4634
5035
  this.hooks.view.call(view);
4635
5036
  });
4636
5037
  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
5038
  return {
4643
5039
  start: () => {
4644
5040
  flowController.start().then((endState) => {
4645
5041
  const flowResult = {
4646
- endState: resolveStrings(endState),
5042
+ endState: resolveStrings(endState, false),
4647
5043
  data: dataController.serialize()
4648
5044
  };
4649
5045
  return flowResult;
@@ -4696,7 +5092,9 @@ const _Player = class {
4696
5092
  ref,
4697
5093
  status: "completed",
4698
5094
  flow: state.flow,
4699
- dataModel: state.controllers.data.getModel()
5095
+ controllers: {
5096
+ data: state.controllers.data.makeReadOnly()
5097
+ }
4700
5098
  };
4701
5099
  return maybeUpdateState(__spreadValues(__spreadValues({}, yield state.flowResult), endProps));
4702
5100
  } catch (error) {
@@ -4720,6 +5118,7 @@ Player.info = {
4720
5118
 
4721
5119
  exports.ApplicabilityPlugin = ApplicabilityPlugin;
4722
5120
  exports.AssetTransformCorePlugin = AssetTransformCorePlugin;
5121
+ exports.BINDING_BRACKETS_REGEX = BINDING_BRACKETS_REGEX;
4723
5122
  exports.BindingInstance = BindingInstance;
4724
5123
  exports.BindingParser = BindingParser;
4725
5124
  exports.Builder = Builder;
@@ -4747,12 +5146,15 @@ exports.Player = Player;
4747
5146
  exports.ProxyLogger = ProxyLogger;
4748
5147
  exports.ROOT_BINDING = ROOT_BINDING;
4749
5148
  exports.Resolver = Resolver;
5149
+ exports.SCHEMA_VALIDATION_PROVIDER_NAME = SCHEMA_VALIDATION_PROVIDER_NAME;
4750
5150
  exports.SIMPLE_BINDING_REGEX = SIMPLE_BINDING_REGEX;
4751
5151
  exports.SchemaController = SchemaController;
4752
5152
  exports.StringResolverPlugin = StringResolverPlugin;
4753
5153
  exports.SwitchPlugin = SwitchPlugin;
4754
5154
  exports.TapableLogger = TapableLogger;
4755
5155
  exports.TemplatePlugin = TemplatePlugin;
5156
+ exports.VALIDATION_PROVIDER_NAME_SYMBOL = VALIDATION_PROVIDER_NAME_SYMBOL;
5157
+ exports.VIEW_VALIDATION_PROVIDER_NAME = VIEW_VALIDATION_PROVIDER_NAME;
4756
5158
  exports.ValidationBindingTrackerViewPlugin = ValidationBindingTrackerViewPlugin;
4757
5159
  exports.ValidationController = ValidationController;
4758
5160
  exports.ValidationMiddleware = ValidationMiddleware;
@@ -4767,8 +5169,11 @@ exports.findNextExp = findNextExp;
4767
5169
  exports.getBindingSegments = getBindingSegments;
4768
5170
  exports.isBinding = isBinding;
4769
5171
  exports.isExpressionNode = isExpressionNode;
5172
+ exports.isObjectExpression = isObjectExpression;
4770
5173
  exports.maybeConvertToNum = maybeConvertToNum;
4771
5174
  exports.parse = parse;
5175
+ exports.parseExpression = parseExpression;
5176
+ exports.removeBindingAndChildrenFromMap = removeBindingAndChildrenFromMap;
4772
5177
  exports.resolveDataRefs = resolveDataRefs;
4773
5178
  exports.resolveDataRefsInString = resolveDataRefsInString;
4774
5179
  exports.resolveExpressionsInString = resolveExpressionsInString;