Files
web/packages/common/utils/imageVault.ts
Erik Tiekstra f06e466827 Feat/BOOK-240 hero video
Approved-by: Chuma Mcphoy (We Ahead)
Approved-by: Christel Westerberg
2025-12-11 08:35:27 +00:00

210 lines
4.8 KiB
TypeScript

import { z } from "zod"
import { focalPointSchema } from "./focalPoint"
const deprecatedMetaDataSchema = z.object({
DefinitionType: z.number().nullish(),
Description: z.string().nullable(),
LanguageId: z.number().nullable(),
MetadataDefinitionId: z.number(),
Name: z.string(),
Value: z.string().nullable(),
})
/**
* Defines a media asset, original or conversion
*/
const deprecatedMediaConversionSchema = z.object({
/**
* Aspect ratio of the conversion
*/
AspectRatio: z.number(),
/**
* Content type of the conversion
*/
ContentType: z.string(),
/**
* Aspect ratio of the selected/requested format
*/
FormatAspectRatio: z.number(),
/**
* Height of the selected/requested format
*/
FormatHeight: z.number(),
/**
* Width of the selected/requested format
*/
FormatWidth: z.number(),
/**
* Height, in pixels, of the conversion
*/
Height: z.number(),
/**
* Html representing the conversion
*/
Html: z.string(),
/**
* Id of the selected media format
*/
MediaFormatId: z.number(),
/**
* Name of the media format
*/
MediaFormatName: z.string(),
/**
* Name of the conversion
*/
Name: z.string(),
/**
* The url to the conversion
*/
Url: z.string(),
/**
* Width, in pixels, of the conversion
*/
Width: z.number(),
})
/**
* The response from ImageVault when inserting an asset
*/
export const deprecatedImageVaultAssetSchema = z.object({
/**
* The media item id of the asset
*/
Id: z.number(),
/**
* The id of the vault where the asset resides
*/
VaultId: z.number(),
/**
* The name of the asset
*/
Name: z.string(),
/**
* The conversion selected by the user. Is an array but will only contain one object
*/
MediaConversions: z.array(deprecatedMediaConversionSchema),
Metadata: z.array(deprecatedMetaDataSchema),
/**
* Date when the asset was added to ImageVault
*/
DateAdded: z.string(),
/**
* Name of the user that added the asset to ImageVault
*/
AddedBy: z.string(),
FocalPoint: focalPointSchema.optional(),
})
export const imageVaultAssetSchema = z.object({
imageVaultId: z.number(),
fileName: z.string(),
url: z.string(),
dimensions: z.object({
width: z.number(),
height: z.number(),
aspectRatio: z.number(),
}),
focalPoint: focalPointSchema,
meta: z.object({ alt: z.string(), caption: z.string() }),
})
export const transformedImageVaultAssetSchema = imageVaultAssetSchema
.or(deprecatedImageVaultAssetSchema)
.nullish()
.or(
// Temp since there is a bug in Contentstack
// sending empty objects when there has been an
// image selected previously but has since been
// deleted
z.object({})
)
.transform((data) => {
if (!data || Object.keys(data).length === 0) {
return undefined
}
if ("imageVaultId" in data && "fileName" in data) {
return mapImageVaultAssetResponseToImageVaultAsset(data)
}
if ("Name" in data && "Id" in data) {
return mapInsertResponseToImageVaultAsset(data)
}
})
export type FocalPoint = z.infer<typeof focalPointSchema>
export type DeprecatedImageVaultAssetResponse = z.infer<
typeof deprecatedImageVaultAssetSchema
>
export type ImageVaultAssetResponse = z.infer<typeof imageVaultAssetSchema>
export type ImageVaultAsset = {
id: number
title: string
url: string
dimensions: {
width: number
height: number
aspectRatio: number
}
meta: { alt: string | undefined | null; caption: string | undefined | null }
focalPoint: FocalPoint
}
export function mapInsertResponseToImageVaultAsset(
response: DeprecatedImageVaultAssetResponse
): ImageVaultAsset {
const alt = response.Metadata?.find((meta) =>
meta.Name.includes("AltText_")
)?.Value
const caption = response.Metadata?.find((meta) =>
meta.Name.includes("Title_")
)?.Value
const mediaConversion = response.MediaConversions[0]
const aspectRatio =
mediaConversion.FormatAspectRatio ||
mediaConversion.AspectRatio ||
mediaConversion.Width / mediaConversion.Height
return {
id: response.Id,
title: response.Name,
url: mediaConversion.Url,
dimensions: {
width: mediaConversion.Width,
height: mediaConversion.Height,
aspectRatio,
},
meta: {
alt,
caption,
},
focalPoint: response.FocalPoint || { x: 50, y: 50 },
}
}
export function mapImageVaultAssetResponseToImageVaultAsset(
response: ImageVaultAssetResponse
): ImageVaultAsset {
return {
id: response.imageVaultId,
title: response.fileName,
url: response.url,
dimensions: {
width: response.dimensions.width,
height: response.dimensions.height,
aspectRatio: response.dimensions.aspectRatio,
},
meta: {
alt: response.meta.alt,
caption: response.meta.caption,
},
focalPoint: response.focalPoint,
}
}