@salesforce/lds-runtime-mobile 1.129.0 → 1.130.8
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/main.js +112 -29
- package/package.json +3 -3
- package/sfdc/main.js +112 -29
package/dist/main.js
CHANGED
|
@@ -2096,6 +2096,7 @@ const recordPrefix = '.data.uiapi.query';
|
|
|
2096
2096
|
const recordSuffix = 'edges';
|
|
2097
2097
|
const pathPrefix = '$';
|
|
2098
2098
|
const recordsCTE = 'recordsCTE';
|
|
2099
|
+
const MultiPickListValueSeparator$1 = ';';
|
|
2099
2100
|
function cteSql() {
|
|
2100
2101
|
return (`WITH ${recordsCTE} AS NOT materialized ` +
|
|
2101
2102
|
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`);
|
|
@@ -2264,16 +2265,26 @@ function existsPredicateToSql(exists) {
|
|
|
2264
2265
|
}
|
|
2265
2266
|
function comparisonPredicateToSql(predicate) {
|
|
2266
2267
|
const operator = comparisonOperatorToSql(predicate.operator);
|
|
2267
|
-
|
|
2268
|
+
let { sql: left, bindings: leftBindings } = expressionToSql(predicate.left, undefined, predicate.operator);
|
|
2268
2269
|
if (predicate.right.type === ValueType.DateEnum ||
|
|
2269
2270
|
predicate.right.type === ValueType.DateTimeEnum ||
|
|
2270
2271
|
predicate.right.type === ValueType.DateArray ||
|
|
2271
2272
|
predicate.right.type === ValueType.DateTimeArray ||
|
|
2272
|
-
predicate.right.type === ValueType.DateValue
|
|
2273
|
-
|
|
2273
|
+
predicate.right.type === ValueType.DateValue ||
|
|
2274
|
+
predicate.right.type === ValueType.DateTimeValue) {
|
|
2275
|
+
const dateFunction = predicate.right.type === ValueType.DateTimeEnum ||
|
|
2276
|
+
predicate.right.type === ValueType.DateTimeArray ||
|
|
2277
|
+
predicate.right.type === ValueType.DateTimeValue
|
|
2278
|
+
? 'datetime'
|
|
2279
|
+
: 'date';
|
|
2280
|
+
const fieldDateValue = `${dateFunction}(${left})`;
|
|
2274
2281
|
return comparisonDateLiteralToSql(fieldDateValue, predicate.operator, predicate.right);
|
|
2275
2282
|
}
|
|
2276
|
-
|
|
2283
|
+
if (predicate.right.type === ValueType.RelativeDate) {
|
|
2284
|
+
const dateFunc = predicate.right.hasTime ? 'datetime' : 'date';
|
|
2285
|
+
left = `${dateFunc}(${left})`;
|
|
2286
|
+
}
|
|
2287
|
+
const { sql: right, bindings: rightBindings } = expressionToSql(predicate.right, undefined, predicate.operator);
|
|
2277
2288
|
let bindings = leftBindings.concat(rightBindings);
|
|
2278
2289
|
if (predicate.operator === ComparisonOperator.eq &&
|
|
2279
2290
|
predicate.right.type === ValueType.StringLiteral &&
|
|
@@ -2358,11 +2369,21 @@ function coerceToTargetDataType(initialSql, targetDataType) {
|
|
|
2358
2369
|
return initialSql;
|
|
2359
2370
|
}
|
|
2360
2371
|
}
|
|
2361
|
-
function expressionToSql(expression, targetDataType) {
|
|
2372
|
+
function expressionToSql(expression, targetDataType, operator) {
|
|
2362
2373
|
switch (expression.type) {
|
|
2363
2374
|
case ValueType.Extract: {
|
|
2375
|
+
// displayValue's for Booleans are special, they return null
|
|
2376
|
+
if (expression.subfield === 'displayValue' && targetDataType === 'Boolean') {
|
|
2377
|
+
return { sql: 'null', bindings: [] };
|
|
2378
|
+
}
|
|
2364
2379
|
let path = extractPath(expression.field, expression.subfield);
|
|
2365
|
-
|
|
2380
|
+
// For multiple picklist includes/excluding filtering, we need to prefix and suffix the field value with ';'
|
|
2381
|
+
// to make the match safe.
|
|
2382
|
+
// sample: field value: 'item12;item123', input value is 'item1'; they need to be converted to
|
|
2383
|
+
// ';item12;item123;' and '%;item1;%' first, then do sqlite like operation.
|
|
2384
|
+
let sql = operator === ComparisonOperator.includes || operator === ComparisonOperator.excludes
|
|
2385
|
+
? `'${MultiPickListValueSeparator$1}' || json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}') || '${MultiPickListValueSeparator$1}'`
|
|
2386
|
+
: `json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}')`;
|
|
2366
2387
|
if (targetDataType !== undefined) {
|
|
2367
2388
|
sql = coerceToTargetDataType(sql, targetDataType);
|
|
2368
2389
|
}
|
|
@@ -2409,7 +2430,7 @@ function expressionToSql(expression, targetDataType) {
|
|
|
2409
2430
|
case ValueType.StringLiteral:
|
|
2410
2431
|
return stringLiteralToSql(expression);
|
|
2411
2432
|
case ValueType.MultiPicklistSet:
|
|
2412
|
-
return multiPicklistToSql$1(expression);
|
|
2433
|
+
return multiPicklistToSql$1(expression, operator);
|
|
2413
2434
|
}
|
|
2414
2435
|
}
|
|
2415
2436
|
function stringLiteralToSql(string) {
|
|
@@ -2425,14 +2446,18 @@ function expressionArrayToSql(expressions, toSql) {
|
|
|
2425
2446
|
const bindings = results.length > 0 ? results.map((v) => v.bindings).reduce(flatten$1) : [];
|
|
2426
2447
|
return { sql, bindings };
|
|
2427
2448
|
}
|
|
2428
|
-
function multiPicklistToSql$1({ value }) {
|
|
2449
|
+
function multiPicklistToSql$1({ value }, operator) {
|
|
2429
2450
|
// Individual multipicklist terms that delimited by semicolon are stored server-side
|
|
2430
2451
|
// as lexically sorted strings and treated like logical ANDs. We can approximate this
|
|
2431
2452
|
// behavior in SQL with wildcarded `LIKE` SQL operators. Terms with no delimiter can
|
|
2432
2453
|
// be treated as string literals. Multiple terms are logically OR'd together to
|
|
2433
2454
|
// match the behavior described in SOQL documentation (https://sfdc.co/c9j0r)
|
|
2455
|
+
// To make sure the match is safe for includes/excludes. the value is prefix and
|
|
2456
|
+
// suffix with ';', like 'abc' to '%;abc;%'. raw value for eq and ne.
|
|
2434
2457
|
const sql = '?';
|
|
2435
|
-
const binding =
|
|
2458
|
+
const binding = operator === ComparisonOperator.includes || operator === ComparisonOperator.excludes
|
|
2459
|
+
? `%${MultiPickListValueSeparator$1}${value}${MultiPickListValueSeparator$1}%`
|
|
2460
|
+
: value;
|
|
2436
2461
|
return { sql, bindings: [binding] };
|
|
2437
2462
|
}
|
|
2438
2463
|
function relativeDateToSql(expression) {
|
|
@@ -2503,8 +2528,12 @@ function comparisonDateLiteralToSql(leftOperand, operator, dateInput) {
|
|
|
2503
2528
|
}
|
|
2504
2529
|
}
|
|
2505
2530
|
if (dateInput.type === ValueType.DateValue || dateInput.type === ValueType.DateTimeValue) {
|
|
2531
|
+
const dateFunction = dateInput.type === ValueType.DateTimeValue ? 'datetime' : 'date';
|
|
2506
2532
|
const compOperator = comparisonOperatorToSql(operator);
|
|
2507
|
-
return {
|
|
2533
|
+
return {
|
|
2534
|
+
sql: leftOperand + ` ${compOperator} ` + `${dateFunction}(?)`,
|
|
2535
|
+
bindings: [`${dateInput.value}`],
|
|
2536
|
+
};
|
|
2508
2537
|
}
|
|
2509
2538
|
return { sql: '', bindings: [] };
|
|
2510
2539
|
}
|
|
@@ -2735,15 +2764,41 @@ function fieldFilter(fieldName, fieldNode, alias, apiName, input, joins) {
|
|
|
2735
2764
|
return dateRangeComparison(op.value, op.operator, extract);
|
|
2736
2765
|
}
|
|
2737
2766
|
if (op.type === 'MultiPicklistSetOperator') {
|
|
2767
|
+
const operator = op.operator === ComparisonOperator.includes
|
|
2768
|
+
? CompoundOperator.or
|
|
2769
|
+
: CompoundOperator.and;
|
|
2770
|
+
const children = [];
|
|
2771
|
+
const length = op.value.value.length;
|
|
2772
|
+
for (let i = 0; i < length; i++) {
|
|
2773
|
+
const term = op.value.value[i];
|
|
2774
|
+
if (term !== null) {
|
|
2775
|
+
const splittedValue = term.split(MultiPickListValueSeparator$1);
|
|
2776
|
+
if (splittedValue.length === 1) {
|
|
2777
|
+
children.push(comparison(extract, op.operator, {
|
|
2778
|
+
type: ValueType.MultiPicklistSet,
|
|
2779
|
+
value: term,
|
|
2780
|
+
}));
|
|
2781
|
+
}
|
|
2782
|
+
else {
|
|
2783
|
+
children.push({
|
|
2784
|
+
type: PredicateType$1.compound,
|
|
2785
|
+
operator: op.operator === ComparisonOperator.includes
|
|
2786
|
+
? CompoundOperator.and
|
|
2787
|
+
: CompoundOperator.or,
|
|
2788
|
+
children: splittedValue.map((singleValue) => {
|
|
2789
|
+
return comparison(extract, op.operator, {
|
|
2790
|
+
type: ValueType.MultiPicklistSet,
|
|
2791
|
+
value: singleValue,
|
|
2792
|
+
});
|
|
2793
|
+
}),
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2738
2798
|
return {
|
|
2739
2799
|
type: PredicateType$1.compound,
|
|
2740
|
-
operator
|
|
2741
|
-
children
|
|
2742
|
-
return comparison(extract, op.operator, {
|
|
2743
|
-
type: ValueType.MultiPicklistSet,
|
|
2744
|
-
value: term,
|
|
2745
|
-
});
|
|
2746
|
-
}),
|
|
2800
|
+
operator,
|
|
2801
|
+
children,
|
|
2747
2802
|
};
|
|
2748
2803
|
}
|
|
2749
2804
|
if (op.type === 'StringSetOperator' && op.value.value.includes(null)) {
|
|
@@ -2807,8 +2862,6 @@ function dateRangeComparison(dateRange, operator, compareDate) {
|
|
|
2807
2862
|
return comparison(compareDate, gte, dateRange.start);
|
|
2808
2863
|
}
|
|
2809
2864
|
}
|
|
2810
|
-
const dateRegEx = /^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))$/;
|
|
2811
|
-
const dateTimeRegEx = /^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9](\.[0-9]{3})?Z$/;
|
|
2812
2865
|
function dateFunctions(operatorNode, extract, dataType) {
|
|
2813
2866
|
if (dataType !== 'Date' && dataType !== 'DateTime') {
|
|
2814
2867
|
return success([]);
|
|
@@ -2886,7 +2939,7 @@ function isStringOperatorType(value) {
|
|
|
2886
2939
|
return isScalarOperatorType(value) || value === like;
|
|
2887
2940
|
}
|
|
2888
2941
|
function isPicklistOperatorType(value) {
|
|
2889
|
-
let values = [eq, ne];
|
|
2942
|
+
let values = [eq, ne, like, lt, gt, lte, gte];
|
|
2890
2943
|
return values.includes(value);
|
|
2891
2944
|
}
|
|
2892
2945
|
function isCurrencyOperatorType(value) {
|
|
@@ -3237,8 +3290,11 @@ function operatorWithValue(operator, valueNode, objectInfoDataType) {
|
|
|
3237
3290
|
message(`Comparison operator ${operator} is not supported for type ${objectInfoDataType}.`),
|
|
3238
3291
|
]);
|
|
3239
3292
|
}
|
|
3293
|
+
function isValidDate(value) {
|
|
3294
|
+
return isNaN(Date.parse(value)) === false;
|
|
3295
|
+
}
|
|
3240
3296
|
function dateInput(node) {
|
|
3241
|
-
return parseDateNode(node,
|
|
3297
|
+
return parseDateNode(node, false, 'YYYY-MM-DD', isValidDate).map((result) => {
|
|
3242
3298
|
switch (result.type) {
|
|
3243
3299
|
case ValueType.NullValue:
|
|
3244
3300
|
return result;
|
|
@@ -3252,7 +3308,7 @@ function dateInput(node) {
|
|
|
3252
3308
|
});
|
|
3253
3309
|
}
|
|
3254
3310
|
function dateTimeInput(node) {
|
|
3255
|
-
return parseDateNode(node,
|
|
3311
|
+
return parseDateNode(node, true, 'YYYY-MM-DDTHH:MM:SS.SSSZ, YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DDTHH:MM:SS.SSS+|-HH:MM, or YYYY-MM-DDTHH:MM:SS+|-HH:MM', isValidDate).map((result) => {
|
|
3256
3312
|
switch (result.type) {
|
|
3257
3313
|
case ValueType.NullValue:
|
|
3258
3314
|
return result;
|
|
@@ -3277,7 +3333,7 @@ function parseNullValue(op) {
|
|
|
3277
3333
|
}
|
|
3278
3334
|
return failure(message(`Null can not be compared with ${op}`));
|
|
3279
3335
|
}
|
|
3280
|
-
function parseDateNode(node,
|
|
3336
|
+
function parseDateNode(node, hasTime, dateFormat, isValidDate) {
|
|
3281
3337
|
const typeName = hasTime ? 'DateTime' : 'Date';
|
|
3282
3338
|
if (!isObjectValueNode$1(node)) {
|
|
3283
3339
|
return failure(message(`Comparison value must be a ${typeName} input.`));
|
|
@@ -3285,7 +3341,12 @@ function parseDateNode(node, regex, hasTime, dateFormat) {
|
|
|
3285
3341
|
const valueField = node.fields.value;
|
|
3286
3342
|
if (valueField !== undefined) {
|
|
3287
3343
|
if (is(valueField, 'StringValue')) {
|
|
3288
|
-
|
|
3344
|
+
// check the date is valid
|
|
3345
|
+
// then make sure if it isnt suppose to contain time stamps that it doesnt
|
|
3346
|
+
// and if it should have a timestamp it should contain it
|
|
3347
|
+
const includesTimeStamp = valueField.value.includes('T');
|
|
3348
|
+
if (isValidDate(valueField.value) &&
|
|
3349
|
+
((hasTime && includesTimeStamp) || (!hasTime && !includesTimeStamp))) {
|
|
3289
3350
|
return success(stringLiteral(valueField.value));
|
|
3290
3351
|
}
|
|
3291
3352
|
return failure(message(`${typeName} format must be ${dateFormat}.`));
|
|
@@ -4277,7 +4338,20 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4277
4338
|
// await it here to normalize the input to a snapshot
|
|
4278
4339
|
const nonEvaluatedSnapshot = await nonEvaluatedSnapshotOrPromise;
|
|
4279
4340
|
// if the non-eval result has errors we want to return to caller
|
|
4280
|
-
|
|
4341
|
+
const nonEvaluatedGQLSnapshot = nonEvaluatedSnapshot;
|
|
4342
|
+
if (isErrorSnapshotThatShouldGetReturnedToCaller$1(nonEvaluatedGQLSnapshot)) {
|
|
4343
|
+
const { data: gqlData } = nonEvaluatedGQLSnapshot;
|
|
4344
|
+
if (hasGraphQlErrors$1(gqlData) && gqlData !== undefined) {
|
|
4345
|
+
return {
|
|
4346
|
+
...nonEvaluatedSnapshot,
|
|
4347
|
+
data: undefined,
|
|
4348
|
+
state: 'Error',
|
|
4349
|
+
error: {
|
|
4350
|
+
errorType: 'adapterError',
|
|
4351
|
+
error: gqlData.errors,
|
|
4352
|
+
},
|
|
4353
|
+
};
|
|
4354
|
+
}
|
|
4281
4355
|
return nonEvaluatedSnapshot;
|
|
4282
4356
|
}
|
|
4283
4357
|
let rootQuery;
|
|
@@ -6872,9 +6946,18 @@ function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draf
|
|
|
6872
6946
|
const makePredicate = fieldInfo.dataType === 'MultiPicklist'
|
|
6873
6947
|
? createMultiPicklistPredicate
|
|
6874
6948
|
: createSinglePredicate;
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6949
|
+
const predicate = makePredicate(idProcessingNeeded ? sanitizePredicateIDValue(value, draftFunctions) : value, operator, fieldInfo, alias);
|
|
6950
|
+
// for the case where we have a not equals predicate that's value is not null
|
|
6951
|
+
// we need to compound into an or statement to also inlcude the null values for that field
|
|
6952
|
+
if (operator === '!=' && typeof value === 'string') {
|
|
6953
|
+
// create a is null predicate
|
|
6954
|
+
const isNullPredicate = createSinglePredicate(null, '=', fieldInfo, alias);
|
|
6955
|
+
// compound the predicates into an or predicate
|
|
6956
|
+
predicates.push(transformCompoundPredicate('or', [predicate, isNullPredicate]));
|
|
6957
|
+
}
|
|
6958
|
+
else {
|
|
6959
|
+
predicates.push(predicate);
|
|
6960
|
+
}
|
|
6878
6961
|
}
|
|
6879
6962
|
}
|
|
6880
6963
|
}
|
|
@@ -15627,4 +15710,4 @@ register({
|
|
|
15627
15710
|
});
|
|
15628
15711
|
|
|
15629
15712
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15630
|
-
// version: 1.
|
|
15713
|
+
// version: 1.130.8-e6645fb41
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.130.8",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"path": "./dist/main.js",
|
|
59
59
|
"maxSize": {
|
|
60
60
|
"none": "650 kB",
|
|
61
|
-
"min": "
|
|
61
|
+
"min": "255 kB",
|
|
62
62
|
"compressed": "100 kB"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"path": "./sfdc/main.js",
|
|
67
67
|
"maxSize": {
|
|
68
68
|
"none": "650 kB",
|
|
69
|
-
"min": "
|
|
69
|
+
"min": "255 kB",
|
|
70
70
|
"compressed": "100 kB"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/sfdc/main.js
CHANGED
|
@@ -2096,6 +2096,7 @@ const recordPrefix = '.data.uiapi.query';
|
|
|
2096
2096
|
const recordSuffix = 'edges';
|
|
2097
2097
|
const pathPrefix = '$';
|
|
2098
2098
|
const recordsCTE = 'recordsCTE';
|
|
2099
|
+
const MultiPickListValueSeparator$1 = ';';
|
|
2099
2100
|
function cteSql() {
|
|
2100
2101
|
return (`WITH ${recordsCTE} AS NOT materialized ` +
|
|
2101
2102
|
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`);
|
|
@@ -2264,16 +2265,26 @@ function existsPredicateToSql(exists) {
|
|
|
2264
2265
|
}
|
|
2265
2266
|
function comparisonPredicateToSql(predicate) {
|
|
2266
2267
|
const operator = comparisonOperatorToSql(predicate.operator);
|
|
2267
|
-
|
|
2268
|
+
let { sql: left, bindings: leftBindings } = expressionToSql(predicate.left, undefined, predicate.operator);
|
|
2268
2269
|
if (predicate.right.type === ValueType.DateEnum ||
|
|
2269
2270
|
predicate.right.type === ValueType.DateTimeEnum ||
|
|
2270
2271
|
predicate.right.type === ValueType.DateArray ||
|
|
2271
2272
|
predicate.right.type === ValueType.DateTimeArray ||
|
|
2272
|
-
predicate.right.type === ValueType.DateValue
|
|
2273
|
-
|
|
2273
|
+
predicate.right.type === ValueType.DateValue ||
|
|
2274
|
+
predicate.right.type === ValueType.DateTimeValue) {
|
|
2275
|
+
const dateFunction = predicate.right.type === ValueType.DateTimeEnum ||
|
|
2276
|
+
predicate.right.type === ValueType.DateTimeArray ||
|
|
2277
|
+
predicate.right.type === ValueType.DateTimeValue
|
|
2278
|
+
? 'datetime'
|
|
2279
|
+
: 'date';
|
|
2280
|
+
const fieldDateValue = `${dateFunction}(${left})`;
|
|
2274
2281
|
return comparisonDateLiteralToSql(fieldDateValue, predicate.operator, predicate.right);
|
|
2275
2282
|
}
|
|
2276
|
-
|
|
2283
|
+
if (predicate.right.type === ValueType.RelativeDate) {
|
|
2284
|
+
const dateFunc = predicate.right.hasTime ? 'datetime' : 'date';
|
|
2285
|
+
left = `${dateFunc}(${left})`;
|
|
2286
|
+
}
|
|
2287
|
+
const { sql: right, bindings: rightBindings } = expressionToSql(predicate.right, undefined, predicate.operator);
|
|
2277
2288
|
let bindings = leftBindings.concat(rightBindings);
|
|
2278
2289
|
if (predicate.operator === ComparisonOperator.eq &&
|
|
2279
2290
|
predicate.right.type === ValueType.StringLiteral &&
|
|
@@ -2358,11 +2369,21 @@ function coerceToTargetDataType(initialSql, targetDataType) {
|
|
|
2358
2369
|
return initialSql;
|
|
2359
2370
|
}
|
|
2360
2371
|
}
|
|
2361
|
-
function expressionToSql(expression, targetDataType) {
|
|
2372
|
+
function expressionToSql(expression, targetDataType, operator) {
|
|
2362
2373
|
switch (expression.type) {
|
|
2363
2374
|
case ValueType.Extract: {
|
|
2375
|
+
// displayValue's for Booleans are special, they return null
|
|
2376
|
+
if (expression.subfield === 'displayValue' && targetDataType === 'Boolean') {
|
|
2377
|
+
return { sql: 'null', bindings: [] };
|
|
2378
|
+
}
|
|
2364
2379
|
let path = extractPath(expression.field, expression.subfield);
|
|
2365
|
-
|
|
2380
|
+
// For multiple picklist includes/excluding filtering, we need to prefix and suffix the field value with ';'
|
|
2381
|
+
// to make the match safe.
|
|
2382
|
+
// sample: field value: 'item12;item123', input value is 'item1'; they need to be converted to
|
|
2383
|
+
// ';item12;item123;' and '%;item1;%' first, then do sqlite like operation.
|
|
2384
|
+
let sql = operator === ComparisonOperator.includes || operator === ComparisonOperator.excludes
|
|
2385
|
+
? `'${MultiPickListValueSeparator$1}' || json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}') || '${MultiPickListValueSeparator$1}'`
|
|
2386
|
+
: `json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}')`;
|
|
2366
2387
|
if (targetDataType !== undefined) {
|
|
2367
2388
|
sql = coerceToTargetDataType(sql, targetDataType);
|
|
2368
2389
|
}
|
|
@@ -2409,7 +2430,7 @@ function expressionToSql(expression, targetDataType) {
|
|
|
2409
2430
|
case ValueType.StringLiteral:
|
|
2410
2431
|
return stringLiteralToSql(expression);
|
|
2411
2432
|
case ValueType.MultiPicklistSet:
|
|
2412
|
-
return multiPicklistToSql$1(expression);
|
|
2433
|
+
return multiPicklistToSql$1(expression, operator);
|
|
2413
2434
|
}
|
|
2414
2435
|
}
|
|
2415
2436
|
function stringLiteralToSql(string) {
|
|
@@ -2425,14 +2446,18 @@ function expressionArrayToSql(expressions, toSql) {
|
|
|
2425
2446
|
const bindings = results.length > 0 ? results.map((v) => v.bindings).reduce(flatten$1) : [];
|
|
2426
2447
|
return { sql, bindings };
|
|
2427
2448
|
}
|
|
2428
|
-
function multiPicklistToSql$1({ value }) {
|
|
2449
|
+
function multiPicklistToSql$1({ value }, operator) {
|
|
2429
2450
|
// Individual multipicklist terms that delimited by semicolon are stored server-side
|
|
2430
2451
|
// as lexically sorted strings and treated like logical ANDs. We can approximate this
|
|
2431
2452
|
// behavior in SQL with wildcarded `LIKE` SQL operators. Terms with no delimiter can
|
|
2432
2453
|
// be treated as string literals. Multiple terms are logically OR'd together to
|
|
2433
2454
|
// match the behavior described in SOQL documentation (https://sfdc.co/c9j0r)
|
|
2455
|
+
// To make sure the match is safe for includes/excludes. the value is prefix and
|
|
2456
|
+
// suffix with ';', like 'abc' to '%;abc;%'. raw value for eq and ne.
|
|
2434
2457
|
const sql = '?';
|
|
2435
|
-
const binding =
|
|
2458
|
+
const binding = operator === ComparisonOperator.includes || operator === ComparisonOperator.excludes
|
|
2459
|
+
? `%${MultiPickListValueSeparator$1}${value}${MultiPickListValueSeparator$1}%`
|
|
2460
|
+
: value;
|
|
2436
2461
|
return { sql, bindings: [binding] };
|
|
2437
2462
|
}
|
|
2438
2463
|
function relativeDateToSql(expression) {
|
|
@@ -2503,8 +2528,12 @@ function comparisonDateLiteralToSql(leftOperand, operator, dateInput) {
|
|
|
2503
2528
|
}
|
|
2504
2529
|
}
|
|
2505
2530
|
if (dateInput.type === ValueType.DateValue || dateInput.type === ValueType.DateTimeValue) {
|
|
2531
|
+
const dateFunction = dateInput.type === ValueType.DateTimeValue ? 'datetime' : 'date';
|
|
2506
2532
|
const compOperator = comparisonOperatorToSql(operator);
|
|
2507
|
-
return {
|
|
2533
|
+
return {
|
|
2534
|
+
sql: leftOperand + ` ${compOperator} ` + `${dateFunction}(?)`,
|
|
2535
|
+
bindings: [`${dateInput.value}`],
|
|
2536
|
+
};
|
|
2508
2537
|
}
|
|
2509
2538
|
return { sql: '', bindings: [] };
|
|
2510
2539
|
}
|
|
@@ -2735,15 +2764,41 @@ function fieldFilter(fieldName, fieldNode, alias, apiName, input, joins) {
|
|
|
2735
2764
|
return dateRangeComparison(op.value, op.operator, extract);
|
|
2736
2765
|
}
|
|
2737
2766
|
if (op.type === 'MultiPicklistSetOperator') {
|
|
2767
|
+
const operator = op.operator === ComparisonOperator.includes
|
|
2768
|
+
? CompoundOperator.or
|
|
2769
|
+
: CompoundOperator.and;
|
|
2770
|
+
const children = [];
|
|
2771
|
+
const length = op.value.value.length;
|
|
2772
|
+
for (let i = 0; i < length; i++) {
|
|
2773
|
+
const term = op.value.value[i];
|
|
2774
|
+
if (term !== null) {
|
|
2775
|
+
const splittedValue = term.split(MultiPickListValueSeparator$1);
|
|
2776
|
+
if (splittedValue.length === 1) {
|
|
2777
|
+
children.push(comparison(extract, op.operator, {
|
|
2778
|
+
type: ValueType.MultiPicklistSet,
|
|
2779
|
+
value: term,
|
|
2780
|
+
}));
|
|
2781
|
+
}
|
|
2782
|
+
else {
|
|
2783
|
+
children.push({
|
|
2784
|
+
type: PredicateType$1.compound,
|
|
2785
|
+
operator: op.operator === ComparisonOperator.includes
|
|
2786
|
+
? CompoundOperator.and
|
|
2787
|
+
: CompoundOperator.or,
|
|
2788
|
+
children: splittedValue.map((singleValue) => {
|
|
2789
|
+
return comparison(extract, op.operator, {
|
|
2790
|
+
type: ValueType.MultiPicklistSet,
|
|
2791
|
+
value: singleValue,
|
|
2792
|
+
});
|
|
2793
|
+
}),
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2738
2798
|
return {
|
|
2739
2799
|
type: PredicateType$1.compound,
|
|
2740
|
-
operator
|
|
2741
|
-
children
|
|
2742
|
-
return comparison(extract, op.operator, {
|
|
2743
|
-
type: ValueType.MultiPicklistSet,
|
|
2744
|
-
value: term,
|
|
2745
|
-
});
|
|
2746
|
-
}),
|
|
2800
|
+
operator,
|
|
2801
|
+
children,
|
|
2747
2802
|
};
|
|
2748
2803
|
}
|
|
2749
2804
|
if (op.type === 'StringSetOperator' && op.value.value.includes(null)) {
|
|
@@ -2807,8 +2862,6 @@ function dateRangeComparison(dateRange, operator, compareDate) {
|
|
|
2807
2862
|
return comparison(compareDate, gte, dateRange.start);
|
|
2808
2863
|
}
|
|
2809
2864
|
}
|
|
2810
|
-
const dateRegEx = /^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))$/;
|
|
2811
|
-
const dateTimeRegEx = /^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9](\.[0-9]{3})?Z$/;
|
|
2812
2865
|
function dateFunctions(operatorNode, extract, dataType) {
|
|
2813
2866
|
if (dataType !== 'Date' && dataType !== 'DateTime') {
|
|
2814
2867
|
return success([]);
|
|
@@ -2886,7 +2939,7 @@ function isStringOperatorType(value) {
|
|
|
2886
2939
|
return isScalarOperatorType(value) || value === like;
|
|
2887
2940
|
}
|
|
2888
2941
|
function isPicklistOperatorType(value) {
|
|
2889
|
-
let values = [eq, ne];
|
|
2942
|
+
let values = [eq, ne, like, lt, gt, lte, gte];
|
|
2890
2943
|
return values.includes(value);
|
|
2891
2944
|
}
|
|
2892
2945
|
function isCurrencyOperatorType(value) {
|
|
@@ -3237,8 +3290,11 @@ function operatorWithValue(operator, valueNode, objectInfoDataType) {
|
|
|
3237
3290
|
message(`Comparison operator ${operator} is not supported for type ${objectInfoDataType}.`),
|
|
3238
3291
|
]);
|
|
3239
3292
|
}
|
|
3293
|
+
function isValidDate(value) {
|
|
3294
|
+
return isNaN(Date.parse(value)) === false;
|
|
3295
|
+
}
|
|
3240
3296
|
function dateInput(node) {
|
|
3241
|
-
return parseDateNode(node,
|
|
3297
|
+
return parseDateNode(node, false, 'YYYY-MM-DD', isValidDate).map((result) => {
|
|
3242
3298
|
switch (result.type) {
|
|
3243
3299
|
case ValueType.NullValue:
|
|
3244
3300
|
return result;
|
|
@@ -3252,7 +3308,7 @@ function dateInput(node) {
|
|
|
3252
3308
|
});
|
|
3253
3309
|
}
|
|
3254
3310
|
function dateTimeInput(node) {
|
|
3255
|
-
return parseDateNode(node,
|
|
3311
|
+
return parseDateNode(node, true, 'YYYY-MM-DDTHH:MM:SS.SSSZ, YYYY-MM-DDTHH:MM:SSZ, YYYY-MM-DDTHH:MM:SS.SSS+|-HH:MM, or YYYY-MM-DDTHH:MM:SS+|-HH:MM', isValidDate).map((result) => {
|
|
3256
3312
|
switch (result.type) {
|
|
3257
3313
|
case ValueType.NullValue:
|
|
3258
3314
|
return result;
|
|
@@ -3277,7 +3333,7 @@ function parseNullValue(op) {
|
|
|
3277
3333
|
}
|
|
3278
3334
|
return failure(message(`Null can not be compared with ${op}`));
|
|
3279
3335
|
}
|
|
3280
|
-
function parseDateNode(node,
|
|
3336
|
+
function parseDateNode(node, hasTime, dateFormat, isValidDate) {
|
|
3281
3337
|
const typeName = hasTime ? 'DateTime' : 'Date';
|
|
3282
3338
|
if (!isObjectValueNode$1(node)) {
|
|
3283
3339
|
return failure(message(`Comparison value must be a ${typeName} input.`));
|
|
@@ -3285,7 +3341,12 @@ function parseDateNode(node, regex, hasTime, dateFormat) {
|
|
|
3285
3341
|
const valueField = node.fields.value;
|
|
3286
3342
|
if (valueField !== undefined) {
|
|
3287
3343
|
if (is(valueField, 'StringValue')) {
|
|
3288
|
-
|
|
3344
|
+
// check the date is valid
|
|
3345
|
+
// then make sure if it isnt suppose to contain time stamps that it doesnt
|
|
3346
|
+
// and if it should have a timestamp it should contain it
|
|
3347
|
+
const includesTimeStamp = valueField.value.includes('T');
|
|
3348
|
+
if (isValidDate(valueField.value) &&
|
|
3349
|
+
((hasTime && includesTimeStamp) || (!hasTime && !includesTimeStamp))) {
|
|
3289
3350
|
return success(stringLiteral(valueField.value));
|
|
3290
3351
|
}
|
|
3291
3352
|
return failure(message(`${typeName} format must be ${dateFormat}.`));
|
|
@@ -4277,7 +4338,20 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4277
4338
|
// await it here to normalize the input to a snapshot
|
|
4278
4339
|
const nonEvaluatedSnapshot = await nonEvaluatedSnapshotOrPromise;
|
|
4279
4340
|
// if the non-eval result has errors we want to return to caller
|
|
4280
|
-
|
|
4341
|
+
const nonEvaluatedGQLSnapshot = nonEvaluatedSnapshot;
|
|
4342
|
+
if (isErrorSnapshotThatShouldGetReturnedToCaller$1(nonEvaluatedGQLSnapshot)) {
|
|
4343
|
+
const { data: gqlData } = nonEvaluatedGQLSnapshot;
|
|
4344
|
+
if (hasGraphQlErrors$1(gqlData) && gqlData !== undefined) {
|
|
4345
|
+
return {
|
|
4346
|
+
...nonEvaluatedSnapshot,
|
|
4347
|
+
data: undefined,
|
|
4348
|
+
state: 'Error',
|
|
4349
|
+
error: {
|
|
4350
|
+
errorType: 'adapterError',
|
|
4351
|
+
error: gqlData.errors,
|
|
4352
|
+
},
|
|
4353
|
+
};
|
|
4354
|
+
}
|
|
4281
4355
|
return nonEvaluatedSnapshot;
|
|
4282
4356
|
}
|
|
4283
4357
|
let rootQuery;
|
|
@@ -6872,9 +6946,18 @@ function filterToPredicates(where, recordType, alias, objectInfoMap, joins, draf
|
|
|
6872
6946
|
const makePredicate = fieldInfo.dataType === 'MultiPicklist'
|
|
6873
6947
|
? createMultiPicklistPredicate
|
|
6874
6948
|
: createSinglePredicate;
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6949
|
+
const predicate = makePredicate(idProcessingNeeded ? sanitizePredicateIDValue(value, draftFunctions) : value, operator, fieldInfo, alias);
|
|
6950
|
+
// for the case where we have a not equals predicate that's value is not null
|
|
6951
|
+
// we need to compound into an or statement to also inlcude the null values for that field
|
|
6952
|
+
if (operator === '!=' && typeof value === 'string') {
|
|
6953
|
+
// create a is null predicate
|
|
6954
|
+
const isNullPredicate = createSinglePredicate(null, '=', fieldInfo, alias);
|
|
6955
|
+
// compound the predicates into an or predicate
|
|
6956
|
+
predicates.push(transformCompoundPredicate('or', [predicate, isNullPredicate]));
|
|
6957
|
+
}
|
|
6958
|
+
else {
|
|
6959
|
+
predicates.push(predicate);
|
|
6960
|
+
}
|
|
6878
6961
|
}
|
|
6879
6962
|
}
|
|
6880
6963
|
}
|
|
@@ -15627,4 +15710,4 @@ register({
|
|
|
15627
15710
|
});
|
|
15628
15711
|
|
|
15629
15712
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15630
|
-
// version: 1.
|
|
15713
|
+
// version: 1.130.8-e6645fb41
|