UNPKG

@prismicio/client

Version:

The official JavaScript + TypeScript client library for Prismic

253 lines (220 loc) 6.86 kB
import type { MigrationLinkToMediaField } from "../types/migration/Asset" import { type MigrationImage, type MigrationLinkToMedia, type MigrationRTImageNode, PrismicMigrationAsset, } from "../types/migration/Asset" import type { MigrationContentRelationship, MigrationContentRelationshipField, } from "../types/migration/ContentRelationship" import { PrismicMigrationDocument } from "../types/migration/Document" import type { MaybeLink } from "../types/migration/Link" import type { FilledImageFieldImage } from "../types/value/image" import type { LinkField, OptionalLinkProperties } from "../types/value/link" import { LinkType } from "../types/value/link" import type { RTImageNode } from "../types/value/richText" import { RichTextNodeType } from "../types/value/richText" import * as isFilled from "../helpers/isFilled" import type { Migration } from "../Migration" import * as isMigration from "./isMigrationValue" import { getOptionalLinkProperties } from "./getOptionalLinkProperties" /** * Resolves a migration content relationship to a content relationship field. * * @param relation - Content relationship to resolve. * * @returns Resolved content relationship field. */ export async function resolveMigrationContentRelationship( relation: MaybeLink<MigrationContentRelationship>, ): Promise<MigrationContentRelationshipField & OptionalLinkProperties> { if (typeof relation === "function") { return resolveMigrationContentRelationship(await relation()) } if (relation instanceof PrismicMigrationDocument) { return relation.document.id ? { link_type: LinkType.Document, id: relation.document.id } : { link_type: LinkType.Any } } const optionalLinkProperties = relation && "link_type" in relation ? getOptionalLinkProperties(relation) : undefined if (relation) { if ( isMigration.contentRelationship(relation.id) || typeof relation.id !== "string" ) { return { ...optionalLinkProperties, ...(await resolveMigrationContentRelationship(relation.id)), } } // This is only called when resolveMigrationContentRelationship recursively // calls itself from the statement above and the resolved content relation // is a Prismic document value. return { ...optionalLinkProperties, link_type: LinkType.Document, id: relation.id, } } return { ...optionalLinkProperties, link_type: LinkType.Any, } } /** * Resolves a migration image to an image field. * * @param migrationAsset - Asset to resolve. * @param migration - Migration instance. * @param withThumbnails - Whether to include thumbnails. * * @returns Resolved image field. */ export const resolveMigrationImage = ( image: MigrationImage, migration: Migration, withThumbnails?: boolean, ): FilledImageFieldImage | undefined => { const { id: master, ...thumbnails } = image instanceof PrismicMigrationAsset ? { id: image } : image const asset = migration._assets.get(master.config.id)?.asset const maybeInitialField = master.originalField if (asset) { const parameters = (maybeInitialField?.url || asset.url).split("?")[1] const url = `${asset.url.split("?")[0]}${parameters ? `?${parameters}` : ""}` const dimensions: FilledImageFieldImage["dimensions"] = { width: asset.width!, height: asset.height!, } const edit: FilledImageFieldImage["edit"] = maybeInitialField && "edit" in maybeInitialField ? maybeInitialField?.edit : { x: 0, y: 0, zoom: 1, background: "transparent" } // We give priority to the asset's specific alt text, then the image's general alt text const alt = master.config.alt || asset.alt || null const resolvedThumbnails: Record<string, FilledImageFieldImage> = {} if (withThumbnails) { for (const [name, thumbnail] of Object.entries(thumbnails)) { const resolvedThumbnail = resolveMigrationImage(thumbnail, migration) if (resolvedThumbnail) { resolvedThumbnails[name] = resolvedThumbnail } } } return { id: asset.id, url, dimensions, edit, alt: alt, copyright: asset.credits || null, ...resolvedThumbnails, } } } /** * Resolves a migration rich text image node to a regular rich text image node. * * @param rtImageNode - Migration rich text image node to resolve. * @param migration - Migration instance. * * @returns Resolved rich text image node. */ export const resolveMigrationRTImageNode = async ( rtImageNode: MigrationRTImageNode, migration: Migration, ): Promise<RTImageNode | undefined> => { const image = resolveMigrationImage(rtImageNode.id, migration) if (image) { const linkTo = (await resolveMigrationDocumentData( rtImageNode.linkTo, migration, )) as LinkField return { ...image, type: RichTextNodeType.image, linkTo: isFilled.link(linkTo) ? linkTo : undefined, } } } /** * Resolves a migration link to media to a regular link to media field. * * @param linkToMedia - Migration link to media to resolve. * @param migration - Migration instance. * * @returns Resolved link to media field. */ export const resolveMigrationLinkToMedia = ( linkToMedia: MaybeLink<MigrationLinkToMedia>, migration: Migration, ): MigrationLinkToMediaField => { const asset = migration._assets.get(linkToMedia.id.config.id)?.asset const optionalLinkProperties = getOptionalLinkProperties(linkToMedia) if (asset) { return { ...optionalLinkProperties, id: asset.id, link_type: LinkType.Media, } } return { ...optionalLinkProperties, link_type: LinkType.Any, } } /** * Resolves a migration document data to actual data ready to be sent to the * Migration API. * * @param input - Migration link to media to resolve. * @param migration - Migration instance. * * @returns Resolved data. */ export async function resolveMigrationDocumentData( input: unknown, migration: Migration, ): Promise<unknown> { // Migration fields if (isMigration.contentRelationship(input)) { return resolveMigrationContentRelationship(input) } if (isMigration.image(input)) { return resolveMigrationImage(input, migration, true) } if (isMigration.linkToMedia(input)) { return resolveMigrationLinkToMedia(input, migration) } if (isMigration.rtImageNode(input)) { return resolveMigrationRTImageNode(input, migration) } if (typeof input === "function") { return await resolveMigrationDocumentData(await input(), migration) } // Object traversing if (Array.isArray(input)) { const res = [] for (const element of input) { res.push(await resolveMigrationDocumentData(element, migration)) } return res.filter(Boolean) } if (input && typeof input === "object") { const res: Record<PropertyKey, unknown> = {} for (const key in input) { res[key] = await resolveMigrationDocumentData( input[key as keyof typeof input], migration, ) } return res } // Primitives return input }