From b7c04b3a6ed4fa1b8f4db8769b05de79304c7cfd Mon Sep 17 00:00:00 2001 From: dbahiense Date: Tue, 23 Jul 2024 10:10:29 -0300 Subject: [PATCH] setup convex --- convex/_generated/api.d.ts | 4 ++ convex/_generated/dataModel.d.ts | 34 +++++++------- convex/auth.config.ts | 10 +++++ convex/http.ts | 72 ++++++++++++++++++++++++++++++ convex/tasks.ts | 4 +- providers/ConvexClerkProvider.tsx | 31 +++++++++++++ providers/ConvexClientProvider.tsx | 10 ----- 7 files changed, 137 insertions(+), 28 deletions(-) create mode 100644 convex/auth.config.ts create mode 100644 convex/http.ts create mode 100644 providers/ConvexClerkProvider.tsx delete mode 100644 providers/ConvexClientProvider.tsx diff --git a/convex/_generated/api.d.ts b/convex/_generated/api.d.ts index cabdc2a..fafcd30 100644 --- a/convex/_generated/api.d.ts +++ b/convex/_generated/api.d.ts @@ -14,7 +14,9 @@ import type { FilterApi, FunctionReference, } from "convex/server"; +import type * as http from "../http.js"; import type * as tasks from "../tasks.js"; +import type * as users from "../users.js"; /** * A utility for referencing Convex functions in your app's API. @@ -25,7 +27,9 @@ import type * as tasks from "../tasks.js"; * ``` */ declare const fullApi: ApiFromModules<{ + http: typeof http; tasks: typeof tasks; + users: typeof users; }>; export declare const api: FilterApi< typeof fullApi, diff --git a/convex/_generated/dataModel.d.ts b/convex/_generated/dataModel.d.ts index 51ea936..3f4afe7 100644 --- a/convex/_generated/dataModel.d.ts +++ b/convex/_generated/dataModel.d.ts @@ -9,29 +9,29 @@ * @module */ -import { AnyDataModel } from "convex/server"; +import type { + DataModelFromSchemaDefinition, + DocumentByName, + TableNamesInDataModel, + SystemTableNames, +} from "convex/server"; import type { GenericId } from "convex/values"; - -/** - * No `schema.ts` file found! - * - * This generated code has permissive types like `Doc = any` because - * Convex doesn't know your schema. If you'd like more type safety, see - * https://docs.convex.dev/using/schemas for instructions on how to add a - * schema file. - * - * After you change a schema, rerun codegen with `npx convex dev`. - */ +import schema from "../schema.js"; /** * The names of all of your Convex tables. */ -export type TableNames = string; +export type TableNames = TableNamesInDataModel; /** * The type of a document stored in Convex. + * + * @typeParam TableName - A string literal type of the table name (like "users"). */ -export type Doc = any; +export type Doc = DocumentByName< + DataModel, + TableName +>; /** * An identifier for a document in Convex. @@ -43,8 +43,10 @@ export type Doc = any; * * IDs are just strings at runtime, but this type can be used to distinguish them from other * strings when type checking. + * + * @typeParam TableName - A string literal type of the table name (like "users"). */ -export type Id = +export type Id = GenericId; /** @@ -56,4 +58,4 @@ export type Id = * This type is used to parameterize methods like `queryGeneric` and * `mutationGeneric` to make them type-safe. */ -export type DataModel = AnyDataModel; +export type DataModel = DataModelFromSchemaDefinition; diff --git a/convex/auth.config.ts b/convex/auth.config.ts new file mode 100644 index 0000000..927b36c --- /dev/null +++ b/convex/auth.config.ts @@ -0,0 +1,10 @@ +const authConfig = { + providers: [ + { + domain: "https://evident-skink-35.clerk.accounts.dev", + applicationID: "convex", + }, + ] +}; + +export default authConfig; \ No newline at end of file diff --git a/convex/http.ts b/convex/http.ts new file mode 100644 index 0000000..812b254 --- /dev/null +++ b/convex/http.ts @@ -0,0 +1,72 @@ +// ===== reference links ===== +// https://www.convex.dev/templates (open the link and choose for clerk than you will get the github link mentioned below) +// https://github.dev/webdevcody/thumbnail-critique/blob/6637671d72513cfe13d00cb7a2990b23801eb327/convex/schema.ts + +import type { WebhookEvent } from "@clerk/nextjs/server"; +import { httpRouter } from "convex/server"; +import { Webhook } from "svix"; + +import { internal } from "./_generated/api"; +import { httpAction } from "./_generated/server"; + +const handleClerkWebhook = httpAction(async (ctx, request) => { + const event = await validateRequest(request); + if (!event) { + return new Response("Invalid request", { status: 400 }); + } + switch (event.type) { + case "user.created": + await ctx.runMutation(internal.users.createUser, { + clerkId: event.data.id, + email: event.data.email_addresses[0].email_address, + imageUrl: event.data.image_url, + name: event.data.first_name as string, + }); + break; + case "user.updated": + await ctx.runMutation(internal.users.updateUser, { + clerkId: event.data.id, + imageUrl: event.data.image_url, + email: event.data.email_addresses[0].email_address, + }); + break; + case "user.deleted": + await ctx.runMutation(internal.users.deleteUser, { + clerkId: event.data.id as string, + }); + break; + } + return new Response(null, { + status: 200, + }); +}); + +const http = httpRouter(); + +http.route({ + path: "/clerk", + method: "POST", + handler: handleClerkWebhook, +}); + +const validateRequest = async ( + req: Request +): Promise => { + // key note : add the webhook secret variable to the environment variables field in convex dashboard setting + const webhookSecret = process.env.CLERK_WEBHOOK_SECRET!; + if (!webhookSecret) { + throw new Error("CLERK_WEBHOOK_SECRET is not defined"); + } + const payloadString = await req.text(); + const headerPayload = req.headers; + const svixHeaders = { + "svix-id": headerPayload.get("svix-id")!, + "svix-timestamp": headerPayload.get("svix-timestamp")!, + "svix-signature": headerPayload.get("svix-signature")!, + }; + const wh = new Webhook(webhookSecret); + const event = wh.verify(payloadString, svixHeaders); + return event as unknown as WebhookEvent; +}; + +export default http; \ No newline at end of file diff --git a/convex/tasks.ts b/convex/tasks.ts index d8186b8..2cbe9f3 100644 --- a/convex/tasks.ts +++ b/convex/tasks.ts @@ -1,8 +1,8 @@ -import { query } from "./_generated/server"; +/*import { query } from "./_generated/server"; export const get = query({ args: {}, handler: async (ctx) => { return await ctx.db.query("tasks").collect(); }, -}); \ No newline at end of file +});*/ \ No newline at end of file diff --git a/providers/ConvexClerkProvider.tsx b/providers/ConvexClerkProvider.tsx new file mode 100644 index 0000000..604319c --- /dev/null +++ b/providers/ConvexClerkProvider.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { ReactNode } from "react"; +import { ClerkProvider, useAuth } from "@clerk/nextjs"; +import { ConvexProviderWithClerk } from "convex/react-clerk"; +import { ConvexReactClient } from "convex/react"; + +const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL as string); + +const ConvexClerkProvider = ({ children }: { children: ReactNode}) => ( + + + { children } + + +); + +export default ConvexClerkProvider; \ No newline at end of file diff --git a/providers/ConvexClientProvider.tsx b/providers/ConvexClientProvider.tsx deleted file mode 100644 index bc549c7..0000000 --- a/providers/ConvexClientProvider.tsx +++ /dev/null @@ -1,10 +0,0 @@ -"use client"; - -import { ConvexProvider, ConvexReactClient } from "convex/react"; -import { ReactNode } from "react"; - -const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!); - -export function ConvexClientProvider({ children }: { children: ReactNode }) { - return {children}; -} \ No newline at end of file