👏

【Drizzle ORM】NextJs14 と Drizzle ORM【#6 User Created】

2024/07/14に公開

【#6 User Created】

YouTube: https://youtu.be/EdYTemxThs4
https://youtu.be/EdYTemxThs4

今回はユーザー作成時の処理を実装します。

今回ユーザーテーブルのIDの設定は作成時の処理の中で設定します。
「nanoid」や「uuid」でも良いのですが、
https://www.npmjs.com/package/nanoid
https://www.npmjs.com/package/uuid

今回は「@paralleldrive/cuid2」を使用します。
https://www.npmjs.com/package/@paralleldrive/cuid2

npm i @paralleldrive/cuid2

まずはスキーマにClerkのユーザーIDのフィールドを追加します。

db/schema.ts
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";

export const users = pgTable("users_table", {
  id: text("id").primaryKey(),
  clerkId: text("clerk_id").notNull().unique(),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
  imageUrl: text("image_url"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at")
    .notNull()
    .$onUpdate(() => new Date()),
});

export const insertUsersSchema = createInsertSchema(users);

スキーマの追加ができましたら、
以下のコマンドを実行して、
スキーマをデータベースに反映します。

npm run db:generate
npm run db:migrate

次に、ユーザーの登録処理を実装します。

app/api/webhooks/clerk/route.ts
import { Webhook } from "svix";
import { headers } from "next/headers";
import { WebhookEvent } from "@clerk/nextjs/server";
import { createId } from "@paralleldrive/cuid2";

import { db } from "@/db/drizzle";
import { users } from "@/db/schema";

export async function POST(req: Request) {
  // You can find this in the Clerk Dashboard -> Webhooks -> choose the endpoint
  const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

  if (!WEBHOOK_SECRET) {
    throw new Error(
      "Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local"
    );
  }

  // Get the headers
  const headerPayload = headers();
  const svix_id = headerPayload.get("svix-id");
  const svix_timestamp = headerPayload.get("svix-timestamp");
  const svix_signature = headerPayload.get("svix-signature");

  // If there are no headers, error out
  if (!svix_id || !svix_timestamp || !svix_signature) {
    return new Response("Error occured -- no svix headers", {
      status: 400,
    });
  }

  // Get the body
  const payload = await req.json();
  const body = JSON.stringify(payload);

  // Create a new Svix instance with your secret.
  const wh = new Webhook(WEBHOOK_SECRET);

  let evt: WebhookEvent;

  // Verify the payload with the headers
  try {
    evt = wh.verify(body, {
      "svix-id": svix_id,
      "svix-timestamp": svix_timestamp,
      "svix-signature": svix_signature,
    }) as WebhookEvent;
  } catch (err) {
    console.error("Error verifying webhook:", err);
    return new Response("Error occured", {
      status: 400,
    });
  }

  // Do something with the payload
  // For this guide, you simply log the payload to the console
  // const { id } = evt.data;
  // console.log(`Webhook with and ID of ${id} and type of ${eventType}`);
  // console.log("Webhook body:", body);

  const eventType = evt.type;

  if (eventType === "user.created") {
    const [data] = await db
      .insert(users)
      .values({
        id: createId(),
        clerkId: payload.data.id,
        imageUrl: payload.data.image_url,
        name: payload.data.first_name + " " + payload.data.last_name,
        email: payload.data.email_addresses[0].email_address,
      })
      .returning();

    console.log(data);
  }

  return new Response("", { status: 200 });
}

Discussion