154 lines
5.0 KiB
TypeScript
154 lines
5.0 KiB
TypeScript
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/server-runtime";
|
|
import { json } from "@remix-run/server-runtime";
|
|
import type { ScheduleObject } from "@trigger.dev/core/v3";
|
|
import { UpdateScheduleOptions } from "@trigger.dev/core/v3";
|
|
import { z } from "zod";
|
|
import { Prisma, prisma } from "~/db.server";
|
|
import { clientSafeErrorMessage } from "~/utils/prismaErrors";
|
|
import { scheduleUniqWhereClause } from "~/models/schedules.server";
|
|
import { ViewSchedulePresenter } from "~/presenters/v3/ViewSchedulePresenter.server";
|
|
import { authenticateApiRequest } from "~/services/apiAuth.server";
|
|
import { logger } from "~/services/logger.server";
|
|
import type { UpsertSchedule } from "~/v3/schedules";
|
|
import { ServiceValidationError } from "~/v3/services/baseService.server";
|
|
import { UpsertTaskScheduleService } from "~/v3/services/upsertTaskSchedule.server";
|
|
|
|
const ParamsSchema = z.object({
|
|
scheduleId: z.string(),
|
|
});
|
|
|
|
export async function action({ request, params }: ActionFunctionArgs) {
|
|
// Authenticate the request
|
|
const authenticationResult = await authenticateApiRequest(request);
|
|
|
|
if (!authenticationResult) {
|
|
return json({ error: "Invalid or Missing API Key" }, { status: 401 });
|
|
}
|
|
|
|
const parsedParams = ParamsSchema.safeParse(params);
|
|
|
|
if (!parsedParams.success) {
|
|
return json(
|
|
{ error: "Invalid request parameters", issues: parsedParams.error.issues },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const method = request.method.toUpperCase();
|
|
|
|
switch (method) {
|
|
case "DELETE": {
|
|
try {
|
|
const deletedSchedule = await prisma.taskSchedule.delete({
|
|
where: scheduleUniqWhereClause(
|
|
authenticationResult.environment.projectId,
|
|
parsedParams.data.scheduleId
|
|
),
|
|
});
|
|
|
|
return json(
|
|
{
|
|
id: deletedSchedule.friendlyId,
|
|
},
|
|
{ status: 200 }
|
|
);
|
|
} catch (error) {
|
|
// Check if it's a Prisma error
|
|
if (error instanceof Prisma.PrismaClientKnownRequestError) {
|
|
return json(
|
|
{
|
|
error: error.code === "P2025" ? "Schedule not found" : clientSafeErrorMessage(error),
|
|
},
|
|
{ status: error.code === "P2025" ? 404 : 422 }
|
|
);
|
|
} else {
|
|
logger.error("Failed to delete schedule", { error });
|
|
return json({ error: "Something went wrong, please try again." }, { status: 500 });
|
|
}
|
|
}
|
|
}
|
|
case "PUT": {
|
|
const rawBody = await request.json();
|
|
|
|
const body = UpdateScheduleOptions.safeParse(rawBody);
|
|
|
|
if (!body.success) {
|
|
return json({ error: "Invalid request body", issues: body.error.issues }, { status: 400 });
|
|
}
|
|
|
|
const service = new UpsertTaskScheduleService();
|
|
|
|
try {
|
|
const options: UpsertSchedule = {
|
|
friendlyId: parsedParams.data.scheduleId,
|
|
taskIdentifier: body.data.task,
|
|
cron: body.data.cron,
|
|
timezone: body.data.timezone,
|
|
environments: [authenticationResult.environment.id],
|
|
externalId: body.data.externalId,
|
|
};
|
|
|
|
const schedule = await service.call(authenticationResult.environment.projectId, options);
|
|
|
|
const responseObject: ScheduleObject = {
|
|
id: schedule.id,
|
|
type: schedule.type,
|
|
task: schedule.task,
|
|
active: schedule.active,
|
|
generator: {
|
|
type: "CRON",
|
|
expression: schedule.cron,
|
|
description: schedule.cronDescription,
|
|
},
|
|
timezone: schedule.timezone,
|
|
externalId: schedule.externalId ?? undefined,
|
|
deduplicationKey: schedule.deduplicationKey,
|
|
environments: schedule.environments,
|
|
nextRun: schedule.nextRun,
|
|
};
|
|
|
|
return json(responseObject, { status: 200 });
|
|
} catch (error) {
|
|
if (error instanceof ServiceValidationError) {
|
|
return json({ error: error.message }, { status: 422 });
|
|
}
|
|
|
|
logger.error("Failed to upsert schedule", { error });
|
|
return json({ error: "Something went wrong, please try again." }, { status: 500 });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function loader({ request, params }: LoaderFunctionArgs) {
|
|
// Authenticate the request
|
|
const authenticationResult = await authenticateApiRequest(request);
|
|
|
|
if (!authenticationResult) {
|
|
return json({ error: "Invalid or Missing API Key" }, { status: 401 });
|
|
}
|
|
|
|
const parsedParams = ParamsSchema.safeParse(params);
|
|
|
|
if (!parsedParams.success) {
|
|
return json(
|
|
{ error: "Invalid request parameters", issues: parsedParams.error.issues },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const presenter = new ViewSchedulePresenter();
|
|
|
|
const result = await presenter.call({
|
|
projectId: authenticationResult.environment.projectId,
|
|
friendlyId: parsedParams.data.scheduleId,
|
|
environmentId: authenticationResult.environment.id,
|
|
});
|
|
|
|
if (!result) {
|
|
return json({ error: "Schedule not found" }, { status: 404 });
|
|
}
|
|
|
|
return json(presenter.toJSONResponse(result), { status: 200 });
|
|
}
|