diff --git a/packages/mux-video/README.md b/packages/mux-video/README.md index 618371f..676fac4 100644 --- a/packages/mux-video/README.md +++ b/packages/mux-video/README.md @@ -82,6 +82,9 @@ export default buildConfig({ | `posterExtension` | `'webp' \| 'jpg' \| 'png'` | `"png"` | The image format to use for video posters. | | `animatedGifExtension` | `'gif' \| 'webp'` | `"gif"` | The image format to use for animated preview thumbnails. | | `adminThumbnail` | `'gif' \| 'image' \| 'none'` | `"gif"` | Specifies the type of thumbnail to display for videos in the collection list view. | +| `posterExtension` | `'jpg' \| 'png' \| 'webp'` | `"png"` | The file extension to use for generated poster images. | +| `animatedGifExtension` | `'gif' \| 'webp'` | `"gif"` | The file extension to use for generated animated gifs. | +| `onInitBehavior` | `"createOnly" \| "deleteOnly" \| "createAndDelete" \| "none"` | `"none"` | What to do on plugin initialization when there are discrepancies between videos in Mux and entries in the Payload collection. | | `autoCreateOnWebhook` | `boolean` | `false` | If enabled, the Mux webhook will automatically create videos that are missing in Payload when webhooks are received from Mux. Useful for uploading videos directly in Mux and automatically backfilling them in Payload. | diff --git a/packages/mux-video/src/lib/onInitExtension.ts b/packages/mux-video/src/lib/onInitExtension.ts index 754b3b3..ef7f311 100644 --- a/packages/mux-video/src/lib/onInitExtension.ts +++ b/packages/mux-video/src/lib/onInitExtension.ts @@ -1,8 +1,83 @@ +import Mux from '@mux/mux-node' import type { Payload } from 'payload' import type { MuxVideoPluginOptions } from '../types' +import { getAssetMetadata } from './getAssetMetadata' -export const onInitExtension = (pluginOptions: MuxVideoPluginOptions, payload: Payload): void => { +export const onInitExtension = async ( + pluginOptions: MuxVideoPluginOptions, + payload: Payload, + mux: Mux, +): Promise => { try { + if (pluginOptions.onInitBehavior === 'none') { + return + } + + const videos = await mux.video.assets.list() + const ids = videos.data.map((video) => video.id) + const collection = (pluginOptions.extendCollection as string) ?? 'mux-video' + + const existingVideos = await payload.find({ + collection, + where: { + assetId: { + in: ids, + }, + }, + limit: videos.data.length, + }) + + const shouldCreate = + pluginOptions.onInitBehavior === 'createOnly' || + pluginOptions.onInitBehavior === 'createAndDelete' + const shouldDelete = + pluginOptions.onInitBehavior === 'deleteOnly' || + pluginOptions.onInitBehavior === 'createAndDelete' + + if (shouldCreate) { + const missingVideos = videos.data.filter( + (video) => !existingVideos.docs.find((doc) => doc.assetId === video.id), + ) + payload.logger.info( + `[payload-mux] Creating missing Mux video entries (${missingVideos.length})...`, + ) + + for (const video of missingVideos) { + await payload.create({ + collection, + data: { + title: `Video ${video.id}`, + assetId: video.id, + ...video, + ...getAssetMetadata(video), + }, + }) + } + } + + if (shouldDelete) { + const extraVideos = await payload.find({ + collection, + limit: 100, + where: { + assetId: { + not_in: ids, + }, + }, + }) + payload.logger.info( + `[payload-mux] Deleting extra Mux video entries (${extraVideos.docs.length})...`, + ) + + for (const video of extraVideos.docs) { + if (pluginOptions.onInitBehavior === 'createAndDelete') { + await payload.delete({ + collection, + id: video.id, + }) + } + } + } } catch (err: unknown) { payload.logger.error({ err, msg: 'Error in onInitExtension' }) } diff --git a/packages/mux-video/src/plugin.ts b/packages/mux-video/src/plugin.ts index 346c852..fb48c7f 100644 --- a/packages/mux-video/src/plugin.ts +++ b/packages/mux-video/src/plugin.ts @@ -74,7 +74,7 @@ export const muxVideoPlugin = await incomingConfig.onInit(payload) } - onInitExtension(pluginOptions, payload) + await onInitExtension(pluginOptions, payload, mux) } return config diff --git a/packages/mux-video/src/types.ts b/packages/mux-video/src/types.ts index 194f19c..2a40018 100644 --- a/packages/mux-video/src/types.ts +++ b/packages/mux-video/src/types.ts @@ -121,6 +121,17 @@ export type MuxVideoPluginOptions = { */ animatedGifExtension?: 'gif' | 'webp' + /** + * What to do with mismatching videos on initialization. + * - `"createOnly"`: Create entries for videos that do not exist in the Payload collection. + * - `"deleteOnly"`: Delete entries for videos that no longer exist on Mux. + * - `"createAndDelete"`: Create entries for missing videos and delete entries for videos that no longer exist on Mux. + * - `"none"`: Do nothing on initialization. + * + * @default "none" + */ + onInitBehavior?: "createOnly" | "deleteOnly" | "createAndDelete" | "none" + /** * An optional function to determine whether the current request is allowed to upload files. * Should return a boolean or a Promise resolving to a boolean.