import { z } from "zod"; import { createTask } from "../../../service/scheduler"; import { addTask } from "../../../scheduler/engine"; import { Cron } from "croner"; const createTaskSchema = z.object({ name: z.string().min(1), cronExpression: z.string().min(1), type: z.enum(["function", "http"]), functionName: z.string().optional(), functionPayload: z.string().optional(), httpMethod: z.enum(["GET", "POST", "PUT", "DELETE"]).optional(), httpUrl: z.string().url().optional(), httpHeaders: z.string().optional(), httpBody: z.string().optional(), catchUp: z.union([z.boolean(), z.number()]).optional(), enabled: z.union([z.boolean(), z.number()]).optional(), maxRetries: z.number().int().min(0).optional(), retryDelaySeconds: z.number().int().min(1).optional(), timeoutSeconds: z.number().int().min(1).optional(), }); export default defineWrappedResponseHandler(async (event) => { const body = await readBody(event); const parsed = createTaskSchema.safeParse(body); if (!parsed.success) { return R.throwError(422, "Validation failed", parsed.error.issues); } // Validate cron expression try { new Cron(parsed.data.cronExpression); } catch { return R.throwError(422, "Invalid cron expression", null); } // function type must specify functionName if (parsed.data.type === "function" && !parsed.data.functionName) { return R.throwError(422, "functionName required for function type", null); } // http type must specify httpUrl if (parsed.data.type === "http" && !parsed.data.httpUrl) { return R.throwError(422, "httpUrl required for http type", null); } const task = await createTask({ ...parsed.data, catchUp: parsed.data.catchUp ? 1 : 0, enabled: parsed.data.enabled !== undefined ? (parsed.data.enabled ? 1 : 0) : 1, }); if (task) { addTask(task.id); } return R.success(task); });