in app/routes/api.jobs.tsx [91:218]
export async function action({ request }: ActionFunctionArgs) {
console.log("POST /api/jobs");
if (request.method !== "POST") {
return json({ error: "Method not allowed" }, { status: 405 });
}
// Check authentication
const cookieHeader = request.headers.get("Cookie");
const credentials = extractCredentialsFromCookie(cookieHeader);
if (!hasValidCredentials(credentials)) {
return json(
{
error: {
code: "UNAUTHORIZED",
message:
"Authentication required - please provide API credentials through the UI",
},
},
{ status: 401 }
);
}
try {
const { title, description, branch, author, repository } =
await request.json();
// Validation
if (!title || title.length === 0 || title.length > 200) {
return json(
{
error: {
code: "VALIDATION_ERROR",
message: "Title is required and must be between 1-200 characters",
details: [
{
field: "title",
message:
"Title is required and must be between 1-200 characters",
},
],
},
},
{ status: 400 }
);
}
if (description && description.length > 1000) {
return json(
{
error: {
code: "VALIDATION_ERROR",
message: "Description must be less than 1000 characters",
details: [
{
field: "description",
message: "Description must be less than 1000 characters",
},
],
},
},
{ status: 400 }
);
}
// Validate repository URL if provided
if (repository?.url) {
const githubUrlPattern =
/^https:\/\/github\.com\/[\w\-\.]+\/[\w\-\.]+(?:\.git)?(?:\/)?$/;
if (!githubUrlPattern.test(repository.url)) {
return json(
{
error: {
code: "VALIDATION_ERROR",
message: "Repository URL must be a valid GitHub repository URL",
details: [
{
field: "repository.url",
message:
"Repository URL must be a valid GitHub repository URL (e.g., https://github.com/username/repo)",
},
],
},
},
{ status: 400 }
);
}
}
// Use the authenticated user as the author if not provided
// Support both HuggingFace and GitHub usernames
const authenticatedAuthor = getEffectiveUsername(credentials);
const job: Job = {
id: uuidv4(),
title,
description: description || "",
status: "pending",
createdAt: new Date(),
updatedAt: new Date(),
branch: branch || undefined,
author: author || authenticatedAuthor, // Use authenticated user if author not provided
repository: repository || undefined,
};
const jobStore = getJobStore();
await jobStore.createJob(job);
// Start processing job asynchronously with credentials
const jobProcessor = getJobProcessor();
jobProcessor.processJob(job.id, jobStore, credentials).catch((error) => {
console.error(`Failed to process job ${job.id}:`, error);
});
return json(job, { status: 201 });
} catch (error) {
console.error("Error creating job:", error);
return json(
{
error: {
code: "INTERNAL_ERROR",
message: "Failed to create job",
},
},
{ status: 500 }
);
}
}