@indiekit/endpoint-media
Version:
Micropub media endpoint for Indiekit. Enables publishing media files (audio, photos, videos) to your website using the Micropub protocol.
112 lines (90 loc) • 3.27 kB
JavaScript
import { IndiekitError } from "@indiekit/error";
import { getCanonicalUrl } from "@indiekit/util";
import makeDebug from "debug";
import { getFileProperties, getMediaType } from "./file.js";
import { renderPath } from "./utils.js";
const debug = makeDebug("indiekit:endpoint-media:media-data");
export const mediaData = {
/**
* Create media data
* @param {object} application - Application configuration
* @param {object} publication - Publication configuration
* @param {object} file - File
* @returns {Promise<object>} Media data
*/
async create(application, publication, file) {
debug(`Create %O`, { file });
const { timeZone } = application;
const { me, postTypes } = publication;
// Media properties
const properties = await getFileProperties(publication, file, timeZone);
// Get post type configuration
const type = await getMediaType(file);
properties["media-type"] = type;
// Throw error if trying to create unsupported media
const supportedMediaTypes = ["audio", "photo", "video"];
if (!supportedMediaTypes.includes(type)) {
throw IndiekitError.unsupportedMediaType(type);
}
// Get post type configuration
const typeConfig = postTypes[type];
if (!typeConfig || !typeConfig.media?.path) {
throw IndiekitError.notImplemented(type);
}
// Media paths
const path = await renderPath(
typeConfig.media.path,
properties,
application,
);
const url = await renderPath(
typeConfig.media.url || typeConfig.media.path,
properties,
application,
);
properties.url = getCanonicalUrl(url, me);
// Update media properties based on type configuration
const urlPathSegment = properties.url.split("/");
properties.filename = urlPathSegment.at(-1);
const mediaData = { path, properties };
// Add data to media collection (or replace existing if present)
const mediaCollection = application?.collections?.get("media");
if (mediaCollection) {
const query = { "properties.url": properties.url };
await mediaCollection.replaceOne(query, mediaData, { upsert: true });
}
return mediaData;
},
/**
* Read media data
* @param {object} application - Application configuration
* @param {string} url - URL of existing media
* @returns {Promise<object>} Media data
*/
async read(application, url) {
debug(`Read ${url}`);
const query = { "properties.url": url };
const mediaCollection = application?.collections?.get("media");
const mediaData = await mediaCollection.findOne(query);
if (!mediaData) {
throw IndiekitError.notFound(url);
}
return mediaData;
},
/**
* Delete media data
* @param {object} application - Application configuration
* @param {string} url - URL of existing post
* @returns {Promise<boolean>} Media data deleted
*/
async delete(application, url) {
debug(`Delete ${url}`);
const query = { "properties.url": url };
const mediaCollection = application?.collections?.get("media");
const result = await mediaCollection.deleteOne(query);
if (result?.deletedCount === 1) {
return true;
}
throw new Error("No media data to delete");
},
};