@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 +114 -113
- package/dist/types/priming/SqlitePrimingStore.d.ts +0 -5
- package/dist/types/utils/ObjectInfoService.d.ts +5 -0
- package/package.json +1 -1
- package/sfdc/main.js +114 -113
- package/sfdc/types/priming/SqlitePrimingStore.d.ts +0 -5
- package/sfdc/types/utils/ObjectInfoService.d.ts +5 -0
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,
|
|
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 &&
|
|
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) =>
|
|
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
|
-
|
|
9638
|
-
|
|
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
|
|
12088
|
-
if (
|
|
12089
|
-
|
|
12109
|
+
if (dataType === 'Reference' && relationshipName !== null) {
|
|
12110
|
+
if (draftFieldValue === null) {
|
|
12111
|
+
recordFields[relationshipName] = {
|
|
12112
|
+
displayValue: null,
|
|
12113
|
+
value: null,
|
|
12114
|
+
};
|
|
12090
12115
|
}
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
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
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
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
|
-
|
|
12408
|
-
|
|
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
|
|
15387
|
-
|
|
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.
|
|
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
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,
|
|
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 &&
|
|
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) =>
|
|
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
|
-
|
|
9638
|
-
|
|
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
|
|
12088
|
-
if (
|
|
12089
|
-
|
|
12109
|
+
if (dataType === 'Reference' && relationshipName !== null) {
|
|
12110
|
+
if (draftFieldValue === null) {
|
|
12111
|
+
recordFields[relationshipName] = {
|
|
12112
|
+
displayValue: null,
|
|
12113
|
+
value: null,
|
|
12114
|
+
};
|
|
12090
12115
|
}
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
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
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
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
|
-
|
|
12408
|
-
|
|
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
|
|
15387
|
-
|
|
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.
|
|
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 {};
|