summaryrefslogtreecommitdiff
path: root/app/routes/api-artists.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/routes/api-artists.tsx')
-rw-r--r--app/routes/api-artists.tsx47
1 files changed, 47 insertions, 0 deletions
diff --git a/app/routes/api-artists.tsx b/app/routes/api-artists.tsx
new file mode 100644
index 0000000..ed762bf
--- /dev/null
+++ b/app/routes/api-artists.tsx
@@ -0,0 +1,47 @@
+import type { ActionFunctionArgs } from "react-router";
+import { createArtist, getIpAddress, listArtists, toSlug } from "~/lib/db.server";
+
+export function loader() {
+ return Response.json(listArtists());
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ if (request.method !== "POST") {
+ return Response.json({ error: "Method not allowed" }, { status: 405 });
+ }
+
+ let body: Record<string, unknown>;
+ try {
+ body = await request.json();
+ } catch {
+ return Response.json({ error: "Invalid JSON body" }, { status: 400 });
+ }
+
+ const name = (body.name as string | undefined)?.trim();
+ if (!name) return Response.json({ error: "name is required" }, { status: 400 });
+
+ const slug = (body.slug as string | undefined)?.trim() || toSlug(name);
+ if (!slug) return Response.json({ error: "could not derive slug from name" }, { status: 400 });
+
+ const id = crypto.randomUUID();
+ try {
+ const artist = createArtist({
+ id,
+ slug,
+ name,
+ links: (body.links as { label: string; url: string }[]) || [],
+ message: (body.message as string) || "API import",
+ ip_address: getIpAddress(request),
+ });
+ return Response.json(artist, { status: 201 });
+ } catch (e) {
+ if (e instanceof Error && e.message.includes("UNIQUE constraint failed: artists.slug")) {
+ return Response.json({ error: "slug already in use" }, { status: 409 });
+ }
+ throw e;
+ }
+}
+
+export default function () {
+ return null;
+}