@player-ui/player 0.3.1-next.1 → 0.4.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +197 -39
- package/dist/index.d.ts +38 -13
- package/dist/index.esm.js +197 -40
- package/package.json +5 -4
- package/src/binding/resolver.ts +1 -3
- package/src/controllers/data.ts +4 -2
- package/src/controllers/validation/controller.ts +26 -13
- package/src/data/model.ts +5 -0
- package/src/expressions/evaluator.ts +1 -1
- package/src/expressions/parser.ts +64 -18
- package/src/expressions/types.ts +27 -12
- package/src/expressions/utils.ts +124 -1
- package/src/player.ts +28 -13
- package/src/string-resolver/index.ts +1 -0
- package/src/validator/validation-middleware.ts +21 -3
- package/src/view/plugins/string-resolver.ts +27 -5
package/dist/index.cjs.js
CHANGED
|
@@ -847,6 +847,15 @@ function throwError(message, index) {
|
|
|
847
847
|
err.description = message;
|
|
848
848
|
throw err;
|
|
849
849
|
}
|
|
850
|
+
function createSpanningLocation(start, end) {
|
|
851
|
+
if (!start || !end) {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
return {
|
|
855
|
+
start: start.start,
|
|
856
|
+
end: end.end
|
|
857
|
+
};
|
|
858
|
+
}
|
|
850
859
|
function getMaxKeyLen(obj) {
|
|
851
860
|
let maxLen = 0;
|
|
852
861
|
Object.keys(obj).forEach((key) => {
|
|
@@ -868,7 +877,7 @@ const thisStr = "this";
|
|
|
868
877
|
function binaryPrecedence(opVal) {
|
|
869
878
|
return binaryOps[opVal] || 0;
|
|
870
879
|
}
|
|
871
|
-
function createBinaryExpression(operator, left, right) {
|
|
880
|
+
function createBinaryExpression(operator, left, right, location) {
|
|
872
881
|
let type;
|
|
873
882
|
if (operator === "||" || operator === "&&") {
|
|
874
883
|
type = "LogicalExpression";
|
|
@@ -884,7 +893,8 @@ function createBinaryExpression(operator, left, right) {
|
|
|
884
893
|
type,
|
|
885
894
|
operator,
|
|
886
895
|
left,
|
|
887
|
-
right
|
|
896
|
+
right,
|
|
897
|
+
location
|
|
888
898
|
};
|
|
889
899
|
}
|
|
890
900
|
function isDecimalDigit(ch) {
|
|
@@ -904,6 +914,16 @@ function parseExpression(expr) {
|
|
|
904
914
|
const charCodeAtFunc = expr.charCodeAt;
|
|
905
915
|
const { length } = expr;
|
|
906
916
|
let index = 0;
|
|
917
|
+
const getLocation = (startChar) => {
|
|
918
|
+
return {
|
|
919
|
+
start: {
|
|
920
|
+
character: startChar
|
|
921
|
+
},
|
|
922
|
+
end: {
|
|
923
|
+
character: index
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
};
|
|
907
927
|
function exprI(i) {
|
|
908
928
|
return charAtFunc.call(expr, i);
|
|
909
929
|
}
|
|
@@ -917,6 +937,7 @@ function parseExpression(expr) {
|
|
|
917
937
|
let key;
|
|
918
938
|
let value;
|
|
919
939
|
let chCode;
|
|
940
|
+
const startCharIndex = index;
|
|
920
941
|
++index;
|
|
921
942
|
while (index < length) {
|
|
922
943
|
gobbleSpaces();
|
|
@@ -962,7 +983,8 @@ function parseExpression(expr) {
|
|
|
962
983
|
return {
|
|
963
984
|
__id: ExpNodeOpaqueIdentifier,
|
|
964
985
|
type: "Object",
|
|
965
|
-
attributes
|
|
986
|
+
attributes,
|
|
987
|
+
location: getLocation(startCharIndex)
|
|
966
988
|
};
|
|
967
989
|
}
|
|
968
990
|
function gobbleSpaces() {
|
|
@@ -974,6 +996,7 @@ function parseExpression(expr) {
|
|
|
974
996
|
function gobbleExpression() {
|
|
975
997
|
const test = gobbleBinaryExpression();
|
|
976
998
|
gobbleSpaces();
|
|
999
|
+
const startCharIndex = index;
|
|
977
1000
|
if (index < length && exprICode(index) === QUMARK_CODE) {
|
|
978
1001
|
index++;
|
|
979
1002
|
const consequent = gobbleExpression();
|
|
@@ -992,7 +1015,8 @@ function parseExpression(expr) {
|
|
|
992
1015
|
type: "ConditionalExpression",
|
|
993
1016
|
test,
|
|
994
1017
|
consequent,
|
|
995
|
-
alternate
|
|
1018
|
+
alternate,
|
|
1019
|
+
location: getLocation(startCharIndex)
|
|
996
1020
|
};
|
|
997
1021
|
}
|
|
998
1022
|
throwError("Expected :", index);
|
|
@@ -1038,7 +1062,7 @@ function parseExpression(expr) {
|
|
|
1038
1062
|
right = stack.pop();
|
|
1039
1063
|
biop = stack.pop().value;
|
|
1040
1064
|
left = stack.pop();
|
|
1041
|
-
node = createBinaryExpression(biop, left, right);
|
|
1065
|
+
node = createBinaryExpression(biop, left, right, createSpanningLocation(left.location, right.location));
|
|
1042
1066
|
stack.push(node);
|
|
1043
1067
|
}
|
|
1044
1068
|
node = gobbleToken();
|
|
@@ -1051,7 +1075,7 @@ function parseExpression(expr) {
|
|
|
1051
1075
|
i = stack.length - 1;
|
|
1052
1076
|
node = stack[i];
|
|
1053
1077
|
while (i > 1) {
|
|
1054
|
-
node = createBinaryExpression(stack[i - 1].value, stack[i - 2], node);
|
|
1078
|
+
node = createBinaryExpression(stack[i - 1].value, stack[i - 2], node, createSpanningLocation(stack[i - 2].location, node.location));
|
|
1055
1079
|
i -= 2;
|
|
1056
1080
|
}
|
|
1057
1081
|
return node;
|
|
@@ -1059,6 +1083,7 @@ function parseExpression(expr) {
|
|
|
1059
1083
|
function gobbleToken() {
|
|
1060
1084
|
gobbleSpaces();
|
|
1061
1085
|
const ch = exprICode(index);
|
|
1086
|
+
const startCharIndex = index;
|
|
1062
1087
|
if (isDecimalDigit(ch) || ch === PERIOD_CODE) {
|
|
1063
1088
|
return gobbleNumericLiteral();
|
|
1064
1089
|
}
|
|
@@ -1087,7 +1112,8 @@ function parseExpression(expr) {
|
|
|
1087
1112
|
type: "UnaryExpression",
|
|
1088
1113
|
operator: toCheck,
|
|
1089
1114
|
argument: gobbleToken(),
|
|
1090
|
-
prefix: true
|
|
1115
|
+
prefix: true,
|
|
1116
|
+
location: getLocation(startCharIndex)
|
|
1091
1117
|
};
|
|
1092
1118
|
}
|
|
1093
1119
|
toCheck = toCheck.substr(0, --tcLen);
|
|
@@ -1096,6 +1122,7 @@ function parseExpression(expr) {
|
|
|
1096
1122
|
}
|
|
1097
1123
|
function gobbleNumericLiteral() {
|
|
1098
1124
|
let num = "";
|
|
1125
|
+
const startCharIndex = index;
|
|
1099
1126
|
while (isDecimalDigit(exprICode(index))) {
|
|
1100
1127
|
num += exprI(index++);
|
|
1101
1128
|
}
|
|
@@ -1129,13 +1156,15 @@ function parseExpression(expr) {
|
|
|
1129
1156
|
__id: ExpNodeOpaqueIdentifier,
|
|
1130
1157
|
type: "Literal",
|
|
1131
1158
|
value: parseFloat(num),
|
|
1132
|
-
raw: num
|
|
1159
|
+
raw: num,
|
|
1160
|
+
location: getLocation(startCharIndex)
|
|
1133
1161
|
};
|
|
1134
1162
|
}
|
|
1135
1163
|
function gobbleStringLiteral() {
|
|
1136
1164
|
const quote = exprI(index++);
|
|
1137
1165
|
let str = "";
|
|
1138
1166
|
let closed = false;
|
|
1167
|
+
const startCharIndex = index;
|
|
1139
1168
|
while (index < length) {
|
|
1140
1169
|
let ch = exprI(index++);
|
|
1141
1170
|
if (ch === quote) {
|
|
@@ -1175,13 +1204,15 @@ function parseExpression(expr) {
|
|
|
1175
1204
|
__id: ExpNodeOpaqueIdentifier,
|
|
1176
1205
|
type: "Literal",
|
|
1177
1206
|
value: str,
|
|
1178
|
-
raw: `${quote}${str}${quote}
|
|
1207
|
+
raw: `${quote}${str}${quote}`,
|
|
1208
|
+
location: getLocation(startCharIndex)
|
|
1179
1209
|
};
|
|
1180
1210
|
}
|
|
1181
1211
|
function gobbleModelRef() {
|
|
1182
1212
|
let str = "";
|
|
1183
1213
|
let closed = false;
|
|
1184
1214
|
let openBraceCount = 1;
|
|
1215
|
+
const startCharIndex = index;
|
|
1185
1216
|
index += 2;
|
|
1186
1217
|
while (index < length) {
|
|
1187
1218
|
const ch = exprI(index++);
|
|
@@ -1207,7 +1238,8 @@ function parseExpression(expr) {
|
|
|
1207
1238
|
return {
|
|
1208
1239
|
__id: ExpNodeOpaqueIdentifier,
|
|
1209
1240
|
type: "ModelRef",
|
|
1210
|
-
ref: str
|
|
1241
|
+
ref: str,
|
|
1242
|
+
location: getLocation(startCharIndex)
|
|
1211
1243
|
};
|
|
1212
1244
|
}
|
|
1213
1245
|
function gobbleIdentifier() {
|
|
@@ -1232,19 +1264,22 @@ function parseExpression(expr) {
|
|
|
1232
1264
|
__id: ExpNodeOpaqueIdentifier,
|
|
1233
1265
|
type: "Literal",
|
|
1234
1266
|
value: literals[identifier],
|
|
1235
|
-
raw: identifier
|
|
1267
|
+
raw: identifier,
|
|
1268
|
+
location: getLocation(start)
|
|
1236
1269
|
};
|
|
1237
1270
|
}
|
|
1238
1271
|
if (identifier === thisStr) {
|
|
1239
1272
|
return {
|
|
1240
1273
|
__id: ExpNodeOpaqueIdentifier,
|
|
1241
|
-
type: "ThisExpression"
|
|
1274
|
+
type: "ThisExpression",
|
|
1275
|
+
location: getLocation(start)
|
|
1242
1276
|
};
|
|
1243
1277
|
}
|
|
1244
1278
|
return {
|
|
1245
1279
|
__id: ExpNodeOpaqueIdentifier,
|
|
1246
1280
|
type: "Identifier",
|
|
1247
|
-
name: identifier
|
|
1281
|
+
name: identifier,
|
|
1282
|
+
location: getLocation(start)
|
|
1248
1283
|
};
|
|
1249
1284
|
}
|
|
1250
1285
|
function gobbleArguments(termination) {
|
|
@@ -1273,6 +1308,7 @@ function parseExpression(expr) {
|
|
|
1273
1308
|
function gobbleVariable() {
|
|
1274
1309
|
let charIndex = exprICode(index);
|
|
1275
1310
|
let node = charIndex === OPAREN_CODE ? gobbleGroup() : gobbleIdentifier();
|
|
1311
|
+
const startCharIndex = index;
|
|
1276
1312
|
gobbleSpaces();
|
|
1277
1313
|
charIndex = exprICode(index);
|
|
1278
1314
|
while (charIndex === PERIOD_CODE || charIndex === OBRACK_CODE || charIndex === OPAREN_CODE) {
|
|
@@ -1284,7 +1320,8 @@ function parseExpression(expr) {
|
|
|
1284
1320
|
type: "MemberExpression",
|
|
1285
1321
|
computed: false,
|
|
1286
1322
|
object: node,
|
|
1287
|
-
property: gobbleIdentifier()
|
|
1323
|
+
property: gobbleIdentifier(),
|
|
1324
|
+
location: getLocation(startCharIndex)
|
|
1288
1325
|
};
|
|
1289
1326
|
} else if (charIndex === OBRACK_CODE) {
|
|
1290
1327
|
node = {
|
|
@@ -1292,7 +1329,8 @@ function parseExpression(expr) {
|
|
|
1292
1329
|
type: "MemberExpression",
|
|
1293
1330
|
computed: true,
|
|
1294
1331
|
object: node,
|
|
1295
|
-
property: gobbleExpression()
|
|
1332
|
+
property: gobbleExpression(),
|
|
1333
|
+
location: getLocation(startCharIndex)
|
|
1296
1334
|
};
|
|
1297
1335
|
gobbleSpaces();
|
|
1298
1336
|
charIndex = exprICode(index);
|
|
@@ -1305,7 +1343,8 @@ function parseExpression(expr) {
|
|
|
1305
1343
|
__id: ExpNodeOpaqueIdentifier,
|
|
1306
1344
|
type: "CallExpression",
|
|
1307
1345
|
args: gobbleArguments(CPAREN_CODE),
|
|
1308
|
-
callTarget: node
|
|
1346
|
+
callTarget: node,
|
|
1347
|
+
location: getLocation(startCharIndex)
|
|
1309
1348
|
};
|
|
1310
1349
|
}
|
|
1311
1350
|
gobbleSpaces();
|
|
@@ -1324,11 +1363,13 @@ function parseExpression(expr) {
|
|
|
1324
1363
|
throwError("Unclosed (", index);
|
|
1325
1364
|
}
|
|
1326
1365
|
function gobbleArray() {
|
|
1366
|
+
const startCharIndex = index;
|
|
1327
1367
|
index++;
|
|
1328
1368
|
return {
|
|
1329
1369
|
__id: ExpNodeOpaqueIdentifier,
|
|
1330
1370
|
type: "ArrayExpression",
|
|
1331
|
-
elements: gobbleArguments(CBRACK_CODE)
|
|
1371
|
+
elements: gobbleArguments(CBRACK_CODE),
|
|
1372
|
+
location: getLocation(startCharIndex)
|
|
1332
1373
|
};
|
|
1333
1374
|
}
|
|
1334
1375
|
const nodes = [];
|
|
@@ -1351,7 +1392,8 @@ function parseExpression(expr) {
|
|
|
1351
1392
|
return {
|
|
1352
1393
|
__id: ExpNodeOpaqueIdentifier,
|
|
1353
1394
|
type: "Compound",
|
|
1354
|
-
body: nodes
|
|
1395
|
+
body: nodes,
|
|
1396
|
+
location: getLocation(0)
|
|
1355
1397
|
};
|
|
1356
1398
|
}
|
|
1357
1399
|
|
|
@@ -1629,6 +1671,76 @@ class ExpressionEvaluator {
|
|
|
1629
1671
|
function withoutContext(fn) {
|
|
1630
1672
|
return (_context, ...args) => fn(...args);
|
|
1631
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
|
+
}
|
|
1632
1744
|
|
|
1633
1745
|
const severities = ["trace", "debug", "info", "warn", "error"];
|
|
1634
1746
|
|
|
@@ -1965,6 +2077,8 @@ function traverseObject(val, options) {
|
|
|
1965
2077
|
return resolveDataRefsInString(val, options);
|
|
1966
2078
|
}
|
|
1967
2079
|
case "object": {
|
|
2080
|
+
if (!val)
|
|
2081
|
+
return val;
|
|
1968
2082
|
const keys = Object.keys(val);
|
|
1969
2083
|
let newVal = val;
|
|
1970
2084
|
if (keys.length > 0) {
|
|
@@ -2020,14 +2134,22 @@ class ValidationMiddleware {
|
|
|
2020
2134
|
if (validations === void 0) {
|
|
2021
2135
|
nextTransaction.push([binding, value]);
|
|
2022
2136
|
} else if (validations instanceof Set) {
|
|
2023
|
-
|
|
2137
|
+
validations.forEach((validation) => {
|
|
2138
|
+
invalidBindings.push(validation.binding);
|
|
2139
|
+
if (!validation.isStrong) {
|
|
2140
|
+
nextTransaction.push([validation.binding, value]);
|
|
2141
|
+
}
|
|
2142
|
+
});
|
|
2024
2143
|
} else {
|
|
2025
2144
|
(_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
|
|
2026
2145
|
}
|
|
2027
2146
|
});
|
|
2028
2147
|
if (next && nextTransaction.length > 0) {
|
|
2029
2148
|
nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
|
|
2030
|
-
|
|
2149
|
+
const result = next.set(nextTransaction, options);
|
|
2150
|
+
if (invalidBindings.length === 0) {
|
|
2151
|
+
return result;
|
|
2152
|
+
}
|
|
2031
2153
|
}
|
|
2032
2154
|
return invalidBindings.map((binding) => {
|
|
2033
2155
|
return {
|
|
@@ -2693,14 +2815,27 @@ const findBasePath = (node) => {
|
|
|
2693
2815
|
return findBasePath(parentNode);
|
|
2694
2816
|
};
|
|
2695
2817
|
class StringResolverPlugin {
|
|
2818
|
+
constructor() {
|
|
2819
|
+
this.propertiesToSkipCache = new Map();
|
|
2820
|
+
}
|
|
2696
2821
|
applyResolver(resolver) {
|
|
2697
2822
|
resolver.hooks.resolve.tap("string-resolver", (value, node, options) => {
|
|
2698
|
-
var _a, _b, _c, _d;
|
|
2823
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2699
2824
|
if (node.type === exports.NodeType.Empty || node.type === exports.NodeType.Unknown) {
|
|
2700
2825
|
return null;
|
|
2701
2826
|
}
|
|
2702
2827
|
if (node.type === exports.NodeType.Value || node.type === exports.NodeType.Asset || node.type === exports.NodeType.View) {
|
|
2703
|
-
|
|
2828
|
+
let propsToSkip;
|
|
2829
|
+
if (node.type === exports.NodeType.Asset || node.type === exports.NodeType.View) {
|
|
2830
|
+
propsToSkip = new Set((_c = (_b = (_a = node.plugins) == null ? void 0 : _a.stringResolver) == null ? void 0 : _b.propertiesToSkip) != null ? _c : ["exp"]);
|
|
2831
|
+
if ((_d = node.value) == null ? void 0 : _d.id) {
|
|
2832
|
+
this.propertiesToSkipCache.set(node.value.id, propsToSkip);
|
|
2833
|
+
}
|
|
2834
|
+
} else if (((_e = node.parent) == null ? void 0 : _e.type) === exports.NodeType.MultiNode && (((_g = (_f = node.parent) == null ? void 0 : _f.parent) == null ? void 0 : _g.type) === exports.NodeType.Asset || ((_i = (_h = node.parent) == null ? void 0 : _h.parent) == null ? void 0 : _i.type) === exports.NodeType.View) && ((_j = node.parent.parent.value) == null ? void 0 : _j.id) && this.propertiesToSkipCache.has(node.parent.parent.value.id)) {
|
|
2835
|
+
propsToSkip = this.propertiesToSkipCache.get(node.parent.parent.value.id);
|
|
2836
|
+
} else {
|
|
2837
|
+
propsToSkip = new Set(["exp"]);
|
|
2838
|
+
}
|
|
2704
2839
|
const nodePath = findBasePath(node);
|
|
2705
2840
|
if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
|
|
2706
2841
|
return node.value;
|
|
@@ -3526,19 +3661,30 @@ class ValidationController {
|
|
|
3526
3661
|
getDataMiddleware() {
|
|
3527
3662
|
return [
|
|
3528
3663
|
new ValidationMiddleware((binding) => {
|
|
3664
|
+
var _a;
|
|
3529
3665
|
if (!this.options) {
|
|
3530
3666
|
return;
|
|
3531
3667
|
}
|
|
3532
3668
|
this.updateValidationsForBinding(binding, "change", this.options);
|
|
3533
3669
|
const strongValidation = this.getValidationForBinding(binding);
|
|
3534
|
-
if (strongValidation == null ? void 0 : strongValidation.get())
|
|
3670
|
+
if (((_a = strongValidation == null ? void 0 : strongValidation.get()) == null ? void 0 : _a.severity) === "error") {
|
|
3535
3671
|
return strongValidation.get();
|
|
3672
|
+
}
|
|
3536
3673
|
const newInvalidBindings = new Set();
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3674
|
+
this.validations.forEach((weakValidation, strongBinding) => {
|
|
3675
|
+
var _a2;
|
|
3676
|
+
if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
|
|
3677
|
+
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
|
+
});
|
|
3685
|
+
});
|
|
3540
3686
|
}
|
|
3541
|
-
}
|
|
3687
|
+
});
|
|
3542
3688
|
if (newInvalidBindings.size > 0) {
|
|
3543
3689
|
return newInvalidBindings;
|
|
3544
3690
|
}
|
|
@@ -3564,7 +3710,9 @@ class ValidationController {
|
|
|
3564
3710
|
ignoreDefaultValue: true
|
|
3565
3711
|
});
|
|
3566
3712
|
if (originalValue !== withoutDefault) {
|
|
3567
|
-
this.options.model.set([[binding, originalValue]]
|
|
3713
|
+
this.options.model.set([[binding, originalValue]], {
|
|
3714
|
+
silent: true
|
|
3715
|
+
});
|
|
3568
3716
|
}
|
|
3569
3717
|
this.updateValidationsForBinding(binding, "load", this.options, () => {
|
|
3570
3718
|
view.update(new Set([binding]));
|
|
@@ -3604,7 +3752,7 @@ class ValidationController {
|
|
|
3604
3752
|
this.validations.forEach((validation, vBinding) => {
|
|
3605
3753
|
if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
|
|
3606
3754
|
validation.update(trigger, true, (validationObj) => {
|
|
3607
|
-
const response = this.validationRunner(validationObj, context,
|
|
3755
|
+
const response = this.validationRunner(validationObj, context, vBinding);
|
|
3608
3756
|
return response ? { message: response.message } : void 0;
|
|
3609
3757
|
});
|
|
3610
3758
|
}
|
|
@@ -3691,16 +3839,16 @@ class ValidationController {
|
|
|
3691
3839
|
return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
|
|
3692
3840
|
}
|
|
3693
3841
|
validateView(trigger = "navigation") {
|
|
3694
|
-
var _a, _b;
|
|
3695
3842
|
this.updateValidationsForView(trigger);
|
|
3696
3843
|
const validations = new Map();
|
|
3697
|
-
|
|
3844
|
+
this.getBindings().forEach((b) => {
|
|
3845
|
+
var _a, _b;
|
|
3698
3846
|
const invalid = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.get();
|
|
3699
3847
|
if (invalid) {
|
|
3700
3848
|
(_b = this.options) == null ? void 0 : _b.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(invalid)}`);
|
|
3701
3849
|
validations.set(b, invalid);
|
|
3702
3850
|
}
|
|
3703
|
-
}
|
|
3851
|
+
});
|
|
3704
3852
|
return {
|
|
3705
3853
|
canTransition: validations.size === 0,
|
|
3706
3854
|
validations: validations.size ? validations : void 0
|
|
@@ -4070,8 +4218,9 @@ class DataController {
|
|
|
4070
4218
|
}
|
|
4071
4219
|
});
|
|
4072
4220
|
this.hooks.onSet.call(normalizedTransaction);
|
|
4221
|
+
this.hooks.onSet.call(normalizedTransaction);
|
|
4073
4222
|
if (setUpdates.length > 0) {
|
|
4074
|
-
this.hooks.onUpdate.call(setUpdates);
|
|
4223
|
+
this.hooks.onUpdate.call(setUpdates, options);
|
|
4075
4224
|
}
|
|
4076
4225
|
return result;
|
|
4077
4226
|
}
|
|
@@ -4272,8 +4421,8 @@ var __async = (__this, __arguments, generator) => {
|
|
|
4272
4421
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
4273
4422
|
});
|
|
4274
4423
|
};
|
|
4275
|
-
const PLAYER_VERSION = "0.
|
|
4276
|
-
const COMMIT = "
|
|
4424
|
+
const PLAYER_VERSION = "0.4.0-next.1";
|
|
4425
|
+
const COMMIT = "f66def4fd8f14f4898927c9ff6061d6094b7b250";
|
|
4277
4426
|
const _Player = class {
|
|
4278
4427
|
constructor(config) {
|
|
4279
4428
|
this.logger = new TapableLogger();
|
|
@@ -4400,17 +4549,18 @@ const _Player = class {
|
|
|
4400
4549
|
}
|
|
4401
4550
|
flowController.hooks.flow.tap("player", (flow) => {
|
|
4402
4551
|
flow.hooks.beforeTransition.tap("player", (state, transitionVal) => {
|
|
4403
|
-
|
|
4552
|
+
const computedTransitionVal = state.transitions[transitionVal] ? transitionVal : "*";
|
|
4553
|
+
if (state.onEnd && state.transitions[computedTransitionVal]) {
|
|
4404
4554
|
if (typeof state.onEnd === "object" && "exp" in state.onEnd) {
|
|
4405
4555
|
expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(state.onEnd.exp);
|
|
4406
4556
|
} else {
|
|
4407
4557
|
expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(state.onEnd);
|
|
4408
4558
|
}
|
|
4409
4559
|
}
|
|
4410
|
-
if (!("transitions" in state) || !state.transitions[
|
|
4560
|
+
if (!("transitions" in state) || !state.transitions[computedTransitionVal]) {
|
|
4411
4561
|
return state;
|
|
4412
4562
|
}
|
|
4413
|
-
return timm.setIn(state, ["transitions",
|
|
4563
|
+
return timm.setIn(state, ["transitions", computedTransitionVal], resolveStrings(state.transitions[computedTransitionVal]));
|
|
4414
4564
|
});
|
|
4415
4565
|
flow.hooks.skipTransition.tap("validation", (currentState) => {
|
|
4416
4566
|
var _a;
|
|
@@ -4438,7 +4588,14 @@ const _Player = class {
|
|
|
4438
4588
|
if (newState.value.state_type === "ACTION") {
|
|
4439
4589
|
const { exp } = newState.value;
|
|
4440
4590
|
queueMicrotask__default["default"](() => {
|
|
4441
|
-
|
|
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
|
+
}
|
|
4442
4599
|
});
|
|
4443
4600
|
}
|
|
4444
4601
|
expressionEvaluator.reset();
|
|
@@ -4604,6 +4761,7 @@ exports.ViewController = ViewController;
|
|
|
4604
4761
|
exports.ViewInstance = ViewInstance;
|
|
4605
4762
|
exports.caresAboutDataChanges = caresAboutDataChanges;
|
|
4606
4763
|
exports.constructModelForPipeline = constructModelForPipeline;
|
|
4764
|
+
exports.findClosestNodeAtPosition = findClosestNodeAtPosition;
|
|
4607
4765
|
exports.findInArray = findInArray;
|
|
4608
4766
|
exports.findNextExp = findNextExp;
|
|
4609
4767
|
exports.getBindingSegments = getBindingSegments;
|
package/dist/index.d.ts
CHANGED
|
@@ -165,6 +165,10 @@ interface DataModelOptions {
|
|
|
165
165
|
* A flag to set to ignore any default value in the schema, and just use the raw value
|
|
166
166
|
*/
|
|
167
167
|
ignoreDefaultValue?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* A flag to indicate that this update should happen silently
|
|
170
|
+
*/
|
|
171
|
+
silent?: boolean;
|
|
168
172
|
/** Other context associated with this request */
|
|
169
173
|
context?: {
|
|
170
174
|
/** The data model to use when getting other data from the context of this request */
|
|
@@ -370,11 +374,23 @@ declare type ExpressionHandler<T extends readonly unknown[] = unknown[], R = voi
|
|
|
370
374
|
declare const ExpNodeOpaqueIdentifier: unique symbol;
|
|
371
375
|
/** Checks if the input is an already processed Expression node */
|
|
372
376
|
declare function isExpressionNode(x: any): x is ExpressionNode;
|
|
377
|
+
interface NodePosition {
|
|
378
|
+
/** The character location */
|
|
379
|
+
character: number;
|
|
380
|
+
}
|
|
381
|
+
interface NodeLocation {
|
|
382
|
+
/** The start of the node */
|
|
383
|
+
start: NodePosition;
|
|
384
|
+
/** The end of the node */
|
|
385
|
+
end: NodePosition;
|
|
386
|
+
}
|
|
373
387
|
interface BaseNode<T> {
|
|
374
388
|
/** The thing to discriminate the AST type on */
|
|
375
389
|
type: T;
|
|
376
390
|
/** How to tell this apart from other objects */
|
|
377
391
|
__id: typeof ExpNodeOpaqueIdentifier;
|
|
392
|
+
/** The location of the node in the source expression string */
|
|
393
|
+
location?: NodeLocation;
|
|
378
394
|
}
|
|
379
395
|
/** A helper interface for nodes that container left and right children */
|
|
380
396
|
interface DirectionalNode {
|
|
@@ -393,11 +409,7 @@ interface BinaryNode extends BaseNode<'BinaryExpression'>, DirectionalNode {
|
|
|
393
409
|
/** The operation to perform on the nodes */
|
|
394
410
|
operator: string;
|
|
395
411
|
}
|
|
396
|
-
interface LogicalNode extends BaseNode<'LogicalExpression'
|
|
397
|
-
/** The left hand side of the equation */
|
|
398
|
-
left: any;
|
|
399
|
-
/** The right hand side of the equation */
|
|
400
|
-
right: any;
|
|
412
|
+
interface LogicalNode extends BaseNode<'LogicalExpression'>, DirectionalNode {
|
|
401
413
|
/** The logical operation to perform on the nodes */
|
|
402
414
|
operator: string;
|
|
403
415
|
}
|
|
@@ -405,7 +417,7 @@ interface UnaryNode extends BaseNode<'UnaryExpression'> {
|
|
|
405
417
|
/** The operation to perform on the node */
|
|
406
418
|
operator: string;
|
|
407
419
|
/** The single argument that the operation should be performed on */
|
|
408
|
-
argument:
|
|
420
|
+
argument: ExpressionNode;
|
|
409
421
|
}
|
|
410
422
|
declare type ThisNode = BaseNode<'ThisExpression'>;
|
|
411
423
|
interface ModelRefNode extends BaseNode<'ModelRef'> {
|
|
@@ -416,9 +428,9 @@ interface ObjectNode extends BaseNode<'Object'> {
|
|
|
416
428
|
/** */
|
|
417
429
|
attributes: Array<{
|
|
418
430
|
/** The property name of the object */
|
|
419
|
-
key:
|
|
431
|
+
key: ExpressionNode;
|
|
420
432
|
/** the associated value */
|
|
421
|
-
value:
|
|
433
|
+
value: ExpressionNode;
|
|
422
434
|
}>;
|
|
423
435
|
}
|
|
424
436
|
interface MemberExpressionNode extends BaseNode<'MemberExpression'> {
|
|
@@ -443,13 +455,13 @@ interface CompoundNode extends BaseNode<'Compound'> {
|
|
|
443
455
|
}
|
|
444
456
|
interface CallExpressionNode extends BaseNode<'CallExpression'> {
|
|
445
457
|
/** The arguments to the function */
|
|
446
|
-
args:
|
|
458
|
+
args: ExpressionNode[];
|
|
447
459
|
/** The function name */
|
|
448
460
|
callTarget: IdentifierNode;
|
|
449
461
|
}
|
|
450
462
|
interface ArrayExpressionNode extends BaseNode<'ArrayExpression'> {
|
|
451
463
|
/** The items in an array */
|
|
452
|
-
elements:
|
|
464
|
+
elements: ExpressionNode[];
|
|
453
465
|
}
|
|
454
466
|
interface IdentifierNode extends BaseNode<'Identifier'> {
|
|
455
467
|
/** The variable name */
|
|
@@ -505,6 +517,8 @@ declare class ExpressionEvaluator {
|
|
|
505
517
|
|
|
506
518
|
/** Generates a function by removing the first context argument */
|
|
507
519
|
declare function withoutContext<T extends unknown[], Return>(fn: (...args: T) => Return): ExpressionHandler<T, Return>;
|
|
520
|
+
/** Get the node in the expression that's closest to the desired position */
|
|
521
|
+
declare function findClosestNodeAtPosition(node: ExpressionNode, position: NodePosition): ExpressionNode | undefined;
|
|
508
522
|
|
|
509
523
|
declare type FormatOptions = Omit<Formatting.Reference, 'type'>;
|
|
510
524
|
/**
|
|
@@ -961,6 +975,8 @@ declare class TemplatePlugin implements ViewPlugin {
|
|
|
961
975
|
|
|
962
976
|
/** A plugin that resolves all string references for each node */
|
|
963
977
|
declare class StringResolverPlugin implements ViewPlugin {
|
|
978
|
+
private propertiesToSkipCache;
|
|
979
|
+
constructor();
|
|
964
980
|
applyResolver(resolver: Resolver): void;
|
|
965
981
|
apply(view: View): void;
|
|
966
982
|
}
|
|
@@ -1275,7 +1291,7 @@ declare class DataController implements DataModelWithParser<DataModelOptions> {
|
|
|
1275
1291
|
onDelete: SyncHook<[any], Record<string, any>>;
|
|
1276
1292
|
onSet: SyncHook<[BatchSetTransaction], Record<string, any>>;
|
|
1277
1293
|
onGet: SyncHook<[any, any], Record<string, any>>;
|
|
1278
|
-
onUpdate: SyncHook<[Updates], Record<string, any>>;
|
|
1294
|
+
onUpdate: SyncHook<[Updates, DataModelOptions | undefined], Record<string, any>>;
|
|
1279
1295
|
format: SyncWaterfallHook<[any, BindingInstance], Record<string, any>>;
|
|
1280
1296
|
deformat: SyncWaterfallHook<[any, BindingInstance], Record<string, any>>;
|
|
1281
1297
|
serialize: SyncWaterfallHook<[any], Record<string, any>>;
|
|
@@ -1434,10 +1450,19 @@ interface ValidatorContext {
|
|
|
1434
1450
|
}
|
|
1435
1451
|
declare type ValidatorFunction<Options = unknown> = (context: ValidatorContext, value: any, options?: Options) => Omit<BaseValidationResponse, 'severity'> | undefined;
|
|
1436
1452
|
|
|
1453
|
+
/**
|
|
1454
|
+
* A BindingInstance with an indicator of whether or not it's a strong binding
|
|
1455
|
+
*/
|
|
1456
|
+
declare type StrongOrWeakBinding = {
|
|
1457
|
+
/** BindingInstance in question */
|
|
1458
|
+
binding: BindingInstance;
|
|
1459
|
+
/** Boolean indicating whether the relevant BindingInstance is a strong binding */
|
|
1460
|
+
isStrong: boolean;
|
|
1461
|
+
};
|
|
1437
1462
|
/**
|
|
1438
1463
|
* Returns a validation object if the data is invalid or an set of BindingsInstances if the binding itself is a weak ref of another invalid validation
|
|
1439
1464
|
*/
|
|
1440
|
-
declare type MiddlewareChecker = (binding: BindingInstance, model: DataModelImpl) => ValidationResponse | Set<
|
|
1465
|
+
declare type MiddlewareChecker = (binding: BindingInstance, model: DataModelImpl) => ValidationResponse | Set<StrongOrWeakBinding> | undefined;
|
|
1441
1466
|
/**
|
|
1442
1467
|
* Middleware for the data-model that caches the results of invalid data
|
|
1443
1468
|
*/
|
|
@@ -1611,4 +1636,4 @@ declare class FlowExpPlugin implements PlayerPlugin {
|
|
|
1611
1636
|
apply(player: Player): void;
|
|
1612
1637
|
}
|
|
1613
1638
|
|
|
1614
|
-
export { AnyAssetType, ApplicabilityPlugin, ArrayExpressionNode, AssetTransformCorePlugin, AssignmentNode, BaseFlowState, BaseNode, BatchSetTransaction, BeforeTransformFunction, BinaryNode, BinaryOperator, BinaryOperatorAdvanced, BinaryOperatorBasic, BindingFactory, BindingInstance, BindingLike, BindingParser, BindingParserOptions, BindingTracker, Builder, CallExpressionNode, CompletedState, CompoundNode, ConditionalExpressionNode, ConsoleLogger, ConstantsController, ConstantsProvider, ControllerState, DataController, DataModelImpl, DataModelMiddleware, DataModelOptions, DataModelWithParser, DataPipeline, DependencyMiddleware, DependencyModel, DependencySets, DependencyTracker, DirectionalNode, EMPTY_NODE, ErrorState, ErrorValidationResponse, ExpNodeOpaqueIdentifier, ExpressionContext, ExpressionEvaluator, ExpressionEvaluatorFunction, ExpressionEvaluatorOptions, ExpressionHandler, ExpressionLiteralType, ExpressionNode, ExpressionNodeType, ExpressionType, FlowController, FlowExpPlugin, FlowInstance, FormatDefinition, FormatFunction, FormatHandler, FormatOptions, FormatType, Getter, HookOptions, IdentifierNode, InProgressState, LiteralNode, LocalModel, LocalStateStore, LogFn, Logger, LoggerProvider, LogicalNode, MemberExpressionNode, MiddlewareChecker, ModelRefNode, ModificationNode, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NamedState, Node, NodeType, NoopLogger, NotStartedState, ObjectNode, OperatorProcessingOptions, Options, ParseObjectOptions, Parser, PipelinedDataModel, Player, PlayerConfigOptions, PlayerFlowExecutionData, PlayerFlowState, PlayerFlowStatus, PlayerInfo, PlayerPlugin, ProxyLogger, ROOT_BINDING, RawBinding, RawBindingSegment, RawSetTransaction, RawSetType, Resolve, Resolver, SIMPLE_BINDING_REGEX, SchemaController, Severity, StatefulValidationObject, Store, StringResolverPlugin, SwitchPlugin, TapableLogger, TemplatePlugin, ThisNode, TransformFunction, TransformFunctions, TransformRegistry, TransitionFunction, TransitionOptions, UnaryNode, UnaryOperator, Updates, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidationObject, ValidationProvider, ValidationResponse, ValidatorContext, ValidatorFunction, ValidatorRegistry, ViewController, ViewControllerOptions, ViewInstance, ViewPlugin, WarningValidationResponse, caresAboutDataChanges, constructModelForPipeline, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, maybeConvertToNum, parse, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };
|
|
1639
|
+
export { AnyAssetType, ApplicabilityPlugin, ArrayExpressionNode, AssetTransformCorePlugin, AssignmentNode, BaseFlowState, BaseNode, BatchSetTransaction, BeforeTransformFunction, BinaryNode, BinaryOperator, BinaryOperatorAdvanced, BinaryOperatorBasic, BindingFactory, BindingInstance, BindingLike, BindingParser, BindingParserOptions, BindingTracker, Builder, CallExpressionNode, CompletedState, CompoundNode, ConditionalExpressionNode, ConsoleLogger, ConstantsController, ConstantsProvider, ControllerState, DataController, DataModelImpl, DataModelMiddleware, DataModelOptions, DataModelWithParser, DataPipeline, DependencyMiddleware, DependencyModel, DependencySets, DependencyTracker, DirectionalNode, EMPTY_NODE, ErrorState, ErrorValidationResponse, ExpNodeOpaqueIdentifier, ExpressionContext, ExpressionEvaluator, ExpressionEvaluatorFunction, ExpressionEvaluatorOptions, ExpressionHandler, ExpressionLiteralType, ExpressionNode, ExpressionNodeType, ExpressionType, FlowController, FlowExpPlugin, FlowInstance, FormatDefinition, FormatFunction, FormatHandler, FormatOptions, FormatType, Getter, HookOptions, IdentifierNode, InProgressState, LiteralNode, LocalModel, LocalStateStore, LogFn, Logger, LoggerProvider, LogicalNode, MemberExpressionNode, MiddlewareChecker, ModelRefNode, ModificationNode, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NamedState, Node, NodeLocation, NodePosition, NodeType, NoopLogger, NotStartedState, ObjectNode, OperatorProcessingOptions, Options, ParseObjectOptions, Parser, PipelinedDataModel, Player, PlayerConfigOptions, PlayerFlowExecutionData, PlayerFlowState, PlayerFlowStatus, PlayerInfo, PlayerPlugin, ProxyLogger, ROOT_BINDING, RawBinding, RawBindingSegment, RawSetTransaction, RawSetType, Resolve, Resolver, SIMPLE_BINDING_REGEX, SchemaController, Severity, StatefulValidationObject, Store, StringResolverPlugin, StrongOrWeakBinding, SwitchPlugin, TapableLogger, TemplatePlugin, ThisNode, TransformFunction, TransformFunctions, TransformRegistry, TransitionFunction, TransitionOptions, UnaryNode, UnaryOperator, Updates, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidationObject, ValidationProvider, ValidationResponse, ValidatorContext, ValidatorFunction, ValidatorRegistry, ViewController, ViewControllerOptions, ViewInstance, ViewPlugin, WarningValidationResponse, caresAboutDataChanges, constructModelForPipeline, findClosestNodeAtPosition, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, maybeConvertToNum, parse, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };
|