import { Config } from '@stackbit/sdk'; import { AssetSource, DistributiveOmit, FieldImageProps, Logger } from '@stackbit/types'; import * as ContentStoreTypes from '../types'; const BUILT_IN_ASSET_SOURCES = ['cloudinary', 'bynder', 'aprimo'] as const; type BuiltInAssetSources = (typeof BUILT_IN_ASSET_SOURCES)[number]; export function getAssetSourcesForClient(stackbitConfig: Config | null): DistributiveOmit[] { if (!stackbitConfig) { return []; } const assetSources = stackbitConfig.assetSources ?? []; return assetSources.reduce((accum: DistributiveOmit[], assetSource: AssetSource) => { if (assetSource.type === 'iframe') { if (!assetSource.name || !assetSource.url) { return accum; } const { transform, preview, ...rest } = assetSource; return accum.concat(rest); } else { const name = assetSource.name ?? (BUILT_IN_ASSET_SOURCES.includes(assetSource.type) ? assetSource.type : null); if (!name) { return accum; } const { transform, preview, ...rest } = assetSource; return accum.concat({ ...rest, name: name }); } return accum; }, []); } export function transformAssetSourceDataForAssetSource({ sourceData, assetSource, logger }: { sourceData: any; assetSource: AssetSource; logger: Logger; }): any { if (typeof assetSource.transform === 'function') { return assetSource.transform({ assetData: sourceData, getLogger: () => logger }); } else { return sourceData; } } export function getImageFieldsFromSourceData({ sourceData, imageModelField, assetSources, logger }: { sourceData: any; imageModelField: FieldImageProps; assetSources: AssetSource[]; logger: Logger; }): ContentStoreTypes.ImageFields { const imageAssetSource = getAssetSourceBySourceName(assetSources, imageModelField.source); if (imageAssetSource?.preview) { const preview = typeof imageAssetSource.preview === 'function' ? imageAssetSource.preview({ assetData: sourceData, getLogger: () => logger }) : imageAssetSource.preview; return { title: { type: 'string', value: preview?.title ?? '' }, url: { type: 'string', value: preview.image ?? '' } }; } if (imageAssetSource?.type === 'cloudinary') { return { title: { type: 'string', value: sourceData?.public_id }, url: { type: 'string', value: sourceData?.derived?.[0]?.secure_url ?? sourceData?.secure_url } }; } if (imageAssetSource?.type === 'bynder') { // contentful and sanity has own structures and returns fields in the own csi modules // git has full response from bynder client so uses this fn return { title: { type: 'string', value: sourceData?.name }, url: { type: 'string', value: sourceData?.files?.webImage?.url } }; } if (imageAssetSource?.type === 'aprimo') { return { title: { type: 'string', value: sourceData?.title }, url: { type: 'string', value: sourceData?.rendition?.publicuri } }; } return { title: { type: 'string', value: '' }, url: { type: 'string', value: typeof sourceData === 'string' ? sourceData : '' } }; } function isBuiltInAssetSource(assetSource: string): assetSource is BuiltInAssetSources { return BUILT_IN_ASSET_SOURCES.includes(assetSource as BuiltInAssetSources); } export function getAssetSourceBySourceName(assetSources: AssetSource[], assetSourceName: string | undefined): AssetSource | undefined { if (!assetSourceName) { return undefined; } const assetSource = assetSources.find((assetSources) => assetSources.name === assetSourceName); if (!assetSource) { // for build-in asset sources, use the name of the source (field[type=image].source) as its type if (isBuiltInAssetSource(assetSourceName)) { return { type: assetSourceName, name: assetSourceName }; } } return assetSource; }