import "../../../../base64-CmWvODNW.mjs";
import "../../../../types-CuW0zWDA.mjs";
import { n as normalizeMime, t as matchesMimeAllowlist } from "../../../../mime-CCEzze7W.mjs";
import { n as apiSuccess, r as handleError, t as apiError } from "../../../../error-CkAseSqZ.mjs";
import { n as parseBody, t as isParseError } from "../../../../parse-GmjecGct.mjs";
import { Bt as DEFAULT_MAX_UPLOAD_SIZE, Zt as mediaUploadUrlBody } from "../../../../redirects-DXEXBAII.mjs";
import "../../../../byline-fields-2Lp5Hbgf.mjs";
import "../../../../status-CqJQX1QN.mjs";
import "../../../../api/schemas/index.mjs";
import { n as requirePerm } from "../../../../authorize-Dz88F_Fw.mjs";
import { n as resolveFieldAllowlist, t as GLOBAL_UPLOAD_ALLOWLIST } from "../../../../media-allowlist-CRHEeJ_i.mjs";
import { ulid } from "ulidx";
import * as path from "node:path";
import { MediaRepository } from "emdash";

//#region src/astro/routes/api/media/upload-url.ts
/**
* Media upload URL endpoint
*
* POST /_emdash/api/media/upload-url
*
* Returns a signed URL for direct upload to storage.
* Creates a pending media record that must be confirmed after upload.
*/
const prerender = false;
/**
* Get a signed upload URL for direct-to-storage upload
*/
const POST = async ({ request, locals }) => {
	const { emdash, user } = locals;
	const denied = requirePerm(user, "media:upload");
	if (denied) return denied;
	if (!emdash?.storage) return apiError("NO_STORAGE", "Storage not configured. Signed URL uploads require S3-compatible storage.", 501);
	if (!emdash?.db) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
	try {
		const maxSize = emdash.config.maxUploadSize ?? DEFAULT_MAX_UPLOAD_SIZE;
		if (!Number.isFinite(maxSize) || maxSize <= 0) return apiError("CONFIGURATION_ERROR", "Invalid maxUploadSize configuration. Expected a positive finite number.", 500);
		const body = await parseBody(request, mediaUploadUrlBody(maxSize));
		if (isParseError(body)) return body;
		const allowlist = (body.fieldId ? await resolveFieldAllowlist(emdash.db, body.fieldId) : null) ?? [...GLOBAL_UPLOAD_ALLOWLIST];
		if (!matchesMimeAllowlist(body.contentType, allowlist)) return apiError("INVALID_TYPE", "File type not allowed", 400);
		const repo = new MediaRepository(emdash.db);
		if (body.contentHash) {
			const existing = await repo.findByContentHash(body.contentHash);
			if (existing) return apiSuccess({
				existing: true,
				mediaId: existing.id,
				storageKey: existing.storageKey,
				url: `/_emdash/api/media/file/${existing.storageKey}`
			});
		}
		const storageKey = `${ulid()}${path.extname(body.filename) || ""}`;
		const mediaItem = await repo.createPending({
			filename: body.filename,
			mimeType: normalizeMime(body.contentType),
			size: body.size,
			storageKey,
			contentHash: body.contentHash,
			authorId: user?.id
		});
		const signedUrl = await emdash.storage.getSignedUploadUrl({
			key: storageKey,
			contentType: body.contentType,
			size: body.size,
			expiresIn: 3600
		});
		return apiSuccess({
			uploadUrl: signedUrl.url,
			method: signedUrl.method,
			headers: signedUrl.headers,
			mediaId: mediaItem.id,
			storageKey,
			expiresAt: signedUrl.expiresAt
		});
	} catch (error) {
		if (error instanceof Error && "code" in error && error.code === "NOT_SUPPORTED") return apiError("NOT_SUPPORTED", "Storage does not support signed upload URLs. Use direct upload.", 501);
		return handleError(error, "Failed to generate upload URL", "UPLOAD_URL_ERROR");
	}
};

//#endregion
export { POST, prerender };
//# sourceMappingURL=upload-url.mjs.map