@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.esm.js CHANGED
@@ -1,11 +1,11 @@
1
1
  export * from '@player-ui/types';
2
2
  import { SyncBailHook, SyncWaterfallHook, SyncHook } from 'tapable-ts';
3
- import NestedError from 'nested-error-stacks';
3
+ import { NestedError } from 'ts-nested-error';
4
4
  import flatten$1 from 'arr-flatten';
5
5
  import P from 'parsimmon';
6
6
  import { Grammars } from 'ebnf';
7
7
  import get from 'dlv';
8
- import { setIn, addLast, set, omit, removeAt } from 'timm';
8
+ import { setIn, removeAt, omit, clone, addLast, set } from 'timm';
9
9
  import { dequal } from 'dequal';
10
10
  import defer from 'p-defer';
11
11
  import queueMicrotask from 'queue-microtask';
@@ -93,7 +93,8 @@ const isIdentifierChar = (char) => {
93
93
  return false;
94
94
  }
95
95
  const charCode = char.charCodeAt(0);
96
- return charCode >= 48 && charCode <= 57 || charCode >= 65 && charCode <= 90 || charCode >= 97 && charCode <= 122 || charCode === 95 || charCode === 45 || charCode === 64;
96
+ 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;
97
+ return !matches;
97
98
  };
98
99
  const parse$1 = (path) => {
99
100
  let index = 1;
@@ -457,6 +458,8 @@ var __spreadValues$d = (a, b) => {
457
458
  return a;
458
459
  };
459
460
  const SIMPLE_BINDING_REGEX = /^[\w\-@]+(\.[\w\-@]+)*$/;
461
+ const BINDING_BRACKETS_REGEX = /[\s()*=`{}'"[\]]/;
462
+ const LAZY_BINDING_REGEX = /^[^.]+(\..+)*$/;
460
463
  const DEFAULT_OPTIONS = {
461
464
  get: () => {
462
465
  throw new Error("Not Implemented");
@@ -481,7 +484,7 @@ class BindingParser {
481
484
  }
482
485
  normalizePath(path, resolveOptions) {
483
486
  var _a, _b;
484
- if (path.match(SIMPLE_BINDING_REGEX) && this.hooks.skipOptimization.call(path) !== true) {
487
+ if (!BINDING_BRACKETS_REGEX.test(path) && LAZY_BINDING_REGEX.test(path) && this.hooks.skipOptimization.call(path) !== true) {
485
488
  return { path: path.split("."), updates: void 0 };
486
489
  }
487
490
  const ast = (_a = this.parseCache[path]) != null ? _a : parse$1(path);
@@ -542,7 +545,7 @@ class BindingParser {
542
545
  updates = __spreadValues$d(__spreadValues$d({}, updates), normalized.updates);
543
546
  }
544
547
  const updateKeys = Object.keys(updates);
545
- if (updateKeys.length > 0) {
548
+ if (!options.readOnly && updateKeys.length > 0) {
546
549
  const updateTransaction = updateKeys.map((updatedBinding) => [
547
550
  this.parse(updatedBinding),
548
551
  updates[updatedBinding]
@@ -638,6 +641,10 @@ class DependencyMiddleware extends DependencyTracker {
638
641
  this.addReadDep(binding);
639
642
  return next == null ? void 0 : next.get(binding, options);
640
643
  }
644
+ delete(binding, options, next) {
645
+ this.addWriteDep(binding);
646
+ return next == null ? void 0 : next.delete(binding, options);
647
+ }
641
648
  }
642
649
  class DependencyModel extends DependencyTracker {
643
650
  constructor(rootModel) {
@@ -654,6 +661,10 @@ class DependencyModel extends DependencyTracker {
654
661
  this.addReadDep(binding);
655
662
  return this.rootModel.get(binding, options);
656
663
  }
664
+ delete(binding, options) {
665
+ this.addWriteDep(binding);
666
+ return this.rootModel.delete(binding, options);
667
+ }
657
668
  }
658
669
 
659
670
  class NOOPDataModel {
@@ -663,15 +674,18 @@ class NOOPDataModel {
663
674
  set() {
664
675
  return [];
665
676
  }
677
+ delete() {
678
+ }
666
679
  }
667
680
  const NOOP_MODEL = new NOOPDataModel();
668
681
 
669
682
  const ROOT_BINDING = new BindingInstance([]);
670
683
  function withParser(model, parseBinding) {
671
- function maybeParse(binding) {
684
+ function maybeParse(binding, readOnly) {
672
685
  const parsed = isBinding(binding) ? binding : parseBinding(binding, {
673
686
  get: model.get,
674
- set: model.set
687
+ set: model.set,
688
+ readOnly
675
689
  });
676
690
  if (!parsed) {
677
691
  throw new Error("Unable to parse binding");
@@ -680,10 +694,13 @@ function withParser(model, parseBinding) {
680
694
  }
681
695
  return {
682
696
  get(binding, options) {
683
- return model.get(maybeParse(binding), options);
697
+ return model.get(maybeParse(binding, true), options);
684
698
  },
685
699
  set(transaction, options) {
686
- return model.set(transaction.map(([key, val]) => [maybeParse(key), val]), options);
700
+ return model.set(transaction.map(([key, val]) => [maybeParse(key, false), val]), options);
701
+ },
702
+ delete(binding, options) {
703
+ return model.delete(maybeParse(binding, false), options);
687
704
  }
688
705
  };
689
706
  }
@@ -692,8 +709,27 @@ function toModel(middleware, defaultOptions, next) {
692
709
  return middleware;
693
710
  }
694
711
  return {
695
- get: (binding, options) => middleware.get(binding, options != null ? options : defaultOptions, next),
696
- set: (transaction, options) => middleware.set(transaction, options != null ? options : defaultOptions, next)
712
+ get: (binding, options) => {
713
+ const resolvedOptions = options != null ? options : defaultOptions;
714
+ if (middleware.get) {
715
+ return middleware.get(binding, resolvedOptions, next);
716
+ }
717
+ return next == null ? void 0 : next.get(binding, resolvedOptions);
718
+ },
719
+ set: (transaction, options) => {
720
+ const resolvedOptions = options != null ? options : defaultOptions;
721
+ if (middleware.set) {
722
+ return middleware.set(transaction, resolvedOptions, next);
723
+ }
724
+ return next == null ? void 0 : next.set(transaction, resolvedOptions);
725
+ },
726
+ delete: (binding, options) => {
727
+ const resolvedOptions = options != null ? options : defaultOptions;
728
+ if (middleware.delete) {
729
+ return middleware.delete(binding, resolvedOptions, next);
730
+ }
731
+ return next == null ? void 0 : next.delete(binding, resolvedOptions);
732
+ }
697
733
  };
698
734
  }
699
735
  function constructModelForPipeline(pipeline) {
@@ -701,7 +737,7 @@ function constructModelForPipeline(pipeline) {
701
737
  return NOOP_MODEL;
702
738
  }
703
739
  if (pipeline.length === 1) {
704
- return pipeline[0];
740
+ return toModel(pipeline[0]);
705
741
  }
706
742
  function createModelWithOptions(options) {
707
743
  var _a;
@@ -716,6 +752,10 @@ function constructModelForPipeline(pipeline) {
716
752
  set: (transaction, options) => {
717
753
  var _a;
718
754
  return (_a = createModelWithOptions(options)) == null ? void 0 : _a.set(transaction, options);
755
+ },
756
+ delete: (binding, options) => {
757
+ var _a;
758
+ return (_a = createModelWithOptions(options)) == null ? void 0 : _a.delete(binding, options);
719
759
  }
720
760
  };
721
761
  }
@@ -752,6 +792,9 @@ class PipelinedDataModel {
752
792
  get(binding, options) {
753
793
  return this.effectiveDataModel.get(binding, options);
754
794
  }
795
+ delete(binding, options) {
796
+ return this.effectiveDataModel.delete(binding, options);
797
+ }
755
798
  }
756
799
 
757
800
  class LocalModel {
@@ -778,11 +821,24 @@ class LocalModel {
778
821
  });
779
822
  return effectiveOperations;
780
823
  }
824
+ delete(binding) {
825
+ const parentBinding = binding.parent();
826
+ if (parentBinding) {
827
+ const parentValue = this.get(parentBinding);
828
+ if (parentValue !== void 0) {
829
+ if (Array.isArray(parentValue)) {
830
+ this.model = setIn(this.model, parentBinding.asArray(), removeAt(parentValue, binding.key()));
831
+ } else {
832
+ this.model = setIn(this.model, parentBinding.asArray(), omit(parentValue, binding.key()));
833
+ }
834
+ }
835
+ }
836
+ }
781
837
  }
782
838
 
783
839
  const ExpNodeOpaqueIdentifier = Symbol("Expression Node ID");
784
840
  function isExpressionNode(x) {
785
- return typeof x === "object" && x.__id === ExpNodeOpaqueIdentifier;
841
+ return typeof x === "object" && x !== null && !Array.isArray(x) && x.__id === ExpNodeOpaqueIdentifier;
786
842
  }
787
843
 
788
844
  const PERIOD_CODE = 46;
@@ -896,7 +952,9 @@ function isIdentifierPart(ch) {
896
952
  function isModelRefStart(ch0, ch1) {
897
953
  return ch0 === OCURL_CODE && ch1 === OCURL_CODE;
898
954
  }
899
- function parseExpression(expr) {
955
+ function parseExpression(expr, options) {
956
+ var _a;
957
+ const strictMode = (_a = options == null ? void 0 : options.strict) != null ? _a : true;
900
958
  const charAtFunc = expr.charAt;
901
959
  const charCodeAtFunc = expr.charCodeAt;
902
960
  const { length } = expr;
@@ -1290,6 +1348,9 @@ function parseExpression(expr) {
1290
1348
  }
1291
1349
  args.push(node);
1292
1350
  }
1351
+ if (charIndex !== termination) {
1352
+ throwError(`Expected ${String.fromCharCode(termination)}`, index);
1353
+ }
1293
1354
  return args;
1294
1355
  }
1295
1356
  function gobbleVariable() {
@@ -1360,28 +1421,41 @@ function parseExpression(expr) {
1360
1421
  };
1361
1422
  }
1362
1423
  const nodes = [];
1363
- while (index < length) {
1364
- const chIndex = exprICode(index);
1365
- if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1366
- index++;
1367
- continue;
1424
+ try {
1425
+ while (index < length) {
1426
+ const chIndex = exprICode(index);
1427
+ if (chIndex === SEMCOL_CODE || chIndex === COMMA_CODE) {
1428
+ index++;
1429
+ continue;
1430
+ }
1431
+ const node = gobbleExpression();
1432
+ if (node) {
1433
+ nodes.push(node);
1434
+ } else if (index < length) {
1435
+ throwError(`Unexpected "${exprI(index)}"`, index);
1436
+ }
1368
1437
  }
1369
- const node = gobbleExpression();
1370
- if (node) {
1371
- nodes.push(node);
1372
- } else if (index < length) {
1373
- throwError(`Unexpected "${exprI(index)}"`, index);
1438
+ if (nodes.length === 1) {
1439
+ return nodes[0];
1374
1440
  }
1441
+ return {
1442
+ __id: ExpNodeOpaqueIdentifier,
1443
+ type: "Compound",
1444
+ body: nodes,
1445
+ location: getLocation(0)
1446
+ };
1447
+ } catch (e) {
1448
+ if (strictMode || !(e instanceof Error)) {
1449
+ throw e;
1450
+ }
1451
+ return {
1452
+ __id: ExpNodeOpaqueIdentifier,
1453
+ type: "Compound",
1454
+ body: nodes,
1455
+ location: getLocation(0),
1456
+ error: e
1457
+ };
1375
1458
  }
1376
- if (nodes.length === 1) {
1377
- return nodes[0];
1378
- }
1379
- return {
1380
- __id: ExpNodeOpaqueIdentifier,
1381
- type: "Compound",
1382
- body: nodes,
1383
- location: getLocation(0)
1384
- };
1385
1459
  }
1386
1460
 
1387
1461
  const setDataVal = (_context, binding, value) => {
@@ -1391,16 +1465,108 @@ const getDataVal = (_context, binding) => {
1391
1465
  return _context.model.get(binding);
1392
1466
  };
1393
1467
  const deleteDataVal = (_context, binding) => {
1394
- return _context.model.set([[binding, void 0]]);
1468
+ return _context.model.delete(binding);
1469
+ };
1470
+ const conditional = (ctx, condition, ifTrue, ifFalse) => {
1471
+ const resolution = ctx.evaluate(condition);
1472
+ if (resolution) {
1473
+ return ctx.evaluate(ifTrue);
1474
+ }
1475
+ if (ifFalse) {
1476
+ return ctx.evaluate(ifFalse);
1477
+ }
1478
+ return null;
1395
1479
  };
1480
+ conditional.resolveParams = false;
1396
1481
 
1397
1482
  var DEFAULT_EXPRESSION_HANDLERS = /*#__PURE__*/Object.freeze({
1398
1483
  __proto__: null,
1399
1484
  setDataVal: setDataVal,
1400
1485
  getDataVal: getDataVal,
1401
- deleteDataVal: deleteDataVal
1486
+ deleteDataVal: deleteDataVal,
1487
+ conditional: conditional
1402
1488
  });
1403
1489
 
1490
+ function withoutContext(fn) {
1491
+ return (_context, ...args) => fn(...args);
1492
+ }
1493
+ function isInRange(position, location) {
1494
+ return position.character >= location.start.character && position.character <= location.end.character;
1495
+ }
1496
+ function findClosestNodeAtPosition(node, position) {
1497
+ var _a, _b, _c, _d, _e;
1498
+ switch (node.type) {
1499
+ case "Modification":
1500
+ case "Assignment":
1501
+ case "LogicalExpression":
1502
+ case "BinaryExpression": {
1503
+ const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1504
+ if (check) {
1505
+ return check;
1506
+ }
1507
+ break;
1508
+ }
1509
+ case "UnaryExpression": {
1510
+ const checkArg = findClosestNodeAtPosition(node.argument, position);
1511
+ if (checkArg) {
1512
+ return checkArg;
1513
+ }
1514
+ break;
1515
+ }
1516
+ case "MemberExpression": {
1517
+ const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1518
+ if (checkObject) {
1519
+ return checkObject;
1520
+ }
1521
+ break;
1522
+ }
1523
+ case "ConditionalExpression": {
1524
+ const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1525
+ if (checkObject) {
1526
+ return checkObject;
1527
+ }
1528
+ break;
1529
+ }
1530
+ case "ArrayExpression":
1531
+ case "Compound": {
1532
+ const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1533
+ const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1534
+ if (anyElements) {
1535
+ return anyElements;
1536
+ }
1537
+ break;
1538
+ }
1539
+ case "Object": {
1540
+ const checkObject = node.attributes.reduce((found, next) => {
1541
+ var _a2;
1542
+ return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1543
+ }, void 0);
1544
+ if (checkObject) {
1545
+ return checkObject;
1546
+ }
1547
+ break;
1548
+ }
1549
+ case "CallExpression": {
1550
+ const anyArgs = (_e = node.args.find((arg) => {
1551
+ return findClosestNodeAtPosition(arg, position);
1552
+ })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1553
+ if (anyArgs) {
1554
+ return anyArgs;
1555
+ }
1556
+ break;
1557
+ }
1558
+ }
1559
+ if (node.location && isInRange(position, node.location)) {
1560
+ return node;
1561
+ }
1562
+ }
1563
+ function isObjectExpression(expr) {
1564
+ if (isExpressionNode(expr)) {
1565
+ return false;
1566
+ }
1567
+ return typeof expr === "object" && expr !== null && !Array.isArray(expr) && "value" in expr;
1568
+ }
1569
+
1404
1570
  var __defProp$c = Object.defineProperty;
1405
1571
  var __defProps$a = Object.defineProperties;
1406
1572
  var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
@@ -1461,6 +1627,8 @@ class ExpressionEvaluator {
1461
1627
  this.vars = {};
1462
1628
  this.hooks = {
1463
1629
  resolve: new SyncWaterfallHook(),
1630
+ resolveOptions: new SyncWaterfallHook(),
1631
+ beforeEvaluate: new SyncWaterfallHook(),
1464
1632
  onError: new SyncBailHook()
1465
1633
  };
1466
1634
  this.expressionsCache = new Map();
@@ -1479,21 +1647,25 @@ class ExpressionEvaluator {
1479
1647
  reset() {
1480
1648
  this.expressionsCache.clear();
1481
1649
  }
1482
- evaluate(expression, options) {
1483
- const opts = __spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1484
- resolveNode: (node) => this._execAST(node, opts)
1485
- });
1650
+ evaluate(expr, options) {
1651
+ var _a;
1652
+ const resolvedOpts = this.hooks.resolveOptions.call(__spreadProps$a(__spreadValues$c(__spreadValues$c({}, this.defaultHookOptions), options), {
1653
+ resolveNode: (node) => this._execAST(node, resolvedOpts)
1654
+ }));
1655
+ let expression = (_a = this.hooks.beforeEvaluate.call(expr, resolvedOpts)) != null ? _a : expr;
1656
+ while (isObjectExpression(expression)) {
1657
+ expression = expression.value;
1658
+ }
1486
1659
  if (typeof expression === "number" || typeof expression === "boolean" || expression === void 0 || expression === null) {
1487
1660
  return expression;
1488
1661
  }
1489
1662
  if (isExpressionNode(expression)) {
1490
- return this._execAST(expression, opts);
1663
+ return this._execAST(expression, resolvedOpts);
1491
1664
  }
1492
- if (typeof expression === "object") {
1493
- const values = Array.isArray(expression) ? expression : Object.values(expression);
1494
- return values.reduce((_nothing, exp) => this.evaluate(exp, options), null);
1665
+ if (Array.isArray(expression)) {
1666
+ return expression.reduce((_nothing, exp) => this.evaluate(exp, options), null);
1495
1667
  }
1496
- return this._execString(String(expression), opts);
1668
+ return this._execString(String(expression), resolvedOpts);
1497
1669
  }
1498
1670
  addExpressionFunction(name, handler) {
1499
1671
  this.operators.expressions.set(name, handler);
@@ -1531,7 +1703,7 @@ class ExpressionEvaluator {
1531
1703
  this.expressionsCache.set(matchedExp, expAST);
1532
1704
  return this._execAST(expAST, options);
1533
1705
  } catch (e) {
1534
- if (!this.hooks.onError.call(e)) {
1706
+ if (options.throwErrors || !this.hooks.onError.call(e)) {
1535
1707
  throw e;
1536
1708
  }
1537
1709
  }
@@ -1585,25 +1757,18 @@ class ExpressionEvaluator {
1585
1757
  }
1586
1758
  if (node.type === "CallExpression") {
1587
1759
  const expressionName = node.callTarget.name;
1588
- if (expressionName === "conditional") {
1589
- const condition = resolveNode(node.args[0]);
1590
- if (condition) {
1591
- return resolveNode(node.args[1]);
1592
- }
1593
- if (node.args[2]) {
1594
- return resolveNode(node.args[2]);
1595
- }
1596
- return null;
1597
- }
1598
1760
  const operator = this.operators.expressions.get(expressionName);
1599
1761
  if (!operator) {
1600
1762
  throw new Error(`Unknown expression function: ${expressionName}`);
1601
1763
  }
1764
+ if ("resolveParams" in operator && operator.resolveParams === false) {
1765
+ return operator(expressionContext, ...node.args);
1766
+ }
1602
1767
  const args = node.args.map((n) => resolveNode(n));
1603
1768
  return operator(expressionContext, ...args);
1604
1769
  }
1605
1770
  if (node.type === "ModelRef") {
1606
- return model.get(node.ref);
1771
+ return model.get(node.ref, { context: { model: options.model } });
1607
1772
  }
1608
1773
  if (node.type === "MemberExpression") {
1609
1774
  const obj = resolveNode(node.object);
@@ -1655,80 +1820,6 @@ class ExpressionEvaluator {
1655
1820
  }
1656
1821
  }
1657
1822
 
1658
- function withoutContext(fn) {
1659
- return (_context, ...args) => fn(...args);
1660
- }
1661
- function isInRange(position, location) {
1662
- return position.character >= location.start.character && position.character <= location.end.character;
1663
- }
1664
- function findClosestNodeAtPosition(node, position) {
1665
- var _a, _b, _c, _d, _e;
1666
- switch (node.type) {
1667
- case "Modification":
1668
- case "Assignment":
1669
- case "LogicalExpression":
1670
- case "BinaryExpression": {
1671
- const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1672
- if (check) {
1673
- return check;
1674
- }
1675
- break;
1676
- }
1677
- case "UnaryExpression": {
1678
- const checkArg = findClosestNodeAtPosition(node.argument, position);
1679
- if (checkArg) {
1680
- return checkArg;
1681
- }
1682
- break;
1683
- }
1684
- case "MemberExpression": {
1685
- const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1686
- if (checkObject) {
1687
- return checkObject;
1688
- }
1689
- break;
1690
- }
1691
- case "ConditionalExpression": {
1692
- const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1693
- if (checkObject) {
1694
- return checkObject;
1695
- }
1696
- break;
1697
- }
1698
- case "ArrayExpression":
1699
- case "Compound": {
1700
- const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1701
- const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1702
- if (anyElements) {
1703
- return anyElements;
1704
- }
1705
- break;
1706
- }
1707
- case "Object": {
1708
- const checkObject = node.attributes.reduce((found, next) => {
1709
- var _a2;
1710
- return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1711
- }, void 0);
1712
- if (checkObject) {
1713
- return checkObject;
1714
- }
1715
- break;
1716
- }
1717
- case "CallExpression": {
1718
- const anyArgs = (_e = node.args.find((arg) => {
1719
- return findClosestNodeAtPosition(arg, position);
1720
- })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1721
- if (anyArgs) {
1722
- return anyArgs;
1723
- }
1724
- break;
1725
- }
1726
- }
1727
- if (node.location && isInRange(position, node.location)) {
1728
- return node;
1729
- }
1730
- }
1731
-
1732
1823
  const severities = ["trace", "debug", "info", "warn", "error"];
1733
1824
 
1734
1825
  class ConsoleLogger {
@@ -1885,6 +1976,9 @@ function parse(schema) {
1885
1976
  if (type.isArray) {
1886
1977
  nestedPath.push("[]");
1887
1978
  }
1979
+ if (type.isRecord) {
1980
+ nestedPath.push("{}");
1981
+ }
1888
1982
  if (type.type && schema[type.type]) {
1889
1983
  parseQueue.push({
1890
1984
  path: nestedPath,
@@ -1933,8 +2027,20 @@ class SchemaController {
1933
2027
  if (cached) {
1934
2028
  return cached;
1935
2029
  }
1936
- const normalized = binding.asArray().map((p) => typeof p === "number" ? "[]" : p).join(".");
1937
- this.bindingSchemaNormalizedCache.set(binding, normalized);
2030
+ let bindingArray = binding.asArray();
2031
+ let normalized = bindingArray.map((p) => typeof p === "number" ? "[]" : p).join(".");
2032
+ if (normalized) {
2033
+ this.bindingSchemaNormalizedCache.set(binding, normalized);
2034
+ bindingArray = normalized.split(".");
2035
+ }
2036
+ bindingArray.forEach((item) => {
2037
+ const recordBinding = bindingArray.map((p) => p === item ? "{}" : p).join(".");
2038
+ if (this.schema.get(recordBinding)) {
2039
+ this.bindingSchemaNormalizedCache.set(binding, recordBinding);
2040
+ bindingArray = recordBinding.split(".");
2041
+ normalized = recordBinding;
2042
+ }
2043
+ });
1938
2044
  return normalized;
1939
2045
  }
1940
2046
  getType(binding) {
@@ -2021,6 +2127,9 @@ function findNextExp(str) {
2021
2127
  };
2022
2128
  }
2023
2129
  function resolveExpressionsInString(val, { evaluate }) {
2130
+ if (!evaluate) {
2131
+ return val;
2132
+ }
2024
2133
  const expMatch = /@\[.*?\]@/;
2025
2134
  let newVal = val;
2026
2135
  let match = newVal.match(expMatch);
@@ -2038,9 +2147,9 @@ function resolveExpressionsInString(val, { evaluate }) {
2038
2147
  return newVal;
2039
2148
  }
2040
2149
  function resolveDataRefsInString(val, options) {
2041
- const { model } = options;
2150
+ const { model, formatted = true } = options;
2042
2151
  let workingString = resolveExpressionsInString(val, options);
2043
- if (typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2152
+ if (!model || typeof workingString !== "string" || workingString.indexOf(DOUBLE_OPEN_CURLY) === -1) {
2044
2153
  return workingString;
2045
2154
  }
2046
2155
  while (workingString.indexOf(DOUBLE_OPEN_CURLY) !== -1) {
@@ -2050,7 +2159,7 @@ function resolveDataRefsInString(val, options) {
2050
2159
  }
2051
2160
  const { start, end } = expLocation;
2052
2161
  const binding = workingString.substring(start + DOUBLE_OPEN_CURLY.length, end - DOUBLE_OPEN_CURLY.length).trim();
2053
- const evaledVal = model.get(binding, { formatted: true });
2162
+ const evaledVal = model.get(binding, { formatted });
2054
2163
  if (start === 0 && end === workingString.length && typeof evaledVal !== "string") {
2055
2164
  return evaledVal;
2056
2165
  }
@@ -2069,9 +2178,9 @@ function traverseObject(val, options) {
2069
2178
  const keys = Object.keys(val);
2070
2179
  let newVal = val;
2071
2180
  if (keys.length > 0) {
2072
- for (const key of keys) {
2181
+ keys.forEach((key) => {
2073
2182
  newVal = setIn(newVal, [key], traverseObject(val[key], options));
2074
- }
2183
+ });
2075
2184
  }
2076
2185
  return newVal;
2077
2186
  }
@@ -2083,6 +2192,36 @@ function resolveDataRefs(val, options) {
2083
2192
  return traverseObject(val, options);
2084
2193
  }
2085
2194
 
2195
+ function removeBindingAndChildrenFromMap(sourceMap, binding) {
2196
+ const targetMap = new Map(sourceMap);
2197
+ const parentBinding = binding.parent();
2198
+ const property = binding.key();
2199
+ targetMap.forEach((_value, trackedBinding) => {
2200
+ if (binding === trackedBinding || binding.contains(trackedBinding)) {
2201
+ targetMap.delete(trackedBinding);
2202
+ }
2203
+ });
2204
+ if (typeof property === "number") {
2205
+ const bindingsToRewrite = Array.from(sourceMap.keys()).filter((b) => {
2206
+ if (parentBinding.contains(b)) {
2207
+ const [childIndex] = b.relative(parentBinding);
2208
+ return typeof childIndex === "number" && childIndex > property;
2209
+ }
2210
+ return false;
2211
+ }).sort();
2212
+ bindingsToRewrite.forEach((trackedBinding) => {
2213
+ const [childIndex, ...childPath] = trackedBinding.relative(parentBinding);
2214
+ if (typeof childIndex === "number") {
2215
+ const newSegments = [childIndex - 1, ...childPath];
2216
+ const newChildBinding = parentBinding.descendent(newSegments);
2217
+ targetMap.set(newChildBinding, targetMap.get(trackedBinding));
2218
+ targetMap.delete(trackedBinding);
2219
+ }
2220
+ });
2221
+ }
2222
+ return targetMap;
2223
+ }
2224
+
2086
2225
  var __defProp$a = Object.defineProperty;
2087
2226
  var __defProps$8 = Object.defineProperties;
2088
2227
  var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
@@ -2107,12 +2246,15 @@ class ValidationMiddleware {
2107
2246
  this.validator = validator;
2108
2247
  this.shadowModelPaths = new Map();
2109
2248
  this.logger = options == null ? void 0 : options.logger;
2249
+ this.shouldIncludeInvalid = options == null ? void 0 : options.shouldIncludeInvalid;
2110
2250
  }
2111
2251
  set(transaction, options, next) {
2112
2252
  const asModel = toModel(this, __spreadProps$8(__spreadValues$a({}, options), { includeInvalid: true }), next);
2113
2253
  const nextTransaction = [];
2254
+ const includedBindings = new Set();
2114
2255
  transaction.forEach(([binding, value]) => {
2115
2256
  this.shadowModelPaths.set(binding, value);
2257
+ includedBindings.add(binding);
2116
2258
  });
2117
2259
  const invalidBindings = [];
2118
2260
  this.shadowModelPaths.forEach((value, binding) => {
@@ -2123,22 +2265,25 @@ class ValidationMiddleware {
2123
2265
  } else if (validations instanceof Set) {
2124
2266
  validations.forEach((validation) => {
2125
2267
  invalidBindings.push(validation.binding);
2126
- if (!validation.isStrong) {
2268
+ if (!validation.isStrong && validation.binding.asString() === binding.asString()) {
2127
2269
  nextTransaction.push([validation.binding, value]);
2128
2270
  }
2129
2271
  });
2130
- } else {
2272
+ } else if (includedBindings.has(binding)) {
2273
+ invalidBindings.push(binding);
2131
2274
  (_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
2132
2275
  }
2133
2276
  });
2277
+ let validResults = [];
2134
2278
  if (next && nextTransaction.length > 0) {
2135
2279
  nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
2136
2280
  const result = next.set(nextTransaction, options);
2137
2281
  if (invalidBindings.length === 0) {
2138
2282
  return result;
2139
2283
  }
2284
+ validResults = result;
2140
2285
  }
2141
- return invalidBindings.map((binding) => {
2286
+ const invalidResults = invalidBindings.map((binding) => {
2142
2287
  return {
2143
2288
  binding,
2144
2289
  oldValue: asModel.get(binding),
@@ -2146,10 +2291,12 @@ class ValidationMiddleware {
2146
2291
  force: true
2147
2292
  };
2148
2293
  });
2294
+ return [...validResults, ...invalidResults];
2149
2295
  }
2150
2296
  get(binding, options, next) {
2297
+ var _a, _b;
2151
2298
  let val = next == null ? void 0 : next.get(binding, options);
2152
- if ((options == null ? void 0 : options.includeInvalid) === true) {
2299
+ if ((_b = (_a = this.shouldIncludeInvalid) == null ? void 0 : _a.call(this, options)) != null ? _b : (options == null ? void 0 : options.includeInvalid) === true) {
2153
2300
  this.shadowModelPaths.forEach((shadowValue, shadowBinding) => {
2154
2301
  if (shadowBinding === binding) {
2155
2302
  val = shadowValue;
@@ -2162,6 +2309,10 @@ class ValidationMiddleware {
2162
2309
  }
2163
2310
  return val;
2164
2311
  }
2312
+ delete(binding, options, next) {
2313
+ this.shadowModelPaths = removeBindingAndChildrenFromMap(this.shadowModelPaths, binding);
2314
+ return next == null ? void 0 : next.delete(binding, options);
2315
+ }
2165
2316
  }
2166
2317
 
2167
2318
  class ValidatorRegistry {
@@ -2246,6 +2397,9 @@ class Parser {
2246
2397
  }
2247
2398
  return tapped;
2248
2399
  }
2400
+ hasTemplateValues(obj, localKey) {
2401
+ return Object.hasOwnProperty.call(obj, "template") && Array.isArray(obj == null ? void 0 : obj.template) && obj.template.length && obj.template.find((tmpl) => tmpl.output === localKey);
2402
+ }
2249
2403
  parseObject(obj, type = NodeType.Value, options = { templateDepth: 0 }) {
2250
2404
  var _a;
2251
2405
  const nodeType = this.hooks.determineNodeType.call(obj);
@@ -2263,12 +2417,19 @@ class Parser {
2263
2417
  if (!localObj) {
2264
2418
  return currentValue;
2265
2419
  }
2266
- const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : Object.entries(localObj);
2420
+ const objEntries = Array.isArray(localObj) ? localObj.map((v, i) => [i, v]) : [
2421
+ ...Object.entries(localObj),
2422
+ ...Object.getOwnPropertySymbols(localObj).map((s) => [
2423
+ s,
2424
+ localObj[s]
2425
+ ])
2426
+ ];
2267
2427
  const defaultValue = {
2268
2428
  children: [],
2269
2429
  value: currentValue
2270
2430
  };
2271
2431
  const newValue = objEntries.reduce((accumulation, current) => {
2432
+ var _b;
2272
2433
  const _a2 = accumulation, { children: children2 } = _a2, rest = __objRest$1(_a2, ["children"]);
2273
2434
  const [localKey, localValue] = current;
2274
2435
  if (localKey === "asset" && typeof localValue === "object") {
@@ -2286,14 +2447,19 @@ class Parser {
2286
2447
  }
2287
2448
  } else if (this.hooks.determineNodeType.call(localKey) === NodeType.Template && Array.isArray(localValue)) {
2288
2449
  const templateChildren = localValue.map((template) => {
2289
- var _a3, _b;
2450
+ var _a3, _b2;
2290
2451
  const templateAST = this.hooks.onCreateASTNode.call({
2291
2452
  type: NodeType.Template,
2292
2453
  depth: (_a3 = options.templateDepth) != null ? _a3 : 0,
2293
2454
  data: template.data,
2294
2455
  template: template.value,
2295
- dynamic: (_b = template.dynamic) != null ? _b : false
2456
+ dynamic: (_b2 = template.dynamic) != null ? _b2 : false
2296
2457
  }, template);
2458
+ if ((templateAST == null ? void 0 : templateAST.type) === NodeType.MultiNode) {
2459
+ templateAST.values.forEach((v) => {
2460
+ v.parent = templateAST;
2461
+ });
2462
+ }
2297
2463
  if (templateAST) {
2298
2464
  return {
2299
2465
  path: [...path, template.output],
@@ -2307,6 +2473,18 @@ class Parser {
2307
2473
  });
2308
2474
  } else if (localValue && this.hooks.determineNodeType.call(localValue) === NodeType.Switch) {
2309
2475
  const localSwitch = this.hooks.parseNode.call(localValue, NodeType.Value, options, NodeType.Switch);
2476
+ if (localSwitch && localSwitch.type === NodeType.Value && ((_b = localSwitch.children) == null ? void 0 : _b.length) === 1 && localSwitch.value === void 0) {
2477
+ const firstChild = localSwitch.children[0];
2478
+ return __spreadProps$7(__spreadValues$9({}, rest), {
2479
+ children: [
2480
+ ...children2,
2481
+ {
2482
+ path: [...path, localKey, ...firstChild.path],
2483
+ value: firstChild.value
2484
+ }
2485
+ ]
2486
+ });
2487
+ }
2310
2488
  if (localSwitch) {
2311
2489
  return __spreadProps$7(__spreadValues$9({}, rest), {
2312
2490
  children: [
@@ -2323,7 +2501,7 @@ class Parser {
2323
2501
  if (childValues.length > 0) {
2324
2502
  const multiNode = this.hooks.onCreateASTNode.call({
2325
2503
  type: NodeType.MultiNode,
2326
- override: true,
2504
+ override: !this.hasTemplateValues(localObj, localKey),
2327
2505
  values: childValues
2328
2506
  }, localValue);
2329
2507
  if ((multiNode == null ? void 0 : multiNode.type) === NodeType.MultiNode) {
@@ -2346,7 +2524,7 @@ class Parser {
2346
2524
  } else if (localValue && typeof localValue === "object") {
2347
2525
  const determineNodeType = this.hooks.determineNodeType.call(localValue);
2348
2526
  if (determineNodeType === NodeType.Applicability) {
2349
- const parsedNode = this.hooks.parseNode.call(localValue, type, options, determineNodeType);
2527
+ const parsedNode = this.hooks.parseNode.call(localValue, NodeType.Value, options, determineNodeType);
2350
2528
  if (parsedNode) {
2351
2529
  return __spreadProps$7(__spreadValues$9({}, rest), {
2352
2530
  children: [
@@ -2468,6 +2646,11 @@ const withContext = (model) => {
2468
2646
  return model.set(transaction, __spreadValues$7({
2469
2647
  context: { model }
2470
2648
  }, options));
2649
+ },
2650
+ delete: (binding, options) => {
2651
+ return model.delete(binding, __spreadValues$7({
2652
+ context: { model }
2653
+ }, options));
2471
2654
  }
2472
2655
  };
2473
2656
  };
@@ -2497,12 +2680,16 @@ class Resolver {
2497
2680
  this.hooks.beforeUpdate.call(changes);
2498
2681
  const resolveCache = new Map();
2499
2682
  this.idCache.clear();
2683
+ const prevASTMap = new Map(this.ASTMap);
2500
2684
  this.ASTMap.clear();
2501
- const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options));
2685
+ const updated = this.computeTree(this.root, void 0, changes, resolveCache, toNodeResolveOptions(this.options), void 0, prevASTMap);
2502
2686
  this.resolveCache = resolveCache;
2503
2687
  this.hooks.afterUpdate.call(updated.value);
2504
2688
  return updated.value;
2505
2689
  }
2690
+ getResolveCache() {
2691
+ return new Map(this.resolveCache);
2692
+ }
2506
2693
  getNodeID(node) {
2507
2694
  var _a;
2508
2695
  if (!node) {
@@ -2534,7 +2721,19 @@ class Resolver {
2534
2721
  }
2535
2722
  return this.resolveCache.get(node);
2536
2723
  }
2537
- computeTree(node, parent, dataChanges, cacheUpdate, options) {
2724
+ cloneNode(node) {
2725
+ const clonedNode = clone(node);
2726
+ Object.keys(clonedNode).forEach((key) => {
2727
+ if (key === "parent")
2728
+ return;
2729
+ const value = clonedNode[key];
2730
+ if (typeof value === "object" && value !== null) {
2731
+ clonedNode[key] = Array.isArray(value) ? [...value] : __spreadValues$7({}, value);
2732
+ }
2733
+ });
2734
+ return clonedNode;
2735
+ }
2736
+ computeTree(node, parent, dataChanges, cacheUpdate, options, parentNode, prevASTMap) {
2538
2737
  var _a, _b;
2539
2738
  const dependencyModel = new DependencyModel(options.data.model);
2540
2739
  dependencyModel.trackSubset("core");
@@ -2555,34 +2754,40 @@ class Resolver {
2555
2754
  updated: false
2556
2755
  });
2557
2756
  cacheUpdate.set(node, update2);
2558
- const repopulateASTMapFromCache = (resolvedAST3, AST) => {
2757
+ const repopulateASTMapFromCache = (resolvedNode, AST, ASTParent) => {
2559
2758
  var _a2;
2560
- this.ASTMap.set(resolvedAST3, AST);
2561
- if ("children" in resolvedAST3) {
2562
- (_a2 = resolvedAST3.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => {
2563
- const { node: childResolvedAST } = this.getPreviousResult(childAST) || {};
2564
- if (!childResolvedAST)
2565
- return;
2566
- repopulateASTMapFromCache(childResolvedAST, childAST);
2567
- if (childResolvedAST.type === NodeType.MultiNode) {
2568
- childResolvedAST.values.forEach((mChildAST) => {
2569
- const { node: mChildResolvedAST } = this.getPreviousResult(mChildAST) || {};
2570
- if (!mChildResolvedAST)
2571
- return;
2572
- repopulateASTMapFromCache(mChildResolvedAST, mChildAST);
2573
- });
2574
- }
2575
- });
2759
+ const { node: resolvedAST2 } = resolvedNode;
2760
+ this.ASTMap.set(resolvedAST2, AST);
2761
+ const resolvedUpdate = __spreadProps$5(__spreadValues$7({}, resolvedNode), {
2762
+ updated: false
2763
+ });
2764
+ cacheUpdate.set(AST, resolvedUpdate);
2765
+ const handleChildNode = (childNode) => {
2766
+ var _a3;
2767
+ const originalChildNode = (_a3 = prevASTMap.get(childNode)) != null ? _a3 : childNode;
2768
+ const previousChildResult = this.getPreviousResult(originalChildNode);
2769
+ if (!previousChildResult)
2770
+ return;
2771
+ repopulateASTMapFromCache(previousChildResult, originalChildNode, AST);
2772
+ };
2773
+ if ("children" in resolvedAST2) {
2774
+ (_a2 = resolvedAST2.children) == null ? void 0 : _a2.forEach(({ value: childAST }) => handleChildNode(childAST));
2775
+ } else if (resolvedAST2.type === NodeType.MultiNode) {
2776
+ resolvedAST2.values.forEach(handleChildNode);
2576
2777
  }
2778
+ this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate);
2577
2779
  };
2578
- const resolvedAST2 = previousResult.node;
2579
- repopulateASTMapFromCache(resolvedAST2, node);
2580
- this.hooks.afterNodeUpdate.call(node, parent, update2);
2780
+ previousResult.node.parent = parentNode;
2781
+ repopulateASTMapFromCache(previousResult, node, parent);
2581
2782
  return update2;
2582
2783
  }
2583
- const resolvedAST = (_a = this.hooks.beforeResolve.call(node, resolveOptions)) != null ? _a : {
2784
+ const clonedNode = __spreadProps$5(__spreadValues$7({}, this.cloneNode(node)), {
2785
+ parent: parentNode
2786
+ });
2787
+ const resolvedAST = (_a = this.hooks.beforeResolve.call(clonedNode, resolveOptions)) != null ? _a : {
2584
2788
  type: NodeType.Empty
2585
2789
  };
2790
+ resolvedAST.parent = parentNode;
2586
2791
  resolveOptions.node = resolvedAST;
2587
2792
  this.ASTMap.set(resolvedAST, node);
2588
2793
  let resolved = this.hooks.resolve.call(void 0, resolvedAST, resolveOptions);
@@ -2593,22 +2798,15 @@ class Resolver {
2593
2798
  const childDependencies = new Set();
2594
2799
  dependencyModel.trackSubset("children");
2595
2800
  if ("children" in resolvedAST) {
2596
- (_b = resolvedAST.children) == null ? void 0 : _b.forEach((child) => {
2597
- const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions);
2598
- let { updated: childUpdated, value: childValue } = computedChildTree;
2599
- const { node: childNode, dependencies: childTreeDeps } = computedChildTree;
2801
+ const newChildren = (_b = resolvedAST.children) == null ? void 0 : _b.map((child) => {
2802
+ const computedChildTree = this.computeTree(child.value, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2803
+ const {
2804
+ dependencies: childTreeDeps,
2805
+ node: childNode,
2806
+ updated: childUpdated,
2807
+ value: childValue
2808
+ } = computedChildTree;
2600
2809
  childTreeDeps.forEach((binding) => childDependencies.add(binding));
2601
- if (childNode.type === NodeType.MultiNode) {
2602
- childValue = [];
2603
- childNode.values.forEach((mValue) => {
2604
- const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions);
2605
- if (mTree.value !== void 0 && mTree.value !== null) {
2606
- childValue.push(mTree.value);
2607
- }
2608
- mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2609
- childUpdated = childUpdated || mTree.updated;
2610
- });
2611
- }
2612
2810
  if (childValue) {
2613
2811
  if (childNode.type === NodeType.MultiNode && !childNode.override) {
2614
2812
  const arr = addLast(get(resolved, child.path, []), childValue);
@@ -2618,7 +2816,22 @@ class Resolver {
2618
2816
  }
2619
2817
  }
2620
2818
  updated = updated || childUpdated;
2819
+ return __spreadProps$5(__spreadValues$7({}, child), { value: childNode });
2820
+ });
2821
+ resolvedAST.children = newChildren;
2822
+ } else if (resolvedAST.type === NodeType.MultiNode) {
2823
+ const childValue = [];
2824
+ const newValues = resolvedAST.values.map((mValue) => {
2825
+ const mTree = this.computeTree(mValue, node, dataChanges, cacheUpdate, resolveOptions, resolvedAST, prevASTMap);
2826
+ if (mTree.value !== void 0 && mTree.value !== null) {
2827
+ childValue.push(mTree.value);
2828
+ }
2829
+ mTree.dependencies.forEach((bindingDep) => childDependencies.add(bindingDep));
2830
+ updated = updated || mTree.updated;
2831
+ return mTree.node;
2621
2832
  });
2833
+ resolvedAST.values = newValues;
2834
+ resolved = childValue;
2622
2835
  }
2623
2836
  childDependencies.forEach((bindingDep) => dependencyModel.addChildReadDep(bindingDep));
2624
2837
  dependencyModel.trackSubset("core");
@@ -2687,13 +2900,10 @@ class TemplatePlugin {
2687
2900
  }
2688
2901
  });
2689
2902
  const result = {
2690
- parent: node.parent,
2691
2903
  type: NodeType.MultiNode,
2904
+ override: false,
2692
2905
  values
2693
2906
  };
2694
- result.values.forEach((innerNode) => {
2695
- innerNode.parent = result;
2696
- });
2697
2907
  return result;
2698
2908
  }
2699
2909
  applyParser(parser) {
@@ -2787,19 +2997,20 @@ function resolveAllRefs(node, resolveOptions, propertiesToSkip) {
2787
2997
  });
2788
2998
  return newNode;
2789
2999
  }
2790
- const findBasePath = (node) => {
3000
+ const findBasePath = (node, resolver) => {
2791
3001
  var _a, _b, _c;
2792
3002
  const parentNode = node.parent;
2793
3003
  if (!parentNode) {
2794
3004
  return [];
2795
3005
  }
2796
3006
  if ("children" in parentNode) {
2797
- return (_c = (_b = (_a = parentNode.children) == null ? void 0 : _a.find((child) => child.value === node)) == null ? void 0 : _b.path) != null ? _c : [];
3007
+ const original = resolver.getSourceNode(node);
3008
+ return (_c = (_b = (_a = parentNode.children) == null ? void 0 : _a.find((child) => child.value === original)) == null ? void 0 : _b.path) != null ? _c : [];
2798
3009
  }
2799
3010
  if (parentNode.type !== NodeType.MultiNode) {
2800
3011
  return [];
2801
3012
  }
2802
- return findBasePath(parentNode);
3013
+ return findBasePath(parentNode, resolver);
2803
3014
  };
2804
3015
  class StringResolverPlugin {
2805
3016
  constructor() {
@@ -2823,7 +3034,7 @@ class StringResolverPlugin {
2823
3034
  } else {
2824
3035
  propsToSkip = new Set(["exp"]);
2825
3036
  }
2826
- const nodePath = findBasePath(node);
3037
+ const nodePath = findBasePath(node, resolver);
2827
3038
  if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
2828
3039
  return node.value;
2829
3040
  }
@@ -2843,7 +3054,7 @@ class ApplicabilityPlugin {
2843
3054
  let newNode = node;
2844
3055
  if ((node == null ? void 0 : node.type) === NodeType.Applicability) {
2845
3056
  const isApplicable = options.evaluate(node.expression);
2846
- if (!isApplicable) {
3057
+ if (isApplicable === false) {
2847
3058
  return null;
2848
3059
  }
2849
3060
  newNode = node.value;
@@ -3149,7 +3360,8 @@ class FlowInstance {
3149
3360
  skipTransition: new SyncBailHook(),
3150
3361
  beforeTransition: new SyncWaterfallHook(),
3151
3362
  resolveTransitionNode: new SyncWaterfallHook(),
3152
- transition: new SyncHook()
3363
+ transition: new SyncHook(),
3364
+ afterTransition: new SyncHook()
3153
3365
  };
3154
3366
  this.id = id;
3155
3367
  this.flow = flow;
@@ -3196,7 +3408,7 @@ class FlowInstance {
3196
3408
  } else {
3197
3409
  const skipTransition = this.hooks.skipTransition.call(this.currentState);
3198
3410
  if (skipTransition) {
3199
- (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState} b/c hook told us to`);
3411
+ (_d = this.log) == null ? void 0 : _d.debug(`Skipping transition from ${this.currentState.name} b/c hook told us to`);
3200
3412
  return;
3201
3413
  }
3202
3414
  }
@@ -3235,6 +3447,7 @@ class FlowInstance {
3235
3447
  this.hooks.onEnd.call(this.flow.onEnd);
3236
3448
  }
3237
3449
  this.hooks.transition.call(prevState, __spreadValues$5({}, newCurrentState));
3450
+ this.hooks.afterTransition.call(this);
3238
3451
  }
3239
3452
  }
3240
3453
 
@@ -3269,6 +3482,7 @@ class FlowController {
3269
3482
  this.start = this.start.bind(this);
3270
3483
  this.run = this.run.bind(this);
3271
3484
  this.transition = this.transition.bind(this);
3485
+ this.addNewFlow = this.addNewFlow.bind(this);
3272
3486
  }
3273
3487
  transition(stateTransition, options) {
3274
3488
  if (this.current === void 0) {
@@ -3277,20 +3491,9 @@ class FlowController {
3277
3491
  this.current.transition(stateTransition, options);
3278
3492
  }
3279
3493
  addNewFlow(flow) {
3280
- return __async$1(this, null, function* () {
3281
- this.navStack.push(flow);
3282
- this.current = flow;
3283
- flow.hooks.transition.tap("flow-controller", (_oldState, newState) => __async$1(this, null, function* () {
3284
- var _a, _b;
3285
- if (newState.value.state_type === "FLOW") {
3286
- (_a = this.log) == null ? void 0 : _a.debug(`Got FLOW state. Loading flow ${newState.value.ref}`);
3287
- const endState = yield this.run(newState.value.ref);
3288
- (_b = this.log) == null ? void 0 : _b.debug(`Flow ended. Using outcome: ${endState.outcome}`);
3289
- flow.transition(endState.outcome);
3290
- }
3291
- }));
3292
- this.hooks.flow.call(flow);
3293
- });
3494
+ this.navStack.push(flow);
3495
+ this.current = flow;
3496
+ this.hooks.flow.call(flow);
3294
3497
  }
3295
3498
  run(startState) {
3296
3499
  return __async$1(this, null, function* () {
@@ -3305,6 +3508,18 @@ class FlowController {
3305
3508
  (_a = this.log) == null ? void 0 : _a.debug(`Starting flow: ${startState}`);
3306
3509
  const flow = new FlowInstance(startState, startFlow, { logger: this.log });
3307
3510
  this.addNewFlow(flow);
3511
+ flow.hooks.afterTransition.tap("flow-controller", (flowInstance) => {
3512
+ var _a2, _b, _c;
3513
+ if (((_a2 = flowInstance.currentState) == null ? void 0 : _a2.value.state_type) === "FLOW") {
3514
+ const subflowId = (_b = flowInstance.currentState) == null ? void 0 : _b.value.ref;
3515
+ (_c = this.log) == null ? void 0 : _c.debug(`Loading subflow ${subflowId}`);
3516
+ this.run(subflowId).then((subFlowEndState) => {
3517
+ var _a3;
3518
+ (_a3 = this.log) == null ? void 0 : _a3.debug(`Subflow ended. Using outcome: ${subFlowEndState.outcome}`);
3519
+ flowInstance.transition(subFlowEndState == null ? void 0 : subFlowEndState.outcome);
3520
+ });
3521
+ }
3522
+ });
3308
3523
  const end = yield flow.start();
3309
3524
  this.navStack.pop();
3310
3525
  if (this.navStack.length > 0) {
@@ -3357,11 +3572,18 @@ class ValidationBindingTrackerViewPlugin {
3357
3572
  getBindings() {
3358
3573
  return this.trackedBindings;
3359
3574
  }
3575
+ trackBinding(binding) {
3576
+ var _a, _b;
3577
+ if (this.trackedBindings.has(binding)) {
3578
+ return;
3579
+ }
3580
+ this.trackedBindings.add(binding);
3581
+ (_b = (_a = this.options.callbacks) == null ? void 0 : _a.onAdd) == null ? void 0 : _b.call(_a, binding);
3582
+ }
3360
3583
  applyResolver(resolver) {
3361
3584
  this.trackedBindings.clear();
3362
3585
  const tracked = new Map();
3363
3586
  const sections = new Map();
3364
- const seenBindings = new Set();
3365
3587
  let lastViewUpdateChangeSet;
3366
3588
  const nodeTree = new Map();
3367
3589
  let lastComputedBindingTree = new Map();
@@ -3408,31 +3630,34 @@ class ValidationBindingTrackerViewPlugin {
3408
3630
  parent = parent.parent;
3409
3631
  }
3410
3632
  }
3411
- if (!seenBindings.has(parsed)) {
3412
- seenBindings.add(parsed);
3413
- (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3414
- }
3633
+ this.trackedBindings.add(parsed);
3634
+ (_d = (_c = this.options.callbacks) == null ? void 0 : _c.onAdd) == null ? void 0 : _d.call(_c, parsed);
3415
3635
  };
3416
3636
  return __spreadProps$3(__spreadValues$4({}, options), {
3417
3637
  validation: __spreadProps$3(__spreadValues$4({}, options.validation), {
3418
3638
  get: (binding, getOptions) => {
3419
- var _a;
3639
+ var _a, _b;
3420
3640
  if (getOptions == null ? void 0 : getOptions.track) {
3421
3641
  track(binding);
3422
3642
  }
3423
- const eow = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding);
3424
- if ((eow == null ? void 0 : eow.displayTarget) === void 0 || (eow == null ? void 0 : eow.displayTarget) === "field") {
3425
- return eow;
3643
+ const eows = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions);
3644
+ const firstFieldEOW = eows == null ? void 0 : eows.find((eow) => eow.displayTarget === "field" || eow.displayTarget === void 0);
3645
+ return firstFieldEOW;
3646
+ },
3647
+ getValidationsForBinding(binding, getOptions) {
3648
+ var _a, _b, _c;
3649
+ if (getOptions == null ? void 0 : getOptions.track) {
3650
+ track(binding);
3426
3651
  }
3427
- return void 0;
3652
+ return (_c = (_b = (_a = options.validation) == null ? void 0 : _a._getValidationForBinding(binding)) == null ? void 0 : _b.getAll(getOptions)) != null ? _c : [];
3428
3653
  },
3429
3654
  getChildren: (type) => {
3430
3655
  var _a;
3431
3656
  const validations = new Array();
3432
3657
  (_a = lastComputedBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3433
- var _a2;
3434
- const eow = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding);
3435
- if (eow && type === eow.displayTarget) {
3658
+ var _a2, _b;
3659
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3660
+ if (eow && (type === void 0 || type === eow.displayTarget)) {
3436
3661
  validations.push(eow);
3437
3662
  }
3438
3663
  });
@@ -3442,8 +3667,8 @@ class ValidationBindingTrackerViewPlugin {
3442
3667
  var _a;
3443
3668
  const validations = new Array();
3444
3669
  (_a = lastSectionBindingTree.get(node)) == null ? void 0 : _a.forEach((binding) => {
3445
- var _a2;
3446
- const eow = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding);
3670
+ var _a2, _b;
3671
+ const eow = (_b = (_a2 = options.validation) == null ? void 0 : _a2._getValidationForBinding(binding)) == null ? void 0 : _b.get();
3447
3672
  if (eow && eow.displayTarget === "section") {
3448
3673
  validations.push(eow);
3449
3674
  }
@@ -3462,7 +3687,7 @@ class ValidationBindingTrackerViewPlugin {
3462
3687
  });
3463
3688
  });
3464
3689
  resolver.hooks.afterNodeUpdate.tap(CONTEXT, (node, parent, update) => {
3465
- var _a, _b, _c;
3690
+ var _a, _b;
3466
3691
  if (parent) {
3467
3692
  addToTree(node, parent);
3468
3693
  }
@@ -3477,7 +3702,7 @@ class ValidationBindingTrackerViewPlugin {
3477
3702
  currentBindingTree.set(node, (_b = lastComputedBindingTree.get(node)) != null ? _b : new Set());
3478
3703
  }
3479
3704
  if (node === resolver.root) {
3480
- this.trackedBindings = (_c = currentBindingTree.get(node)) != null ? _c : new Set();
3705
+ this.trackedBindings = new Set(currentBindingTree.get(node));
3481
3706
  lastComputedBindingTree = currentBindingTree;
3482
3707
  lastSectionBindingTree.clear();
3483
3708
  sections.forEach((nodeSet, sectionNode) => {
@@ -3519,11 +3744,23 @@ var __spreadValues$3 = (a, b) => {
3519
3744
  return a;
3520
3745
  };
3521
3746
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
3747
+ const SCHEMA_VALIDATION_PROVIDER_NAME = "schema";
3748
+ const VIEW_VALIDATION_PROVIDER_NAME = "view";
3749
+ const VALIDATION_PROVIDER_NAME_SYMBOL = Symbol.for("validation-provider-name");
3750
+ function isSubset(subset, containingSet) {
3751
+ if (subset.size > containingSet.size)
3752
+ return false;
3753
+ for (const entry of subset)
3754
+ if (!containingSet.has(entry))
3755
+ return false;
3756
+ return true;
3757
+ }
3522
3758
  function createStatefulValidationObject(obj) {
3523
3759
  return {
3524
3760
  value: obj,
3525
3761
  type: obj.severity,
3526
- state: "none"
3762
+ state: "none",
3763
+ isBlockingNavigation: false
3527
3764
  };
3528
3765
  }
3529
3766
  class ValidatedBinding {
@@ -3538,44 +3775,68 @@ class ValidatedBinding {
3538
3775
  possibleValidations.forEach((vObj) => {
3539
3776
  const { trigger } = vObj;
3540
3777
  if (this.validationsByState[trigger]) {
3541
- this.validationsByState[trigger].push(createStatefulValidationObject(vObj));
3778
+ const statefulValidationObject = createStatefulValidationObject(vObj);
3779
+ this.validationsByState[trigger].push(statefulValidationObject);
3542
3780
  } else {
3543
3781
  log == null ? void 0 : log.warn(`Unknown validation trigger: ${trigger}`);
3544
3782
  }
3545
3783
  });
3546
3784
  this.weakBindings = weakBindings != null ? weakBindings : new Set();
3547
3785
  }
3786
+ get allValidations() {
3787
+ return Object.values(this.validationsByState).flat();
3788
+ }
3789
+ checkIfBlocking(statefulObj) {
3790
+ if (statefulObj.state === "active") {
3791
+ const { isBlockingNavigation } = statefulObj;
3792
+ return isBlockingNavigation;
3793
+ }
3794
+ return false;
3795
+ }
3796
+ getAll() {
3797
+ return this.applicableValidations.reduce((all, statefulObj) => {
3798
+ if (statefulObj.state === "active" && statefulObj.response) {
3799
+ return [
3800
+ ...all,
3801
+ __spreadProps$2(__spreadValues$3({}, statefulObj.response), {
3802
+ blocking: this.checkIfBlocking(statefulObj)
3803
+ })
3804
+ ];
3805
+ }
3806
+ return all;
3807
+ }, []);
3808
+ }
3548
3809
  get() {
3549
- const firstError = this.applicableValidations.find((statefulObj) => {
3550
- const blocking = this.currentPhase === "navigation" ? statefulObj.value.blocking : true;
3551
- return statefulObj.state === "active" && blocking !== false;
3810
+ const firstInvalid = this.applicableValidations.find((statefulObj) => {
3811
+ return statefulObj.state === "active" && statefulObj.response;
3552
3812
  });
3553
- if ((firstError == null ? void 0 : firstError.state) === "active") {
3554
- return firstError.response;
3813
+ if ((firstInvalid == null ? void 0 : firstInvalid.state) === "active") {
3814
+ return __spreadProps$2(__spreadValues$3({}, firstInvalid.response), {
3815
+ blocking: this.checkIfBlocking(firstInvalid)
3816
+ });
3555
3817
  }
3556
3818
  }
3557
- runApplicableValidations(runner, canDismiss) {
3558
- this.applicableValidations = this.applicableValidations.map((obj) => {
3819
+ runApplicableValidations(runner, canDismiss, phase) {
3820
+ this.applicableValidations = this.applicableValidations.map((originalValue) => {
3559
3821
  var _a, _b, _c;
3560
- if (obj.state === "dismissed") {
3561
- return obj;
3822
+ if (originalValue.state === "dismissed") {
3823
+ return originalValue;
3562
3824
  }
3563
- const blocking = (_a = obj.value.blocking) != null ? _a : obj.value.severity === "warning" && "once" || obj.value.severity === "error" && true;
3564
- const dismissable = canDismiss && blocking === "once";
3565
- if (this.currentPhase === "navigation" && obj.state === "active" && dismissable) {
3825
+ const blocking = (_a = originalValue.value.blocking) != null ? _a : originalValue.value.severity === "warning" && "once" || true;
3826
+ const obj = setIn(originalValue, ["value", "blocking"], blocking);
3827
+ const isBlockingNavigation = blocking === true || blocking === "once" && !canDismiss;
3828
+ if (phase === "navigation" && obj.state === "active" && obj.value.blocking !== true) {
3566
3829
  if (obj.value.severity === "warning") {
3567
3830
  const warn = obj;
3568
- if (warn.dismissable && warn.response.dismiss) {
3831
+ if (warn.dismissable && warn.response.dismiss && (warn.response.blocking !== "once" || !warn.response.blocking)) {
3569
3832
  warn.response.dismiss();
3570
3833
  } else {
3834
+ if ((warn == null ? void 0 : warn.response.blocking) === "once") {
3835
+ warn.response.blocking = false;
3836
+ }
3571
3837
  warn.dismissable = true;
3572
3838
  }
3573
- return obj;
3574
- }
3575
- if (obj.value.severity === "error") {
3576
- const err = obj;
3577
- err.state = "none";
3578
- return obj;
3839
+ return warn;
3579
3840
  }
3580
3841
  }
3581
3842
  const response = runner(obj.value);
@@ -3583,7 +3844,8 @@ class ValidatedBinding {
3583
3844
  type: obj.type,
3584
3845
  value: obj.value,
3585
3846
  state: response ? "active" : "none",
3586
- dismissable: obj.value.severity === "warning" && this.currentPhase === "navigation",
3847
+ isBlockingNavigation,
3848
+ dismissable: obj.value.severity === "warning" && phase === "navigation",
3587
3849
  response: response ? __spreadProps$2(__spreadValues$3({}, obj.value), {
3588
3850
  message: (_b = response.message) != null ? _b : "Something is broken",
3589
3851
  severity: obj.value.severity,
@@ -3601,11 +3863,12 @@ class ValidatedBinding {
3601
3863
  });
3602
3864
  }
3603
3865
  update(phase, canDismiss, runner) {
3866
+ const newApplicableValidations = [];
3604
3867
  if (phase === "load" && this.currentPhase !== void 0) {
3605
3868
  return;
3606
3869
  }
3607
3870
  if (this.currentPhase === "navigation" || phase === this.currentPhase) {
3608
- this.runApplicableValidations(runner, canDismiss);
3871
+ this.runApplicableValidations(runner, canDismiss, phase);
3609
3872
  return;
3610
3873
  }
3611
3874
  if (phase === "load") {
@@ -3618,14 +3881,19 @@ class ValidatedBinding {
3618
3881
  ...this.validationsByState.change
3619
3882
  ];
3620
3883
  } else if (phase === "navigation" && (this.currentPhase === "load" || this.currentPhase === "change")) {
3884
+ this.applicableValidations.forEach((element) => {
3885
+ if (!(element.type === "error" && element.state === "active" && element.isBlockingNavigation === false)) {
3886
+ newApplicableValidations.push(element);
3887
+ }
3888
+ });
3621
3889
  this.applicableValidations = [
3622
- ...this.applicableValidations,
3623
- ...this.currentPhase === "load" ? this.validationsByState.change : [],
3624
- ...this.validationsByState.navigation
3890
+ ...newApplicableValidations,
3891
+ ...this.validationsByState.navigation,
3892
+ ...this.currentPhase === "load" ? this.validationsByState.change : []
3625
3893
  ];
3626
3894
  this.currentPhase = "navigation";
3627
3895
  }
3628
- this.runApplicableValidations(runner, canDismiss);
3896
+ this.runApplicableValidations(runner, canDismiss, phase);
3629
3897
  }
3630
3898
  }
3631
3899
  class ValidationController {
@@ -3633,20 +3901,34 @@ class ValidationController {
3633
3901
  this.hooks = {
3634
3902
  createValidatorRegistry: new SyncHook(),
3635
3903
  onAddValidation: new SyncWaterfallHook(),
3636
- onRemoveValidation: new SyncWaterfallHook()
3904
+ onRemoveValidation: new SyncWaterfallHook(),
3905
+ resolveValidationProviders: new SyncWaterfallHook(),
3906
+ onTrackBinding: new SyncHook()
3637
3907
  };
3638
3908
  this.validations = new Map();
3639
3909
  this.weakBindingTracker = new Set();
3640
- this.lastActiveBindings = new Set();
3641
3910
  this.schema = schema;
3642
3911
  this.options = options;
3643
- this.providers = [schema];
3912
+ this.reset();
3644
3913
  }
3645
3914
  setOptions(options) {
3646
3915
  this.options = options;
3647
3916
  }
3648
3917
  getDataMiddleware() {
3649
3918
  return [
3919
+ {
3920
+ set: (transaction, options, next) => {
3921
+ var _a;
3922
+ return (_a = next == null ? void 0 : next.set(transaction, options)) != null ? _a : [];
3923
+ },
3924
+ get: (binding, options, next) => {
3925
+ return next == null ? void 0 : next.get(binding, options);
3926
+ },
3927
+ delete: (binding, options, next) => {
3928
+ this.validations = removeBindingAndChildrenFromMap(this.validations, binding);
3929
+ return next == null ? void 0 : next.delete(binding, options);
3930
+ }
3931
+ },
3650
3932
  new ValidationMiddleware((binding) => {
3651
3933
  var _a;
3652
3934
  if (!this.options) {
@@ -3662,13 +3944,17 @@ class ValidationController {
3662
3944
  var _a2;
3663
3945
  if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
3664
3946
  weakValidation == null ? void 0 : weakValidation.weakBindings.forEach((weakBinding) => {
3665
- weakBinding === strongBinding ? newInvalidBindings.add({
3666
- binding: weakBinding,
3667
- isStrong: true
3668
- }) : newInvalidBindings.add({
3669
- binding: weakBinding,
3670
- isStrong: false
3671
- });
3947
+ if (weakBinding === strongBinding) {
3948
+ newInvalidBindings.add({
3949
+ binding: weakBinding,
3950
+ isStrong: true
3951
+ });
3952
+ } else {
3953
+ newInvalidBindings.add({
3954
+ binding: weakBinding,
3955
+ isStrong: false
3956
+ });
3957
+ }
3672
3958
  });
3673
3959
  }
3674
3960
  });
@@ -3681,6 +3967,35 @@ class ValidationController {
3681
3967
  }) })
3682
3968
  ];
3683
3969
  }
3970
+ getValidationProviders() {
3971
+ if (this.providers) {
3972
+ return this.providers;
3973
+ }
3974
+ this.providers = this.hooks.resolveValidationProviders.call([
3975
+ {
3976
+ source: SCHEMA_VALIDATION_PROVIDER_NAME,
3977
+ provider: this.schema
3978
+ },
3979
+ {
3980
+ source: VIEW_VALIDATION_PROVIDER_NAME,
3981
+ provider: {
3982
+ getValidationsForBinding: (binding) => {
3983
+ var _a, _b;
3984
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForBinding) == null ? void 0 : _b.call(_a, binding);
3985
+ },
3986
+ getValidationsForView: () => {
3987
+ var _a, _b;
3988
+ return (_b = (_a = this.viewValidationProvider) == null ? void 0 : _a.getValidationsForView) == null ? void 0 : _b.call(_a);
3989
+ }
3990
+ }
3991
+ }
3992
+ ]);
3993
+ return this.providers;
3994
+ }
3995
+ reset() {
3996
+ this.validations.clear();
3997
+ this.tracker = void 0;
3998
+ }
3684
3999
  onView(view) {
3685
4000
  this.validations.clear();
3686
4001
  if (!this.options) {
@@ -3689,7 +4004,7 @@ class ValidationController {
3689
4004
  const bindingTrackerPlugin = new ValidationBindingTrackerViewPlugin(__spreadProps$2(__spreadValues$3({}, this.options), {
3690
4005
  callbacks: {
3691
4006
  onAdd: (binding) => {
3692
- if (!this.options) {
4007
+ if (!this.options || this.getValidationForBinding(binding) !== void 0) {
3693
4008
  return;
3694
4009
  }
3695
4010
  const originalValue = this.options.model.get(binding);
@@ -3704,21 +4019,28 @@ class ValidationController {
3704
4019
  this.updateValidationsForBinding(binding, "load", this.options, () => {
3705
4020
  view.update(new Set([binding]));
3706
4021
  });
4022
+ this.hooks.onTrackBinding.call(binding);
3707
4023
  }
3708
4024
  }
3709
4025
  }));
3710
4026
  this.tracker = bindingTrackerPlugin;
3711
- this.providers = [this.schema, view];
4027
+ this.viewValidationProvider = view;
3712
4028
  bindingTrackerPlugin.apply(view);
3713
4029
  }
3714
- updateValidationsForBinding(binding, trigger, context, onDismiss) {
4030
+ updateValidationsForBinding(binding, trigger, validationContext, onDismiss) {
3715
4031
  var _a;
4032
+ const context = validationContext != null ? validationContext : this.options;
4033
+ if (!context) {
4034
+ throw new Error(`Context is required for executing validations`);
4035
+ }
3716
4036
  if (trigger === "load") {
3717
- const possibleValidations = this.providers.reduce((vals, provider) => {
3718
- var _a2, _b;
4037
+ const possibleValidations = this.getValidationProviders().reduce((vals, provider) => {
4038
+ var _a2, _b, _c, _d;
3719
4039
  return [
3720
4040
  ...vals,
3721
- ...(_b = (_a2 = provider.getValidationsForBinding) == null ? void 0 : _a2.call(provider, binding)) != null ? _b : []
4041
+ ...(_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), {
4042
+ [VALIDATION_PROVIDER_NAME_SYMBOL]: provider.source
4043
+ }))) != null ? _d : []
3722
4044
  ];
3723
4045
  }, []);
3724
4046
  if (possibleValidations.length === 0) {
@@ -3728,7 +4050,7 @@ class ValidationController {
3728
4050
  }
3729
4051
  const trackedValidations = this.validations.get(binding);
3730
4052
  trackedValidations == null ? void 0 : trackedValidations.update(trigger, true, (validationObj) => {
3731
- const response = this.validationRunner(validationObj, context, binding);
4053
+ const response = this.validationRunner(validationObj, binding, context);
3732
4054
  if (this.weakBindingTracker.size > 0) {
3733
4055
  const t = this.validations.get(binding);
3734
4056
  this.weakBindingTracker.forEach((b) => t.weakBindings.add(b));
@@ -3739,27 +4061,33 @@ class ValidationController {
3739
4061
  this.validations.forEach((validation, vBinding) => {
3740
4062
  if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
3741
4063
  validation.update(trigger, true, (validationObj) => {
3742
- const response = this.validationRunner(validationObj, context, vBinding);
4064
+ const response = this.validationRunner(validationObj, vBinding, context);
3743
4065
  return response ? { message: response.message } : void 0;
3744
4066
  });
3745
4067
  }
3746
4068
  });
3747
4069
  }
3748
4070
  }
3749
- validationRunner(validationObj, context, binding) {
3750
- const handler = this.getValidator(validationObj.type);
4071
+ validationRunner(validationObj, binding, context = this.options) {
4072
+ var _a;
4073
+ if (!context) {
4074
+ throw new Error("No context provided to validation runner");
4075
+ }
4076
+ const handler = (_a = validationObj.handler) != null ? _a : this.getValidator(validationObj.type);
3751
4077
  const weakBindings = new Set();
3752
4078
  const model = {
3753
- get(b, options = { includeInvalid: true }) {
4079
+ get(b, options) {
3754
4080
  weakBindings.add(isBinding(b) ? binding : context.parseBinding(b));
3755
- return context.model.get(b, options);
4081
+ return context.model.get(b, __spreadProps$2(__spreadValues$3({}, options), { includeInvalid: true }));
3756
4082
  },
3757
- set: context.model.set
4083
+ set: context.model.set,
4084
+ delete: context.model.delete
3758
4085
  };
3759
4086
  const result = handler == null ? void 0 : handler(__spreadProps$2(__spreadValues$3({}, context), {
3760
4087
  evaluate: (exp, options = { model }) => context.evaluate(exp, options),
3761
4088
  model,
3762
- validation: validationObj
4089
+ validation: validationObj,
4090
+ schemaType: this.schema.getType(binding)
3763
4091
  }), context.model.get(binding, {
3764
4092
  includeInvalid: true,
3765
4093
  formatted: validationObj.dataTarget === "formatted"
@@ -3783,29 +4111,27 @@ class ValidationController {
3783
4111
  }
3784
4112
  }
3785
4113
  updateValidationsForView(trigger) {
3786
- const { activeBindings } = this;
3787
- const canDismiss = trigger !== "navigation" || this.setCompare(this.lastActiveBindings, activeBindings);
3788
- this.getBindings().forEach((binding) => {
3789
- var _a;
3790
- (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, canDismiss, (obj) => {
3791
- if (!this.options) {
3792
- return;
3793
- }
3794
- return this.validationRunner(obj, this.options, binding);
4114
+ const isNavigationTrigger = trigger === "navigation";
4115
+ const lastActiveBindings = this.activeBindings;
4116
+ const updateValidations = (dismissValidations) => {
4117
+ this.getBindings().forEach((binding) => {
4118
+ var _a;
4119
+ (_a = this.validations.get(binding)) == null ? void 0 : _a.update(trigger, dismissValidations, (obj) => {
4120
+ if (!this.options) {
4121
+ return;
4122
+ }
4123
+ return this.validationRunner(obj, binding, this.options);
4124
+ });
3795
4125
  });
3796
- });
3797
- if (trigger === "navigation") {
3798
- this.lastActiveBindings = activeBindings;
4126
+ };
4127
+ updateValidations(!isNavigationTrigger);
4128
+ if (isNavigationTrigger) {
4129
+ const { activeBindings } = this;
4130
+ if (isSubset(activeBindings, lastActiveBindings)) {
4131
+ updateValidations(true);
4132
+ }
3799
4133
  }
3800
4134
  }
3801
- setCompare(set1, set2) {
3802
- if (set1.size !== set2.size)
3803
- return false;
3804
- for (const entry of set1)
3805
- if (!set2.has(entry))
3806
- return false;
3807
- return true;
3808
- }
3809
4135
  get activeBindings() {
3810
4136
  return new Set(Array.from(this.getBindings()).filter((b) => {
3811
4137
  var _a;
@@ -3825,19 +4151,30 @@ class ValidationController {
3825
4151
  var _a, _b;
3826
4152
  return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
3827
4153
  }
4154
+ trackBinding(binding) {
4155
+ var _a;
4156
+ (_a = this.tracker) == null ? void 0 : _a.trackBinding(binding);
4157
+ }
3828
4158
  validateView(trigger = "navigation") {
3829
4159
  this.updateValidationsForView(trigger);
3830
4160
  const validations = new Map();
4161
+ let canTransition = true;
3831
4162
  this.getBindings().forEach((b) => {
3832
- var _a, _b;
3833
- const invalid = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.get();
3834
- if (invalid) {
3835
- (_b = this.options) == null ? void 0 : _b.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(invalid)}`);
3836
- validations.set(b, invalid);
3837
- }
4163
+ var _a;
4164
+ const allValidations = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.getAll();
4165
+ allValidations == null ? void 0 : allValidations.forEach((v) => {
4166
+ var _a2;
4167
+ if (trigger === "navigation" && v.blocking) {
4168
+ (_a2 = this.options) == null ? void 0 : _a2.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(v)}`);
4169
+ canTransition = false;
4170
+ }
4171
+ if (!validations.has(b)) {
4172
+ validations.set(b, v);
4173
+ }
4174
+ });
3838
4175
  });
3839
4176
  return {
3840
- canTransition: validations.size === 0,
4177
+ canTransition,
3841
4178
  validations: validations.size ? validations : void 0
3842
4179
  };
3843
4180
  }
@@ -3847,8 +4184,7 @@ class ValidationController {
3847
4184
  forView(parser) {
3848
4185
  return {
3849
4186
  _getValidationForBinding: (binding) => {
3850
- var _a;
3851
- return (_a = this.getValidationForBinding(isBinding(binding) ? binding : parser(binding))) == null ? void 0 : _a.get();
4187
+ return this.getValidationForBinding(isBinding(binding) ? binding : parser(binding));
3852
4188
  },
3853
4189
  getAll: () => {
3854
4190
  const bindings = this.getBindings();
@@ -3868,6 +4204,9 @@ class ValidationController {
3868
4204
  get() {
3869
4205
  throw new Error("Error Access be provided by the view plugin");
3870
4206
  },
4207
+ getValidationsForBinding() {
4208
+ throw new Error("Error rollup should be provided by the view plugin");
4209
+ },
3871
4210
  getChildren() {
3872
4211
  throw new Error("Error rollup should be provided by the view plugin");
3873
4212
  },
@@ -3878,7 +4217,7 @@ class ValidationController {
3878
4217
  throw new Error("Tracking should be provided by the view plugin");
3879
4218
  },
3880
4219
  register: () => {
3881
- throw new Error("Section funcationality hould be provided by the view plugin");
4220
+ throw new Error("Section functionality should be provided by the view plugin");
3882
4221
  },
3883
4222
  type: (binding) => this.schema.getType(isBinding(binding) ? binding : parser(binding))
3884
4223
  };
@@ -3994,10 +4333,11 @@ class AssetTransformCorePlugin {
3994
4333
  };
3995
4334
  };
3996
4335
  resolver.hooks.beforeResolve.tap("asset-transform", (node, options) => {
4336
+ var _a;
3997
4337
  if (node && (node.type === "asset" || node.type === "view")) {
3998
4338
  const transform = this.registry.get(node.value);
3999
4339
  if (transform == null ? void 0 : transform.beforeResolve) {
4000
- const store = getStore(node, this.beforeResolveSymbol);
4340
+ const store = getStore((_a = options.node) != null ? _a : node, this.beforeResolveSymbol);
4001
4341
  return transform.beforeResolve(node, options, store);
4002
4342
  }
4003
4343
  }
@@ -4075,14 +4415,26 @@ class ViewController {
4075
4415
  }
4076
4416
  });
4077
4417
  });
4078
- options.model.hooks.onUpdate.tap("viewController", (updates) => {
4418
+ const update = (updates) => {
4079
4419
  if (this.currentView) {
4080
4420
  if (this.optimizeUpdates) {
4081
- this.queueUpdate(new Set(updates.map((t) => t.binding)));
4421
+ this.queueUpdate(updates);
4082
4422
  } else {
4083
4423
  this.currentView.update();
4084
4424
  }
4085
4425
  }
4426
+ };
4427
+ options.model.hooks.onUpdate.tap("viewController", (updates) => {
4428
+ update(new Set(updates.map((t) => t.binding)));
4429
+ });
4430
+ options.model.hooks.onDelete.tap("viewController", (binding) => {
4431
+ const parentBinding = binding.parent();
4432
+ const property = binding.key();
4433
+ if (typeof property === "number" && parentBinding) {
4434
+ update(new Set([parentBinding]));
4435
+ } else {
4436
+ update(new Set([binding]));
4437
+ }
4086
4438
  });
4087
4439
  }
4088
4440
  queueUpdate(bindings) {
@@ -4127,6 +4479,25 @@ class ViewController {
4127
4479
  }
4128
4480
  }
4129
4481
 
4482
+ class ReadOnlyDataController {
4483
+ constructor(controller, logger) {
4484
+ this.controller = controller;
4485
+ this.logger = logger;
4486
+ }
4487
+ get(binding, options) {
4488
+ return this.controller.get(binding, options);
4489
+ }
4490
+ set(transaction, options) {
4491
+ var _a;
4492
+ (_a = this.logger) == null ? void 0 : _a.error("Error: Tried to set in a read only instance of the DataController");
4493
+ return [];
4494
+ }
4495
+ delete(binding, options) {
4496
+ var _a;
4497
+ (_a = this.logger) == null ? void 0 : _a.error("Error: Tried to delete in a read only instance of the DataController");
4498
+ }
4499
+ }
4500
+
4130
4501
  class DataController {
4131
4502
  constructor(model, options) {
4132
4503
  this.hooks = {
@@ -4183,16 +4554,19 @@ class DataController {
4183
4554
  });
4184
4555
  }
4185
4556
  const setUpdates = normalizedTransaction.reduce((updates, [binding, newVal]) => {
4186
- var _a;
4557
+ var _a, _b;
4187
4558
  const oldVal = this.get(binding, { includeInvalid: true });
4188
- if (!dequal(oldVal, newVal)) {
4189
- updates.push({
4190
- binding,
4191
- newValue: newVal,
4192
- oldValue: oldVal
4193
- });
4559
+ const update = {
4560
+ binding,
4561
+ newValue: newVal,
4562
+ oldValue: oldVal
4563
+ };
4564
+ if (dequal(oldVal, newVal)) {
4565
+ (_a = this.logger) == null ? void 0 : _a.debug(`Skipping update for path: ${binding.asString()}. Value was unchanged: ${oldVal}`);
4566
+ } else {
4567
+ updates.push(update);
4568
+ (_b = this.logger) == null ? void 0 : _b.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4194
4569
  }
4195
- (_a = this.logger) == null ? void 0 : _a.debug(`Setting path: ${binding.asString()} from: ${oldVal} to: ${newVal}`);
4196
4570
  return updates;
4197
4571
  }, []);
4198
4572
  const result = this.getModel().set(normalizedTransaction, options);
@@ -4205,17 +4579,16 @@ class DataController {
4205
4579
  }
4206
4580
  });
4207
4581
  this.hooks.onSet.call(normalizedTransaction);
4208
- this.hooks.onSet.call(normalizedTransaction);
4209
4582
  if (setUpdates.length > 0) {
4210
4583
  this.hooks.onUpdate.call(setUpdates, options);
4211
4584
  }
4212
4585
  return result;
4213
4586
  }
4214
- resolve(binding) {
4215
- return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding) : binding;
4587
+ resolve(binding, readOnly) {
4588
+ return Array.isArray(binding) || typeof binding === "string" ? this.pathResolver.parse(binding, { readOnly }) : binding;
4216
4589
  }
4217
4590
  get(binding, options) {
4218
- const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding);
4591
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, true);
4219
4592
  let result = this.getModel().get(resolved, options);
4220
4593
  if (result === void 0 && !(options == null ? void 0 : options.ignoreDefaultValue)) {
4221
4594
  const defaultVal = this.hooks.resolveDefaultValue.call(resolved);
@@ -4225,48 +4598,33 @@ class DataController {
4225
4598
  }
4226
4599
  if (options == null ? void 0 : options.formatted) {
4227
4600
  result = this.hooks.format.call(result, resolved);
4601
+ } else if ((options == null ? void 0 : options.formatted) === false) {
4602
+ result = this.hooks.deformat.call(result, resolved);
4228
4603
  }
4229
4604
  this.hooks.onGet.call(binding, result);
4230
4605
  return result;
4231
4606
  }
4232
- delete(binding) {
4233
- if (binding === void 0 || binding === null) {
4234
- throw new Error(`Invalid arguments: delete expects a data path (string)`);
4235
- }
4236
- const resolved = this.resolve(binding);
4237
- this.hooks.onDelete.call(resolved);
4238
- this.deleteData(resolved);
4239
- }
4240
- getTrash() {
4241
- return this.trash;
4242
- }
4243
- addToTrash(binding) {
4244
- this.trash.add(binding);
4245
- }
4246
- deleteData(binding) {
4247
- const parentBinding = binding.parent();
4248
- const parentPath = parentBinding.asString();
4249
- const property = binding.key();
4250
- const existedBeforeDelete = Object.prototype.hasOwnProperty.call(this.get(parentBinding), property);
4251
- if (property !== void 0) {
4252
- const parent = parentBinding ? this.get(parentBinding) : void 0;
4253
- if (parentPath && Array.isArray(parent)) {
4254
- if (parent.length > property) {
4255
- this.set([[parentBinding, removeAt(parent, property)]]);
4256
- }
4257
- } else if (parentPath && parent[property]) {
4258
- this.set([[parentBinding, omit(parent, property)]]);
4259
- } else if (!parentPath) {
4260
- this.getModel().reset(omit(this.get(""), property));
4261
- }
4607
+ delete(binding, options) {
4608
+ if (typeof binding !== "string" && !Array.isArray(binding) && !(binding instanceof BindingInstance)) {
4609
+ throw new Error("Invalid arguments: delete expects a data path (string)");
4262
4610
  }
4263
- if (existedBeforeDelete && !this.get(binding)) {
4264
- this.addToTrash(binding);
4611
+ const resolved = binding instanceof BindingInstance ? binding : this.resolve(binding, false);
4612
+ const parentBinding = resolved.parent();
4613
+ const property = resolved.key();
4614
+ const parentValue = this.get(parentBinding);
4615
+ const existedBeforeDelete = typeof parentValue === "object" && parentValue !== null && Object.prototype.hasOwnProperty.call(parentValue, property);
4616
+ this.getModel().delete(resolved, options);
4617
+ if (existedBeforeDelete && !this.get(resolved)) {
4618
+ this.trash.add(resolved);
4265
4619
  }
4620
+ this.hooks.onDelete.call(resolved);
4266
4621
  }
4267
4622
  serialize() {
4268
4623
  return this.hooks.serialize.call(this.get(""));
4269
4624
  }
4625
+ makeReadOnly() {
4626
+ return new ReadOnlyDataController(this, this.logger);
4627
+ }
4270
4628
  }
4271
4629
 
4272
4630
  var __defProp$1 = Object.defineProperty;
@@ -4323,10 +4681,15 @@ class ConstantsController {
4323
4681
  this.tempStore.set(namespace, new LocalModel(data));
4324
4682
  }
4325
4683
  }
4326
- clearTemporaryValues() {
4327
- this.tempStore.forEach((value) => {
4328
- value.reset();
4329
- });
4684
+ clearTemporaryValues(namespace) {
4685
+ var _a;
4686
+ if (namespace) {
4687
+ (_a = this.tempStore.get(namespace)) == null ? void 0 : _a.reset();
4688
+ } else {
4689
+ this.tempStore.forEach((value) => {
4690
+ value.reset();
4691
+ });
4692
+ }
4330
4693
  }
4331
4694
  }
4332
4695
 
@@ -4364,6 +4727,39 @@ class FlowExpPlugin {
4364
4727
  }
4365
4728
  }
4366
4729
 
4730
+ const createFormatFunction = (schema) => {
4731
+ const handler = (ctx, value, formatName) => {
4732
+ var _a, _b;
4733
+ return (_b = (_a = schema.getFormatterForType({ type: formatName })) == null ? void 0 : _a.format(value)) != null ? _b : value;
4734
+ };
4735
+ return handler;
4736
+ };
4737
+ class DefaultExpPlugin {
4738
+ constructor() {
4739
+ this.name = "flow-exp-plugin";
4740
+ }
4741
+ apply(player) {
4742
+ let formatFunction;
4743
+ player.hooks.schema.tap(this.name, (schemaController) => {
4744
+ formatFunction = createFormatFunction(schemaController);
4745
+ });
4746
+ player.hooks.expressionEvaluator.tap(this.name, (expEvaluator) => {
4747
+ if (formatFunction) {
4748
+ expEvaluator.addExpressionFunction("format", formatFunction);
4749
+ }
4750
+ expEvaluator.addExpressionFunction("log", (ctx, ...args) => {
4751
+ player.logger.info(...args);
4752
+ });
4753
+ expEvaluator.addExpressionFunction("debug", (ctx, ...args) => {
4754
+ player.logger.debug(...args);
4755
+ });
4756
+ expEvaluator.addExpressionFunction("eval", (ctx, ...args) => {
4757
+ return ctx.evaluate(...args);
4758
+ });
4759
+ });
4760
+ }
4761
+ }
4762
+
4367
4763
  const NOT_STARTED_STATE = {
4368
4764
  ref: Symbol("not-started"),
4369
4765
  status: "not-started"
@@ -4408,8 +4804,8 @@ var __async = (__this, __arguments, generator) => {
4408
4804
  step((generator = generator.apply(__this, __arguments)).next());
4409
4805
  });
4410
4806
  };
4411
- const PLAYER_VERSION = "0.4.0";
4412
- const COMMIT = "39b851fc45e4903eae2f5b0697dea142c890443c";
4807
+ const PLAYER_VERSION = "0.4.1-next.0";
4808
+ const COMMIT = "3fca14a3bf47195b400f5989a2f3ecbc5f73ac4b";
4413
4809
  const _Player = class {
4414
4810
  constructor(config) {
4415
4811
  this.logger = new TapableLogger();
@@ -4430,14 +4826,15 @@ const _Player = class {
4430
4826
  resolveFlowContent: new SyncWaterfallHook()
4431
4827
  };
4432
4828
  var _a;
4433
- const initialPlugins = [];
4434
- const flowExpPlugin = new FlowExpPlugin();
4435
- initialPlugins.push(flowExpPlugin);
4436
4829
  if (config == null ? void 0 : config.logger) {
4437
4830
  this.logger.addHandler(config.logger);
4438
4831
  }
4439
4832
  this.config = config || {};
4440
- this.config.plugins = [...this.config.plugins || [], ...initialPlugins];
4833
+ this.config.plugins = [
4834
+ new DefaultExpPlugin(),
4835
+ ...this.config.plugins || [],
4836
+ new FlowExpPlugin()
4837
+ ];
4441
4838
  (_a = this.config.plugins) == null ? void 0 : _a.forEach((plugin) => {
4442
4839
  plugin.apply(this);
4443
4840
  });
@@ -4528,10 +4925,11 @@ const _Player = class {
4528
4925
  flowResultDeferred.reject(e);
4529
4926
  return true;
4530
4927
  });
4531
- function resolveStrings(val) {
4928
+ function resolveStrings(val, formatted) {
4532
4929
  return resolveDataRefs(val, {
4533
4930
  model: dataController,
4534
- evaluate: expressionEvaluator.evaluate
4931
+ evaluate: expressionEvaluator.evaluate,
4932
+ formatted
4535
4933
  });
4536
4934
  }
4537
4935
  flowController.hooks.flow.tap("player", (flow) => {
@@ -4567,23 +4965,21 @@ const _Player = class {
4567
4965
  newState = setIn(state, ["ref"], resolveStrings(state.ref));
4568
4966
  }
4569
4967
  if ("param" in state) {
4570
- newState = setIn(state, ["param"], resolveStrings(state.param));
4968
+ newState = setIn(state, ["param"], resolveStrings(state.param, false));
4571
4969
  }
4572
4970
  return newState;
4573
4971
  });
4574
4972
  flow.hooks.transition.tap("player", (_oldState, newState) => {
4575
- if (newState.value.state_type === "ACTION") {
4576
- const { exp } = newState.value;
4577
- queueMicrotask(() => {
4578
- try {
4579
- flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4580
- } catch (error) {
4581
- const state = this.getState();
4582
- if (error instanceof Error && state.status === "in-progress") {
4583
- state.fail(error);
4584
- }
4585
- }
4586
- });
4973
+ if (newState.value.state_type !== "VIEW") {
4974
+ validationController.reset();
4975
+ }
4976
+ });
4977
+ flow.hooks.afterTransition.tap("player", (flowInstance) => {
4978
+ var _a;
4979
+ const value = (_a = flowInstance.currentState) == null ? void 0 : _a.value;
4980
+ if (value && value.state_type === "ACTION") {
4981
+ const { exp } = value;
4982
+ flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4587
4983
  }
4588
4984
  expressionEvaluator.reset();
4589
4985
  });
@@ -4601,6 +4997,11 @@ const _Player = class {
4601
4997
  parseBinding,
4602
4998
  transition: flowController.transition,
4603
4999
  model: dataController,
5000
+ utils: {
5001
+ findPlugin: (pluginSymbol) => {
5002
+ return this.findPlugin(pluginSymbol);
5003
+ }
5004
+ },
4604
5005
  logger: this.logger,
4605
5006
  flowController,
4606
5007
  schema,
@@ -4614,23 +5015,19 @@ const _Player = class {
4614
5015
  },
4615
5016
  validation: __spreadProps(__spreadValues({}, validationController.forView(parseBinding)), {
4616
5017
  type: (b) => schema.getType(parseBinding(b))
4617
- })
5018
+ }),
5019
+ constants: this.constantsController
4618
5020
  });
4619
5021
  viewController.hooks.view.tap("player", (view) => {
4620
5022
  validationController.onView(view);
4621
5023
  this.hooks.view.call(view);
4622
5024
  });
4623
5025
  this.hooks.viewController.call(viewController);
4624
- const formatFunction = (ctx, value, formatName) => {
4625
- var _a, _b;
4626
- return (_b = (_a = schema.getFormatterForType({ type: formatName })) == null ? void 0 : _a.format(value)) != null ? _b : value;
4627
- };
4628
- expressionEvaluator.addExpressionFunction("format", formatFunction);
4629
5026
  return {
4630
5027
  start: () => {
4631
5028
  flowController.start().then((endState) => {
4632
5029
  const flowResult = {
4633
- endState: resolveStrings(endState),
5030
+ endState: resolveStrings(endState, false),
4634
5031
  data: dataController.serialize()
4635
5032
  };
4636
5033
  return flowResult;
@@ -4683,7 +5080,9 @@ const _Player = class {
4683
5080
  ref,
4684
5081
  status: "completed",
4685
5082
  flow: state.flow,
4686
- dataModel: state.controllers.data.getModel()
5083
+ controllers: {
5084
+ data: state.controllers.data.makeReadOnly()
5085
+ }
4687
5086
  };
4688
5087
  return maybeUpdateState(__spreadValues(__spreadValues({}, yield state.flowResult), endProps));
4689
5088
  } catch (error) {
@@ -4705,5 +5104,5 @@ Player.info = {
4705
5104
  commit: COMMIT
4706
5105
  };
4707
5106
 
4708
- export { ApplicabilityPlugin, AssetTransformCorePlugin, BindingInstance, BindingParser, Builder, ConsoleLogger, ConstantsController, DataController, DependencyMiddleware, DependencyModel, DependencyTracker, EMPTY_NODE, ExpNodeOpaqueIdentifier, ExpressionEvaluator, FlowController, FlowExpPlugin, FlowInstance, LocalModel, LocalStateStore, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NodeType, NoopLogger, Parser, PipelinedDataModel, Player, ProxyLogger, ROOT_BINDING, Resolver, SIMPLE_BINDING_REGEX, SchemaController, StringResolverPlugin, SwitchPlugin, TapableLogger, TemplatePlugin, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidatorRegistry, ViewController, ViewInstance, caresAboutDataChanges, constructModelForPipeline, findClosestNodeAtPosition, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, maybeConvertToNum, parse, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };
5107
+ export { ApplicabilityPlugin, AssetTransformCorePlugin, BINDING_BRACKETS_REGEX, BindingInstance, BindingParser, Builder, ConsoleLogger, ConstantsController, DataController, DependencyMiddleware, DependencyModel, DependencyTracker, EMPTY_NODE, ExpNodeOpaqueIdentifier, ExpressionEvaluator, FlowController, FlowExpPlugin, FlowInstance, LocalModel, LocalStateStore, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NodeType, NoopLogger, Parser, PipelinedDataModel, Player, ProxyLogger, ROOT_BINDING, Resolver, SCHEMA_VALIDATION_PROVIDER_NAME, SIMPLE_BINDING_REGEX, SchemaController, StringResolverPlugin, SwitchPlugin, TapableLogger, TemplatePlugin, VALIDATION_PROVIDER_NAME_SYMBOL, VIEW_VALIDATION_PROVIDER_NAME, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidatorRegistry, ViewController, ViewInstance, caresAboutDataChanges, constructModelForPipeline, findClosestNodeAtPosition, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, isObjectExpression, maybeConvertToNum, parse, parseExpression, removeBindingAndChildrenFromMap, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };
4709
5108
  //# sourceMappingURL=index.esm.js.map