UNPKG

next-video

Version:

A React component for adding video to your Next.js application. It extends both the video element and your Next app with features for automatic video optimization.

81 lines (80 loc) 2.71 kB
import * as path from "node:path"; import { cwd } from "node:process"; import { stat } from "node:fs/promises"; import { getVideoConfig } from "./config.js"; import { deepMerge, camelCase, isRemote, toSafePath } from "./utils/utils.js"; import * as transformers from "./providers/transformers.js"; async function getAsset(filePath) { const videoConfig = await getVideoConfig(); const assetConfigPath = await getAssetConfigPath(filePath); return videoConfig.loadAsset(assetConfigPath); } async function getAssetConfigPath(filePath) { return `${await getAssetPath(filePath)}.json`; } async function getAssetPath(filePath) { if (!isRemote(filePath)) return filePath; const { folder, remoteSourceAssetPath = defaultRemoteSourceAssetPath } = await getVideoConfig(); if (!folder) throw new Error("Missing video `folder` config."); return path.join(folder, remoteSourceAssetPath(filePath)); } function defaultRemoteSourceAssetPath(url) { const urlObj = new URL(url); return toSafePath(decodeURIComponent(`${urlObj.hostname}${urlObj.pathname}`)); } async function createAsset(filePath, assetDetails) { const videoConfig = await getVideoConfig(); const assetConfigPath = await getAssetConfigPath(filePath); let originalFilePath = filePath; if (!isRemote(filePath)) { originalFilePath = path.relative(cwd(), filePath); } const newAssetDetails = { status: "pending", // overwritable ...assetDetails, originalFilePath, provider: videoConfig.provider, providerMetadata: {}, createdAt: Date.now(), updatedAt: Date.now() }; if (!isRemote(filePath)) { try { newAssetDetails.size = (await stat(filePath))?.size; } catch { } } await videoConfig.saveAsset(assetConfigPath, newAssetDetails); return newAssetDetails; } async function updateAsset(filePath, assetDetails) { const videoConfig = await getVideoConfig(); const assetConfigPath = await getAssetConfigPath(filePath); const currentAsset = await getAsset(filePath); if (!currentAsset) { throw new Error(`Asset not found: ${filePath}`); } let newAssetDetails = deepMerge(currentAsset, assetDetails, { updatedAt: Date.now() }); newAssetDetails = transformAsset(transformers, newAssetDetails); await videoConfig.updateAsset(assetConfigPath, newAssetDetails); return newAssetDetails; } function transformAsset(transformers2, asset) { const provider = asset.provider; if (!provider) return asset; for (let [key, transformer] of Object.entries(transformers2)) { if (key === camelCase(provider)) { return transformer.transform(asset); } } return asset; } export { createAsset, getAsset, getAssetConfigPath, updateAsset };