@salesforce/lds-runtime-mobile 1.428.0-dev1 → 1.428.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -25,12 +25,12 @@ import caseSensitiveUserId from '@salesforce/user/Id';
25
25
  import { Kind as Kind$1, visit as visit$1, isObjectType, defaultFieldResolver, buildSchema, parse as parse$8, extendSchema, isScalarType, execute, print } from '@luvio/graphql-parser';
26
26
  import graphqlRelationshipFieldsPerf from '@salesforce/gate/lds.graphqlRelationshipFieldsPerf';
27
27
  import FIRST_DAY_OF_WEEK from '@salesforce/i18n/firstDayOfWeek';
28
+ import { entityFetchedGraphqlMetadataSchema, entityFetchedMetadataSchema } from 'o11y_schema/sf_lightningsdk';
28
29
  import graphqQueryFieldLimit from '@salesforce/gate/lmr.graphqQueryFieldLimit';
29
30
  import graphqlPartialEmitParity from '@salesforce/gate/lmr.graphqlPartialEmitParity';
30
31
  import { pdpEventSchema } from 'o11y_schema/sf_pdp';
31
32
  import { instrument as instrument$1 } from '@salesforce/lds-bindings';
32
33
  import ldsAdapterO11yLoggingGate from '@salesforce/gate/lmr.ldsAdapterO11yLogging';
33
- import { entityFetchedMetadataSchema } from 'o11y_schema/sf_lightningsdk';
34
34
  import LOCALE from '@salesforce/i18n/locale';
35
35
  import CURRENCY from '@salesforce/i18n/currency';
36
36
  import TIMEZONE from '@salesforce/i18n/timeZone';
@@ -2395,6 +2395,13 @@ class DurableDraftQueue {
2395
2395
  // has last set the queue to be started
2396
2396
  return;
2397
2397
  }
2398
+ // This is important because if there is a dangling timeout handler
2399
+ // it can fire on an empty queue, marking it as waiting, and then
2400
+ // not add another timeout handler to restart it
2401
+ if (this.timeoutHandler) {
2402
+ clearTimeout(this.timeoutHandler);
2403
+ this.timeoutHandler = undefined;
2404
+ }
2398
2405
  this.retryIntervalMilliseconds = 0;
2399
2406
  this.state = DraftQueueState.Started;
2400
2407
  await this.notifyChangedListeners({
@@ -2551,6 +2558,9 @@ class DurableDraftQueue {
2551
2558
  const queue = await this.getQueueActions();
2552
2559
  const action = queue[0];
2553
2560
  if (action === undefined) {
2561
+ if (this.state === DraftQueueState.Waiting) {
2562
+ this.state = DraftQueueState.Started;
2563
+ }
2554
2564
  this.processingAction = undefined;
2555
2565
  return ProcessActionResult.NO_ACTION_TO_PROCESS;
2556
2566
  }
@@ -50660,6 +50670,7 @@ const replaceDraftIdsInVariables = (variables, draftFunctions, unmappedDraftIDs)
50660
50670
  };
50661
50671
  // create the runtime cache for the graphql schema when the factory creates the adapter
50662
50672
  const graphqlSchemaCache = new CachedGraphQLSchema();
50673
+ const ldsInstrumentation$1 = getInstrumentation('lds');
50663
50674
  function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio, isDraftId, buildCachedSnapshotCachePolicy, buildNetworkSnapshotCachePolicy) {
50664
50675
  const getCanonicalId = getCanonicalIdFunction(luvio);
50665
50676
  return async function draftAwareGraphQLAdapter(config, requestContext = {}) {
@@ -50840,6 +50851,14 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
50840
50851
  if (graphqlPartialEmitParity.isOpen({ fallback: false }) && missingFieldsMap.size > 0) {
50841
50852
  return createMissingFieldsErrorSnapshot(nonEvaluatedSnapshot, missingFieldsMap);
50842
50853
  }
50854
+ // Log GraphQL metadata for observability (only for successful queries with empty data)
50855
+ const hasEmptyData = checkForEmptyData(gqlResult);
50856
+ if (hasEmptyData) {
50857
+ ldsInstrumentation$1.log(entityFetchedGraphqlMetadataSchema, {
50858
+ query: redactQueryData(print(config.query)),
50859
+ isEmptyData: hasEmptyData,
50860
+ });
50861
+ }
50843
50862
  // if the non-eval'ed snapshot was an error then we return a synthetic
50844
50863
  // Fulfilled snapshot (this only happens in this code path if
50845
50864
  // the error is network error or 504), otherwise we spread over
@@ -50920,6 +50939,50 @@ function createMissingFieldsErrorSnapshot(originalSnapshot, missingFieldsMap) {
50920
50939
  },
50921
50940
  };
50922
50941
  }
50942
+ /**
50943
+ * Redacts sensitive data from a GraphQL query string and flattens to single line.
50944
+ * Replaces string and numeric values in query arguments with *.
50945
+ */
50946
+ function redactQueryData(queryString) {
50947
+ // First, flatten the query to a single line (remove newlines and extra whitespace)
50948
+ const flattened = queryString.replace(/\s+/g, ' ').trim();
50949
+ // Match entity types with arguments like "Account(...)" - must be after whitespace/brace, not after @
50950
+ // This matches query entity arguments but skips directive arguments
50951
+ return flattened.replace(/([\s{])(\w+)\s*\(\s*([^)]+?)\s*\)(\s*[@{])/g, (match, before, entityType, args, after) => {
50952
+ // Check if this looks like it has query parameters (contains colons)
50953
+ if (!args.includes(':')) {
50954
+ return match;
50955
+ }
50956
+ // Redact strings, numbers, and variables in the arguments
50957
+ const redactedArgs = args.replace(/"[^"]*"|\$\w+|:\s*(-?\d+\.?\d*)/g, (m) => {
50958
+ if (m.startsWith('"'))
50959
+ return '"*"';
50960
+ if (m.startsWith('$'))
50961
+ return '*';
50962
+ return ': *';
50963
+ });
50964
+ return `${before}${entityType}(${redactedArgs})${after}`;
50965
+ });
50966
+ }
50967
+ /**
50968
+ * Checks if the GraphQL result contains any data edges.
50969
+ * Returns true if no data edges are found in the query results.
50970
+ */
50971
+ function checkForEmptyData(gqlResult) {
50972
+ const data = gqlResult.data;
50973
+ if (!data || !data.uiapi || !data.uiapi.query) {
50974
+ return true;
50975
+ }
50976
+ const query = data.uiapi.query;
50977
+ // Check all entity types in the query for edges - using for...in to avoid array allocation
50978
+ for (const entityType in query) {
50979
+ const entity = query[entityType];
50980
+ if (entity && entity.edges && isArray$3(entity.edges) && entity.edges.length > 0) {
50981
+ return false;
50982
+ }
50983
+ }
50984
+ return true;
50985
+ }
50923
50986
 
50924
50987
  function environmentAwareGraphQLBatchAdapterFactory(objectInfoService, luvio, isDraftId, buildCachedSnapshotCachePolicy, buildNetworkSnapshotCachePolicy) {
50925
50988
  return async function environmentAwareGraphQLBatchAdapter(config, requestContext = {}) {
@@ -52474,6 +52537,9 @@ function extractApiNameFromConfig(adapterName, config, completedNetworkRequests)
52474
52537
  }
52475
52538
  function logCacheMissObservability(report) {
52476
52539
  const { snapshotState, adapterName, config } = report;
52540
+ // don't try to log cache miss data on the graphql adapter
52541
+ if (adapterName === 'graphql')
52542
+ return;
52477
52543
  // Check for offline conditions (short-circuits on first match)
52478
52544
  const isOffline = report.completedNetworkRequests.some((request) => {
52479
52545
  const response = request.response;
@@ -58883,7 +58949,7 @@ function buildServiceDescriptor$b(luvio) {
58883
58949
  },
58884
58950
  };
58885
58951
  }
58886
- // version: 1.428.0-dev1-52205c6c54
58952
+ // version: 1.428.0-9a846cb61f
58887
58953
 
58888
58954
  /**
58889
58955
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -58909,7 +58975,7 @@ function buildServiceDescriptor$a(notifyRecordUpdateAvailable, getNormalizedLuvi
58909
58975
  },
58910
58976
  };
58911
58977
  }
58912
- // version: 1.428.0-dev1-52205c6c54
58978
+ // version: 1.428.0-9a846cb61f
58913
58979
 
58914
58980
  /*!
58915
58981
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -61569,4 +61635,4 @@ register({
61569
61635
  });
61570
61636
 
61571
61637
  export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, initializeOneStore, registerReportObserver, reportGraphqlQueryParseError };
61572
- // version: 1.428.0-dev1-c95a813572
61638
+ // version: 1.428.0-b7f20524d9
@@ -1 +1,2 @@
1
1
  export declare const entityFetchedMetadataSchema: {};
2
+ export declare const entityFetchedGraphqlMetadataSchema: {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.428.0-dev1",
3
+ "version": "1.428.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
@@ -35,11 +35,11 @@
35
35
  "@conduit-client/service-bindings-imperative": "3.18.0",
36
36
  "@conduit-client/service-bindings-lwc": "3.18.0",
37
37
  "@conduit-client/service-provisioner": "3.18.0",
38
- "@salesforce/lds-adapters-uiapi": "^1.428.0-dev1",
39
- "@salesforce/lds-bindings": "^1.428.0-dev1",
40
- "@salesforce/lds-instrumentation": "^1.428.0-dev1",
41
- "@salesforce/lds-luvio-service": "^1.428.0-dev1",
42
- "@salesforce/lds-luvio-uiapi-records-service": "^1.428.0-dev1",
38
+ "@salesforce/lds-adapters-uiapi": "^1.428.0",
39
+ "@salesforce/lds-bindings": "^1.428.0",
40
+ "@salesforce/lds-instrumentation": "^1.428.0",
41
+ "@salesforce/lds-luvio-service": "^1.428.0",
42
+ "@salesforce/lds-luvio-uiapi-records-service": "^1.428.0",
43
43
  "@salesforce/user": "0.0.21",
44
44
  "o11y": "250.7.0",
45
45
  "o11y_schema": "256.126.0"
@@ -60,16 +60,16 @@
60
60
  "@conduit-client/service-pubsub": "3.18.0",
61
61
  "@conduit-client/service-store": "3.18.0",
62
62
  "@conduit-client/utils": "3.18.0",
63
- "@salesforce/lds-adapters-graphql": "^1.428.0-dev1",
64
- "@salesforce/lds-drafts": "^1.428.0-dev1",
65
- "@salesforce/lds-durable-records": "^1.428.0-dev1",
66
- "@salesforce/lds-network-adapter": "^1.428.0-dev1",
67
- "@salesforce/lds-network-nimbus": "^1.428.0-dev1",
68
- "@salesforce/lds-store-binary": "^1.428.0-dev1",
69
- "@salesforce/lds-store-nimbus": "^1.428.0-dev1",
70
- "@salesforce/lds-store-sql": "^1.428.0-dev1",
71
- "@salesforce/lds-utils-adapters": "^1.428.0-dev1",
72
- "@salesforce/nimbus-plugin-lds": "^1.428.0-dev1",
63
+ "@salesforce/lds-adapters-graphql": "^1.428.0",
64
+ "@salesforce/lds-drafts": "^1.428.0",
65
+ "@salesforce/lds-durable-records": "^1.428.0",
66
+ "@salesforce/lds-network-adapter": "^1.428.0",
67
+ "@salesforce/lds-network-nimbus": "^1.428.0",
68
+ "@salesforce/lds-store-binary": "^1.428.0",
69
+ "@salesforce/lds-store-nimbus": "^1.428.0",
70
+ "@salesforce/lds-store-sql": "^1.428.0",
71
+ "@salesforce/lds-utils-adapters": "^1.428.0",
72
+ "@salesforce/nimbus-plugin-lds": "^1.428.0",
73
73
  "babel-plugin-dynamic-import-node": "^2.3.3",
74
74
  "wait-for-expect": "^3.0.2"
75
75
  },
package/sfdc/main.js CHANGED
@@ -25,12 +25,12 @@ import caseSensitiveUserId from '@salesforce/user/Id';
25
25
  import { Kind as Kind$1, visit as visit$1, isObjectType, defaultFieldResolver, buildSchema, parse as parse$8, extendSchema, isScalarType, execute, print } from 'force/ldsGraphqlParser';
26
26
  import graphqlRelationshipFieldsPerf from '@salesforce/gate/lds.graphqlRelationshipFieldsPerf';
27
27
  import FIRST_DAY_OF_WEEK from '@salesforce/i18n/firstDayOfWeek';
28
+ import { entityFetchedGraphqlMetadataSchema, entityFetchedMetadataSchema } from 'o11y_schema/sf_lightningsdk';
28
29
  import graphqQueryFieldLimit from '@salesforce/gate/lmr.graphqQueryFieldLimit';
29
30
  import graphqlPartialEmitParity from '@salesforce/gate/lmr.graphqlPartialEmitParity';
30
31
  import { pdpEventSchema } from 'o11y_schema/sf_pdp';
31
32
  import { instrument as instrument$1 } from 'force/ldsBindings';
32
33
  import ldsAdapterO11yLoggingGate from '@salesforce/gate/lmr.ldsAdapterO11yLogging';
33
- import { entityFetchedMetadataSchema } from 'o11y_schema/sf_lightningsdk';
34
34
  import LOCALE from '@salesforce/i18n/locale';
35
35
  import CURRENCY from '@salesforce/i18n/currency';
36
36
  import TIMEZONE from '@salesforce/i18n/timeZone';
@@ -2395,6 +2395,13 @@ class DurableDraftQueue {
2395
2395
  // has last set the queue to be started
2396
2396
  return;
2397
2397
  }
2398
+ // This is important because if there is a dangling timeout handler
2399
+ // it can fire on an empty queue, marking it as waiting, and then
2400
+ // not add another timeout handler to restart it
2401
+ if (this.timeoutHandler) {
2402
+ clearTimeout(this.timeoutHandler);
2403
+ this.timeoutHandler = undefined;
2404
+ }
2398
2405
  this.retryIntervalMilliseconds = 0;
2399
2406
  this.state = DraftQueueState.Started;
2400
2407
  await this.notifyChangedListeners({
@@ -2551,6 +2558,9 @@ class DurableDraftQueue {
2551
2558
  const queue = await this.getQueueActions();
2552
2559
  const action = queue[0];
2553
2560
  if (action === undefined) {
2561
+ if (this.state === DraftQueueState.Waiting) {
2562
+ this.state = DraftQueueState.Started;
2563
+ }
2554
2564
  this.processingAction = undefined;
2555
2565
  return ProcessActionResult.NO_ACTION_TO_PROCESS;
2556
2566
  }
@@ -50660,6 +50670,7 @@ const replaceDraftIdsInVariables = (variables, draftFunctions, unmappedDraftIDs)
50660
50670
  };
50661
50671
  // create the runtime cache for the graphql schema when the factory creates the adapter
50662
50672
  const graphqlSchemaCache = new CachedGraphQLSchema();
50673
+ const ldsInstrumentation$1 = getInstrumentation('lds');
50663
50674
  function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio, isDraftId, buildCachedSnapshotCachePolicy, buildNetworkSnapshotCachePolicy) {
50664
50675
  const getCanonicalId = getCanonicalIdFunction(luvio);
50665
50676
  return async function draftAwareGraphQLAdapter(config, requestContext = {}) {
@@ -50840,6 +50851,14 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
50840
50851
  if (graphqlPartialEmitParity.isOpen({ fallback: false }) && missingFieldsMap.size > 0) {
50841
50852
  return createMissingFieldsErrorSnapshot(nonEvaluatedSnapshot, missingFieldsMap);
50842
50853
  }
50854
+ // Log GraphQL metadata for observability (only for successful queries with empty data)
50855
+ const hasEmptyData = checkForEmptyData(gqlResult);
50856
+ if (hasEmptyData) {
50857
+ ldsInstrumentation$1.log(entityFetchedGraphqlMetadataSchema, {
50858
+ query: redactQueryData(print(config.query)),
50859
+ isEmptyData: hasEmptyData,
50860
+ });
50861
+ }
50843
50862
  // if the non-eval'ed snapshot was an error then we return a synthetic
50844
50863
  // Fulfilled snapshot (this only happens in this code path if
50845
50864
  // the error is network error or 504), otherwise we spread over
@@ -50920,6 +50939,50 @@ function createMissingFieldsErrorSnapshot(originalSnapshot, missingFieldsMap) {
50920
50939
  },
50921
50940
  };
50922
50941
  }
50942
+ /**
50943
+ * Redacts sensitive data from a GraphQL query string and flattens to single line.
50944
+ * Replaces string and numeric values in query arguments with *.
50945
+ */
50946
+ function redactQueryData(queryString) {
50947
+ // First, flatten the query to a single line (remove newlines and extra whitespace)
50948
+ const flattened = queryString.replace(/\s+/g, ' ').trim();
50949
+ // Match entity types with arguments like "Account(...)" - must be after whitespace/brace, not after @
50950
+ // This matches query entity arguments but skips directive arguments
50951
+ return flattened.replace(/([\s{])(\w+)\s*\(\s*([^)]+?)\s*\)(\s*[@{])/g, (match, before, entityType, args, after) => {
50952
+ // Check if this looks like it has query parameters (contains colons)
50953
+ if (!args.includes(':')) {
50954
+ return match;
50955
+ }
50956
+ // Redact strings, numbers, and variables in the arguments
50957
+ const redactedArgs = args.replace(/"[^"]*"|\$\w+|:\s*(-?\d+\.?\d*)/g, (m) => {
50958
+ if (m.startsWith('"'))
50959
+ return '"*"';
50960
+ if (m.startsWith('$'))
50961
+ return '*';
50962
+ return ': *';
50963
+ });
50964
+ return `${before}${entityType}(${redactedArgs})${after}`;
50965
+ });
50966
+ }
50967
+ /**
50968
+ * Checks if the GraphQL result contains any data edges.
50969
+ * Returns true if no data edges are found in the query results.
50970
+ */
50971
+ function checkForEmptyData(gqlResult) {
50972
+ const data = gqlResult.data;
50973
+ if (!data || !data.uiapi || !data.uiapi.query) {
50974
+ return true;
50975
+ }
50976
+ const query = data.uiapi.query;
50977
+ // Check all entity types in the query for edges - using for...in to avoid array allocation
50978
+ for (const entityType in query) {
50979
+ const entity = query[entityType];
50980
+ if (entity && entity.edges && isArray$3(entity.edges) && entity.edges.length > 0) {
50981
+ return false;
50982
+ }
50983
+ }
50984
+ return true;
50985
+ }
50923
50986
 
50924
50987
  function environmentAwareGraphQLBatchAdapterFactory(objectInfoService, luvio, isDraftId, buildCachedSnapshotCachePolicy, buildNetworkSnapshotCachePolicy) {
50925
50988
  return async function environmentAwareGraphQLBatchAdapter(config, requestContext = {}) {
@@ -52474,6 +52537,9 @@ function extractApiNameFromConfig(adapterName, config, completedNetworkRequests)
52474
52537
  }
52475
52538
  function logCacheMissObservability(report) {
52476
52539
  const { snapshotState, adapterName, config } = report;
52540
+ // don't try to log cache miss data on the graphql adapter
52541
+ if (adapterName === 'graphql')
52542
+ return;
52477
52543
  // Check for offline conditions (short-circuits on first match)
52478
52544
  const isOffline = report.completedNetworkRequests.some((request) => {
52479
52545
  const response = request.response;
@@ -58883,7 +58949,7 @@ function buildServiceDescriptor$b(luvio) {
58883
58949
  },
58884
58950
  };
58885
58951
  }
58886
- // version: 1.428.0-dev1-52205c6c54
58952
+ // version: 1.428.0-9a846cb61f
58887
58953
 
58888
58954
  /**
58889
58955
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -58909,7 +58975,7 @@ function buildServiceDescriptor$a(notifyRecordUpdateAvailable, getNormalizedLuvi
58909
58975
  },
58910
58976
  };
58911
58977
  }
58912
- // version: 1.428.0-dev1-52205c6c54
58978
+ // version: 1.428.0-9a846cb61f
58913
58979
 
58914
58980
  /*!
58915
58981
  * Copyright (c) 2022, Salesforce, Inc.,
@@ -61569,4 +61635,4 @@ register({
61569
61635
  });
61570
61636
 
61571
61637
  export { O11Y_NAMESPACE_LDS_MOBILE, getRuntime, ingest$1o as ingestDenormalizedRecordRepresentation, initializeOneStore, registerReportObserver, reportGraphqlQueryParseError };
61572
- // version: 1.428.0-dev1-c95a813572
61638
+ // version: 1.428.0-b7f20524d9
@@ -1 +1,2 @@
1
1
  export declare const entityFetchedMetadataSchema: {};
2
+ export declare const entityFetchedGraphqlMetadataSchema: {};