@salesforce/lds-runtime-mobile 1.247.0 → 1.248.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 +329 -110
- package/package.json +1 -1
- package/sfdc/main.js +329 -110
package/dist/main.js
CHANGED
|
@@ -15,7 +15,7 @@ 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, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from '@luvio/engine';
|
|
17
17
|
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
18
|
-
import { parseAndVisit, Kind, visit, execute,
|
|
18
|
+
import { parseAndVisit, Kind, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from '@luvio/graphql-parser';
|
|
19
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';
|
|
20
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
21
21
|
import { idleDetector, getInstrumentation } from 'o11y/client';
|
|
@@ -7077,7 +7077,7 @@ function isArrayLike(x) {
|
|
|
7077
7077
|
|
|
7078
7078
|
const { create: create$4, keys: keys$4, values: values$2, entries: entries$3, assign: assign$4 } = Object;
|
|
7079
7079
|
const { stringify: stringify$4, parse: parse$4 } = JSON;
|
|
7080
|
-
const { isArray: isArray$2 } = Array;
|
|
7080
|
+
const { isArray: isArray$2, from: from$1 } = Array;
|
|
7081
7081
|
|
|
7082
7082
|
function recordLoaderFactory(query) {
|
|
7083
7083
|
async function batchRecordQuery(ids) {
|
|
@@ -9308,25 +9308,6 @@ const additionalSchemaDefinitions = /* GraphQL */ `
|
|
|
9308
9308
|
}
|
|
9309
9309
|
`;
|
|
9310
9310
|
const baseTypeDefinitions = uiapiSchemaString + additionalSchemaDefinitions;
|
|
9311
|
-
/**
|
|
9312
|
-
*
|
|
9313
|
-
* @param objectInfos
|
|
9314
|
-
* @returns Type definition string and entity type names which support polymorphism.
|
|
9315
|
-
*/
|
|
9316
|
-
function generateTypeDefinitions(objectInfos) {
|
|
9317
|
-
if (keys$4(objectInfos).length === 0)
|
|
9318
|
-
return { typeDefs: baseTypeDefinitions, polyFieldTypeNames: [] };
|
|
9319
|
-
const { recordQueries, recordConnections, polyFieldTypeNameArr } = generateRecordQueries(objectInfos);
|
|
9320
|
-
const typeDefs = `
|
|
9321
|
-
${baseTypeDefinitions}
|
|
9322
|
-
|
|
9323
|
-
extend type RecordQuery {
|
|
9324
|
-
${recordQueries}
|
|
9325
|
-
}
|
|
9326
|
-
${recordConnections}
|
|
9327
|
-
`;
|
|
9328
|
-
return { typeDefs, polyFieldTypeNames: polyFieldTypeNameArr };
|
|
9329
|
-
}
|
|
9330
9311
|
const fieldsStaticallyAdded = [
|
|
9331
9312
|
'ApiName',
|
|
9332
9313
|
'DisplayValue',
|
|
@@ -9336,99 +9317,340 @@ const fieldsStaticallyAdded = [
|
|
|
9336
9317
|
'SystemModstamp',
|
|
9337
9318
|
'WeakEtag',
|
|
9338
9319
|
];
|
|
9339
|
-
|
|
9320
|
+
class CachedGraphQLSchema {
|
|
9321
|
+
constructor() {
|
|
9322
|
+
this._schema = buildBaseSchema();
|
|
9323
|
+
this._polymorphicFieldTypeNames = [];
|
|
9324
|
+
}
|
|
9325
|
+
getSchema() {
|
|
9326
|
+
return this._schema;
|
|
9327
|
+
}
|
|
9328
|
+
setSchema(value) {
|
|
9329
|
+
this._schema = value;
|
|
9330
|
+
}
|
|
9331
|
+
getPolymorphicFieldTypeNames() {
|
|
9332
|
+
return this._polymorphicFieldTypeNames;
|
|
9333
|
+
}
|
|
9334
|
+
setPolymorphicFieldTypeNames(value) {
|
|
9335
|
+
this._polymorphicFieldTypeNames = value;
|
|
9336
|
+
}
|
|
9337
|
+
set(schema, polymorphicFieldTypeNames) {
|
|
9338
|
+
this._schema = schema;
|
|
9339
|
+
this._polymorphicFieldTypeNames = polymorphicFieldTypeNames;
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9342
|
+
/**
|
|
9343
|
+
* Looks at the injected object info map and checks to see if the existing objects
|
|
9344
|
+
* are within the current schema. It will extend the cached schema if it is not included.
|
|
9345
|
+
* @param objectInfos
|
|
9346
|
+
* @param cache
|
|
9347
|
+
* @returns GraphQLSchema
|
|
9348
|
+
*/
|
|
9349
|
+
function createSchemaWithCache(objectInfos, cache) {
|
|
9350
|
+
const updatedCache = extendSchemaWithObjectInfos(cache, objectInfos);
|
|
9351
|
+
// set the new values to the passed cached schema & polymorphic field names
|
|
9352
|
+
cache.set(updatedCache.getSchema(), updatedCache.getPolymorphicFieldTypeNames());
|
|
9353
|
+
return cache.getSchema();
|
|
9354
|
+
}
|
|
9355
|
+
/**
|
|
9356
|
+
* Extends the current GraphQL Schema with new types based on the given object info map
|
|
9357
|
+
*
|
|
9358
|
+
* @param cache the existing cached schema object
|
|
9359
|
+
* @param objectInfoMap map of object info and apiname for key
|
|
9360
|
+
* @returns CachedGraphQLSchema
|
|
9361
|
+
*/
|
|
9362
|
+
function extendSchemaWithObjectInfos(cache, objectInfoMap) {
|
|
9363
|
+
const { recordQueries, recordConnections, recordExtensions, polyFieldTypeNameArr } = generateRecordQueries(cache.getSchema(), objectInfoMap);
|
|
9364
|
+
const typeDefs = `
|
|
9365
|
+
${recordQueries}
|
|
9366
|
+
${recordConnections}
|
|
9367
|
+
${recordExtensions}
|
|
9368
|
+
`;
|
|
9369
|
+
// if nothing new is added then return the current cache
|
|
9370
|
+
if (typeDefs.trim().length === 0) {
|
|
9371
|
+
return cache;
|
|
9372
|
+
}
|
|
9373
|
+
// parse extensions into DocumentNode to extend the schema
|
|
9374
|
+
const extensions = parse$7(typeDefs);
|
|
9375
|
+
const polymorphicFieldTypeNames = [
|
|
9376
|
+
...polyFieldTypeNameArr,
|
|
9377
|
+
...cache.getPolymorphicFieldTypeNames(),
|
|
9378
|
+
];
|
|
9379
|
+
// extend the schema and add resolvers
|
|
9380
|
+
const schema = addResolversToSchema(extendSchema(cache.getSchema(), extensions), polymorphicFieldTypeNames);
|
|
9381
|
+
cache.setSchema(schema);
|
|
9382
|
+
return cache;
|
|
9383
|
+
}
|
|
9384
|
+
/**
|
|
9385
|
+
* Builds the base schema from uiapi graphql adapter with resolvers attached
|
|
9386
|
+
* @returns GraphQLSchema
|
|
9387
|
+
*/
|
|
9388
|
+
function buildBaseSchema() {
|
|
9389
|
+
return addResolversToSchema(buildSchema(baseTypeDefinitions), []);
|
|
9390
|
+
}
|
|
9391
|
+
/**
|
|
9392
|
+
* Given the existing schema and the object infos it will create a new type for the schema
|
|
9393
|
+
* or extend an existing type to add new fields to it.
|
|
9394
|
+
*
|
|
9395
|
+
* Extends RecordQuery to add new top level queries
|
|
9396
|
+
* extend type RecordQuery {
|
|
9397
|
+
* Account(predicates): AccountConnection
|
|
9398
|
+
* }
|
|
9399
|
+
* @param schema
|
|
9400
|
+
* @param objectInfoMap
|
|
9401
|
+
* @returns
|
|
9402
|
+
*/
|
|
9403
|
+
function generateRecordQueries(schema, objectInfoMap) {
|
|
9340
9404
|
let recordQueries = ``;
|
|
9341
9405
|
let recordConnections = ``;
|
|
9342
|
-
|
|
9406
|
+
let recordExtensions = ``;
|
|
9407
|
+
// use a set to not allow duplicate scalars causing error(s)
|
|
9408
|
+
let addedTypedScalars = new Set();
|
|
9409
|
+
let allPolymorphicFieldTypeNames = new Set();
|
|
9410
|
+
for (const name of keys$4(objectInfoMap)) {
|
|
9411
|
+
const objectInfo = objectInfoMap[name];
|
|
9412
|
+
const { apiName } = objectInfo;
|
|
9413
|
+
const type = schema.getType(apiName);
|
|
9414
|
+
// if type is an ObjectType it exists in the schema
|
|
9415
|
+
if (isObjectType(type)) {
|
|
9416
|
+
const { recordExtension, typedScalars, polymorphicFieldTypeNames } = extendExistingRecordType(schema, type, objectInfo, objectInfoMap);
|
|
9417
|
+
recordExtensions += recordExtension;
|
|
9418
|
+
addedTypedScalars = new Set([...addedTypedScalars, ...typedScalars]);
|
|
9419
|
+
allPolymorphicFieldTypeNames = new Set([
|
|
9420
|
+
...allPolymorphicFieldTypeNames,
|
|
9421
|
+
...polymorphicFieldTypeNames,
|
|
9422
|
+
]);
|
|
9423
|
+
}
|
|
9424
|
+
else {
|
|
9425
|
+
const { recordQueries: newRecordQueries, recordConnections: newRecordConnections, typedScalars, polymorphicFieldTypeNames, } = createNewRecordQuery(schema, objectInfo, objectInfoMap);
|
|
9426
|
+
recordQueries += newRecordQueries;
|
|
9427
|
+
recordConnections += newRecordConnections;
|
|
9428
|
+
addedTypedScalars = new Set([...addedTypedScalars, ...typedScalars]);
|
|
9429
|
+
allPolymorphicFieldTypeNames = new Set([
|
|
9430
|
+
...allPolymorphicFieldTypeNames,
|
|
9431
|
+
...polymorphicFieldTypeNames,
|
|
9432
|
+
]);
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
// transform added scalar types into a list of scalars in string
|
|
9436
|
+
const scalars = [...addedTypedScalars].map((scalar) => `scalar ${scalar}`).join('\n');
|
|
9437
|
+
recordConnections += scalars;
|
|
9438
|
+
// return empty string if no recordQueries were extended
|
|
9439
|
+
const extensionWrapper = recordQueries.length > 0
|
|
9440
|
+
? `
|
|
9441
|
+
extend type RecordQuery {
|
|
9442
|
+
${recordQueries}
|
|
9443
|
+
}`
|
|
9444
|
+
: '';
|
|
9445
|
+
return {
|
|
9446
|
+
recordQueries: extensionWrapper,
|
|
9447
|
+
recordConnections,
|
|
9448
|
+
recordExtensions,
|
|
9449
|
+
polyFieldTypeNameArr: from$1(allPolymorphicFieldTypeNames),
|
|
9450
|
+
};
|
|
9451
|
+
}
|
|
9452
|
+
/**
|
|
9453
|
+
* Will create a new record query extension for something that does not already exist in the schema
|
|
9454
|
+
*
|
|
9455
|
+
* generates:
|
|
9456
|
+
*
|
|
9457
|
+
* type {typename} implements Record {
|
|
9458
|
+
* ...scalar fields
|
|
9459
|
+
* Id: IDValue
|
|
9460
|
+
* ...spanning parent records
|
|
9461
|
+
* User: Parent
|
|
9462
|
+
* ...spanning children queries
|
|
9463
|
+
* Accounts(predicates): AccountConnection
|
|
9464
|
+
* }
|
|
9465
|
+
*
|
|
9466
|
+
* scalars SomeAddedScalar
|
|
9467
|
+
*
|
|
9468
|
+
* @param schema
|
|
9469
|
+
* @param objectInfo
|
|
9470
|
+
* @param objectInfoMap
|
|
9471
|
+
* @returns
|
|
9472
|
+
*/
|
|
9473
|
+
function createNewRecordQuery(schema, objectInfo, objectInfoMap) {
|
|
9343
9474
|
let typedScalars = new Set();
|
|
9344
9475
|
let parentRelationshipFields = new Set();
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9476
|
+
const { apiName, childRelationships, fields: fieldsRepresentation } = objectInfo;
|
|
9477
|
+
typedScalars.add(`${apiName}_Filter`);
|
|
9478
|
+
typedScalars.add(`${apiName}_OrderBy`);
|
|
9479
|
+
const { fields, polymorphicFieldTypeNames } = makeRecordField(values$2(fieldsRepresentation), objectInfoMap, parentRelationshipFields, 'Missing');
|
|
9480
|
+
// handles child relationship
|
|
9481
|
+
const { spanningRecordConnections, typedScalars: spanningConnectionTypedScalars } = makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, parentRelationshipFields);
|
|
9482
|
+
typedScalars = new Set([...typedScalars, ...spanningConnectionTypedScalars]);
|
|
9483
|
+
const recordQueries = `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
|
|
9484
|
+
const isServiceAppointment = apiName === 'ServiceAppointment';
|
|
9485
|
+
const recordConnections = /* GraphQL */ `
|
|
9486
|
+
${isServiceAppointment ? `scalar ${apiName.toUpperCase()}_SCOPE` : ''}
|
|
9487
|
+
|
|
9488
|
+
type ${apiName} implements Record {
|
|
9489
|
+
ApiName: String!
|
|
9490
|
+
DisplayValue: String
|
|
9491
|
+
LastModifiedById: IDValue
|
|
9492
|
+
LastModifiedDate: DateTimeValue
|
|
9493
|
+
RecordTypeId(fallback: Boolean): IDValue
|
|
9494
|
+
SystemModstamp: DateTimeValue
|
|
9495
|
+
WeakEtag: Long!
|
|
9496
|
+
_drafts: JSON
|
|
9497
|
+
${fields}
|
|
9498
|
+
${spanningRecordConnections}
|
|
9357
9499
|
}
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
// the query.
|
|
9364
|
-
if (objectInfos[relation.apiName] !== undefined) {
|
|
9365
|
-
parentRelationshipFields.add(field.relationshipName);
|
|
9366
|
-
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
9367
|
-
}
|
|
9368
|
-
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
9369
|
-
}
|
|
9370
|
-
else if (field.referenceToInfos.length > 1) {
|
|
9371
|
-
parentRelationshipFields.add(field.relationshipName);
|
|
9372
|
-
fields += `${field.relationshipName}: Record\n`;
|
|
9373
|
-
for (const relation of field.referenceToInfos) {
|
|
9374
|
-
if (objectInfos[relation.apiName] !== undefined) {
|
|
9375
|
-
polymorphicFieldTypeNames.add(relation.apiName);
|
|
9376
|
-
}
|
|
9377
|
-
}
|
|
9500
|
+
|
|
9501
|
+
type ${apiName}Connection {
|
|
9502
|
+
edges: [${apiName}Edge]
|
|
9503
|
+
pageInfo: PageInfo!
|
|
9504
|
+
totalCount: Int!
|
|
9378
9505
|
}
|
|
9506
|
+
|
|
9507
|
+
type ${apiName}Edge {
|
|
9508
|
+
node: ${apiName}
|
|
9509
|
+
cursor: String!
|
|
9510
|
+
}
|
|
9511
|
+
|
|
9512
|
+
`;
|
|
9513
|
+
return { recordQueries, recordConnections, typedScalars, polymorphicFieldTypeNames };
|
|
9514
|
+
}
|
|
9515
|
+
/**
|
|
9516
|
+
* Takes the current schema and will extend missing fields to the record.
|
|
9517
|
+
* Assume all scalar fields have already been added, but will extend spanning fields
|
|
9518
|
+
*
|
|
9519
|
+
* extend type Account {
|
|
9520
|
+
* ...spanning parent records
|
|
9521
|
+
* User: User
|
|
9522
|
+
* ...spanning children queries
|
|
9523
|
+
* Users(predicates): UserConnection
|
|
9524
|
+
* }
|
|
9525
|
+
*
|
|
9526
|
+
* @param schema
|
|
9527
|
+
* @param type
|
|
9528
|
+
* @param objectInfo
|
|
9529
|
+
* @param objectInfoMap
|
|
9530
|
+
* @returns
|
|
9531
|
+
*/
|
|
9532
|
+
function extendExistingRecordType(schema, type, objectInfo, objectInfoMap) {
|
|
9533
|
+
// use a set to not allow duplicate scalars causing error(s)
|
|
9534
|
+
let typedScalars = new Set();
|
|
9535
|
+
let parentRelationshipFields = new Set();
|
|
9536
|
+
const existingFields = keys$4(type.getFields());
|
|
9537
|
+
const missingFields = values$2(objectInfo.fields).filter((field) => existingFields.includes(field.apiName) === false);
|
|
9538
|
+
const { fields, polymorphicFieldTypeNames } = makeRecordField(missingFields, objectInfoMap, parentRelationshipFields, 'Cached');
|
|
9539
|
+
const { apiName, childRelationships } = objectInfo;
|
|
9540
|
+
// handles child relationship
|
|
9541
|
+
const { spanningRecordConnections, typedScalars: spanningConnectionTypedScalars } = makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, parentRelationshipFields, existingFields);
|
|
9542
|
+
typedScalars = new Set([...typedScalars, ...spanningConnectionTypedScalars]);
|
|
9543
|
+
const hasExtensions = fields.length > 0 || spanningRecordConnections.length > 0;
|
|
9544
|
+
const recordExtension = hasExtensions
|
|
9545
|
+
? `
|
|
9546
|
+
extend type ${apiName} {
|
|
9547
|
+
${fields}
|
|
9548
|
+
${spanningRecordConnections}
|
|
9549
|
+
}\n`
|
|
9550
|
+
: '';
|
|
9551
|
+
return { recordExtension, typedScalars, polymorphicFieldTypeNames };
|
|
9552
|
+
}
|
|
9553
|
+
/**
|
|
9554
|
+
* Converts child relationships into spanning record connections to be added to record types
|
|
9555
|
+
*
|
|
9556
|
+
* type Record {
|
|
9557
|
+
* Generates -> AccountConnection(first: Int, where: Account_Filter, etc...): AccountConnection
|
|
9558
|
+
* }
|
|
9559
|
+
*
|
|
9560
|
+
* will also generate typed scalars if they have not been added to the existing schema for the spanning connection
|
|
9561
|
+
* example: Account_Filter or Account_OrderBy scalars needed to be defined as predicate types
|
|
9562
|
+
* @param schema
|
|
9563
|
+
* @param childRelationships
|
|
9564
|
+
* @param objectInfoMap
|
|
9565
|
+
* @param existingParentRelationships
|
|
9566
|
+
* @param existingFields
|
|
9567
|
+
* @returns
|
|
9568
|
+
*/
|
|
9569
|
+
function makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, existingParentRelationships, existingFields = []) {
|
|
9570
|
+
let spanningRecordConnections = ``;
|
|
9571
|
+
let typedScalars = new Set();
|
|
9572
|
+
for (const childRelationship of childRelationships) {
|
|
9573
|
+
const { childObjectApiName, relationshipName } = childRelationship;
|
|
9574
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
9575
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9576
|
+
// the query.
|
|
9577
|
+
// If one field has both parent relationship and child relationship with the same name, the child relationship is ignored. This is how the server GQL has implemented as date of 08/07/2023
|
|
9578
|
+
if (existingFields.length > 0 && existingFields.includes(relationshipName)) {
|
|
9579
|
+
continue;
|
|
9379
9580
|
}
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
//
|
|
9384
|
-
//
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
if (objectInfos[childObjectApiName] !== undefined &&
|
|
9388
|
-
!parentRelationshipFields.has(childRelationship.relationshipName)) {
|
|
9389
|
-
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9581
|
+
if (objectInfoMap[childObjectApiName] !== undefined &&
|
|
9582
|
+
!existingParentRelationships.has(relationshipName)) {
|
|
9583
|
+
spanningRecordConnections += `${relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9584
|
+
// if the record type has already been extended then these additional scalars have already been added
|
|
9585
|
+
// to add them again would throw an error
|
|
9586
|
+
const filterScalarType = schema.getType(`${childObjectApiName}_Filter`);
|
|
9587
|
+
if (isScalarType(filterScalarType) === false) {
|
|
9390
9588
|
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
9589
|
+
}
|
|
9590
|
+
const orderByScalarType = schema.getType(`${childObjectApiName}_OrderBy`);
|
|
9591
|
+
if (isScalarType(orderByScalarType) === false) {
|
|
9391
9592
|
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
9392
9593
|
}
|
|
9393
9594
|
}
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9595
|
+
}
|
|
9596
|
+
return { spanningRecordConnections, typedScalars };
|
|
9597
|
+
}
|
|
9598
|
+
/**
|
|
9599
|
+
* Creates scalar and parent relationship fields for a record type
|
|
9600
|
+
*
|
|
9601
|
+
* type RecordName {
|
|
9602
|
+
* generates scalar -> Id: IDValue
|
|
9603
|
+
* generates relationship -> Account: Record
|
|
9604
|
+
* }
|
|
9605
|
+
*
|
|
9606
|
+
* can be used in a type definition or an extension
|
|
9607
|
+
* @param fieldRepresentations
|
|
9608
|
+
* @param objectInfoMap
|
|
9609
|
+
* @param existingParentRelationships
|
|
9610
|
+
* @param recordTypeInSchema
|
|
9611
|
+
* @returns
|
|
9612
|
+
*/
|
|
9613
|
+
function makeRecordField(fieldRepresentations, objectInfoMap, existingParentRelationships, recordTypeInSchema) {
|
|
9614
|
+
const polymorphicFieldTypeNames = new Set();
|
|
9615
|
+
let fields = ``;
|
|
9616
|
+
for (const field of values$2(fieldRepresentations)) {
|
|
9617
|
+
if (!fieldsStaticallyAdded.includes(field.apiName) && recordTypeInSchema === 'Missing') {
|
|
9618
|
+
fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
|
|
9619
|
+
}
|
|
9620
|
+
//handles parent relationship
|
|
9621
|
+
if (field.relationshipName === null) {
|
|
9622
|
+
continue;
|
|
9623
|
+
}
|
|
9624
|
+
// For spanning parent relationships with no union types
|
|
9625
|
+
if (field.referenceToInfos.length === 1) {
|
|
9626
|
+
const [relation] = field.referenceToInfos;
|
|
9627
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
9628
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9629
|
+
// the query.
|
|
9630
|
+
if (objectInfoMap[relation.apiName] !== undefined) {
|
|
9631
|
+
existingParentRelationships.add(field.relationshipName);
|
|
9632
|
+
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
9633
|
+
}
|
|
9634
|
+
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
9635
|
+
}
|
|
9636
|
+
else if (field.referenceToInfos.length > 1) {
|
|
9637
|
+
existingParentRelationships.add(field.relationshipName);
|
|
9638
|
+
fields += `${field.relationshipName}: Record\n`;
|
|
9639
|
+
for (const relation of field.referenceToInfos) {
|
|
9640
|
+
if (objectInfoMap[relation.apiName] !== undefined) {
|
|
9641
|
+
polymorphicFieldTypeNames.add(relation.apiName);
|
|
9642
|
+
}
|
|
9643
|
+
}
|
|
9420
9644
|
}
|
|
9421
|
-
|
|
9422
|
-
`;
|
|
9423
9645
|
}
|
|
9424
|
-
|
|
9425
|
-
return accu + `scalar ${typed}\n`;
|
|
9426
|
-
}, ``);
|
|
9427
|
-
recordConnections += scalars;
|
|
9428
|
-
const polyFieldTypeNameArr = [];
|
|
9429
|
-
polymorphicFieldTypeNames.forEach((fieldType) => polyFieldTypeNameArr.push(fieldType));
|
|
9430
|
-
return { recordQueries, recordConnections, polyFieldTypeNameArr };
|
|
9646
|
+
return { fields, polymorphicFieldTypeNames };
|
|
9431
9647
|
}
|
|
9648
|
+
/**
|
|
9649
|
+
* converts the ObjectInfoRepresentation data type into a defined schema scalar type
|
|
9650
|
+
* @param objectInfoDataType
|
|
9651
|
+
* @param apiName
|
|
9652
|
+
* @returns
|
|
9653
|
+
*/
|
|
9432
9654
|
function dataTypeToType(objectInfoDataType, apiName) {
|
|
9433
9655
|
if (apiName && apiName === 'Id') {
|
|
9434
9656
|
return `ID!`;
|
|
@@ -9470,13 +9692,8 @@ function dataTypeToType(objectInfoDataType, apiName) {
|
|
|
9470
9692
|
return 'String';
|
|
9471
9693
|
}
|
|
9472
9694
|
}
|
|
9473
|
-
function createSchema(objectInfos) {
|
|
9474
|
-
const { typeDefs: typeDefinitions, polyFieldTypeNames } = generateTypeDefinitions(objectInfos);
|
|
9475
|
-
const schema = buildSchema(typeDefinitions);
|
|
9476
|
-
return addResolversToSchema(schema, polyFieldTypeNames);
|
|
9477
|
-
}
|
|
9478
9695
|
|
|
9479
|
-
async function evaluate(config, observers, settings, objectInfos, store, snapshot, draftFunctions) {
|
|
9696
|
+
async function evaluate(config, observers, settings, objectInfos, store, snapshot, cache, draftFunctions) {
|
|
9480
9697
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE, observers);
|
|
9481
9698
|
// this is only wrapped in a try to execute the event after the result was returned
|
|
9482
9699
|
try {
|
|
@@ -9517,7 +9734,7 @@ async function evaluate(config, observers, settings, objectInfos, store, snapsho
|
|
|
9517
9734
|
const contextValue = createContext(store, objectInfos, eventEmitter, settings, snapshot, draftFunctions);
|
|
9518
9735
|
// We're building this from scratch from each request. If this becomes a
|
|
9519
9736
|
// hotspot we can pull it up and memoize it later
|
|
9520
|
-
const schema =
|
|
9737
|
+
const schema = createSchemaWithCache(objectInfos, cache);
|
|
9521
9738
|
eventEmitter({ type: 'graphql-schema-created' });
|
|
9522
9739
|
// execute document against schema/context
|
|
9523
9740
|
let result = (await execute({
|
|
@@ -13012,6 +13229,8 @@ const replaceDraftIdsInVariables = (variables, draftFunctions, unmappedDraftIDs)
|
|
|
13012
13229
|
}, {});
|
|
13013
13230
|
return newVariables;
|
|
13014
13231
|
};
|
|
13232
|
+
// create the runtime cache for the graphql schema when the factory creates the adapter
|
|
13233
|
+
const graphqlSchemaCache = new CachedGraphQLSchema();
|
|
13015
13234
|
function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio, isDraftId) {
|
|
13016
13235
|
const getCanonicalId = (id) => {
|
|
13017
13236
|
var _a;
|
|
@@ -13085,7 +13304,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13085
13304
|
...config,
|
|
13086
13305
|
//need to create another copy of the ast for future writes
|
|
13087
13306
|
query: parse$3(stringify$3(injectedAST)),
|
|
13088
|
-
}, observers, { userId }, objectInfoNeeded, store, nonEvaluatedSnapshot));
|
|
13307
|
+
}, observers, { userId }, objectInfoNeeded, store, nonEvaluatedSnapshot, graphqlSchemaCache));
|
|
13089
13308
|
}
|
|
13090
13309
|
catch (throwable) {
|
|
13091
13310
|
const error = throwable;
|
|
@@ -13114,7 +13333,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13114
13333
|
let { result: rebuildResult, seenRecordIds } = await evaluate({
|
|
13115
13334
|
...config,
|
|
13116
13335
|
query: injectedAST,
|
|
13117
|
-
}, observers, { userId }, objectInfoNeeded, store, originalSnapshot, draftFunctions);
|
|
13336
|
+
}, observers, { userId }, objectInfoNeeded, store, originalSnapshot, graphqlSchemaCache, draftFunctions);
|
|
13118
13337
|
if (!rebuildResult.errors) {
|
|
13119
13338
|
rebuildResult = removeSyntheticFields(rebuildResult, config.query);
|
|
13120
13339
|
}
|
|
@@ -17288,4 +17507,4 @@ register({
|
|
|
17288
17507
|
});
|
|
17289
17508
|
|
|
17290
17509
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17291
|
-
// version: 1.
|
|
17510
|
+
// version: 1.248.0-1f7f01112
|
package/package.json
CHANGED
package/sfdc/main.js
CHANGED
|
@@ -15,7 +15,7 @@ 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, StringKeyInMemoryStore, Reader, deepFreeze, emitAdapterEvent, createCustomAdapterEventEmitter, StoreKeyMap, isFileReference, Environment, Luvio, InMemoryStore } from 'force/luvioEngine';
|
|
17
17
|
import excludeStaleRecordsGate from '@salesforce/gate/lds.graphqlEvalExcludeStaleRecords';
|
|
18
|
-
import { parseAndVisit, Kind, visit, execute,
|
|
18
|
+
import { parseAndVisit, Kind, buildSchema, isObjectType, defaultFieldResolver, visit, execute, parse as parse$7, extendSchema, isScalarType } from 'force/ldsGraphqlParser';
|
|
19
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';
|
|
20
20
|
import caseSensitiveUserId from '@salesforce/user/Id';
|
|
21
21
|
import { idleDetector, getInstrumentation } from 'o11y/client';
|
|
@@ -7077,7 +7077,7 @@ function isArrayLike(x) {
|
|
|
7077
7077
|
|
|
7078
7078
|
const { create: create$4, keys: keys$4, values: values$2, entries: entries$3, assign: assign$4 } = Object;
|
|
7079
7079
|
const { stringify: stringify$4, parse: parse$4 } = JSON;
|
|
7080
|
-
const { isArray: isArray$2 } = Array;
|
|
7080
|
+
const { isArray: isArray$2, from: from$1 } = Array;
|
|
7081
7081
|
|
|
7082
7082
|
function recordLoaderFactory(query) {
|
|
7083
7083
|
async function batchRecordQuery(ids) {
|
|
@@ -9308,25 +9308,6 @@ const additionalSchemaDefinitions = /* GraphQL */ `
|
|
|
9308
9308
|
}
|
|
9309
9309
|
`;
|
|
9310
9310
|
const baseTypeDefinitions = uiapiSchemaString + additionalSchemaDefinitions;
|
|
9311
|
-
/**
|
|
9312
|
-
*
|
|
9313
|
-
* @param objectInfos
|
|
9314
|
-
* @returns Type definition string and entity type names which support polymorphism.
|
|
9315
|
-
*/
|
|
9316
|
-
function generateTypeDefinitions(objectInfos) {
|
|
9317
|
-
if (keys$4(objectInfos).length === 0)
|
|
9318
|
-
return { typeDefs: baseTypeDefinitions, polyFieldTypeNames: [] };
|
|
9319
|
-
const { recordQueries, recordConnections, polyFieldTypeNameArr } = generateRecordQueries(objectInfos);
|
|
9320
|
-
const typeDefs = `
|
|
9321
|
-
${baseTypeDefinitions}
|
|
9322
|
-
|
|
9323
|
-
extend type RecordQuery {
|
|
9324
|
-
${recordQueries}
|
|
9325
|
-
}
|
|
9326
|
-
${recordConnections}
|
|
9327
|
-
`;
|
|
9328
|
-
return { typeDefs, polyFieldTypeNames: polyFieldTypeNameArr };
|
|
9329
|
-
}
|
|
9330
9311
|
const fieldsStaticallyAdded = [
|
|
9331
9312
|
'ApiName',
|
|
9332
9313
|
'DisplayValue',
|
|
@@ -9336,99 +9317,340 @@ const fieldsStaticallyAdded = [
|
|
|
9336
9317
|
'SystemModstamp',
|
|
9337
9318
|
'WeakEtag',
|
|
9338
9319
|
];
|
|
9339
|
-
|
|
9320
|
+
class CachedGraphQLSchema {
|
|
9321
|
+
constructor() {
|
|
9322
|
+
this._schema = buildBaseSchema();
|
|
9323
|
+
this._polymorphicFieldTypeNames = [];
|
|
9324
|
+
}
|
|
9325
|
+
getSchema() {
|
|
9326
|
+
return this._schema;
|
|
9327
|
+
}
|
|
9328
|
+
setSchema(value) {
|
|
9329
|
+
this._schema = value;
|
|
9330
|
+
}
|
|
9331
|
+
getPolymorphicFieldTypeNames() {
|
|
9332
|
+
return this._polymorphicFieldTypeNames;
|
|
9333
|
+
}
|
|
9334
|
+
setPolymorphicFieldTypeNames(value) {
|
|
9335
|
+
this._polymorphicFieldTypeNames = value;
|
|
9336
|
+
}
|
|
9337
|
+
set(schema, polymorphicFieldTypeNames) {
|
|
9338
|
+
this._schema = schema;
|
|
9339
|
+
this._polymorphicFieldTypeNames = polymorphicFieldTypeNames;
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9342
|
+
/**
|
|
9343
|
+
* Looks at the injected object info map and checks to see if the existing objects
|
|
9344
|
+
* are within the current schema. It will extend the cached schema if it is not included.
|
|
9345
|
+
* @param objectInfos
|
|
9346
|
+
* @param cache
|
|
9347
|
+
* @returns GraphQLSchema
|
|
9348
|
+
*/
|
|
9349
|
+
function createSchemaWithCache(objectInfos, cache) {
|
|
9350
|
+
const updatedCache = extendSchemaWithObjectInfos(cache, objectInfos);
|
|
9351
|
+
// set the new values to the passed cached schema & polymorphic field names
|
|
9352
|
+
cache.set(updatedCache.getSchema(), updatedCache.getPolymorphicFieldTypeNames());
|
|
9353
|
+
return cache.getSchema();
|
|
9354
|
+
}
|
|
9355
|
+
/**
|
|
9356
|
+
* Extends the current GraphQL Schema with new types based on the given object info map
|
|
9357
|
+
*
|
|
9358
|
+
* @param cache the existing cached schema object
|
|
9359
|
+
* @param objectInfoMap map of object info and apiname for key
|
|
9360
|
+
* @returns CachedGraphQLSchema
|
|
9361
|
+
*/
|
|
9362
|
+
function extendSchemaWithObjectInfos(cache, objectInfoMap) {
|
|
9363
|
+
const { recordQueries, recordConnections, recordExtensions, polyFieldTypeNameArr } = generateRecordQueries(cache.getSchema(), objectInfoMap);
|
|
9364
|
+
const typeDefs = `
|
|
9365
|
+
${recordQueries}
|
|
9366
|
+
${recordConnections}
|
|
9367
|
+
${recordExtensions}
|
|
9368
|
+
`;
|
|
9369
|
+
// if nothing new is added then return the current cache
|
|
9370
|
+
if (typeDefs.trim().length === 0) {
|
|
9371
|
+
return cache;
|
|
9372
|
+
}
|
|
9373
|
+
// parse extensions into DocumentNode to extend the schema
|
|
9374
|
+
const extensions = parse$7(typeDefs);
|
|
9375
|
+
const polymorphicFieldTypeNames = [
|
|
9376
|
+
...polyFieldTypeNameArr,
|
|
9377
|
+
...cache.getPolymorphicFieldTypeNames(),
|
|
9378
|
+
];
|
|
9379
|
+
// extend the schema and add resolvers
|
|
9380
|
+
const schema = addResolversToSchema(extendSchema(cache.getSchema(), extensions), polymorphicFieldTypeNames);
|
|
9381
|
+
cache.setSchema(schema);
|
|
9382
|
+
return cache;
|
|
9383
|
+
}
|
|
9384
|
+
/**
|
|
9385
|
+
* Builds the base schema from uiapi graphql adapter with resolvers attached
|
|
9386
|
+
* @returns GraphQLSchema
|
|
9387
|
+
*/
|
|
9388
|
+
function buildBaseSchema() {
|
|
9389
|
+
return addResolversToSchema(buildSchema(baseTypeDefinitions), []);
|
|
9390
|
+
}
|
|
9391
|
+
/**
|
|
9392
|
+
* Given the existing schema and the object infos it will create a new type for the schema
|
|
9393
|
+
* or extend an existing type to add new fields to it.
|
|
9394
|
+
*
|
|
9395
|
+
* Extends RecordQuery to add new top level queries
|
|
9396
|
+
* extend type RecordQuery {
|
|
9397
|
+
* Account(predicates): AccountConnection
|
|
9398
|
+
* }
|
|
9399
|
+
* @param schema
|
|
9400
|
+
* @param objectInfoMap
|
|
9401
|
+
* @returns
|
|
9402
|
+
*/
|
|
9403
|
+
function generateRecordQueries(schema, objectInfoMap) {
|
|
9340
9404
|
let recordQueries = ``;
|
|
9341
9405
|
let recordConnections = ``;
|
|
9342
|
-
|
|
9406
|
+
let recordExtensions = ``;
|
|
9407
|
+
// use a set to not allow duplicate scalars causing error(s)
|
|
9408
|
+
let addedTypedScalars = new Set();
|
|
9409
|
+
let allPolymorphicFieldTypeNames = new Set();
|
|
9410
|
+
for (const name of keys$4(objectInfoMap)) {
|
|
9411
|
+
const objectInfo = objectInfoMap[name];
|
|
9412
|
+
const { apiName } = objectInfo;
|
|
9413
|
+
const type = schema.getType(apiName);
|
|
9414
|
+
// if type is an ObjectType it exists in the schema
|
|
9415
|
+
if (isObjectType(type)) {
|
|
9416
|
+
const { recordExtension, typedScalars, polymorphicFieldTypeNames } = extendExistingRecordType(schema, type, objectInfo, objectInfoMap);
|
|
9417
|
+
recordExtensions += recordExtension;
|
|
9418
|
+
addedTypedScalars = new Set([...addedTypedScalars, ...typedScalars]);
|
|
9419
|
+
allPolymorphicFieldTypeNames = new Set([
|
|
9420
|
+
...allPolymorphicFieldTypeNames,
|
|
9421
|
+
...polymorphicFieldTypeNames,
|
|
9422
|
+
]);
|
|
9423
|
+
}
|
|
9424
|
+
else {
|
|
9425
|
+
const { recordQueries: newRecordQueries, recordConnections: newRecordConnections, typedScalars, polymorphicFieldTypeNames, } = createNewRecordQuery(schema, objectInfo, objectInfoMap);
|
|
9426
|
+
recordQueries += newRecordQueries;
|
|
9427
|
+
recordConnections += newRecordConnections;
|
|
9428
|
+
addedTypedScalars = new Set([...addedTypedScalars, ...typedScalars]);
|
|
9429
|
+
allPolymorphicFieldTypeNames = new Set([
|
|
9430
|
+
...allPolymorphicFieldTypeNames,
|
|
9431
|
+
...polymorphicFieldTypeNames,
|
|
9432
|
+
]);
|
|
9433
|
+
}
|
|
9434
|
+
}
|
|
9435
|
+
// transform added scalar types into a list of scalars in string
|
|
9436
|
+
const scalars = [...addedTypedScalars].map((scalar) => `scalar ${scalar}`).join('\n');
|
|
9437
|
+
recordConnections += scalars;
|
|
9438
|
+
// return empty string if no recordQueries were extended
|
|
9439
|
+
const extensionWrapper = recordQueries.length > 0
|
|
9440
|
+
? `
|
|
9441
|
+
extend type RecordQuery {
|
|
9442
|
+
${recordQueries}
|
|
9443
|
+
}`
|
|
9444
|
+
: '';
|
|
9445
|
+
return {
|
|
9446
|
+
recordQueries: extensionWrapper,
|
|
9447
|
+
recordConnections,
|
|
9448
|
+
recordExtensions,
|
|
9449
|
+
polyFieldTypeNameArr: from$1(allPolymorphicFieldTypeNames),
|
|
9450
|
+
};
|
|
9451
|
+
}
|
|
9452
|
+
/**
|
|
9453
|
+
* Will create a new record query extension for something that does not already exist in the schema
|
|
9454
|
+
*
|
|
9455
|
+
* generates:
|
|
9456
|
+
*
|
|
9457
|
+
* type {typename} implements Record {
|
|
9458
|
+
* ...scalar fields
|
|
9459
|
+
* Id: IDValue
|
|
9460
|
+
* ...spanning parent records
|
|
9461
|
+
* User: Parent
|
|
9462
|
+
* ...spanning children queries
|
|
9463
|
+
* Accounts(predicates): AccountConnection
|
|
9464
|
+
* }
|
|
9465
|
+
*
|
|
9466
|
+
* scalars SomeAddedScalar
|
|
9467
|
+
*
|
|
9468
|
+
* @param schema
|
|
9469
|
+
* @param objectInfo
|
|
9470
|
+
* @param objectInfoMap
|
|
9471
|
+
* @returns
|
|
9472
|
+
*/
|
|
9473
|
+
function createNewRecordQuery(schema, objectInfo, objectInfoMap) {
|
|
9343
9474
|
let typedScalars = new Set();
|
|
9344
9475
|
let parentRelationshipFields = new Set();
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9476
|
+
const { apiName, childRelationships, fields: fieldsRepresentation } = objectInfo;
|
|
9477
|
+
typedScalars.add(`${apiName}_Filter`);
|
|
9478
|
+
typedScalars.add(`${apiName}_OrderBy`);
|
|
9479
|
+
const { fields, polymorphicFieldTypeNames } = makeRecordField(values$2(fieldsRepresentation), objectInfoMap, parentRelationshipFields, 'Missing');
|
|
9480
|
+
// handles child relationship
|
|
9481
|
+
const { spanningRecordConnections, typedScalars: spanningConnectionTypedScalars } = makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, parentRelationshipFields);
|
|
9482
|
+
typedScalars = new Set([...typedScalars, ...spanningConnectionTypedScalars]);
|
|
9483
|
+
const recordQueries = `${apiName}(first: Int, where: ${apiName}_Filter, orderBy: ${apiName}_OrderBy, scope: SupportedScopes): ${apiName}Connection\n`;
|
|
9484
|
+
const isServiceAppointment = apiName === 'ServiceAppointment';
|
|
9485
|
+
const recordConnections = /* GraphQL */ `
|
|
9486
|
+
${isServiceAppointment ? `scalar ${apiName.toUpperCase()}_SCOPE` : ''}
|
|
9487
|
+
|
|
9488
|
+
type ${apiName} implements Record {
|
|
9489
|
+
ApiName: String!
|
|
9490
|
+
DisplayValue: String
|
|
9491
|
+
LastModifiedById: IDValue
|
|
9492
|
+
LastModifiedDate: DateTimeValue
|
|
9493
|
+
RecordTypeId(fallback: Boolean): IDValue
|
|
9494
|
+
SystemModstamp: DateTimeValue
|
|
9495
|
+
WeakEtag: Long!
|
|
9496
|
+
_drafts: JSON
|
|
9497
|
+
${fields}
|
|
9498
|
+
${spanningRecordConnections}
|
|
9357
9499
|
}
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
// the query.
|
|
9364
|
-
if (objectInfos[relation.apiName] !== undefined) {
|
|
9365
|
-
parentRelationshipFields.add(field.relationshipName);
|
|
9366
|
-
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
9367
|
-
}
|
|
9368
|
-
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
9369
|
-
}
|
|
9370
|
-
else if (field.referenceToInfos.length > 1) {
|
|
9371
|
-
parentRelationshipFields.add(field.relationshipName);
|
|
9372
|
-
fields += `${field.relationshipName}: Record\n`;
|
|
9373
|
-
for (const relation of field.referenceToInfos) {
|
|
9374
|
-
if (objectInfos[relation.apiName] !== undefined) {
|
|
9375
|
-
polymorphicFieldTypeNames.add(relation.apiName);
|
|
9376
|
-
}
|
|
9377
|
-
}
|
|
9500
|
+
|
|
9501
|
+
type ${apiName}Connection {
|
|
9502
|
+
edges: [${apiName}Edge]
|
|
9503
|
+
pageInfo: PageInfo!
|
|
9504
|
+
totalCount: Int!
|
|
9378
9505
|
}
|
|
9506
|
+
|
|
9507
|
+
type ${apiName}Edge {
|
|
9508
|
+
node: ${apiName}
|
|
9509
|
+
cursor: String!
|
|
9510
|
+
}
|
|
9511
|
+
|
|
9512
|
+
`;
|
|
9513
|
+
return { recordQueries, recordConnections, typedScalars, polymorphicFieldTypeNames };
|
|
9514
|
+
}
|
|
9515
|
+
/**
|
|
9516
|
+
* Takes the current schema and will extend missing fields to the record.
|
|
9517
|
+
* Assume all scalar fields have already been added, but will extend spanning fields
|
|
9518
|
+
*
|
|
9519
|
+
* extend type Account {
|
|
9520
|
+
* ...spanning parent records
|
|
9521
|
+
* User: User
|
|
9522
|
+
* ...spanning children queries
|
|
9523
|
+
* Users(predicates): UserConnection
|
|
9524
|
+
* }
|
|
9525
|
+
*
|
|
9526
|
+
* @param schema
|
|
9527
|
+
* @param type
|
|
9528
|
+
* @param objectInfo
|
|
9529
|
+
* @param objectInfoMap
|
|
9530
|
+
* @returns
|
|
9531
|
+
*/
|
|
9532
|
+
function extendExistingRecordType(schema, type, objectInfo, objectInfoMap) {
|
|
9533
|
+
// use a set to not allow duplicate scalars causing error(s)
|
|
9534
|
+
let typedScalars = new Set();
|
|
9535
|
+
let parentRelationshipFields = new Set();
|
|
9536
|
+
const existingFields = keys$4(type.getFields());
|
|
9537
|
+
const missingFields = values$2(objectInfo.fields).filter((field) => existingFields.includes(field.apiName) === false);
|
|
9538
|
+
const { fields, polymorphicFieldTypeNames } = makeRecordField(missingFields, objectInfoMap, parentRelationshipFields, 'Cached');
|
|
9539
|
+
const { apiName, childRelationships } = objectInfo;
|
|
9540
|
+
// handles child relationship
|
|
9541
|
+
const { spanningRecordConnections, typedScalars: spanningConnectionTypedScalars } = makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, parentRelationshipFields, existingFields);
|
|
9542
|
+
typedScalars = new Set([...typedScalars, ...spanningConnectionTypedScalars]);
|
|
9543
|
+
const hasExtensions = fields.length > 0 || spanningRecordConnections.length > 0;
|
|
9544
|
+
const recordExtension = hasExtensions
|
|
9545
|
+
? `
|
|
9546
|
+
extend type ${apiName} {
|
|
9547
|
+
${fields}
|
|
9548
|
+
${spanningRecordConnections}
|
|
9549
|
+
}\n`
|
|
9550
|
+
: '';
|
|
9551
|
+
return { recordExtension, typedScalars, polymorphicFieldTypeNames };
|
|
9552
|
+
}
|
|
9553
|
+
/**
|
|
9554
|
+
* Converts child relationships into spanning record connections to be added to record types
|
|
9555
|
+
*
|
|
9556
|
+
* type Record {
|
|
9557
|
+
* Generates -> AccountConnection(first: Int, where: Account_Filter, etc...): AccountConnection
|
|
9558
|
+
* }
|
|
9559
|
+
*
|
|
9560
|
+
* will also generate typed scalars if they have not been added to the existing schema for the spanning connection
|
|
9561
|
+
* example: Account_Filter or Account_OrderBy scalars needed to be defined as predicate types
|
|
9562
|
+
* @param schema
|
|
9563
|
+
* @param childRelationships
|
|
9564
|
+
* @param objectInfoMap
|
|
9565
|
+
* @param existingParentRelationships
|
|
9566
|
+
* @param existingFields
|
|
9567
|
+
* @returns
|
|
9568
|
+
*/
|
|
9569
|
+
function makeSpanningRecordConnections(schema, childRelationships, objectInfoMap, existingParentRelationships, existingFields = []) {
|
|
9570
|
+
let spanningRecordConnections = ``;
|
|
9571
|
+
let typedScalars = new Set();
|
|
9572
|
+
for (const childRelationship of childRelationships) {
|
|
9573
|
+
const { childObjectApiName, relationshipName } = childRelationship;
|
|
9574
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
9575
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9576
|
+
// the query.
|
|
9577
|
+
// If one field has both parent relationship and child relationship with the same name, the child relationship is ignored. This is how the server GQL has implemented as date of 08/07/2023
|
|
9578
|
+
if (existingFields.length > 0 && existingFields.includes(relationshipName)) {
|
|
9579
|
+
continue;
|
|
9379
9580
|
}
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
//
|
|
9384
|
-
//
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
if (objectInfos[childObjectApiName] !== undefined &&
|
|
9388
|
-
!parentRelationshipFields.has(childRelationship.relationshipName)) {
|
|
9389
|
-
fields += `${childRelationship.relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9581
|
+
if (objectInfoMap[childObjectApiName] !== undefined &&
|
|
9582
|
+
!existingParentRelationships.has(relationshipName)) {
|
|
9583
|
+
spanningRecordConnections += `${relationshipName}(first: Int, where: ${childObjectApiName}_Filter, orderBy: ${childObjectApiName}_OrderBy, scope: SupportedScopes): ${childObjectApiName}Connection \n`;
|
|
9584
|
+
// if the record type has already been extended then these additional scalars have already been added
|
|
9585
|
+
// to add them again would throw an error
|
|
9586
|
+
const filterScalarType = schema.getType(`${childObjectApiName}_Filter`);
|
|
9587
|
+
if (isScalarType(filterScalarType) === false) {
|
|
9390
9588
|
typedScalars.add(`${childObjectApiName}_Filter`);
|
|
9589
|
+
}
|
|
9590
|
+
const orderByScalarType = schema.getType(`${childObjectApiName}_OrderBy`);
|
|
9591
|
+
if (isScalarType(orderByScalarType) === false) {
|
|
9391
9592
|
typedScalars.add(`${childObjectApiName}_OrderBy`);
|
|
9392
9593
|
}
|
|
9393
9594
|
}
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9595
|
+
}
|
|
9596
|
+
return { spanningRecordConnections, typedScalars };
|
|
9597
|
+
}
|
|
9598
|
+
/**
|
|
9599
|
+
* Creates scalar and parent relationship fields for a record type
|
|
9600
|
+
*
|
|
9601
|
+
* type RecordName {
|
|
9602
|
+
* generates scalar -> Id: IDValue
|
|
9603
|
+
* generates relationship -> Account: Record
|
|
9604
|
+
* }
|
|
9605
|
+
*
|
|
9606
|
+
* can be used in a type definition or an extension
|
|
9607
|
+
* @param fieldRepresentations
|
|
9608
|
+
* @param objectInfoMap
|
|
9609
|
+
* @param existingParentRelationships
|
|
9610
|
+
* @param recordTypeInSchema
|
|
9611
|
+
* @returns
|
|
9612
|
+
*/
|
|
9613
|
+
function makeRecordField(fieldRepresentations, objectInfoMap, existingParentRelationships, recordTypeInSchema) {
|
|
9614
|
+
const polymorphicFieldTypeNames = new Set();
|
|
9615
|
+
let fields = ``;
|
|
9616
|
+
for (const field of values$2(fieldRepresentations)) {
|
|
9617
|
+
if (!fieldsStaticallyAdded.includes(field.apiName) && recordTypeInSchema === 'Missing') {
|
|
9618
|
+
fields += `${field.apiName}: ${dataTypeToType(field.dataType, field.apiName)}\n`;
|
|
9619
|
+
}
|
|
9620
|
+
//handles parent relationship
|
|
9621
|
+
if (field.relationshipName === null) {
|
|
9622
|
+
continue;
|
|
9623
|
+
}
|
|
9624
|
+
// For spanning parent relationships with no union types
|
|
9625
|
+
if (field.referenceToInfos.length === 1) {
|
|
9626
|
+
const [relation] = field.referenceToInfos;
|
|
9627
|
+
// Only add the relationship if there is relevant objectinfos for it,
|
|
9628
|
+
// otherwise we'd be defining types we cannot satisfy and aren't referenced in
|
|
9629
|
+
// the query.
|
|
9630
|
+
if (objectInfoMap[relation.apiName] !== undefined) {
|
|
9631
|
+
existingParentRelationships.add(field.relationshipName);
|
|
9632
|
+
fields += `${field.relationshipName}: ${relation.apiName}\n`;
|
|
9633
|
+
}
|
|
9634
|
+
// For polymorphic field, its type is 'Record' inteface. The concrete entity type name is saved for field resolving of next phase
|
|
9635
|
+
}
|
|
9636
|
+
else if (field.referenceToInfos.length > 1) {
|
|
9637
|
+
existingParentRelationships.add(field.relationshipName);
|
|
9638
|
+
fields += `${field.relationshipName}: Record\n`;
|
|
9639
|
+
for (const relation of field.referenceToInfos) {
|
|
9640
|
+
if (objectInfoMap[relation.apiName] !== undefined) {
|
|
9641
|
+
polymorphicFieldTypeNames.add(relation.apiName);
|
|
9642
|
+
}
|
|
9643
|
+
}
|
|
9420
9644
|
}
|
|
9421
|
-
|
|
9422
|
-
`;
|
|
9423
9645
|
}
|
|
9424
|
-
|
|
9425
|
-
return accu + `scalar ${typed}\n`;
|
|
9426
|
-
}, ``);
|
|
9427
|
-
recordConnections += scalars;
|
|
9428
|
-
const polyFieldTypeNameArr = [];
|
|
9429
|
-
polymorphicFieldTypeNames.forEach((fieldType) => polyFieldTypeNameArr.push(fieldType));
|
|
9430
|
-
return { recordQueries, recordConnections, polyFieldTypeNameArr };
|
|
9646
|
+
return { fields, polymorphicFieldTypeNames };
|
|
9431
9647
|
}
|
|
9648
|
+
/**
|
|
9649
|
+
* converts the ObjectInfoRepresentation data type into a defined schema scalar type
|
|
9650
|
+
* @param objectInfoDataType
|
|
9651
|
+
* @param apiName
|
|
9652
|
+
* @returns
|
|
9653
|
+
*/
|
|
9432
9654
|
function dataTypeToType(objectInfoDataType, apiName) {
|
|
9433
9655
|
if (apiName && apiName === 'Id') {
|
|
9434
9656
|
return `ID!`;
|
|
@@ -9470,13 +9692,8 @@ function dataTypeToType(objectInfoDataType, apiName) {
|
|
|
9470
9692
|
return 'String';
|
|
9471
9693
|
}
|
|
9472
9694
|
}
|
|
9473
|
-
function createSchema(objectInfos) {
|
|
9474
|
-
const { typeDefs: typeDefinitions, polyFieldTypeNames } = generateTypeDefinitions(objectInfos);
|
|
9475
|
-
const schema = buildSchema(typeDefinitions);
|
|
9476
|
-
return addResolversToSchema(schema, polyFieldTypeNames);
|
|
9477
|
-
}
|
|
9478
9695
|
|
|
9479
|
-
async function evaluate(config, observers, settings, objectInfos, store, snapshot, draftFunctions) {
|
|
9696
|
+
async function evaluate(config, observers, settings, objectInfos, store, snapshot, cache, draftFunctions) {
|
|
9480
9697
|
const eventEmitter = createCustomAdapterEventEmitter(GRAPHQL_EVAL_NAMESPACE, observers);
|
|
9481
9698
|
// this is only wrapped in a try to execute the event after the result was returned
|
|
9482
9699
|
try {
|
|
@@ -9517,7 +9734,7 @@ async function evaluate(config, observers, settings, objectInfos, store, snapsho
|
|
|
9517
9734
|
const contextValue = createContext(store, objectInfos, eventEmitter, settings, snapshot, draftFunctions);
|
|
9518
9735
|
// We're building this from scratch from each request. If this becomes a
|
|
9519
9736
|
// hotspot we can pull it up and memoize it later
|
|
9520
|
-
const schema =
|
|
9737
|
+
const schema = createSchemaWithCache(objectInfos, cache);
|
|
9521
9738
|
eventEmitter({ type: 'graphql-schema-created' });
|
|
9522
9739
|
// execute document against schema/context
|
|
9523
9740
|
let result = (await execute({
|
|
@@ -13012,6 +13229,8 @@ const replaceDraftIdsInVariables = (variables, draftFunctions, unmappedDraftIDs)
|
|
|
13012
13229
|
}, {});
|
|
13013
13230
|
return newVariables;
|
|
13014
13231
|
};
|
|
13232
|
+
// create the runtime cache for the graphql schema when the factory creates the adapter
|
|
13233
|
+
const graphqlSchemaCache = new CachedGraphQLSchema();
|
|
13015
13234
|
function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio, isDraftId) {
|
|
13016
13235
|
const getCanonicalId = (id) => {
|
|
13017
13236
|
var _a;
|
|
@@ -13085,7 +13304,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13085
13304
|
...config,
|
|
13086
13305
|
//need to create another copy of the ast for future writes
|
|
13087
13306
|
query: parse$3(stringify$3(injectedAST)),
|
|
13088
|
-
}, observers, { userId }, objectInfoNeeded, store, nonEvaluatedSnapshot));
|
|
13307
|
+
}, observers, { userId }, objectInfoNeeded, store, nonEvaluatedSnapshot, graphqlSchemaCache));
|
|
13089
13308
|
}
|
|
13090
13309
|
catch (throwable) {
|
|
13091
13310
|
const error = throwable;
|
|
@@ -13114,7 +13333,7 @@ function draftAwareGraphQLAdapterFactory(userId, objectInfoService, store, luvio
|
|
|
13114
13333
|
let { result: rebuildResult, seenRecordIds } = await evaluate({
|
|
13115
13334
|
...config,
|
|
13116
13335
|
query: injectedAST,
|
|
13117
|
-
}, observers, { userId }, objectInfoNeeded, store, originalSnapshot, draftFunctions);
|
|
13336
|
+
}, observers, { userId }, objectInfoNeeded, store, originalSnapshot, graphqlSchemaCache, draftFunctions);
|
|
13118
13337
|
if (!rebuildResult.errors) {
|
|
13119
13338
|
rebuildResult = removeSyntheticFields(rebuildResult, config.query);
|
|
13120
13339
|
}
|
|
@@ -17288,4 +17507,4 @@ register({
|
|
|
17288
17507
|
});
|
|
17289
17508
|
|
|
17290
17509
|
export { getRuntime, registerReportObserver, reportGraphqlQueryParseError };
|
|
17291
|
-
// version: 1.
|
|
17510
|
+
// version: 1.248.0-1f7f01112
|