@salesforce/lds-runtime-mobile 1.152.3 → 1.153.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 +73 -12
- package/package.json +7 -7
- package/sfdc/main.js +73 -12
package/dist/main.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { withRegistration, register } from '@salesforce/lds-default-luvio';
|
|
15
15
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from '@salesforce/lds-instrumentation';
|
|
16
16
|
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
17
|
+
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
17
18
|
import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from '@luvio/graphql-parser';
|
|
18
19
|
import { getRecordId18, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion } from '@salesforce/lds-adapters-uiapi';
|
|
19
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
@@ -2125,9 +2126,13 @@ const recordSuffix = 'edges';
|
|
|
2125
2126
|
const pathPrefix = '$';
|
|
2126
2127
|
const recordsCTE = 'recordsCTE';
|
|
2127
2128
|
const MultiPickListValueSeparator$1 = ';';
|
|
2129
|
+
const recordCTESQL = excludeStaleRecordsGate.isOpen({ fallback: false })
|
|
2130
|
+
? `WITH ${recordsCTE} AS NOT materialized ` +
|
|
2131
|
+
`(select data, metadata from lds_data where key like 'UiApi::RecordRepresentation:%')`
|
|
2132
|
+
: `WITH ${recordsCTE} AS NOT materialized ` +
|
|
2133
|
+
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`;
|
|
2128
2134
|
function cteSql() {
|
|
2129
|
-
return
|
|
2130
|
-
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`);
|
|
2135
|
+
return recordCTESQL;
|
|
2131
2136
|
}
|
|
2132
2137
|
function computeSql(rootQuery) {
|
|
2133
2138
|
const fields = rootQuery.connections.map((connection) => {
|
|
@@ -2404,6 +2409,14 @@ function expressionToSql(expression, targetDataType, operator) {
|
|
|
2404
2409
|
if (expression.subfield === 'displayValue' && targetDataType === 'Boolean') {
|
|
2405
2410
|
return { sql: 'null', bindings: [] };
|
|
2406
2411
|
}
|
|
2412
|
+
// metadata extract is somewhat different than a data extract
|
|
2413
|
+
if (expression.metadata === true) {
|
|
2414
|
+
let sql = `json_extract("${expression.jsonAlias}".metadata, '${pathPrefix}.${expression.field}')`;
|
|
2415
|
+
if (targetDataType !== undefined) {
|
|
2416
|
+
sql = coerceToTargetDataType(sql, targetDataType);
|
|
2417
|
+
}
|
|
2418
|
+
return { sql, bindings: [] };
|
|
2419
|
+
}
|
|
2407
2420
|
let path = extractPath(expression.field, expression.subfield);
|
|
2408
2421
|
// For multiple picklist includes/excluding filtering, we need to prefix and suffix the field value with ';'
|
|
2409
2422
|
// to make the match safe.
|
|
@@ -4040,6 +4053,39 @@ function recordQuery(selection, apiName, alias, predicates, input) {
|
|
|
4040
4053
|
const draftsField = { type: FieldType.Scalar, extract, path: 'node._drafts' };
|
|
4041
4054
|
const idExtract = { type: ValueType.Extract, jsonAlias: alias, field: 'Id' };
|
|
4042
4055
|
const idField = { type: FieldType.Scalar, extract: idExtract, path: 'node.Id' };
|
|
4056
|
+
// When the exclude stale records gate is open, inject an additional predicate
|
|
4057
|
+
// to limit the search to records that either have drafts associated to them or
|
|
4058
|
+
// were ingested at least as recently as the query.
|
|
4059
|
+
if (excludeStaleRecordsGate.isOpen({ fallback: false })) {
|
|
4060
|
+
const key = input.connectionKeyBuilder(selection, input.config.variables);
|
|
4061
|
+
const queryMetadata = input.metadata[key];
|
|
4062
|
+
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
4063
|
+
// skip adding the additional predicates
|
|
4064
|
+
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
4065
|
+
const timestamp = queryMetadata.ingestionTimestamp;
|
|
4066
|
+
const timestampCheck = {
|
|
4067
|
+
type: PredicateType$1.comparison,
|
|
4068
|
+
left: {
|
|
4069
|
+
type: ValueType.Extract,
|
|
4070
|
+
jsonAlias: alias,
|
|
4071
|
+
field: 'ingestionTimestamp',
|
|
4072
|
+
metadata: true,
|
|
4073
|
+
},
|
|
4074
|
+
operator: ComparisonOperator.gte,
|
|
4075
|
+
right: { type: ValueType.IntLiteral, value: timestamp },
|
|
4076
|
+
};
|
|
4077
|
+
const isDraft = {
|
|
4078
|
+
type: PredicateType$1.nullComparison,
|
|
4079
|
+
left: { type: ValueType.Extract, jsonAlias: alias, field: 'drafts' },
|
|
4080
|
+
operator: NullComparisonOperator.isNot,
|
|
4081
|
+
};
|
|
4082
|
+
predicates.push({
|
|
4083
|
+
type: PredicateType$1.compound,
|
|
4084
|
+
operator: CompoundOperator.or,
|
|
4085
|
+
children: [timestampCheck, isDraft],
|
|
4086
|
+
});
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4043
4089
|
return queryContainer(internalFields, alias, apiName, predicates).map((result) => {
|
|
4044
4090
|
const { fields, predicates } = result;
|
|
4045
4091
|
const allFields = removeDuplicateFields(fields.concat(...[draftsField, idField]));
|
|
@@ -4310,12 +4356,24 @@ class StoreEvalPreconditioner {
|
|
|
4310
4356
|
* Missing object info records triggers the objectInfoService (same instance shared with Drafts code), to
|
|
4311
4357
|
* use the getObjectInfos adapter to efficiently fetch the necessary records.
|
|
4312
4358
|
*/
|
|
4313
|
-
async createRootQuery(config, objectInfoService, userId, draftFunctions) {
|
|
4359
|
+
async createRootQuery(config, objectInfoService, userId, draftFunctions, connectionKeyBuilder, sqliteStore) {
|
|
4314
4360
|
const { query: ast, variables } = config;
|
|
4315
4361
|
swapVariableArguments(ast, variables);
|
|
4316
4362
|
// Parse out top-level record queries types we know we will need, since spanning fields will
|
|
4317
4363
|
// require at least this top level record present to resolve relationship lookups
|
|
4318
|
-
const
|
|
4364
|
+
const recordSelections = findRecordSelections(ast);
|
|
4365
|
+
let metadata = {};
|
|
4366
|
+
if (excludeStaleRecordsGate.isOpen({ fallback: false })) {
|
|
4367
|
+
const keys = recordSelections.map((rs) => connectionKeyBuilder(rs, variables));
|
|
4368
|
+
let sqlResult = await sqliteStore.query(`select key, metadata from lds_data where key in (${keys
|
|
4369
|
+
.map(() => '?')
|
|
4370
|
+
.join(',')})`, keys);
|
|
4371
|
+
metadata = sqlResult.rows.reduce((metadata, row) => {
|
|
4372
|
+
metadata[row[0]] = JSON.parse(row[1]);
|
|
4373
|
+
return metadata;
|
|
4374
|
+
}, {});
|
|
4375
|
+
}
|
|
4376
|
+
const topLevelNeededRecords = recordSelections.map((selection) => selection.name);
|
|
4319
4377
|
// Seed the initial list of things to fetch
|
|
4320
4378
|
const neededObjectInfos = new Set(topLevelNeededRecords);
|
|
4321
4379
|
// Seed the list of things we've _tried_ to fetch. As we iterate and
|
|
@@ -4355,9 +4413,12 @@ class StoreEvalPreconditioner {
|
|
|
4355
4413
|
};
|
|
4356
4414
|
// Attempt to parse the AST given what we know already...
|
|
4357
4415
|
astTransformResult = transform(ast, {
|
|
4416
|
+
config,
|
|
4358
4417
|
userId,
|
|
4359
4418
|
objectInfoMap,
|
|
4360
4419
|
draftFunctions,
|
|
4420
|
+
connectionKeyBuilder,
|
|
4421
|
+
metadata,
|
|
4361
4422
|
});
|
|
4362
4423
|
if (astTransformResult.isSuccess === false) {
|
|
4363
4424
|
for (const error of astTransformResult.error) {
|
|
@@ -4432,10 +4493,10 @@ async function evaluateSqlite(query, eventEmitter, store) {
|
|
|
4432
4493
|
return { data, seenRecords };
|
|
4433
4494
|
}
|
|
4434
4495
|
const wrapStartEndEvents = (storeEval) => {
|
|
4435
|
-
return async (config, nonEvaluatedSnapshotOrPromise, observers) => {
|
|
4496
|
+
return async (config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder) => {
|
|
4436
4497
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE$1, observers);
|
|
4437
4498
|
eventEmitter({ type: 'graphql-eval-start' });
|
|
4438
|
-
const snapshot = await storeEval(config, nonEvaluatedSnapshotOrPromise, observers);
|
|
4499
|
+
const snapshot = await storeEval(config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder);
|
|
4439
4500
|
eventEmitter({ type: 'graphql-eval-end' });
|
|
4440
4501
|
return snapshot;
|
|
4441
4502
|
};
|
|
@@ -4448,7 +4509,7 @@ function sqliteStoreEvalFactory(userId, sqliteStore, objectInfoService, draftFun
|
|
|
4448
4509
|
const preconditioner = new StoreEvalPreconditioner();
|
|
4449
4510
|
return makeStoreEval(preconditioner, objectInfoService, userId, async () => {
|
|
4450
4511
|
return undefined;
|
|
4451
|
-
}, (query, _context, eventEmitter) => evaluateSqlite(query, eventEmitter, sqliteStore), draftFunctions);
|
|
4512
|
+
}, (query, _context, eventEmitter) => evaluateSqlite(query, eventEmitter, sqliteStore), draftFunctions, sqliteStore);
|
|
4452
4513
|
}
|
|
4453
4514
|
async function noopStoreEval(_config, nonEvaluatedSnapshotOrPromise, _observers) {
|
|
4454
4515
|
return nonEvaluatedSnapshotOrPromise;
|
|
@@ -4467,8 +4528,8 @@ function isErrorSnapshotThatShouldGetReturnedToCaller$1(snapshot) {
|
|
|
4467
4528
|
function generateUniqueRecordId$1() {
|
|
4468
4529
|
return `${GRAPHQL_ROOT_KEY$1}${Date.now() + Math.random().toFixed(5).split('.')[1]}`;
|
|
4469
4530
|
}
|
|
4470
|
-
function makeStoreEval(preconditioner, objectInfoService, userId, contextProvider, queryEvaluator, draftFunctions) {
|
|
4471
|
-
const storeEval = async (config, nonEvaluatedSnapshotOrPromise, observers) => {
|
|
4531
|
+
function makeStoreEval(preconditioner, objectInfoService, userId, contextProvider, queryEvaluator, draftFunctions, sqliteStore) {
|
|
4532
|
+
const storeEval = async (config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder) => {
|
|
4472
4533
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE$1, observers);
|
|
4473
4534
|
// the non-eval'ed input could either be a snapshot or promise of one so
|
|
4474
4535
|
// await it here to normalize the input to a snapshot
|
|
@@ -4497,7 +4558,7 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4497
4558
|
context = await contextProvider();
|
|
4498
4559
|
// Ensures ObjectInfo metadata is available for the request. Sourcing records from L1/L2/Network
|
|
4499
4560
|
// is delegated to the getObjectInfo adapter via objectInfoService
|
|
4500
|
-
rootQuery = await preconditioner.createRootQuery(config, objectInfoService, userId, draftFunctions);
|
|
4561
|
+
rootQuery = await preconditioner.createRootQuery(config, objectInfoService, userId, draftFunctions, connectionKeyBuilder, sqliteStore);
|
|
4501
4562
|
}
|
|
4502
4563
|
catch (error) {
|
|
4503
4564
|
eventEmitter({
|
|
@@ -4528,7 +4589,7 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4528
4589
|
try {
|
|
4529
4590
|
const { data, seenRecords } = await queryEvaluator(rootQuery, context, eventEmitter);
|
|
4530
4591
|
const rebuildWithStoreEval = ((originalSnapshot) => {
|
|
4531
|
-
return storeEval(config, originalSnapshot, observers);
|
|
4592
|
+
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder);
|
|
4532
4593
|
});
|
|
4533
4594
|
const recordId = generateUniqueRecordId$1();
|
|
4534
4595
|
// if the non-eval'ed snapshot was an error then we return a synthetic
|
|
@@ -15706,4 +15767,4 @@ register({
|
|
|
15706
15767
|
});
|
|
15707
15768
|
|
|
15708
15769
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15709
|
-
// version: 1.
|
|
15770
|
+
// version: 1.153.0-8e8a8177b
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/lds-runtime-mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.153.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "LDS runtime for mobile/hybrid environments.",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -57,17 +57,17 @@
|
|
|
57
57
|
{
|
|
58
58
|
"path": "./dist/main.js",
|
|
59
59
|
"maxSize": {
|
|
60
|
-
"none": "
|
|
61
|
-
"min": "
|
|
62
|
-
"compressed": "
|
|
60
|
+
"none": "675 kB",
|
|
61
|
+
"min": "275 kB",
|
|
62
|
+
"compressed": "110 kB"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"path": "./sfdc/main.js",
|
|
67
67
|
"maxSize": {
|
|
68
|
-
"none": "
|
|
69
|
-
"min": "
|
|
70
|
-
"compressed": "
|
|
68
|
+
"none": "675 kB",
|
|
69
|
+
"min": "275 kB",
|
|
70
|
+
"compressed": "110 kB"
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
],
|
package/sfdc/main.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { withRegistration, register } from 'native/ldsEngineMobile';
|
|
15
15
|
import { setupInstrumentation, instrumentAdapter as instrumentAdapter$1, instrumentLuvio, setLdsAdaptersUiapiInstrumentation, setLdsNetworkAdapterInstrumentation } from 'force/ldsInstrumentation';
|
|
16
16
|
import { HttpStatusCode, StoreKeySet, serializeStructuredKey, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
|
|
17
|
+
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
17
18
|
import { parseAndVisit, Kind, visit, execute, buildSchema, isObjectType, defaultFieldResolver } from 'force/ldsGraphqlParser';
|
|
18
19
|
import { getRecordId18, keyBuilderQuickActionExecutionRepresentation, ingestQuickActionExecutionRepresentation, keyBuilderContentDocumentCompositeRepresentation, getResponseCacheKeysContentDocumentCompositeRepresentation, keyBuilderFromTypeContentDocumentCompositeRepresentation, ingestContentDocumentCompositeRepresentation, keyBuilderRecord, getTypeCacheKeysRecord, keyBuilderFromTypeRecordRepresentation, ingestRecord, RecordRepresentationRepresentationType, ObjectInfoRepresentationType, getRecordAdapterFactory, getObjectInfoAdapterFactory, getObjectInfosAdapterFactory, UiApiNamespace, RecordRepresentationType, RecordRepresentationTTL, RecordRepresentationVersion } from 'force/ldsAdaptersUiapi';
|
|
19
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
@@ -2125,9 +2126,13 @@ const recordSuffix = 'edges';
|
|
|
2125
2126
|
const pathPrefix = '$';
|
|
2126
2127
|
const recordsCTE = 'recordsCTE';
|
|
2127
2128
|
const MultiPickListValueSeparator$1 = ';';
|
|
2129
|
+
const recordCTESQL = excludeStaleRecordsGate.isOpen({ fallback: false })
|
|
2130
|
+
? `WITH ${recordsCTE} AS NOT materialized ` +
|
|
2131
|
+
`(select data, metadata from lds_data where key like 'UiApi::RecordRepresentation:%')`
|
|
2132
|
+
: `WITH ${recordsCTE} AS NOT materialized ` +
|
|
2133
|
+
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`;
|
|
2128
2134
|
function cteSql() {
|
|
2129
|
-
return
|
|
2130
|
-
`(select data from lds_data where key like 'UiApi::RecordRepresentation:%')`);
|
|
2135
|
+
return recordCTESQL;
|
|
2131
2136
|
}
|
|
2132
2137
|
function computeSql(rootQuery) {
|
|
2133
2138
|
const fields = rootQuery.connections.map((connection) => {
|
|
@@ -2404,6 +2409,14 @@ function expressionToSql(expression, targetDataType, operator) {
|
|
|
2404
2409
|
if (expression.subfield === 'displayValue' && targetDataType === 'Boolean') {
|
|
2405
2410
|
return { sql: 'null', bindings: [] };
|
|
2406
2411
|
}
|
|
2412
|
+
// metadata extract is somewhat different than a data extract
|
|
2413
|
+
if (expression.metadata === true) {
|
|
2414
|
+
let sql = `json_extract("${expression.jsonAlias}".metadata, '${pathPrefix}.${expression.field}')`;
|
|
2415
|
+
if (targetDataType !== undefined) {
|
|
2416
|
+
sql = coerceToTargetDataType(sql, targetDataType);
|
|
2417
|
+
}
|
|
2418
|
+
return { sql, bindings: [] };
|
|
2419
|
+
}
|
|
2407
2420
|
let path = extractPath(expression.field, expression.subfield);
|
|
2408
2421
|
// For multiple picklist includes/excluding filtering, we need to prefix and suffix the field value with ';'
|
|
2409
2422
|
// to make the match safe.
|
|
@@ -4040,6 +4053,39 @@ function recordQuery(selection, apiName, alias, predicates, input) {
|
|
|
4040
4053
|
const draftsField = { type: FieldType.Scalar, extract, path: 'node._drafts' };
|
|
4041
4054
|
const idExtract = { type: ValueType.Extract, jsonAlias: alias, field: 'Id' };
|
|
4042
4055
|
const idField = { type: FieldType.Scalar, extract: idExtract, path: 'node.Id' };
|
|
4056
|
+
// When the exclude stale records gate is open, inject an additional predicate
|
|
4057
|
+
// to limit the search to records that either have drafts associated to them or
|
|
4058
|
+
// were ingested at least as recently as the query.
|
|
4059
|
+
if (excludeStaleRecordsGate.isOpen({ fallback: false })) {
|
|
4060
|
+
const key = input.connectionKeyBuilder(selection, input.config.variables);
|
|
4061
|
+
const queryMetadata = input.metadata[key];
|
|
4062
|
+
// If there is no metadata for this query or it somehow lacks a timestamp
|
|
4063
|
+
// skip adding the additional predicates
|
|
4064
|
+
if (queryMetadata !== undefined && queryMetadata.ingestionTimestamp !== undefined) {
|
|
4065
|
+
const timestamp = queryMetadata.ingestionTimestamp;
|
|
4066
|
+
const timestampCheck = {
|
|
4067
|
+
type: PredicateType$1.comparison,
|
|
4068
|
+
left: {
|
|
4069
|
+
type: ValueType.Extract,
|
|
4070
|
+
jsonAlias: alias,
|
|
4071
|
+
field: 'ingestionTimestamp',
|
|
4072
|
+
metadata: true,
|
|
4073
|
+
},
|
|
4074
|
+
operator: ComparisonOperator.gte,
|
|
4075
|
+
right: { type: ValueType.IntLiteral, value: timestamp },
|
|
4076
|
+
};
|
|
4077
|
+
const isDraft = {
|
|
4078
|
+
type: PredicateType$1.nullComparison,
|
|
4079
|
+
left: { type: ValueType.Extract, jsonAlias: alias, field: 'drafts' },
|
|
4080
|
+
operator: NullComparisonOperator.isNot,
|
|
4081
|
+
};
|
|
4082
|
+
predicates.push({
|
|
4083
|
+
type: PredicateType$1.compound,
|
|
4084
|
+
operator: CompoundOperator.or,
|
|
4085
|
+
children: [timestampCheck, isDraft],
|
|
4086
|
+
});
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4043
4089
|
return queryContainer(internalFields, alias, apiName, predicates).map((result) => {
|
|
4044
4090
|
const { fields, predicates } = result;
|
|
4045
4091
|
const allFields = removeDuplicateFields(fields.concat(...[draftsField, idField]));
|
|
@@ -4310,12 +4356,24 @@ class StoreEvalPreconditioner {
|
|
|
4310
4356
|
* Missing object info records triggers the objectInfoService (same instance shared with Drafts code), to
|
|
4311
4357
|
* use the getObjectInfos adapter to efficiently fetch the necessary records.
|
|
4312
4358
|
*/
|
|
4313
|
-
async createRootQuery(config, objectInfoService, userId, draftFunctions) {
|
|
4359
|
+
async createRootQuery(config, objectInfoService, userId, draftFunctions, connectionKeyBuilder, sqliteStore) {
|
|
4314
4360
|
const { query: ast, variables } = config;
|
|
4315
4361
|
swapVariableArguments(ast, variables);
|
|
4316
4362
|
// Parse out top-level record queries types we know we will need, since spanning fields will
|
|
4317
4363
|
// require at least this top level record present to resolve relationship lookups
|
|
4318
|
-
const
|
|
4364
|
+
const recordSelections = findRecordSelections(ast);
|
|
4365
|
+
let metadata = {};
|
|
4366
|
+
if (excludeStaleRecordsGate.isOpen({ fallback: false })) {
|
|
4367
|
+
const keys = recordSelections.map((rs) => connectionKeyBuilder(rs, variables));
|
|
4368
|
+
let sqlResult = await sqliteStore.query(`select key, metadata from lds_data where key in (${keys
|
|
4369
|
+
.map(() => '?')
|
|
4370
|
+
.join(',')})`, keys);
|
|
4371
|
+
metadata = sqlResult.rows.reduce((metadata, row) => {
|
|
4372
|
+
metadata[row[0]] = JSON.parse(row[1]);
|
|
4373
|
+
return metadata;
|
|
4374
|
+
}, {});
|
|
4375
|
+
}
|
|
4376
|
+
const topLevelNeededRecords = recordSelections.map((selection) => selection.name);
|
|
4319
4377
|
// Seed the initial list of things to fetch
|
|
4320
4378
|
const neededObjectInfos = new Set(topLevelNeededRecords);
|
|
4321
4379
|
// Seed the list of things we've _tried_ to fetch. As we iterate and
|
|
@@ -4355,9 +4413,12 @@ class StoreEvalPreconditioner {
|
|
|
4355
4413
|
};
|
|
4356
4414
|
// Attempt to parse the AST given what we know already...
|
|
4357
4415
|
astTransformResult = transform(ast, {
|
|
4416
|
+
config,
|
|
4358
4417
|
userId,
|
|
4359
4418
|
objectInfoMap,
|
|
4360
4419
|
draftFunctions,
|
|
4420
|
+
connectionKeyBuilder,
|
|
4421
|
+
metadata,
|
|
4361
4422
|
});
|
|
4362
4423
|
if (astTransformResult.isSuccess === false) {
|
|
4363
4424
|
for (const error of astTransformResult.error) {
|
|
@@ -4432,10 +4493,10 @@ async function evaluateSqlite(query, eventEmitter, store) {
|
|
|
4432
4493
|
return { data, seenRecords };
|
|
4433
4494
|
}
|
|
4434
4495
|
const wrapStartEndEvents = (storeEval) => {
|
|
4435
|
-
return async (config, nonEvaluatedSnapshotOrPromise, observers) => {
|
|
4496
|
+
return async (config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder) => {
|
|
4436
4497
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE$1, observers);
|
|
4437
4498
|
eventEmitter({ type: 'graphql-eval-start' });
|
|
4438
|
-
const snapshot = await storeEval(config, nonEvaluatedSnapshotOrPromise, observers);
|
|
4499
|
+
const snapshot = await storeEval(config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder);
|
|
4439
4500
|
eventEmitter({ type: 'graphql-eval-end' });
|
|
4440
4501
|
return snapshot;
|
|
4441
4502
|
};
|
|
@@ -4448,7 +4509,7 @@ function sqliteStoreEvalFactory(userId, sqliteStore, objectInfoService, draftFun
|
|
|
4448
4509
|
const preconditioner = new StoreEvalPreconditioner();
|
|
4449
4510
|
return makeStoreEval(preconditioner, objectInfoService, userId, async () => {
|
|
4450
4511
|
return undefined;
|
|
4451
|
-
}, (query, _context, eventEmitter) => evaluateSqlite(query, eventEmitter, sqliteStore), draftFunctions);
|
|
4512
|
+
}, (query, _context, eventEmitter) => evaluateSqlite(query, eventEmitter, sqliteStore), draftFunctions, sqliteStore);
|
|
4452
4513
|
}
|
|
4453
4514
|
async function noopStoreEval(_config, nonEvaluatedSnapshotOrPromise, _observers) {
|
|
4454
4515
|
return nonEvaluatedSnapshotOrPromise;
|
|
@@ -4467,8 +4528,8 @@ function isErrorSnapshotThatShouldGetReturnedToCaller$1(snapshot) {
|
|
|
4467
4528
|
function generateUniqueRecordId$1() {
|
|
4468
4529
|
return `${GRAPHQL_ROOT_KEY$1}${Date.now() + Math.random().toFixed(5).split('.')[1]}`;
|
|
4469
4530
|
}
|
|
4470
|
-
function makeStoreEval(preconditioner, objectInfoService, userId, contextProvider, queryEvaluator, draftFunctions) {
|
|
4471
|
-
const storeEval = async (config, nonEvaluatedSnapshotOrPromise, observers) => {
|
|
4531
|
+
function makeStoreEval(preconditioner, objectInfoService, userId, contextProvider, queryEvaluator, draftFunctions, sqliteStore) {
|
|
4532
|
+
const storeEval = async (config, nonEvaluatedSnapshotOrPromise, observers, connectionKeyBuilder) => {
|
|
4472
4533
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE$1, observers);
|
|
4473
4534
|
// the non-eval'ed input could either be a snapshot or promise of one so
|
|
4474
4535
|
// await it here to normalize the input to a snapshot
|
|
@@ -4497,7 +4558,7 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4497
4558
|
context = await contextProvider();
|
|
4498
4559
|
// Ensures ObjectInfo metadata is available for the request. Sourcing records from L1/L2/Network
|
|
4499
4560
|
// is delegated to the getObjectInfo adapter via objectInfoService
|
|
4500
|
-
rootQuery = await preconditioner.createRootQuery(config, objectInfoService, userId, draftFunctions);
|
|
4561
|
+
rootQuery = await preconditioner.createRootQuery(config, objectInfoService, userId, draftFunctions, connectionKeyBuilder, sqliteStore);
|
|
4501
4562
|
}
|
|
4502
4563
|
catch (error) {
|
|
4503
4564
|
eventEmitter({
|
|
@@ -4528,7 +4589,7 @@ function makeStoreEval(preconditioner, objectInfoService, userId, contextProvide
|
|
|
4528
4589
|
try {
|
|
4529
4590
|
const { data, seenRecords } = await queryEvaluator(rootQuery, context, eventEmitter);
|
|
4530
4591
|
const rebuildWithStoreEval = ((originalSnapshot) => {
|
|
4531
|
-
return storeEval(config, originalSnapshot, observers);
|
|
4592
|
+
return storeEval(config, originalSnapshot, observers, connectionKeyBuilder);
|
|
4532
4593
|
});
|
|
4533
4594
|
const recordId = generateUniqueRecordId$1();
|
|
4534
4595
|
// if the non-eval'ed snapshot was an error then we return a synthetic
|
|
@@ -15706,4 +15767,4 @@ register({
|
|
|
15706
15767
|
});
|
|
15707
15768
|
|
|
15708
15769
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
15709
|
-
// version: 1.
|
|
15770
|
+
// version: 1.153.0-8e8a8177b
|