Browse Source

feat: add API endpoints to list and create scheduled tasks

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
main
npmrun 2 weeks ago
parent
commit
61d4d3bcd2
  1. 20
      server/api/scheduler/tasks/index.get.ts
  2. 59
      server/api/scheduler/tasks/index.post.ts

20
server/api/scheduler/tasks/index.get.ts

@ -0,0 +1,20 @@
import { listTasks } from "../../../service/scheduler";
import { listRegisteredTasks } from "../../../scheduler/registry";
export default defineWrappedResponseHandler(async (event) => {
const query = getQuery(event);
const page = query.page ? Number(query.page) : 1;
const pageSize = query.pageSize ? Number(query.pageSize) : 20;
const result = await listTasks({
page,
pageSize,
type: query.type as string | undefined,
enabled: query.enabled !== undefined ? Number(query.enabled) : undefined,
});
return R.success({
...result,
registeredFunctions: listRegisteredTasks(),
});
});

59
server/api/scheduler/tasks/index.post.ts

@ -0,0 +1,59 @@
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);
});
Loading…
Cancel
Save