import { z } from 'zod' import { shareAuthTypeSchema } from '@/lib/api/contracts/public-shares' import { toolJsonResponseSchema } from '@/lib/api/contracts/tools/media/shared' import { defineRouteContract } from '@/lib/api/contracts/types' export const fileManageQuerySchema = z.object({ userId: z.string().min(1).nullable().optional(), workspaceId: z.string().min(1).nullable().optional(), }) export const fileManageWriteBodySchema = z.object({ operation: z.literal('write'), workspaceId: z.string().min(1).optional(), fileName: z.string({ error: 'fileName is required for write operation' }).min(1), content: z.string({ error: 'content is required for write operation' }), contentType: z.string().optional(), }) export const fileManageAppendBodySchema = z.object({ operation: z.literal('append'), workspaceId: z.string().min(1).optional(), fileName: z.string({ error: 'fileName is required for append operation' }).min(1), content: z.string({ error: 'content is required for append operation' }), }) export const fileManageGetBodySchema = z .object({ operation: z.literal('get'), workspaceId: z.string().min(1).optional(), fileId: z.string().min(1).optional(), fileInput: z.unknown().optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for get operation', }) export const fileManageMoveBodySchema = z.object({ operation: z.literal('move'), workspaceId: z.string().min(1).optional(), fileId: z.string().min(1, 'fileId is required for move operation'), targetFolder: z.string().optional().default(''), }) export type FileManageMoveBody = z.input export const fileManageSharingBodySchema = z .object({ operation: z.literal('manage_sharing'), workspaceId: z.string().min(1).optional(), fileId: z.string().min(1).optional(), fileInput: z.unknown().optional(), isActive: z.boolean({ error: 'isActive is required for manage_sharing operation' }), authType: shareAuthTypeSchema.optional(), password: z.string().min(1).max(1024).optional(), allowedEmails: z.array(z.string().min(1)).max(200).optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for manage_sharing operation', }) export type FileManageSharingBody = z.input export const fileManageReadBodySchema = z .object({ operation: z.literal('read'), workspaceId: z.string().min(1).optional(), fileId: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(), fileInput: z.unknown().optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for read operation', }) export const fileManageContentBodySchema = z .object({ operation: z.literal('content'), workspaceId: z.string().min(1).optional(), fileId: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(), fileInput: z.unknown().optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for content operation', }) export const fileManageCompressBodySchema = z .object({ operation: z.literal('compress'), workspaceId: z.string().min(1).optional(), fileId: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).optional(), fileInput: z.unknown().optional(), archiveName: z.string().min(1).max(255).optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for compress operation', }) export const fileManageDecompressBodySchema = z .object({ operation: z.literal('decompress'), workspaceId: z.string().min(1).optional(), fileId: z.string().min(1).optional(), fileInput: z.unknown().optional(), }) .refine((data) => data.fileId !== undefined || data.fileInput !== undefined, { message: 'Either fileId or fileInput is required for decompress operation', }) export const fileManageBodySchema = z.union([ fileManageWriteBodySchema, fileManageAppendBodySchema, fileManageGetBodySchema, fileManageMoveBodySchema, fileManageSharingBodySchema, fileManageReadBodySchema, fileManageContentBodySchema, fileManageCompressBodySchema, fileManageDecompressBodySchema, ]) export const fileManageContract = defineRouteContract({ method: 'POST', path: '/api/tools/file/manage', query: fileManageQuerySchema, body: fileManageBodySchema, response: { mode: 'json', schema: toolJsonResponseSchema }, })