import _ from 'lodash'; import * as StackbitTypes from '@stackbit/types'; import { BackCompatContentSourceInterface } from './backward-compatibility'; import { ContentSourceData, ContentStoreEvent, ProvisionalData, ContentStoreEventType } from '../types'; import { omitByNil } from '@stackbit/utils'; export async function updateProvisionalDataFromContentSource({ contentSourceInstance, csiModelMap, provisionalData }: { contentSourceInstance: BackCompatContentSourceInterface; csiModelMap: Record; provisionalData: ProvisionalData; }): Promise<{ csiDocuments: StackbitTypes.Document[]; csiDocumentMap: Record; csiAssets: StackbitTypes.Asset[]; csiAssetMap: Record; syncContext?: { documentsSyncContext?: unknown; assetsSyncContext?: unknown }; }> { const syncContext: ProvisionalData['syncContext'] = {}; const getDocumentsRes = await contentSourceInstance.getDocuments({ modelMap: csiModelMap, syncContext: provisionalData.syncContext?.documentsSyncContext }); const { csiDocuments, csiDocumentMap, documentsSyncContext } = Array.isArray(getDocumentsRes) ? { csiDocuments: getDocumentsRes, csiDocumentMap: _.keyBy(getDocumentsRes, 'id'), documentsSyncContext: undefined } : { ...updateProvisionalDataWithCSIDocuments({ csiDocuments: getDocumentsRes.documents, provisionalData }), documentsSyncContext: getDocumentsRes.syncContext }; provisionalData.csiDocuments = csiDocuments; provisionalData.csiDocumentMap = csiDocumentMap; syncContext.documentsSyncContext = documentsSyncContext; const getAssetsRes = await contentSourceInstance.getAssets({ syncContext: provisionalData.syncContext?.assetsSyncContext }); const { csiAssets, csiAssetMap, assetsSyncContext } = Array.isArray(getAssetsRes) ? { csiAssets: getAssetsRes, csiAssetMap: _.keyBy(getAssetsRes, 'id'), assetsSyncContext: undefined } : { ...updateProvisionalDataWithCSIAssets({ csiAssets: getAssetsRes.assets, provisionalData }), assetsSyncContext: getAssetsRes.syncContext }; provisionalData.csiAssets = csiAssets; provisionalData.csiAssetMap = csiAssetMap; syncContext.assetsSyncContext = assetsSyncContext; provisionalData.syncContext = omitByNil(syncContext); return { csiDocuments, csiAssets, csiDocumentMap, csiAssetMap, syncContext }; } function updateProvisionalDataWithCSIDocuments({ csiDocuments, provisionalData }: { csiDocuments?: StackbitTypes.Document[]; provisionalData: ProvisionalData; }): { csiDocuments: StackbitTypes.Document[]; csiDocumentMap: Record; } { if (!csiDocuments) { csiDocuments = []; } if (provisionalData.syncContext?.documentsSyncContext && provisionalData.csiDocuments) { for (let idx = 0; idx < csiDocuments.length; idx++) { const csiDocument = csiDocuments[idx]!; const index = provisionalData.csiDocuments.findIndex((doc) => doc.id === csiDocument.id); if (index === -1) { provisionalData.csiDocuments.push(csiDocument); } else { provisionalData.csiDocuments.splice(index, 1, csiDocument); } } let csiDocumentMap: Record; if (provisionalData.csiDocumentMap) { csiDocumentMap = Object.assign(provisionalData.csiDocumentMap, _.keyBy(csiDocuments, 'id')); } else { csiDocumentMap = _.keyBy(provisionalData.csiDocuments, 'id'); provisionalData.csiDocumentMap = csiDocumentMap; } return { csiDocuments: provisionalData.csiDocuments, csiDocumentMap }; } else { const csiDocumentMap = _.keyBy(csiDocuments, 'id'); provisionalData.csiDocuments = csiDocuments; provisionalData.csiDocumentMap = csiDocumentMap; return { csiDocuments, csiDocumentMap }; } } function updateProvisionalDataWithCSIAssets({ csiAssets, provisionalData }: { csiAssets?: StackbitTypes.Asset[]; provisionalData: { srcType: string; srcProjectId: string; csiAssets?: StackbitTypes.Asset[]; csiAssetMap?: Record; syncContext?: { assetsSyncContext?: unknown }; }; }): { csiAssets: StackbitTypes.Asset[]; csiAssetMap: Record; } { if (!csiAssets) { csiAssets = []; } if (provisionalData.syncContext?.assetsSyncContext && provisionalData.csiAssets) { for (let idx = 0; idx < csiAssets.length; idx++) { const csiAsset = csiAssets[idx]!; const index = provisionalData.csiAssets.findIndex((asset) => asset.id === csiAsset.id); if (index === -1) { provisionalData.csiAssets.push(csiAsset); } else { provisionalData.csiAssets.splice(index, 1, csiAsset); } } let csiAssetMap: Record; if (provisionalData.csiAssetMap) { csiAssetMap = Object.assign(provisionalData.csiAssetMap, _.keyBy(csiAssets, 'id')); } else { csiAssetMap = _.keyBy(provisionalData.csiAssets, 'id'); provisionalData.csiAssetMap = csiAssetMap; } return { csiAssets: provisionalData.csiAssets, csiAssetMap }; } else { const csiAssetMap = _.keyBy(csiAssets, 'id'); provisionalData.csiAssets = csiAssets; provisionalData.csiAssetMap = csiAssetMap; return { csiAssets, csiAssetMap }; } } export async function syncContentSource({ contentSourceData, contentSourceEvent }: { contentSourceData: ContentSourceData; contentSourceEvent: ContentStoreEvent & { eventName: typeof ContentStoreEventType.ContentSourceRequestSync }; }): Promise<{ contentChangesData: StackbitTypes.ContentChanges; syncContext: ContentSourceData['syncContext']; }> { const syncContext = { ...(contentSourceEvent.options?.clearDocumentsSyncContext ? {} : { documentsSyncContext: contentSourceData.syncContext?.documentsSyncContext }), ...(contentSourceEvent.options?.clearAssetsSyncContext ? {} : { assetsSyncContext: contentSourceData.syncContext?.assetsSyncContext }) }; const getDocumentsRes = await contentSourceData.instance.getDocuments({ modelMap: contentSourceData.csiModelMap, syncContext: syncContext.documentsSyncContext }); const csiDocuments = Array.isArray(getDocumentsRes) ? getDocumentsRes : getDocumentsRes.documents; const documentsSyncContext = Array.isArray(getDocumentsRes) ? undefined : getDocumentsRes.syncContext; const getAssetsRes = await contentSourceData.instance.getAssets({ syncContext: syncContext.assetsSyncContext }); const csiAssets = Array.isArray(getAssetsRes) ? getAssetsRes : getAssetsRes.assets; const assetsSyncContext = Array.isArray(getAssetsRes) ? undefined : getAssetsRes.syncContext; return { contentChangesData: { documents: csiDocuments, assets: csiAssets }, syncContext: omitByNil({ documentsSyncContext, assetsSyncContext }) }; }