deme4447
deme4447
TTCTheo's Typesafe Cult
Created by deme4447 on 6/18/2023 in #questions
Syncing Clerk User for Prisma User in the Next Pages Directory
If anyone sees this: you'll sync the full attributes object in one prisma column unless you make your prisma model individual properties for each value in the object which you have to destructure before upserting to prisma
5 replies
TTCTheo's Typesafe Cult
Created by deme4447 on 6/18/2023 in #questions
Syncing Clerk User for Prisma User in the Next Pages Directory
Figured it out, just put this in the pages/api/path:
import type { IncomingHttpHeaders } from "http";
import type { NextApiRequest, NextApiResponse } from "next";
import type { WebhookRequiredHeaders } from "svix";
import type { WebhookEvent } from "@clerk/nextjs/server";
import { Webhook } from "svix";
import { prisma } from "~/server/db";
import { NextResponse } from "next/server";

const webhookSecret: string = process.env.CLERK_WEBHOOK_SECRET!;

export default async function handler(
req: NextApiRequestWithSvixRequiredHeaders,
res: NextApiResponse
) {
const payload = req.body as UserData;
console.log("payload", payload);
const headers = req.headers;
console.log("headers", headers);
// Create a new Webhook instance with your webhook secret
const wh = new Webhook(webhookSecret);

let evt: WebhookEvent;

try {
// Verify the webhook payload and headers
evt = wh.verify(JSON.stringify(payload), headers) as WebhookEvent;
console.log("evt", evt);
} catch (err) {
// If the verification fails, return a 400 error
console.error(err as Error);
// return NextResponse.json({}, { status: 400 });
return NextResponse.json({}, { status: 400 });
}

const eventType = evt.type;

if (
eventType === "user.created" ||
eventType === "user.updated" ||
eventType === "user.deleted"
) {
const { id, ...attributes } = evt.data;

console.log(id, "id in clerk-webhook-handlers");
console.log(attributes, "attributes in clerk-webhook-handlers");

// map the return data in to the format we want to store in our database
// const userDataUpsert = {
// externalId: id as string,
// attributes: attributes as Record<string, any>,
// };

await prisma.user.upsert({
where: { externalId: id as string },
create: {
externalId: id as string,
attributes: attributes as Record<string, any>,
},
update: {
attributes: attributes as Record<string, any>,
},
});
}

// return 200 to acknowledge receipt of the event
res.status(201).json({});
}

type NextApiRequestWithSvixRequiredHeaders = NextApiRequest & {
headers: IncomingHttpHeaders & WebhookRequiredHeaders;
};

// type EventType = "user.updated" | "user.created" | "user.deleted" | "*";
import type { IncomingHttpHeaders } from "http";
import type { NextApiRequest, NextApiResponse } from "next";
import type { WebhookRequiredHeaders } from "svix";
import type { WebhookEvent } from "@clerk/nextjs/server";
import { Webhook } from "svix";
import { prisma } from "~/server/db";
import { NextResponse } from "next/server";

const webhookSecret: string = process.env.CLERK_WEBHOOK_SECRET!;

export default async function handler(
req: NextApiRequestWithSvixRequiredHeaders,
res: NextApiResponse
) {
const payload = req.body as UserData;
console.log("payload", payload);
const headers = req.headers;
console.log("headers", headers);
// Create a new Webhook instance with your webhook secret
const wh = new Webhook(webhookSecret);

let evt: WebhookEvent;

try {
// Verify the webhook payload and headers
evt = wh.verify(JSON.stringify(payload), headers) as WebhookEvent;
console.log("evt", evt);
} catch (err) {
// If the verification fails, return a 400 error
console.error(err as Error);
// return NextResponse.json({}, { status: 400 });
return NextResponse.json({}, { status: 400 });
}

const eventType = evt.type;

if (
eventType === "user.created" ||
eventType === "user.updated" ||
eventType === "user.deleted"
) {
const { id, ...attributes } = evt.data;

console.log(id, "id in clerk-webhook-handlers");
console.log(attributes, "attributes in clerk-webhook-handlers");

// map the return data in to the format we want to store in our database
// const userDataUpsert = {
// externalId: id as string,
// attributes: attributes as Record<string, any>,
// };

await prisma.user.upsert({
where: { externalId: id as string },
create: {
externalId: id as string,
attributes: attributes as Record<string, any>,
},
update: {
attributes: attributes as Record<string, any>,
},
});
}

// return 200 to acknowledge receipt of the event
res.status(201).json({});
}

type NextApiRequestWithSvixRequiredHeaders = NextApiRequest & {
headers: IncomingHttpHeaders & WebhookRequiredHeaders;
};

// type EventType = "user.updated" | "user.created" | "user.deleted" | "*";
5 replies