Skip to content

Commit

Permalink
fix: fixing circular ref updates by using store of already fetched da…
Browse files Browse the repository at this point in the history
…ta []
  • Loading branch information
aodhagan-cf committed Oct 23, 2023
1 parent 1597fdd commit 07f6353
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 38 deletions.
9 changes: 2 additions & 7 deletions packages/live-preview-sdk/src/liveUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ interface MergeEntityProps {
contentType: ContentType;
entityReferenceMap: EntityReferenceMap;
gqlParams?: GraphQLParams;
visitedReferences: Set<string>;
}

interface MergeArgumentProps extends Omit<MergeEntityProps, 'dataFromPreviewApp'> {
Expand Down Expand Up @@ -60,7 +59,6 @@ export class LiveUpdates {
locale,
updateFromEntryEditor,
gqlParams,
visitedReferences,
}: Omit<MergeEntityProps, 'dataFromPreviewApp'> & {
dataFromPreviewApp: EntityWithSys;
}): Promise<{
Expand Down Expand Up @@ -89,6 +87,7 @@ export class LiveUpdates {
if (this.isCfEntity(dataFromPreviewApp)) {
// REST
const depth = 0;
const visitedReferenceMap = new Map<string, rest.Reference>();
return {
data: await rest.updateEntity(
contentType,
Expand All @@ -97,7 +96,7 @@ export class LiveUpdates {
locale,
entityReferenceMap,
depth,
visitedReferences
visitedReferenceMap
),
updated: true,
};
Expand Down Expand Up @@ -199,9 +198,6 @@ export class LiveUpdates {
await Promise.all(
[...this.subscriptions].map(async ([, s]) => {
try {
// Reset the visitedReferences set for each new update.
const visitedReferences = new Set<string>();

const { updated, data } = await this.merge({
// Clone the original data on the top level,
// to prevent cloning multiple times (time)
Expand All @@ -212,7 +208,6 @@ export class LiveUpdates {
contentType: contentType,
entityReferenceMap: entityReferenceMap,
gqlParams: s.gqlParams,
visitedReferences,
});

// Only if there was an update, trigger the callback to unnecessary re-renders
Expand Down
4 changes: 2 additions & 2 deletions packages/live-preview-sdk/src/rest/__tests__/entities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import contentTypeAsset from '../../__tests__/fixtures/contentTypeAsset.json';
import { MAX_DEPTH } from '../../constants';
import { clone, resolveReference } from '../../helpers';
import { EntityReferenceMap } from '../../types';
import { updateEntity } from '../entities';
import { Reference, updateEntity } from '../entities';
import { EN, referenceWithRichTextId } from './constants';
import contentTypeEntryJSON from './fixtures/contentType.json';
import {
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('Update REST entry', () => {
locale?: string;
entityReferenceMap?: EntityReferenceMap;
}) => {
const visitedReferences = new Set<string>();
const visitedReferences = new Map<string, Reference>();

return updateEntity(
contentType,
Expand Down
56 changes: 27 additions & 29 deletions packages/live-preview-sdk/src/rest/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../helpers/entities';
import { ContentType, EntityReferenceMap } from '../types';

type Reference = Asset | Entry | WithResourceName<Entry>;
export type Reference = Asset | Entry | WithResourceName<Entry>;

/**
* Resolves the correct field name from the ContentType
Expand All @@ -36,30 +36,28 @@ async function updateRef(
locale: string,
entityReferenceMap: EntityReferenceMap,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
): Promise<Reference | undefined | null> {
let reference;
const id =
'urn' in updateFromEntryEditor.sys
? updateFromEntryEditor.sys.urn
: updateFromEntryEditor.sys.id;

// If the ID of the updateFromEntryEditor is in visitedReferences, then stop the recursion
if (visitedReferences.has(updateFromEntryEditor.sys.id)) {
// if (visitedReferences.has(updateFromEntryEditor.sys.id)) {
if (visitedReferenceMap.has(id)) {
debug.warn('Detected a circular reference, stopping recursion');
reference = entityReferenceMap.get(
'urn' in updateFromEntryEditor.sys
? updateFromEntryEditor.sys.urn
: updateFromEntryEditor.sys.id
);
reference = visitedReferenceMap.get(id);
} else {
visitedReferences.add(
'urn' in updateFromEntryEditor.sys
? updateFromEntryEditor.sys.urn
: updateFromEntryEditor.sys.id
);
const { reference: resolvedReference } = await resolveReference({
entityReferenceMap,
referenceId: updateFromEntryEditor.sys.id,
...(isAsset(updateFromEntryEditor) ? { isAsset: true } : undefined),
locale,
});
reference = resolvedReference;
visitedReferenceMap.set(id, resolvedReference);
}

if (!reference) {
Expand All @@ -82,7 +80,7 @@ async function updateRef(
key as keyof Reference['fields'],
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
// multi ref fields
} else if (Array.isArray(value) && isEntityLink(value[0]) && depth < MAX_DEPTH) {
Expand All @@ -93,7 +91,7 @@ async function updateRef(
key as keyof Reference['fields'],
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
// rich text fields
} else if (isRichText(value)) {
Expand All @@ -104,7 +102,7 @@ async function updateRef(
locale,
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
// single and multi resource link fields
} else if (isResourceLink(value) || (Array.isArray(value) && isResourceLink(value[0]))) {
Expand Down Expand Up @@ -132,7 +130,7 @@ async function updateMultiRefField(
name: keyof Reference['fields'],
entityReferenceMap: EntityReferenceMap,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
) {
if (!updateFromEntryEditor.fields?.[name]) {
delete dataFromPreviewApp.fields[name];
Expand All @@ -148,7 +146,7 @@ async function updateMultiRefField(
locale,
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
)
)
).then((list) => list.filter(Boolean))) as Reference[];
Expand All @@ -164,7 +162,7 @@ async function updateSingleRefField(
name: keyof Reference['fields'],
entityReferenceMap: EntityReferenceMap,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
) {
const matchUpdateFromEntryEditor = updateFromEntryEditor?.fields?.[name] as Reference | undefined;

Expand All @@ -181,7 +179,7 @@ async function updateSingleRefField(
locale,
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);

return dataFromPreviewApp;
Expand All @@ -192,7 +190,7 @@ async function resolveRichTextLinks(
entityReferenceMap: EntityReferenceMap,
locale: string,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
) {
if (SUPPORTED_RICHTEXT_EMBEDS.includes(node.nodeType)) {
if (node.data && node.data.target && node.data.target.sys) {
Expand All @@ -208,7 +206,7 @@ async function resolveRichTextLinks(
locale,
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
}
}
Expand All @@ -221,7 +219,7 @@ async function resolveRichTextLinks(
entityReferenceMap,
locale,
depth + 1,
visitedReferences
visitedReferenceMap
);
}
}
Expand All @@ -234,7 +232,7 @@ async function updateRichTextField(
locale: string,
entityReferenceMap: EntityReferenceMap,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
) {
const richText = updateFromEntryEditor.fields?.[name];

Expand All @@ -243,7 +241,7 @@ async function updateRichTextField(
dataFromPreviewApp.fields[name] = richText;
// Resolve the linked entries or assets within the rich text field
for (const node of richText.content) {
await resolveRichTextLinks(node, entityReferenceMap, locale, depth, visitedReferences);
await resolveRichTextLinks(node, entityReferenceMap, locale, depth, visitedReferenceMap);
}
}
}
Expand All @@ -264,7 +262,7 @@ export async function updateEntity(
locale: string,
entityReferenceMap: EntityReferenceMap,
depth: number,
visitedReferences: Set<string>
visitedReferenceMap: Map<string, Reference>
): Promise<Entry> {
if (dataFromPreviewApp.sys.id !== updateFromEntryEditor.sys.id) {
return dataFromPreviewApp;
Expand All @@ -287,7 +285,7 @@ export async function updateEntity(
name as keyof Reference['fields'],
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
} else if (field.type === 'Array' && field.items?.type === 'Link' && depth < MAX_DEPTH) {
await updateMultiRefField(
Expand All @@ -297,7 +295,7 @@ export async function updateEntity(
name as keyof Reference['fields'],
entityReferenceMap,
depth + 1,
visitedReferences
visitedReferenceMap
);
} else if (field.type === 'RichText') {
await updateRichTextField(
Expand All @@ -307,7 +305,7 @@ export async function updateEntity(
locale,
entityReferenceMap,
depth,
visitedReferences
visitedReferenceMap
);
} else if (field.type === 'ResourceLink') {
//@TODO -- add live updates for resource links
Expand Down
1 change: 1 addition & 0 deletions packages/live-preview-sdk/src/rest/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { updateEntity } from './entities';
export type { Reference } from './entities';

0 comments on commit 07f6353

Please sign in to comment.