import { d as Media } from '../_dts-chunks/media.d-DtIw8UQM.d.ts'; import { O as OnErrorHook } from '../_dts-chunks/on-error.d-DGMUFaZB.d.ts'; import { P as PublicData } from '../_dts-chunks/nextly-error.d-WlStqaV9.d.ts'; import 'zod'; import '../_dts-chunks/error-codes.d-CbwkO1ux.d.ts'; /** * Media Upload Server Action * * Next.js 16 Server Action for uploading media files. * Provides a simpler alternative to API routes for small files (<5MB). * * ## Features * * - Server-side file upload (no client-side FormData serialization) * - Automatic cache revalidation (revalidatePath) * - Type-safe with Zod validation * - Authentication support (when configured) * - Error handling with user-friendly messages * * ## Usage * * ### In Consumer's Next.js App * * ```typescript * // app/actions/media.ts * 'use server'; * * import { uploadMediaAction } from 'nextly/actions/upload-media'; * import { getUserId } from './auth'; // Your auth implementation * * export async function uploadMedia(formData: FormData) { * const userId = await getUserId(); * return uploadMediaAction(formData, { uploadedBy: userId }); * } * ``` * * ### In Client Component * * ```tsx * 'use client'; * * import { uploadMedia } from './actions/media'; * * function UploadForm() { * async function handleSubmit(formData: FormData) { * const result = await uploadMedia(formData); * if (result.success) { * toast.success('Uploaded!'); * } else { * toast.error(result.error); * } * } * * return
...
; * } * ``` * * ## Authentication * * This action is **auth-agnostic** by design. The `uploadedBy` parameter * must be provided by the consumer's authentication implementation. * * Examples: * - Nextly: `const result = await getSession(request, secret); uploadedBy: result.user?.id` * - Clerk: `const { userId } = auth(); uploadedBy: userId` * - Custom: `const user = await getUser(); uploadedBy: user.id` * * ## Limitations * * - **No upload progress**: Server Actions don't support progress events * - **Recommended for small files only** (<5MB) * - **For large files**: Use API route with XMLHttpRequest * * @see packages/db/src/api/media.ts - API route with progress support * @see MEDIA-MANAGEMENT-EXTENDED-PLAN.md - Phase 6 implementation details */ /** * Server Action options */ interface UploadMediaActionOptions { /** * User ID who is uploading the file (required) * Must be obtained from your auth system */ uploadedBy: string; /** * Path to revalidate after successful upload * @default '/admin/media' */ revalidatePath?: string; } /** * Server Action result */ interface UploadMediaActionResult { success: boolean; data?: Media; error?: string; statusCode?: number; } /** * Upload media file via Server Action * * Uploads a file to storage and creates a database record. * Automatically generates thumbnails for images. * * @param formData - FormData containing the file * @param options - Upload options (uploadedBy, revalidatePath) * @returns Upload result with media data or error * * @example Basic usage * ```typescript * 'use server'; * * export async function uploadFile(formData: FormData) { * const userId = await getUserId(); // Your auth function * return uploadMediaAction(formData, { uploadedBy: userId }); * } * ``` * * @example With custom revalidation path * ```typescript * return uploadMediaAction(formData, { * uploadedBy: userId, * revalidatePath: '/dashboard/gallery', * }); * ``` */ declare function uploadMediaAction(formData: FormData, options: UploadMediaActionOptions): Promise; /** * Delete media file via Server Action * * Deletes a file from storage and removes the database record. * * @param mediaId - ID of media to delete * @param options - Options (revalidatePath) * @returns Deletion result * * @example * ```typescript * 'use server'; * * export async function deleteFile(mediaId: string) { * return deleteMediaAction(mediaId); * } * ``` */ declare function deleteMediaAction(mediaId: string, options?: { revalidatePath?: string; }): Promise<{ success: boolean; error?: string; statusCode?: number; }>; /** * Update media metadata via Server Action * * Updates altText, caption, tags, or other metadata fields. * * @param mediaId - ID of media to update * @param updates - Metadata updates * @param options - Options (revalidatePath) * @returns Update result * * @example * ```typescript * 'use server'; * * export async function updateFile( * mediaId: string, * updates: { altText?: string; caption?: string; tags?: string[] } * ) { * return updateMediaAction(mediaId, updates); * } * ``` */ declare function updateMediaAction(mediaId: string, updates: { filename?: string; altText?: string; caption?: string; tags?: string[]; }, options?: { revalidatePath?: string; }): Promise<{ success: boolean; data?: Media; error?: string; statusCode?: number; }>; /** * Wire shape returned by Server Actions wrapped with `withAction`. * * The `error` block matches the canonical HTTP wire-format error block * (modulo the discriminator), so developers learn one shape regardless of * whether they consume a Route Handler or a Server Action. */ type ActionError = { code: string; message: string; messageKey?: string; data?: PublicData; requestId: string; }; /** * Result of a Server Action: either `{ ok: true, data }` on success or * `{ ok: false, error }` on failure. The `ok` discriminator narrows * cleanly via `if (result.ok)` so consumers get type-safe access to either * branch. */ type ActionResult = { ok: true; data: T; } | { ok: false; error: ActionError; }; type WithActionOptions = { /** Per-call observability hook. Fired before the global hook. */ onError?: OnErrorHook; }; /** * Server Action boundary wrapper. Mirrors `withErrorHandler` but returns a * typed `ActionResult` instead of a `Response`, working around Next.js's * production error-digesting (which strips thrown error messages). * * Generic over `TArgs` so it transparently supports both direct-call * actions (`(id: string)`) and form-binding actions * (`(prevState, formData)`) consumed by `useActionState`. * * Sentinel errors (`redirect`, `notFound`, dynamic-API bailouts) are passed * through `unstable_rethrow` first so navigation works as expected. */ declare function withAction(fn: (...args: TArgs) => Promise, options?: WithActionOptions): (...args: TArgs) => Promise>; export { deleteMediaAction, updateMediaAction, uploadMediaAction, withAction }; export type { ActionError, ActionResult, UploadMediaActionOptions, UploadMediaActionResult };