@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.
Files changed (3) hide show
  1. package/dist/main.js +112 -29
  2. package/package.json +3 -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
- const { sql: left, bindings: leftBindings } = expressionToSql(predicate.left);
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
- const fieldDateValue = `date(${left})`;
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
- const { sql: right, bindings: rightBindings } = expressionToSql(predicate.right);
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
- let sql = `json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}')`;
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 = value && value.includes(';') ? `'%${value.split(';').join('%')}%'` : `'%${value}%'`;
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 { sql: leftOperand + ` ${compOperator} ` + '?', bindings: [`${dateInput.value}`] };
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: CompoundOperator.or,
2741
- children: op.value.value.map((term) => {
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, dateRegEx, false, 'YYYY-MM-DD').map((result) => {
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, dateTimeRegEx, true, 'YYYY-MM-DDTHH:MM:SS.SSSZ or YYYY-MM-DDTHH:MM:SSZ').map((result) => {
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, regex, hasTime, dateFormat) {
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
- if (valueField.value.match(regex)) {
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
- if (isErrorSnapshotThatShouldGetReturnedToCaller$1(nonEvaluatedSnapshot)) {
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
- predicates.push(makePredicate(idProcessingNeeded
6876
- ? sanitizePredicateIDValue(value, draftFunctions)
6877
- : value, operator, fieldInfo, alias));
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.129.0-caa83ed0e
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.129.0",
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": "250 kB",
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": "250 kB",
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
- const { sql: left, bindings: leftBindings } = expressionToSql(predicate.left);
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
- const fieldDateValue = `date(${left})`;
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
- const { sql: right, bindings: rightBindings } = expressionToSql(predicate.right);
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
- let sql = `json_extract("${expression.jsonAlias}.JSON", '${pathPrefix}.${path}')`;
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 = value && value.includes(';') ? `'%${value.split(';').join('%')}%'` : `'%${value}%'`;
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 { sql: leftOperand + ` ${compOperator} ` + '?', bindings: [`${dateInput.value}`] };
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: CompoundOperator.or,
2741
- children: op.value.value.map((term) => {
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, dateRegEx, false, 'YYYY-MM-DD').map((result) => {
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, dateTimeRegEx, true, 'YYYY-MM-DDTHH:MM:SS.SSSZ or YYYY-MM-DDTHH:MM:SSZ').map((result) => {
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, regex, hasTime, dateFormat) {
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
- if (valueField.value.match(regex)) {
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
- if (isErrorSnapshotThatShouldGetReturnedToCaller$1(nonEvaluatedSnapshot)) {
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
- predicates.push(makePredicate(idProcessingNeeded
6876
- ? sanitizePredicateIDValue(value, draftFunctions)
6877
- : value, operator, fieldInfo, alias));
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.129.0-caa83ed0e
15713
+ // version: 1.130.8-e6645fb41