in src/router/bundle/bundleParser.ts [181:282]
private static async checkReferences(
orderedBundleEntriesId: string[],
idToRequestWithRef: Record<string, BatchReadWriteRequest>,
fullUrlToRequest: Record<string, BatchReadWriteRequest>,
allRequests: BatchReadWriteRequest[],
serverUrl: string,
dataService: Persistence,
): Promise<BatchReadWriteRequest[]> {
for (let i = 0; i < Object.values(idToRequestWithRef).length; i += 1) {
const requestWithRef = Object.values(idToRequestWithRef)[i];
if (requestWithRef.references) {
for (let j = 0; j < requestWithRef.references.length; j += 1) {
const reference: Reference = requestWithRef.references[j];
let referenceIsFound = false;
if (reference.referenceFullUrl === this.SELF_CONTAINED_REFERENCE) {
referenceIsFound = this.checkReferencesForContainedResources(requestWithRef, reference);
}
// If reference refers to another resource in the bundle, change the id of the reference to match the
// id of the resource.
if (reference.referenceFullUrl in fullUrlToRequest) {
const reqBeingReferenced: BatchReadWriteRequest = fullUrlToRequest[reference.referenceFullUrl];
const { id } = reqBeingReferenced;
set(
requestWithRef,
`resource.${reference.referencePath}`,
`${reqBeingReferenced.resourceType}/${id}`,
);
referenceIsFound = true;
requestWithRef.references[j] = reference;
}
// If references in the Bundle entries does not match the fullUrl of any entries in the Bundle and the reference has the same
// rootUrl as the server, we check if the server has that reference. If the server does not have the
// reference we throw an error
if (!referenceIsFound && [serverUrl, `${serverUrl}/`].includes(reference.rootUrl)) {
let parsedVid = reference.vid;
let vidWithHistory = false;
try {
if (parsedVid) {
if (reference.vid.startsWith('/_history')) {
const parts = parsedVid.split('/');
parsedVid = parts[parts.length - 1];
vidWithHistory = true;
}
// eslint-disable-next-line no-await-in-loop
await dataService.vReadResource({
resourceType: reference.resourceType,
id: reference.id,
vid: parsedVid,
});
} else {
// eslint-disable-next-line no-await-in-loop
await dataService.readResource({
resourceType: reference.resourceType,
id: reference.id,
});
}
} catch (e) {
throw new Error(
`This entry refer to a resource that does not exist on this server. Entry is referring to '${reference.resourceType}/${reference.id}'`,
);
}
const ref = vidWithHistory
? `${reference.resourceType}/${reference.id}/_history/${parsedVid}`
: `${reference.resourceType}/${reference.id}`;
set(requestWithRef, `resource.${reference.referencePath}`, ref);
referenceIsFound = true;
}
if (!referenceIsFound) {
console.log('This resource has a reference to an external server', requestWithRef.fullUrl);
}
}
allRequests.push(requestWithRef);
}
}
const allRequestIds = allRequests.map((req) => {
return req.id;
});
// Add to allRequests, request with fullUrl but was not referenced by any bundle entry
Object.values(fullUrlToRequest).forEach((req) => {
if (!allRequestIds.includes(req.id)) {
allRequests.push(req);
}
});
// @ts-ignore
const orderedAllRequests: BatchReadWriteRequest[] = orderedBundleEntriesId.map((id) => {
return allRequests.find((request) => {
return id === request.id;
});
});
return Object.values(orderedAllRequests).map((request) => {
const updatedRequest = request;
delete updatedRequest.references;
return updatedRequest;
});
}