@salesforce/lds-runtime-mobile 1.248.0 → 1.249.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
@@ -16,7 +16,8 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
16
16
  import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
17
17
  import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
18
18
  import { parseAndVisit, Kind, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from '@luvio/graphql-parser';
19
- import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, keyBuilderObjectInfo, ObjectInfoDirectoryEntryRepresentationType, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
19
+ import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from '@salesforce/lds-adapters-uiapi';
20
+ import ldsIdempotencyWriteDisabled from '@salesforce/gate/lds.idempotencyWriteDisabled';
20
21
  import caseSensitiveUserId from '@salesforce/user/Id';
21
22
  import { idleDetector, getInstrumentation } from 'o11y/client';
22
23
  import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
@@ -1237,12 +1238,12 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1237
1238
  }
1238
1239
  return environment.getNode(key, stagingStore);
1239
1240
  };
1240
- const wrapNormalizedGraphNode = function (normalized) {
1241
+ const wrapNormalizedGraphNode = function (normalized, key) {
1241
1242
  validateNotDisposed();
1242
1243
  if (stagingStore === null) {
1243
1244
  stagingStore = buildIngestStagingStore(environment);
1244
1245
  }
1245
- return environment.wrapNormalizedGraphNode(normalized, stagingStore);
1246
+ return environment.wrapNormalizedGraphNode(normalized, key, stagingStore);
1246
1247
  };
1247
1248
  const rebuildSnapshot = function (snapshot, onRebuild) {
1248
1249
  validateNotDisposed();
@@ -4950,6 +4951,21 @@ class AsyncWorkerPool {
4950
4951
  }
4951
4952
  }
4952
4953
 
4954
+ /**
4955
+ Use Math.random to generate v4 RFC4122 compliant uuid
4956
+ */
4957
+ function uuidv4() {
4958
+ const uuid = [];
4959
+ for (let i = 0; i < 32; i++) {
4960
+ const random = (Math.random() * 16) | 0;
4961
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
4962
+ uuid.push('-');
4963
+ }
4964
+ uuid.push((i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16));
4965
+ }
4966
+ return uuid.join('');
4967
+ }
4968
+
4953
4969
  /**
4954
4970
  * Copyright (c) 2022, Salesforce, Inc.,
4955
4971
  * All rights reserved.
@@ -5163,20 +5179,6 @@ function generateUniqueDraftActionId(existingIds) {
5163
5179
  }
5164
5180
  return newId.toString();
5165
5181
  }
5166
- /**
5167
- Use Math.random to generate v4 RFC4122 compliant uuid
5168
- */
5169
- function uuidv4() {
5170
- const uuid = [];
5171
- for (let i = 0; i < 32; i++) {
5172
- const random = (Math.random() * 16) | 0;
5173
- if (i === 8 || i === 12 || i === 16 || i === 20) {
5174
- uuid.push('-');
5175
- }
5176
- uuid.push((i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16));
5177
- }
5178
- return uuid.join('');
5179
- }
5180
5182
 
5181
5183
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
5182
5184
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
@@ -6053,7 +6055,12 @@ class AbstractResourceRequestActionHandler {
6053
6055
  // the luvio store redirect table, during which a new draft might be enqueued
6054
6056
  // which would not see a necessary mapping.
6055
6057
  this.ephemeralRedirects = {};
6058
+ // determined by Server setup.
6056
6059
  this.isIdempotencySupported = true;
6060
+ // idempotency write flag set by lds
6061
+ this.isLdsIdempotencyWriteDisabled = ldsIdempotencyWriteDisabled.isOpen({
6062
+ fallback: false,
6063
+ });
6057
6064
  }
6058
6065
  enqueue(data) {
6059
6066
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -6410,7 +6417,7 @@ class AbstractResourceRequestActionHandler {
6410
6417
  return [action.targetId];
6411
6418
  }
6412
6419
  hasIdempotencySupport() {
6413
- return this.isIdempotencySupported;
6420
+ return this.isIdempotencySupported && !this.isLdsIdempotencyWriteDisabled;
6414
6421
  }
6415
6422
  async ingestResponses(responses, action) {
6416
6423
  const luvio = this.getLuvio();
@@ -6948,14 +6955,20 @@ function buildQueryTypeStringKey(args) {
6948
6955
  */
6949
6956
 
6950
6957
 
6958
+ const MAX_BATCH_SIZE = 2000;
6951
6959
  class DataLoader {
6952
- constructor(batchLoadFn) {
6960
+ constructor(batchLoadFn, options) {
6953
6961
  this._batchLoadFn = batchLoadFn;
6954
6962
  this._batch = null;
6955
6963
  this._batchScheduleFn = function (fn) {
6956
6964
  setTimeout(fn, 0);
6957
6965
  };
6958
6966
  this._cacheMap = new Map();
6967
+ this._maxBatchSize = MAX_BATCH_SIZE;
6968
+ if (options !== undefined) {
6969
+ const { maxBatchSize } = options;
6970
+ this._maxBatchSize = maxBatchSize || MAX_BATCH_SIZE;
6971
+ }
6959
6972
  }
6960
6973
  load(key) {
6961
6974
  if (key === null || key === undefined) {
@@ -6985,7 +6998,9 @@ class DataLoader {
6985
6998
  // If there is an existing batch which has not yet dispatched and is within
6986
6999
  // the limit of the batch size, then return it.
6987
7000
  const existingBatch = this._batch;
6988
- if (existingBatch !== null && !existingBatch.hasDispatched && !existingBatch.cacheHits) {
7001
+ if (existingBatch !== null &&
7002
+ !existingBatch.hasDispatched &&
7003
+ existingBatch.keys.length < this._maxBatchSize) {
6989
7004
  return existingBatch;
6990
7005
  }
6991
7006
  // Otherwise, create a new batch for this loader.
@@ -9378,7 +9393,9 @@ function extendSchemaWithObjectInfos(cache, objectInfoMap) {
9378
9393
  ];
9379
9394
  // extend the schema and add resolvers
9380
9395
  const schema = addResolversToSchema(extendSchema(cache.getSchema(), extensions), polymorphicFieldTypeNames);
9396
+ const polymorphicFieldTypeNamesSet = new Set(polymorphicFieldTypeNames);
9381
9397
  cache.setSchema(schema);
9398
+ cache.setPolymorphicFieldTypeNames([...polymorphicFieldTypeNamesSet]);
9382
9399
  return cache;
9383
9400
  }
9384
9401
  /**
@@ -9534,7 +9551,10 @@ function extendExistingRecordType(schema, type, objectInfo, objectInfoMap) {
9534
9551
  let typedScalars = new Set();
9535
9552
  let parentRelationshipFields = new Set();
9536
9553
  const existingFields = keys$4(type.getFields());
9537
- const missingFields = values$2(objectInfo.fields).filter((field) => existingFields.includes(field.apiName) === false);
9554
+ const missingFields = values$2(objectInfo.fields).filter((field) => {
9555
+ return (existingFields.includes(field.apiName) === false ||
9556
+ (field.relationshipName !== null && field.referenceToInfos.length > 1));
9557
+ });
9538
9558
  const { fields, polymorphicFieldTypeNames } = makeRecordField(missingFields, objectInfoMap, parentRelationshipFields, 'Cached');
9539
9559
  const { apiName, childRelationships } = objectInfo;
9540
9560
  // handles child relationship
@@ -9634,8 +9654,10 @@ function makeRecordField(fieldRepresentations, objectInfoMap, existingParentRela
9634
9654
  // For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
9635
9655
  }
9636
9656
  else if (field.referenceToInfos.length > 1) {
9637
- existingParentRelationships.add(field.relationshipName);
9638
- fields += `${field.relationshipName}: Record\n`;
9657
+ if (recordTypeInSchema === 'Missing') {
9658
+ existingParentRelationships.add(field.relationshipName);
9659
+ fields += `${field.relationshipName}: Record\n`;
9660
+ }
9639
9661
  for (const relation of field.referenceToInfos) {
9640
9662
  if (objectInfoMap[relation.apiName] !== undefined) {
9641
9663
  polymorphicFieldTypeNames.add(relation.apiName);
@@ -12084,34 +12106,42 @@ function applyReferenceLinksToDraft(record, draftMetadata) {
12084
12106
  }
12085
12107
  const { dataType, relationshipName, referenceToInfos } = fieldInfo;
12086
12108
  const draftFieldValue = record.fields[draftField].value;
12087
- if (dataType === 'Reference' && relationshipName !== null && draftFieldValue !== null) {
12088
- if (typeof draftFieldValue !== 'string') {
12089
- throw Error('reference field value is not a string');
12109
+ if (dataType === 'Reference' && relationshipName !== null) {
12110
+ if (draftFieldValue === null) {
12111
+ recordFields[relationshipName] = {
12112
+ displayValue: null,
12113
+ value: null,
12114
+ };
12090
12115
  }
12091
- const key = getRecordKeyForId(luvio, draftFieldValue);
12092
- const referencedRecord = referencedRecords.get(key);
12093
- recordFields[relationshipName] = {
12094
- displayValue: null,
12095
- value: createLink(key),
12096
- };
12097
- // for custom objects, we select the 'Name' field
12098
- // otherwise we check the object info for name fields.
12099
- //if there are multiple we select 'Name' if it exists, otherwise the first one
12100
- if (referencedRecord !== undefined && referenceToInfos.length > 0) {
12101
- let nameField;
12102
- const referenceToInfo = referenceToInfos[0];
12103
- const nameFields = referenceToInfo.nameFields;
12104
- if (nameFields.length !== 0) {
12105
- nameField = nameFields.find((x) => x === 'Name');
12106
- if (nameField === undefined) {
12107
- nameField = nameFields[0];
12108
- }
12116
+ else {
12117
+ if (typeof draftFieldValue !== 'string') {
12118
+ throw Error('reference field value is not a string');
12109
12119
  }
12110
- if (nameField !== undefined) {
12111
- const nameFieldRef = referencedRecord.fields[nameField];
12112
- if (nameFieldRef) {
12113
- recordFields[relationshipName].displayValue =
12114
- (_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
12120
+ const key = getRecordKeyForId(luvio, draftFieldValue);
12121
+ const referencedRecord = referencedRecords.get(key);
12122
+ recordFields[relationshipName] = {
12123
+ displayValue: null,
12124
+ value: createLink(key),
12125
+ };
12126
+ // for custom objects, we select the 'Name' field
12127
+ // otherwise we check the object info for name fields.
12128
+ //if there are multiple we select 'Name' if it exists, otherwise the first one
12129
+ if (referencedRecord !== undefined && referenceToInfos.length > 0) {
12130
+ let nameField;
12131
+ const referenceToInfo = referenceToInfos[0];
12132
+ const nameFields = referenceToInfo.nameFields;
12133
+ if (nameFields.length !== 0) {
12134
+ nameField = nameFields.find((x) => x === 'Name');
12135
+ if (nameField === undefined) {
12136
+ nameField = nameFields[0];
12137
+ }
12138
+ }
12139
+ if (nameField !== undefined) {
12140
+ const nameFieldRef = referencedRecord.fields[nameField];
12141
+ if (nameFieldRef) {
12142
+ recordFields[relationshipName].displayValue =
12143
+ (_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
12144
+ }
12115
12145
  }
12116
12146
  }
12117
12147
  }
@@ -12404,17 +12434,8 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
12404
12434
  };
12405
12435
  for (const fieldName of keys$3(recordWithSpanningRefLinks.fields)) {
12406
12436
  const fieldKey = buildRecordFieldStoreKey(key, fieldName);
12407
- if (this.collectedFields[fieldKey] !== undefined) {
12408
- const fieldData = recordWithSpanningRefLinks.fields[fieldName];
12409
- normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12410
- publishData(fieldKey, fieldData);
12411
- }
12412
- else if (recordWithSpanningRefLinks.fields[fieldName] &&
12413
- recordWithSpanningRefLinks.fields[fieldName].value &&
12414
- recordWithSpanningRefLinks.fields[fieldName].value.__ref !== undefined) {
12415
- normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12416
- publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
12417
- }
12437
+ normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12438
+ publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
12418
12439
  }
12419
12440
  // publish the normalized record
12420
12441
  publishData(key, normalizedRecord);
@@ -15375,6 +15396,14 @@ class ObjectInfoService {
15375
15396
  return this.updateObjectInfoMapping(keyPrefix, apiName);
15376
15397
  }
15377
15398
  };
15399
+ this.getCachedObjectInfoStatus = async () => {
15400
+ const infos = await this.readObjectInfoDataFromDurableStore();
15401
+ const map = new Map();
15402
+ infos.forEach(({ apiName, expirationTimestamp }) => {
15403
+ map.set(apiName, { expiration: expirationTimestamp });
15404
+ });
15405
+ return map;
15406
+ };
15378
15407
  this.isObjectInfoInDurableStore = async (apiName) => {
15379
15408
  if (this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined) {
15380
15409
  return Promise.resolve(true);
@@ -15383,12 +15412,10 @@ class ObjectInfoService {
15383
15412
  return this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined;
15384
15413
  };
15385
15414
  this.loadObjectInfoMaps = async () => {
15386
- const rows = (await this.durableStore.query(`SELECT json_extract(data, '$.apiName') as ApiName, json_extract(data, '$.keyPrefix') as keyPrefix from lds_data where key like '%ObjectInfoRepresentation%'`, [])).rows;
15387
- for (const row of rows) {
15388
- const apiName = row[0];
15389
- const keyPrefix = row[1];
15415
+ const infos = await this.readObjectInfoDataFromDurableStore();
15416
+ infos.forEach(({ keyPrefix, apiName }) => {
15390
15417
  this.updateObjectInfoMapping(keyPrefix, apiName);
15391
- }
15418
+ });
15392
15419
  };
15393
15420
  this.updateObjectInfoMapping = (keyPrefix, apiName) => {
15394
15421
  this.apiNameToKeyPrefixMemoryCache[apiName] = keyPrefix;
@@ -15432,6 +15459,24 @@ class ObjectInfoService {
15432
15459
  }
15433
15460
  return snapshot.data;
15434
15461
  }
15462
+ async readObjectInfoDataFromDurableStore() {
15463
+ const rows = (await this.durableStore.query(`
15464
+ SELECT
15465
+ json_extract(data, '$.apiName') as ApiName,
15466
+ json_extract(data, '$.keyPrefix') as keyPrefix,
15467
+ JSON_EXTRACT(metadata, '$.expirationTimestamp') AS expirationTimestamp
15468
+ from
15469
+ lds_data
15470
+ where
15471
+ key like '%ObjectInfoRepresentation%'`, [])).rows;
15472
+ return rows.map((row) => {
15473
+ return {
15474
+ apiName: row[0],
15475
+ keyPrefix: row[1],
15476
+ expirationTimestamp: row[2],
15477
+ };
15478
+ });
15479
+ }
15435
15480
  }
15436
15481
 
15437
15482
  function instrumentGraphQLEval(adapter) {
@@ -16530,7 +16575,7 @@ class ConflictPool {
16530
16575
  }
16531
16576
  }
16532
16577
 
16533
- const DEFAULT_BATCH_SIZE = 500;
16578
+ const DEFAULT_BATCH_SIZE$1 = 500;
16534
16579
  const DEFAULT_CONCURRENCY = 6;
16535
16580
  const DEFAULT_GQL_QUERY_BATCH_SIZE = 5;
16536
16581
  class PrimingSession extends EventEmitter {
@@ -16538,7 +16583,7 @@ class PrimingSession extends EventEmitter {
16538
16583
  var _a, _b;
16539
16584
  super();
16540
16585
  this.useBatchGQL = false;
16541
- this.batchSize = (_a = config.batchSize) !== null && _a !== void 0 ? _a : DEFAULT_BATCH_SIZE;
16586
+ this.batchSize = (_a = config.batchSize) !== null && _a !== void 0 ? _a : DEFAULT_BATCH_SIZE$1;
16542
16587
  this.concurrency = (_b = config.concurrency) !== null && _b !== void 0 ? _b : DEFAULT_CONCURRENCY;
16543
16588
  this.recordLoader = config.recordLoader;
16544
16589
  this.recordIngestor = config.recordIngestor;
@@ -17159,10 +17204,6 @@ class NimbusPrimingNetworkAdapter {
17159
17204
  // ref: https://gnome.pages.gitlab.gnome.org/tracker/docs/developer/limits.html?gi-language=c
17160
17205
  const SQLITE_MAX_VARIABLE_NUMBER = 999;
17161
17206
  const PARAMS_PER_RECORD = 3;
17162
- /**
17163
- * No key builder (or adapter) exists for the object info directory, we need to build the key manually
17164
- */
17165
- const ObjectInfoDirectoryKey = `${UiApiNamespace}::${ObjectInfoDirectoryEntryRepresentationType}:`;
17166
17207
  // We need to batch the records to avoid hitting the SQLITE_MAX_VARIABLE_NUMBER limit. Each record has 3 parameters
17167
17208
  const BATCH_SIZE = Math.floor(SQLITE_MAX_VARIABLE_NUMBER / PARAMS_PER_RECORD);
17168
17209
  class SqlitePrimingStore {
@@ -17227,44 +17268,6 @@ class SqlitePrimingStore {
17227
17268
  };
17228
17269
  }
17229
17270
  }
17230
- async readObjectInfoDirectory() {
17231
- const sql = 'SELECT data FROM lds_data WHERE key = ?';
17232
- const params = [ObjectInfoDirectoryKey];
17233
- const result = await this.store.query(sql, params);
17234
- if (result.rows.length === 1) {
17235
- return JSON.parse(result.rows[0][0]);
17236
- }
17237
- return undefined;
17238
- }
17239
- async readObjectApiNames() {
17240
- const sql = 'SELECT key FROM lds_data WHERE key like ?';
17241
- const params = [`%${ObjectInfoRepresentationType}%`];
17242
- const result = await this.store.query(sql, params);
17243
- const apiNames = new Set();
17244
- result.rows.forEach((row) => {
17245
- const key = row[0];
17246
- const parts = key.split(':');
17247
- apiNames.add(parts[parts.length - 1]);
17248
- });
17249
- return apiNames;
17250
- }
17251
- writeObjectInfoDirectory(directory) {
17252
- const sql = 'INSERT or IGNORE into lds_data (key, data) values (?, ?)';
17253
- const params = [ObjectInfoDirectoryKey, JSON.stringify(directory)];
17254
- return this.store.query(sql, params).then(() => { });
17255
- }
17256
- writeObjectInfos(objectInfos) {
17257
- const sql = `INSERT or IGNORE into lds_data (key, data) values ${objectInfos
17258
- .map(() => '(?, ?)')
17259
- .join(',')};`;
17260
- const params = [];
17261
- objectInfos.forEach((objectInfo) => {
17262
- const key = keyBuilderObjectInfo(this.getLuvio(), { apiName: objectInfo.apiName });
17263
- params.push(key);
17264
- params.push(JSON.stringify(objectInfo));
17265
- });
17266
- return this.store.query(sql, params).then(() => { });
17267
- }
17268
17271
  }
17269
17272
  function batchArray(arr, batchSize = BATCH_SIZE) {
17270
17273
  const batches = [];
@@ -17339,9 +17342,7 @@ function primingSessionFactory(config) {
17339
17342
  recordLoader,
17340
17343
  recordIngestor,
17341
17344
  store: primingStore,
17342
- objectInfoLoader: {
17343
- getObjectInfos: objectInfoService.getObjectInfos.bind(objectInfoService),
17344
- },
17345
+ objectInfoLoader: objectInfoService,
17345
17346
  concurrency: config.concurrency,
17346
17347
  batchSize: config.batchSize,
17347
17348
  ldsRecordRefresher: new LdsPrimingRecordRefresher(config.getRecords),
@@ -17507,4 +17508,4 @@ register({
17507
17508
  });
17508
17509
 
17509
17510
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
17510
- // version: 1.248.0-1f7f01112
17511
+ // version: 1.249.0-11c3e1ed5
@@ -1,6 +1,5 @@
1
1
  import type { PrimingStore, RecordWithMetadata, WriteResult } from '@salesforce/lds-priming';
2
2
  import type { Luvio } from '@luvio/engine';
3
- import type { ObjectInfoDirectoryRepresentation, ObjectInfoRepresentation } from '@salesforce/lds-adapters-uiapi';
4
3
  import type { SqliteStore } from '@salesforce/lds-store-sql';
5
4
  export declare class SqlitePrimingStore implements PrimingStore {
6
5
  private readonly getLuvio;
@@ -9,8 +8,4 @@ export declare class SqlitePrimingStore implements PrimingStore {
9
8
  readRecords(ids: string[]): Promise<RecordWithMetadata[]>;
10
9
  writeRecords(records: RecordWithMetadata[], overwrite: boolean): Promise<WriteResult>;
11
10
  private writeBatch;
12
- readObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
13
- readObjectApiNames(): Promise<Set<string>>;
14
- writeObjectInfoDirectory(directory: ObjectInfoDirectoryRepresentation): Promise<void>;
15
- writeObjectInfos(objectInfos: ObjectInfoRepresentation[]): Promise<void>;
16
11
  }
@@ -10,6 +10,9 @@ type ObjectInfoDirectoryConfig = Parameters<ObjectInfoDirectoryAdapterReturn>[0]
10
10
  export type ObjectInfoMap = {
11
11
  [apiName: string]: ObjectInfoRepresentation;
12
12
  };
13
+ interface ObjectInfoStatus {
14
+ expiration: number;
15
+ }
13
16
  export declare class ObjectInfoService {
14
17
  private getObjectInfoAdapter;
15
18
  private getObjectInfosAdapter;
@@ -31,8 +34,10 @@ export declare class ObjectInfoService {
31
34
  getObjectInfos(apiNames: string[]): Promise<ObjectInfoMap>;
32
35
  getObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
33
36
  ensureObjectInfoCached: (apiName: string, entry?: ObjectInfoRepresentation) => Promise<void>;
37
+ getCachedObjectInfoStatus: () => Promise<Map<string, ObjectInfoStatus>>;
34
38
  private isObjectInfoInDurableStore;
35
39
  private loadObjectInfoMaps;
40
+ private readObjectInfoDataFromDurableStore;
36
41
  private updateObjectInfoMapping;
37
42
  }
38
43
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/lds-runtime-mobile",
3
- "version": "1.248.0",
3
+ "version": "1.249.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "LDS runtime for mobile/hybrid environments.",
6
6
  "main": "dist/main.js",
package/sfdc/main.js CHANGED
@@ -16,7 +16,8 @@ import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrum
16
16
  import { HttpStatusCode, StoreKeySet, serializeStructuredKey, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
17
17
  import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
18
18
  import { parseAndVisit, Kind, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from 'force/ldsGraphqlParser';
19
- import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, keyBuilderObjectInfo, ObjectInfoDirectoryEntryRepresentationType, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
19
+ import { RECORD_ID_PREFIX, RECORD_FIELDS_KEY_JUNCTION, isStoreKeyRecordViewEntity, getRecordId18, RECORD_REPRESENTATION_NAME, extractRecordIdFromStoreKey, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, RECORD_VIEW_ENTITY_ID_PREFIX, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, getObjectInfoDirectoryAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion, getRecordsAdapterFactory } from 'force/ldsAdaptersUiapi';
20
+ import ldsIdempotencyWriteDisabled from '@salesforce/gate/lds.idempotencyWriteDisabled';
20
21
  import caseSensitiveUserId from '@salesforce/user/Id';
21
22
  import { idleDetector, getInstrumentation } from 'o11y/client';
22
23
  import ldsUseShortUrlGate from '@salesforce/gate/lds.useShortUrl';
@@ -1237,12 +1238,12 @@ function makeDurable(environment, { durableStore, instrumentation, useRevivingSt
1237
1238
  }
1238
1239
  return environment.getNode(key, stagingStore);
1239
1240
  };
1240
- const wrapNormalizedGraphNode = function (normalized) {
1241
+ const wrapNormalizedGraphNode = function (normalized, key) {
1241
1242
  validateNotDisposed();
1242
1243
  if (stagingStore === null) {
1243
1244
  stagingStore = buildIngestStagingStore(environment);
1244
1245
  }
1245
- return environment.wrapNormalizedGraphNode(normalized, stagingStore);
1246
+ return environment.wrapNormalizedGraphNode(normalized, key, stagingStore);
1246
1247
  };
1247
1248
  const rebuildSnapshot = function (snapshot, onRebuild) {
1248
1249
  validateNotDisposed();
@@ -4950,6 +4951,21 @@ class AsyncWorkerPool {
4950
4951
  }
4951
4952
  }
4952
4953
 
4954
+ /**
4955
+ Use Math.random to generate v4 RFC4122 compliant uuid
4956
+ */
4957
+ function uuidv4() {
4958
+ const uuid = [];
4959
+ for (let i = 0; i < 32; i++) {
4960
+ const random = (Math.random() * 16) | 0;
4961
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
4962
+ uuid.push('-');
4963
+ }
4964
+ uuid.push((i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16));
4965
+ }
4966
+ return uuid.join('');
4967
+ }
4968
+
4953
4969
  /**
4954
4970
  * Copyright (c) 2022, Salesforce, Inc.,
4955
4971
  * All rights reserved.
@@ -5163,20 +5179,6 @@ function generateUniqueDraftActionId(existingIds) {
5163
5179
  }
5164
5180
  return newId.toString();
5165
5181
  }
5166
- /**
5167
- Use Math.random to generate v4 RFC4122 compliant uuid
5168
- */
5169
- function uuidv4() {
5170
- const uuid = [];
5171
- for (let i = 0; i < 32; i++) {
5172
- const random = (Math.random() * 16) | 0;
5173
- if (i === 8 || i === 12 || i === 16 || i === 20) {
5174
- uuid.push('-');
5175
- }
5176
- uuid.push((i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16));
5177
- }
5178
- return uuid.join('');
5179
- }
5180
5182
 
5181
5183
  const HTTP_HEADER_RETRY_AFTER = 'Retry-After';
5182
5184
  const HTTP_HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
@@ -6053,7 +6055,12 @@ class AbstractResourceRequestActionHandler {
6053
6055
  // the luvio store redirect table, during which a new draft might be enqueued
6054
6056
  // which would not see a necessary mapping.
6055
6057
  this.ephemeralRedirects = {};
6058
+ // determined by Server setup.
6056
6059
  this.isIdempotencySupported = true;
6060
+ // idempotency write flag set by lds
6061
+ this.isLdsIdempotencyWriteDisabled = ldsIdempotencyWriteDisabled.isOpen({
6062
+ fallback: false,
6063
+ });
6057
6064
  }
6058
6065
  enqueue(data) {
6059
6066
  return this.draftQueue.enqueue(this.handlerId, data);
@@ -6410,7 +6417,7 @@ class AbstractResourceRequestActionHandler {
6410
6417
  return [action.targetId];
6411
6418
  }
6412
6419
  hasIdempotencySupport() {
6413
- return this.isIdempotencySupported;
6420
+ return this.isIdempotencySupported && !this.isLdsIdempotencyWriteDisabled;
6414
6421
  }
6415
6422
  async ingestResponses(responses, action) {
6416
6423
  const luvio = this.getLuvio();
@@ -6948,14 +6955,20 @@ function buildQueryTypeStringKey(args) {
6948
6955
  */
6949
6956
 
6950
6957
 
6958
+ const MAX_BATCH_SIZE = 2000;
6951
6959
  class DataLoader {
6952
- constructor(batchLoadFn) {
6960
+ constructor(batchLoadFn, options) {
6953
6961
  this._batchLoadFn = batchLoadFn;
6954
6962
  this._batch = null;
6955
6963
  this._batchScheduleFn = function (fn) {
6956
6964
  setTimeout(fn, 0);
6957
6965
  };
6958
6966
  this._cacheMap = new Map();
6967
+ this._maxBatchSize = MAX_BATCH_SIZE;
6968
+ if (options !== undefined) {
6969
+ const { maxBatchSize } = options;
6970
+ this._maxBatchSize = maxBatchSize || MAX_BATCH_SIZE;
6971
+ }
6959
6972
  }
6960
6973
  load(key) {
6961
6974
  if (key === null || key === undefined) {
@@ -6985,7 +6998,9 @@ class DataLoader {
6985
6998
  // If there is an existing batch which has not yet dispatched and is within
6986
6999
  // the limit of the batch size, then return it.
6987
7000
  const existingBatch = this._batch;
6988
- if (existingBatch !== null && !existingBatch.hasDispatched && !existingBatch.cacheHits) {
7001
+ if (existingBatch !== null &&
7002
+ !existingBatch.hasDispatched &&
7003
+ existingBatch.keys.length < this._maxBatchSize) {
6989
7004
  return existingBatch;
6990
7005
  }
6991
7006
  // Otherwise, create a new batch for this loader.
@@ -9378,7 +9393,9 @@ function extendSchemaWithObjectInfos(cache, objectInfoMap) {
9378
9393
  ];
9379
9394
  // extend the schema and add resolvers
9380
9395
  const schema = addResolversToSchema(extendSchema(cache.getSchema(), extensions), polymorphicFieldTypeNames);
9396
+ const polymorphicFieldTypeNamesSet = new Set(polymorphicFieldTypeNames);
9381
9397
  cache.setSchema(schema);
9398
+ cache.setPolymorphicFieldTypeNames([...polymorphicFieldTypeNamesSet]);
9382
9399
  return cache;
9383
9400
  }
9384
9401
  /**
@@ -9534,7 +9551,10 @@ function extendExistingRecordType(schema, type, objectInfo, objectInfoMap) {
9534
9551
  let typedScalars = new Set();
9535
9552
  let parentRelationshipFields = new Set();
9536
9553
  const existingFields = keys$4(type.getFields());
9537
- const missingFields = values$2(objectInfo.fields).filter((field) => existingFields.includes(field.apiName) === false);
9554
+ const missingFields = values$2(objectInfo.fields).filter((field) => {
9555
+ return (existingFields.includes(field.apiName) === false ||
9556
+ (field.relationshipName !== null && field.referenceToInfos.length > 1));
9557
+ });
9538
9558
  const { fields, polymorphicFieldTypeNames } = makeRecordField(missingFields, objectInfoMap, parentRelationshipFields, 'Cached');
9539
9559
  const { apiName, childRelationships } = objectInfo;
9540
9560
  // handles child relationship
@@ -9634,8 +9654,10 @@ function makeRecordField(fieldRepresentations, objectInfoMap, existingParentRela
9634
9654
  // For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
9635
9655
  }
9636
9656
  else if (field.referenceToInfos.length > 1) {
9637
- existingParentRelationships.add(field.relationshipName);
9638
- fields += `${field.relationshipName}: Record\n`;
9657
+ if (recordTypeInSchema === 'Missing') {
9658
+ existingParentRelationships.add(field.relationshipName);
9659
+ fields += `${field.relationshipName}: Record\n`;
9660
+ }
9639
9661
  for (const relation of field.referenceToInfos) {
9640
9662
  if (objectInfoMap[relation.apiName] !== undefined) {
9641
9663
  polymorphicFieldTypeNames.add(relation.apiName);
@@ -12084,34 +12106,42 @@ function applyReferenceLinksToDraft(record, draftMetadata) {
12084
12106
  }
12085
12107
  const { dataType, relationshipName, referenceToInfos } = fieldInfo;
12086
12108
  const draftFieldValue = record.fields[draftField].value;
12087
- if (dataType === 'Reference' && relationshipName !== null && draftFieldValue !== null) {
12088
- if (typeof draftFieldValue !== 'string') {
12089
- throw Error('reference field value is not a string');
12109
+ if (dataType === 'Reference' && relationshipName !== null) {
12110
+ if (draftFieldValue === null) {
12111
+ recordFields[relationshipName] = {
12112
+ displayValue: null,
12113
+ value: null,
12114
+ };
12090
12115
  }
12091
- const key = getRecordKeyForId(luvio, draftFieldValue);
12092
- const referencedRecord = referencedRecords.get(key);
12093
- recordFields[relationshipName] = {
12094
- displayValue: null,
12095
- value: createLink(key),
12096
- };
12097
- // for custom objects, we select the 'Name' field
12098
- // otherwise we check the object info for name fields.
12099
- //if there are multiple we select 'Name' if it exists, otherwise the first one
12100
- if (referencedRecord !== undefined && referenceToInfos.length > 0) {
12101
- let nameField;
12102
- const referenceToInfo = referenceToInfos[0];
12103
- const nameFields = referenceToInfo.nameFields;
12104
- if (nameFields.length !== 0) {
12105
- nameField = nameFields.find((x) => x === 'Name');
12106
- if (nameField === undefined) {
12107
- nameField = nameFields[0];
12108
- }
12116
+ else {
12117
+ if (typeof draftFieldValue !== 'string') {
12118
+ throw Error('reference field value is not a string');
12109
12119
  }
12110
- if (nameField !== undefined) {
12111
- const nameFieldRef = referencedRecord.fields[nameField];
12112
- if (nameFieldRef) {
12113
- recordFields[relationshipName].displayValue =
12114
- (_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
12120
+ const key = getRecordKeyForId(luvio, draftFieldValue);
12121
+ const referencedRecord = referencedRecords.get(key);
12122
+ recordFields[relationshipName] = {
12123
+ displayValue: null,
12124
+ value: createLink(key),
12125
+ };
12126
+ // for custom objects, we select the 'Name' field
12127
+ // otherwise we check the object info for name fields.
12128
+ //if there are multiple we select 'Name' if it exists, otherwise the first one
12129
+ if (referencedRecord !== undefined && referenceToInfos.length > 0) {
12130
+ let nameField;
12131
+ const referenceToInfo = referenceToInfos[0];
12132
+ const nameFields = referenceToInfo.nameFields;
12133
+ if (nameFields.length !== 0) {
12134
+ nameField = nameFields.find((x) => x === 'Name');
12135
+ if (nameField === undefined) {
12136
+ nameField = nameFields[0];
12137
+ }
12138
+ }
12139
+ if (nameField !== undefined) {
12140
+ const nameFieldRef = referencedRecord.fields[nameField];
12141
+ if (nameFieldRef) {
12142
+ recordFields[relationshipName].displayValue =
12143
+ (_a = nameFieldRef.displayValue) !== null && _a !== void 0 ? _a : nameFieldRef.value;
12144
+ }
12115
12145
  }
12116
12146
  }
12117
12147
  }
@@ -12404,17 +12434,8 @@ class UiApiActionHandler extends AbstractResourceRequestActionHandler {
12404
12434
  };
12405
12435
  for (const fieldName of keys$3(recordWithSpanningRefLinks.fields)) {
12406
12436
  const fieldKey = buildRecordFieldStoreKey(key, fieldName);
12407
- if (this.collectedFields[fieldKey] !== undefined) {
12408
- const fieldData = recordWithSpanningRefLinks.fields[fieldName];
12409
- normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12410
- publishData(fieldKey, fieldData);
12411
- }
12412
- else if (recordWithSpanningRefLinks.fields[fieldName] &&
12413
- recordWithSpanningRefLinks.fields[fieldName].value &&
12414
- recordWithSpanningRefLinks.fields[fieldName].value.__ref !== undefined) {
12415
- normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12416
- publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
12417
- }
12437
+ normalizedRecord.fields[fieldName] = { __ref: fieldKey };
12438
+ publishData(fieldKey, recordWithSpanningRefLinks.fields[fieldName]);
12418
12439
  }
12419
12440
  // publish the normalized record
12420
12441
  publishData(key, normalizedRecord);
@@ -15375,6 +15396,14 @@ class ObjectInfoService {
15375
15396
  return this.updateObjectInfoMapping(keyPrefix, apiName);
15376
15397
  }
15377
15398
  };
15399
+ this.getCachedObjectInfoStatus = async () => {
15400
+ const infos = await this.readObjectInfoDataFromDurableStore();
15401
+ const map = new Map();
15402
+ infos.forEach(({ apiName, expirationTimestamp }) => {
15403
+ map.set(apiName, { expiration: expirationTimestamp });
15404
+ });
15405
+ return map;
15406
+ };
15378
15407
  this.isObjectInfoInDurableStore = async (apiName) => {
15379
15408
  if (this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined) {
15380
15409
  return Promise.resolve(true);
@@ -15383,12 +15412,10 @@ class ObjectInfoService {
15383
15412
  return this.apiNameToKeyPrefixMemoryCache[apiName] !== undefined;
15384
15413
  };
15385
15414
  this.loadObjectInfoMaps = async () => {
15386
- const rows = (await this.durableStore.query(`SELECT json_extract(data, '$.apiName') as ApiName, json_extract(data, '$.keyPrefix') as keyPrefix from lds_data where key like '%ObjectInfoRepresentation%'`, [])).rows;
15387
- for (const row of rows) {
15388
- const apiName = row[0];
15389
- const keyPrefix = row[1];
15415
+ const infos = await this.readObjectInfoDataFromDurableStore();
15416
+ infos.forEach(({ keyPrefix, apiName }) => {
15390
15417
  this.updateObjectInfoMapping(keyPrefix, apiName);
15391
- }
15418
+ });
15392
15419
  };
15393
15420
  this.updateObjectInfoMapping = (keyPrefix, apiName) => {
15394
15421
  this.apiNameToKeyPrefixMemoryCache[apiName] = keyPrefix;
@@ -15432,6 +15459,24 @@ class ObjectInfoService {
15432
15459
  }
15433
15460
  return snapshot.data;
15434
15461
  }
15462
+ async readObjectInfoDataFromDurableStore() {
15463
+ const rows = (await this.durableStore.query(`
15464
+ SELECT
15465
+ json_extract(data, '$.apiName') as ApiName,
15466
+ json_extract(data, '$.keyPrefix') as keyPrefix,
15467
+ JSON_EXTRACT(metadata, '$.expirationTimestamp') AS expirationTimestamp
15468
+ from
15469
+ lds_data
15470
+ where
15471
+ key like '%ObjectInfoRepresentation%'`, [])).rows;
15472
+ return rows.map((row) => {
15473
+ return {
15474
+ apiName: row[0],
15475
+ keyPrefix: row[1],
15476
+ expirationTimestamp: row[2],
15477
+ };
15478
+ });
15479
+ }
15435
15480
  }
15436
15481
 
15437
15482
  function instrumentGraphQLEval(adapter) {
@@ -16530,7 +16575,7 @@ class ConflictPool {
16530
16575
  }
16531
16576
  }
16532
16577
 
16533
- const DEFAULT_BATCH_SIZE = 500;
16578
+ const DEFAULT_BATCH_SIZE$1 = 500;
16534
16579
  const DEFAULT_CONCURRENCY = 6;
16535
16580
  const DEFAULT_GQL_QUERY_BATCH_SIZE = 5;
16536
16581
  class PrimingSession extends EventEmitter {
@@ -16538,7 +16583,7 @@ class PrimingSession extends EventEmitter {
16538
16583
  var _a, _b;
16539
16584
  super();
16540
16585
  this.useBatchGQL = false;
16541
- this.batchSize = (_a = config.batchSize) !== null && _a !== void 0 ? _a : DEFAULT_BATCH_SIZE;
16586
+ this.batchSize = (_a = config.batchSize) !== null && _a !== void 0 ? _a : DEFAULT_BATCH_SIZE$1;
16542
16587
  this.concurrency = (_b = config.concurrency) !== null && _b !== void 0 ? _b : DEFAULT_CONCURRENCY;
16543
16588
  this.recordLoader = config.recordLoader;
16544
16589
  this.recordIngestor = config.recordIngestor;
@@ -17159,10 +17204,6 @@ class NimbusPrimingNetworkAdapter {
17159
17204
  // ref: https://gnome.pages.gitlab.gnome.org/tracker/docs/developer/limits.html?gi-language=c
17160
17205
  const SQLITE_MAX_VARIABLE_NUMBER = 999;
17161
17206
  const PARAMS_PER_RECORD = 3;
17162
- /**
17163
- * No key builder (or adapter) exists for the object info directory, we need to build the key manually
17164
- */
17165
- const ObjectInfoDirectoryKey = `${UiApiNamespace}::${ObjectInfoDirectoryEntryRepresentationType}:`;
17166
17207
  // We need to batch the records to avoid hitting the SQLITE_MAX_VARIABLE_NUMBER limit. Each record has 3 parameters
17167
17208
  const BATCH_SIZE = Math.floor(SQLITE_MAX_VARIABLE_NUMBER / PARAMS_PER_RECORD);
17168
17209
  class SqlitePrimingStore {
@@ -17227,44 +17268,6 @@ class SqlitePrimingStore {
17227
17268
  };
17228
17269
  }
17229
17270
  }
17230
- async readObjectInfoDirectory() {
17231
- const sql = 'SELECT data FROM lds_data WHERE key = ?';
17232
- const params = [ObjectInfoDirectoryKey];
17233
- const result = await this.store.query(sql, params);
17234
- if (result.rows.length === 1) {
17235
- return JSON.parse(result.rows[0][0]);
17236
- }
17237
- return undefined;
17238
- }
17239
- async readObjectApiNames() {
17240
- const sql = 'SELECT key FROM lds_data WHERE key like ?';
17241
- const params = [`%${ObjectInfoRepresentationType}%`];
17242
- const result = await this.store.query(sql, params);
17243
- const apiNames = new Set();
17244
- result.rows.forEach((row) => {
17245
- const key = row[0];
17246
- const parts = key.split(':');
17247
- apiNames.add(parts[parts.length - 1]);
17248
- });
17249
- return apiNames;
17250
- }
17251
- writeObjectInfoDirectory(directory) {
17252
- const sql = 'INSERT or IGNORE into lds_data (key, data) values (?, ?)';
17253
- const params = [ObjectInfoDirectoryKey, JSON.stringify(directory)];
17254
- return this.store.query(sql, params).then(() => { });
17255
- }
17256
- writeObjectInfos(objectInfos) {
17257
- const sql = `INSERT or IGNORE into lds_data (key, data) values ${objectInfos
17258
- .map(() => '(?, ?)')
17259
- .join(',')};`;
17260
- const params = [];
17261
- objectInfos.forEach((objectInfo) => {
17262
- const key = keyBuilderObjectInfo(this.getLuvio(), { apiName: objectInfo.apiName });
17263
- params.push(key);
17264
- params.push(JSON.stringify(objectInfo));
17265
- });
17266
- return this.store.query(sql, params).then(() => { });
17267
- }
17268
17271
  }
17269
17272
  function batchArray(arr, batchSize = BATCH_SIZE) {
17270
17273
  const batches = [];
@@ -17339,9 +17342,7 @@ function primingSessionFactory(config) {
17339
17342
  recordLoader,
17340
17343
  recordIngestor,
17341
17344
  store: primingStore,
17342
- objectInfoLoader: {
17343
- getObjectInfos: objectInfoService.getObjectInfos.bind(objectInfoService),
17344
- },
17345
+ objectInfoLoader: objectInfoService,
17345
17346
  concurrency: config.concurrency,
17346
17347
  batchSize: config.batchSize,
17347
17348
  ldsRecordRefresher: new LdsPrimingRecordRefresher(config.getRecords),
@@ -17507,4 +17508,4 @@ register({
17507
17508
  });
17508
17509
 
17509
17510
  export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
17510
- // version: 1.248.0-1f7f01112
17511
+ // version: 1.249.0-11c3e1ed5
@@ -1,6 +1,5 @@
1
1
  import type { PrimingStore, RecordWithMetadata, WriteResult } from '@salesforce/lds-priming';
2
2
  import type { Luvio } from '@luvio/engine';
3
- import type { ObjectInfoDirectoryRepresentation, ObjectInfoRepresentation } from '@salesforce/lds-adapters-uiapi';
4
3
  import type { SqliteStore } from '@salesforce/lds-store-sql';
5
4
  export declare class SqlitePrimingStore implements PrimingStore {
6
5
  private readonly getLuvio;
@@ -9,8 +8,4 @@ export declare class SqlitePrimingStore implements PrimingStore {
9
8
  readRecords(ids: string[]): Promise<RecordWithMetadata[]>;
10
9
  writeRecords(records: RecordWithMetadata[], overwrite: boolean): Promise<WriteResult>;
11
10
  private writeBatch;
12
- readObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
13
- readObjectApiNames(): Promise<Set<string>>;
14
- writeObjectInfoDirectory(directory: ObjectInfoDirectoryRepresentation): Promise<void>;
15
- writeObjectInfos(objectInfos: ObjectInfoRepresentation[]): Promise<void>;
16
11
  }
@@ -10,6 +10,9 @@ type ObjectInfoDirectoryConfig = Parameters<ObjectInfoDirectoryAdapterReturn>[0]
10
10
  export type ObjectInfoMap = {
11
11
  [apiName: string]: ObjectInfoRepresentation;
12
12
  };
13
+ interface ObjectInfoStatus {
14
+ expiration: number;
15
+ }
13
16
  export declare class ObjectInfoService {
14
17
  private getObjectInfoAdapter;
15
18
  private getObjectInfosAdapter;
@@ -31,8 +34,10 @@ export declare class ObjectInfoService {
31
34
  getObjectInfos(apiNames: string[]): Promise<ObjectInfoMap>;
32
35
  getObjectInfoDirectory(): Promise<ObjectInfoDirectoryRepresentation | undefined>;
33
36
  ensureObjectInfoCached: (apiName: string, entry?: ObjectInfoRepresentation) => Promise<void>;
37
+ getCachedObjectInfoStatus: () => Promise<Map<string, ObjectInfoStatus>>;
34
38
  private isObjectInfoInDurableStore;
35
39
  private loadObjectInfoMaps;
40
+ private readObjectInfoDataFromDurableStore;
36
41
  private updateObjectInfoMapping;
37
42
  }
38
43
  export {};