Openstatus www.openstatus.dev

migrate: Clerk to Next Auth (#801)

* wip:

* wip:

* fix: promise

* wip: unsupported edge runtime and google signin button

* fix: disable suspense boundary

* docs: add links

* wip:

* ๐Ÿšง wip

* ๐Ÿšง wip

* ๐Ÿ”ฅ migration clerk

* ๐Ÿ”ฅ migration clerk

* ๐Ÿš‘ fix build

* ๐Ÿ”ฅ migration clerk

* ๐Ÿš‘ fix build

* wib: move into folder and fix middleware cookie

* ๐Ÿš‘ fix build

* ๐Ÿ—‘๏ธ image

* ๐Ÿ˜ญ force redploy

* ๐Ÿ˜ญ force redploy

* ๐Ÿงช fix test

* ๐Ÿงช fix test

* ๐Ÿ”ฅ last update

---------

Co-authored-by: Thibault Le Ouay <thibaultleouay@gmail.Com>

authored by

Maximilian Kaske
Thibault Le Ouay
and committed by
GitHub
eb21f864 9bc040fe

+2907 -1089
+1 -14
README.md
··· 8 8 </a> 9 9 </p> 10 10 11 - <p align="center"> The Open-Source frontend performance monitoring platform. 11 + <p align="center">The Open-Source frontend performance monitoring platform. 12 12 <br /> 13 13 <a href="https://www.openstatus.dev"><strong>Learn more ยป</strong></a> 14 14 <br /> ··· 82 82 - [tinybird](http://tinybird.co/?ref=openstatus.dev) 83 83 - [turso](http://turso.tech/) 84 84 - [drizzle](https://orm.drizzle.team/) 85 - - [clerk](https://clerk.com/) 86 85 - [Resend](https://resend.com/) 87 86 88 87 ## Getting Started ๐Ÿš€ ··· 133 132 server health check 134 133 - open [http://localhost:3002](http://localhost:3002) for the docs 135 134 136 - For [clerk](https://clerk.com), you will need to create a webhook endpoint. To 137 - access the link, you can use tunneling tools like 138 135 [Tunnelmole](https://github.com/robbie-cahill/tunnelmole-client), an open source 139 136 tunnelling tool or ngrok, a popular closed source tunnelling tool. 140 137 ··· 151 148 โžœ ~ tmole 3000 152 149 http://bvdo5f-ip-49-183-170-144.tunnelmole.net is forwarding to localhost:3000 153 150 https://bvdo5f-ip-49-183-170-144.tunnelmole.net is forwarding to localhost:3000 154 - ``` 155 - 156 - Append `/api/webhook/clerk` to the HTTPs URL. 157 - 158 - ### Using ngrok 159 - 160 - After login, append `/api/webhook/clerk` to the link you get after entering: 161 - 162 - ``` 163 - $ ngrok http 3000 164 151 ``` 165 152 166 153 ### Videos
-12
apps/docs/contributing/get-started.mdx
··· 65 65 > cd apps/web 66 66 > pnpm dev 67 67 > ``` 68 - 69 - 7. Clerk Authentication 70 - 71 - For authentication we are using [Clerk](https://clerk.dev/), you will need to 72 - create an account and get your API keys. If you want to work on the backend and 73 - or authenfied page 74 - 75 - After creating an account on clerk you will need to set up a tunnel with ngrok 76 - or svix to your local server. 77 - 78 - Otherwise you can send a post request to the `/api/webhook/clerk` endpoint with 79 - the following body you will find on clerk
+1 -54
apps/docs/contributing/setup-env.mdx
··· 9 9 obtain the values for some of these variables, focusing on the section related 10 10 to Cleark Auth. 11 11 12 - ## Setting up Clerk for auth 13 - 14 - 1. Log in to your Clerk account at [https://clerk.com/](https://clerk.com/) or 15 - create a new account if you don't have one yet. 16 - 17 - 2. Once logged in, go to your dashboard at 18 - [https://dashboard.clerk.com/](https://dashboard.clerk.com/) and select 19 - create a new app if you do not have any application already. 20 - 21 - 3. On the create new app screen, enter your app name and select **Google** and 22 - or **GitHub** under the section _How will your users sign in?_ 23 - 24 - > Please note that using other providers will cause issues in the application 25 - > due to the different payload received from Clerk. 26 - 27 - 4. After setting up your app, navigate to the "DEVELOPERS" section in the 28 - left-hand menu and find "API Keys." 29 - 30 - 5. In the "Quick Copy" section, make sure that Next.js is selected, then click 31 - the copy icon to obtain the keys. Copy the values for 32 - "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY" and "CLERK_SECRET_KEY." 33 - 34 - 6. Paste these values into the `.env` file under their respective variables. It 35 - should look something like this (real values without censorship): 36 - 37 - ![Create your monitor](/images/setup-env/clerk.png) 38 - 39 - ``` 40 - # CLERK for auth 41 - NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_โ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ข 42 - CLERK_SECRET_KEY=sk_test_โ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ขโ€ข 43 - ``` 44 - 45 - Remember to replace the key values with the actual keys obtained from your Clerk 46 - account. 47 - 48 12 ## Setting up Resend for sending emails 49 13 50 14 The "RESEND for email" section in the `.env` file contains the "RESEND_API_KEY" ··· 380 344 turso dev --db-file openstatus-dev.db 381 345 ``` 382 346 383 - It contains some dummy data that you can use to test the application. You still 384 - need to update the `tenant_id` in table `user` with your user account from 385 - Clerk. 386 - 387 - Do the following to get your `tenant_id`: 388 - 389 - ![Sign up with clerk](/images/setup-env/clerk-step1.png) 390 - 391 - Then go in the user section: 392 - 393 - ![Sign up with clerk](/images/setup-env/clerk-step2.png) 394 - 395 - Then copy the `tenant_id`: 396 - 397 - ![Sign up with clerk](/images/setup-env/clerk-step3.png) 398 - 399 - then update the `tenant_id` in the database, for this you can use 400 - drizzle-studio: 347 + It contains some dummy data that you can use to test the application. 401 348 402 349 ![Drizzle studio](/images/setup-env/drizzle-studio.png) 403 350
+1 -1
apps/ingest-worker/package.json
··· 7 7 "dependencies": { 8 8 "@clickhouse/client-web": "0.3.0", 9 9 "@hono/zod-validator": "0.2.1", 10 - "detect-browser": "^5.3.0", 10 + "detect-browser": "5.3.0", 11 11 "hono": "4.1.4", 12 12 "zod": "3.22.4" 13 13 },
+8 -10
apps/web/.env.example
··· 1 - # CLERK for auth 2 - NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=clerk-public-key 3 - CLERK_SECRET_KEY=clerk-secret-key 4 - CLERK_WEBHOOK_SECRET=clerk 5 - NEXT_PUBLIC_CLERK_SIGN_IN_URL=/app/sign-in 6 - NEXT_PUBLIC_CLERK_SIGN_UP_URL=/app/sign-up 7 - NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/app 8 - NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/app 9 - 10 1 # RESEND for email 11 2 RESEND_API_KEY=resend-api-key 12 3 ··· 69 60 # RUM server with separate clickhouse for self-host 70 61 CLICKHOUSE_URL= 71 62 CLICKHOUSE_USERNAME= 72 - CLICKHOUSE_PASSWORD= 63 + CLICKHOUSE_PASSWORD= 64 + 65 + AUTH_SECRET= 66 + AUTH_DRIZZLE_URL=http://127.0.0.1:8080 67 + AUTH_GITHUB_ID= 68 + AUTH_GITHUB_SECRET= 69 + AUTH_GOOGLE_ID= 70 + AUTH_GOOGLE_SECRET=
+4
apps/web/next.config.js
··· 15 15 // "better-sqlite3" 16 16 ], 17 17 optimizePackageImports: ["@tremor/react"], 18 + // FIXME: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout 19 + // TODO: https://nextjs.org/docs/app/api-reference/functions/use-search-params#static-rendering 20 + // TODO: https://nextjs.org/docs/messages/deopted-into-client-rendering 21 + missingSuspenseWithCSRBailout: false, 18 22 }, 19 23 logging: { 20 24 fetches: {
+10 -6
apps/web/package.json
··· 10 10 "tsc": "tsc --noEmit" 11 11 }, 12 12 "dependencies": { 13 - "@clerk/nextjs": "4.29.9", 13 + "@auth/core": "0.30.0", 14 + "@auth/drizzle-adapter": "1.0.1", 14 15 "@google-cloud/tasks": "5.0.0", 15 16 "@headlessui/react": "1.7.17", 16 17 "@hookform/resolvers": "3.3.1", 18 + "@libsql/client": "0.6.0", 17 19 "@openstatus/analytics": "workspace:*", 18 20 "@openstatus/api": "workspace:*", 19 21 "@openstatus/assertions": "workspace:*", 20 22 "@openstatus/db": "workspace:*", 21 23 "@openstatus/emails": "workspace:*", 24 + "@openstatus/next-monitoring": "0.0.2", 22 25 "@openstatus/notification-discord": "workspace:*", 23 26 "@openstatus/notification-emails": "workspace:*", 24 27 "@openstatus/notification-slack": "workspace:*", 25 - "@openstatus/next-monitoring": "0.0.2", 26 28 "@openstatus/plans": "workspace:*", 27 29 "@openstatus/react": "workspace:*", 30 + "@openstatus/rum": "workspace:*", 28 31 "@openstatus/tinybird": "workspace:*", 29 32 "@openstatus/tracker": "workspace:*", 30 33 "@openstatus/ui": "workspace:*", 31 34 "@openstatus/upstash": "workspace:*", 32 35 "@openstatus/utils": "workspace:*", 33 - "@openstatus/rum": "workspace:*", 34 36 "@sentry/integrations": "7.100.1", 35 37 "@sentry/nextjs": "7.100.1", 36 38 "@stripe/stripe-js": "2.1.6", ··· 58 60 "luxon": "3.3.0", 59 61 "micro": "10.0.1", 60 62 "nanoid": "5.0.1", 61 - "next": "14.2.1", 63 + "next": "14.2.3", 64 + "next-auth": "5.0.0-beta.17", 62 65 "next-contentlayer": "0.3.4", 63 66 "next-plausible": "3.12.0", 64 67 "next-themes": "0.2.1", 68 + "random-word-slugs": "0.1.7", 65 69 "react": "18.2.0", 66 70 "react-day-picker": "8.8.2", 67 71 "react-dom": "18.2.0", ··· 73 77 "remark-parse": "10.0.2", 74 78 "remark-rehype": "10.1.0", 75 79 "resend": "1.1.0", 76 - "rss": "^1.2.2", 80 + "rss": "1.2.2", 77 81 "shiki": "0.14.4", 78 82 "sonner": "1.3.1", 79 83 "stripe": "13.8.0", ··· 90 94 "@types/node": "20.8.0", 91 95 "@types/react": "18.2.64", 92 96 "@types/react-dom": "18.2.21", 93 - "@types/rss": "^0.0.32", 97 + "@types/rss": "0.0.32", 94 98 "autoprefixer": "10.4.16", 95 99 "postcss": "8.4.31", 96 100 "rehype-autolink-headings": "7.1.0",
+3
apps/web/src/app/api/auth/[...nextauth]/route.ts
··· 1 + import { handlers } from "@/lib/auth"; 2 + 3 + export const { GET, POST } = handlers;
-57
apps/web/src/app/api/webhook/clerk/route.ts
··· 1 - import type { NextRequest } from "next/server"; 2 - import { NextResponse } from "next/server"; 3 - 4 - import { createTRPCContext } from "@openstatus/api"; 5 - import { lambdaRouter } from "@openstatus/api/src/lambda"; 6 - import { clerkEvent } from "@openstatus/api/src/router/clerk/type"; 7 - 8 - // import { clerkEvent } from "@openstatus/api/src/router/clerk"; 9 - 10 - // export const config = { 11 - // api: { 12 - // bodyParser: false, 13 - // }, 14 - // }; 15 - 16 - export async function POST(req: NextRequest) { 17 - // Get witch headers is missing 18 - // const wh = new Webhook(env.CLERK_WEBHOOK_SECRET); 19 - // const msg = wh.verify(JSON.stringify(await req.json()), req.headers as any); 20 - const json = await req.json(); 21 - const r = clerkEvent.safeParse(json); 22 - if (!r.success) { 23 - return NextResponse.json( 24 - { error: "Internal Server Error" }, 25 - { status: 500 }, 26 - ); 27 - } 28 - 29 - const ctx = createTRPCContext({ req }); 30 - const caller = lambdaRouter.createCaller(ctx); 31 - const event = r.data.type; 32 - switch (event) { 33 - case "user.created": 34 - await caller.clerkRouter.webhooks.userCreated({ data: r.data }); 35 - break; 36 - case "user.updated": 37 - case "user.deleted": 38 - break; 39 - 40 - case "session.created": 41 - await caller.clerkRouter.webhooks.userSignedIn({ data: r.data }); 42 - break; 43 - case "session.revoked": 44 - case "session.removed": 45 - case "session.ended": 46 - break; 47 - 48 - case "organization.created": 49 - case "organizationMembership.created": 50 - break; 51 - 52 - default: 53 - ((d: never) => console.error(`${d} not handled here`))(event); 54 - break; 55 - } 56 - return NextResponse.json({ success: true }); 57 - }
+1 -1
apps/web/src/app/api/webhook/stripe/route.ts
··· 22 22 /** 23 23 * Forward to tRPC API to handle the webhook event 24 24 */ 25 - const ctx = createTRPCContext({ req }); 25 + const ctx = await createTRPCContext({ req }); 26 26 const caller = lambdaRouter.createCaller(ctx); 27 27 28 28 switch (event.type) {
+21 -15
apps/web/src/app/app/(auth)/layout.tsx
··· 1 1 import * as React from "react"; 2 + import Image from "next/image"; 3 + import Link from "next/link"; 2 4 import { redirect } from "next/navigation"; 3 - import { auth } from "@clerk/nextjs"; 5 + 6 + import { auth } from "@/lib/auth"; 4 7 5 - export default function AuthLayout({ 8 + export default async function AuthLayout({ 6 9 children, 7 10 }: { 8 11 children: React.ReactNode; 9 12 }) { 10 - const { userId } = auth(); 13 + const session = await auth(); 14 + if (session) redirect("/app"); 11 15 12 - if (userId) { 13 - redirect("/app"); 14 - } 15 16 return ( 16 - <div className="grid min-h-screen grid-cols-1 md:grid-cols-2 xl:grid-cols-3"> 17 - <aside className="border-border col-span-1 flex w-full items-center justify-center border p-3 backdrop-blur-[2px] md:p-6"> 18 - <div className="w-full max-w-lg text-left"> 17 + <div className="grid min-h-screen grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-5"> 18 + <aside className="border-border col-span-1 flex w-full flex-col gap-4 border p-4 backdrop-blur-[2px] md:p-8 xl:col-span-2"> 19 + <Link href="/" className="relative"> 20 + <Image 21 + src="/icon.png" 22 + alt="OpenStatus" 23 + height={30} 24 + width={30} 25 + className="border-border rounded-full border" 26 + /> 27 + </Link> 28 + <div className="flex w-full max-w-lg flex-1 flex-col justify-center text-left"> 19 29 <h1 className="font-cal text-foreground mb-3 text-2xl"> 20 30 Open Source Monitoring Service 21 31 </h1> ··· 34 44 </a>{" "} 35 45 and let us know your use case! 36 46 </p> 37 - {/* Add Demo tracker here? */} 38 - <div className="h-12" /> 39 - {/* <p className="text-muted-foreground text-right text-sm font-light"> 40 - *your data is safe 41 - </p> */} 42 47 </div> 48 + <div className="md:h-[30px]" /> 43 49 </aside> 44 - <main className="container col-span-1 mx-auto flex items-center justify-center md:col-span-1 xl:col-span-2"> 50 + <main className="container col-span-1 mx-auto flex items-center justify-center md:col-span-1 xl:col-span-3"> 45 51 {children} 46 52 </main> 47 53 </div>
+76
apps/web/src/app/app/(auth)/login/page.tsx
··· 1 + import Link from "next/link"; 2 + import { z } from "zod"; 3 + 4 + import { Button } from "@openstatus/ui"; 5 + 6 + import { Shell } from "@/components/dashboard/shell"; 7 + import { Icons } from "@/components/icons"; 8 + import { signIn } from "@/lib/auth"; 9 + 10 + /** 11 + * allowed URL search params 12 + */ 13 + const searchParamsSchema = z.object({ 14 + redirectTo: z.string().optional().default("/app"), 15 + }); 16 + 17 + export default function Page({ 18 + searchParams, 19 + }: { 20 + searchParams: { [key: string]: string | string[] | undefined }; 21 + }) { 22 + const search = searchParamsSchema.safeParse(searchParams); 23 + const redirectTo = search.success ? search.data.redirectTo : "/app"; 24 + 25 + return ( 26 + <Shell className="my-4 grid w-full max-w-xl gap-6 md:p-10"> 27 + <div className="flex flex-col gap-2 text-center"> 28 + <h1 className="text-3xl font-semibold tracking-tight">Sign In</h1> 29 + <p className="text-muted-foreground text-sm"> 30 + Get started now. No credit card required. 31 + </p> 32 + </div> 33 + <div className="grid gap-3"> 34 + <form 35 + action={async () => { 36 + "use server"; 37 + await signIn("github", { redirectTo }); 38 + }} 39 + className="w-full" 40 + > 41 + <Button type="submit" className="w-full"> 42 + Signin with GitHub <Icons.github className="ml-2 h-4 w-4" /> 43 + </Button> 44 + </form> 45 + <form 46 + action={async () => { 47 + "use server"; 48 + await signIn("google", { redirectTo }); 49 + }} 50 + className="w-full" 51 + > 52 + <Button type="submit" className="w-full" variant="outline"> 53 + Signin with Google <Icons.google className="ml-2 h-4 w-4" /> 54 + </Button> 55 + </form> 56 + </div> 57 + <p className="text-muted-foreground px-8 text-center text-sm"> 58 + By clicking continue, you agree to our{" "} 59 + <Link 60 + href="/legal/terms" 61 + className="hover:text-primary underline underline-offset-4 hover:no-underline" 62 + > 63 + Terms of Service 64 + </Link>{" "} 65 + and{" "} 66 + <Link 67 + href="/legal/privacy" 68 + className="hover:text-primary underline underline-offset-4 hover:no-underline" 69 + > 70 + Privacy Policy 71 + </Link> 72 + . 73 + </p> 74 + </Shell> 75 + ); 76 + }
-5
apps/web/src/app/app/(auth)/sign-in/[[...sign-in]]/page.tsx
··· 1 - import { SignIn } from "@clerk/nextjs"; 2 - 3 - export default function Page() { 4 - return <SignIn redirectUrl={"/app"} afterSignInUrl={"/app"} />; 5 - }
+5
apps/web/src/app/app/(auth)/sign-in/page.tsx
··· 1 + import { redirect } from "next/navigation"; 2 + 3 + export default function Page() { 4 + return redirect("/app/login"); 5 + }
-5
apps/web/src/app/app/(auth)/sign-up/[[...sign-up]]/page.tsx
··· 1 - import { SignUp } from "@clerk/nextjs"; 2 - 3 - export default function Page() { 4 - return <SignUp redirectUrl={"/app"} afterSignUpUrl={"/app"} />; 5 - }
+5
apps/web/src/app/app/(auth)/sign-up/page.tsx
··· 1 + import { redirect } from "next/navigation"; 2 + 3 + export default function Page() { 4 + return redirect("/app/login"); 5 + }
+4 -4
apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/api-token/_components/actions.ts
··· 1 1 "use server"; 2 2 3 - import { currentUser } from "@clerk/nextjs"; 4 3 import { Unkey } from "@unkey/api"; 5 4 6 5 import { db, eq } from "@openstatus/db"; 7 6 import { user, usersToWorkspaces, workspace } from "@openstatus/db/src/schema"; 8 7 9 8 import { env } from "@/env"; 9 + import { auth } from "@/lib/auth"; 10 10 11 11 const unkey = new Unkey({ token: env.UNKEY_TOKEN, cache: "no-cache" }); 12 12 13 13 // REMINDER: server actions should have middlewares to do auth checks 14 14 15 15 export async function create(ownerId: number) { 16 - const _user = await currentUser(); 16 + const session = await auth(); 17 17 18 - if (!_user) return; 18 + if (!session?.user?.id) return; 19 19 20 20 const allowedWorkspaces = await db 21 21 .select() 22 22 .from(usersToWorkspaces) 23 23 .innerJoin(user, eq(user.id, usersToWorkspaces.userId)) 24 24 .innerJoin(workspace, eq(workspace.id, usersToWorkspaces.workspaceId)) 25 - .where(eq(user.tenantId, _user.id)) 25 + .where(eq(user.tenantId, session.user.id)) 26 26 .all(); 27 27 28 28 const allowedIds = allowedWorkspaces.map((i) => i.workspace.id);
+13
apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/user/layout.tsx
··· 1 + import { Header } from "@/components/dashboard/header"; 2 + import { getPageBySegment } from "@/config/pages"; 3 + 4 + const page = getPageBySegment(["settings", "user"]); 5 + 6 + export default function Layout({ children }: { children: React.ReactNode }) { 7 + return ( 8 + <> 9 + <Header title={page?.title} description={page?.description} /> 10 + {children} 11 + </> 12 + ); 13 + }
+7
apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/user/loading.tsx
··· 1 + import { Skeleton } from "@openstatus/ui"; 2 + 3 + // TODO: can be improved... 4 + 5 + export default function Loading() { 6 + return <Skeleton className="h-72 w-full" />; 7 + }
+54
apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/user/page.tsx
··· 1 + "use client"; 2 + 3 + import { useSession } from "next-auth/react"; 4 + 5 + import { 6 + Avatar, 7 + AvatarFallback, 8 + AvatarImage, 9 + Input, 10 + Label, 11 + } from "@openstatus/ui"; 12 + 13 + import Loading from "./loading"; 14 + 15 + export default function UserPage() { 16 + const session = useSession(); 17 + 18 + if (!session.data?.user) { 19 + return <Loading />; 20 + } 21 + 22 + return ( 23 + <div className="flex flex-col gap-8"> 24 + <div className="grid max-w-sm gap-3"> 25 + <div className="grid w-full items-center gap-1.5"> 26 + <Label htmlFor="fullname">Full name</Label> 27 + <Input id="fullname" value={`${session.data.user?.name}`} disabled /> 28 + </div> 29 + <div className="grid w-full items-center gap-1.5"> 30 + <Label htmlFor="email">Email</Label> 31 + <Input 32 + id="email" 33 + type="email" 34 + value={`${session.data.user?.email}`} 35 + disabled 36 + /> 37 + </div> 38 + {/* <div className="flex flex-wrap items-end gap-2"> 39 + <div className="grid items-center gap-1.5"> 40 + <Label htmlFor="avatar">Image</Label> 41 + <Input id="avatar" type="file" className="w-56" disabled /> 42 + </div> 43 + <Avatar className="h-10 w-10"> 44 + <AvatarImage 45 + src={session.data.user?.photoUrl || undefined} 46 + alt={`${session.data.user?.name}`} 47 + /> 48 + <AvatarFallback></AvatarFallback> 49 + </Avatar> 50 + </div> */} 51 + </div> 52 + </div> 53 + ); 54 + }
+2 -2
apps/web/src/app/app/layout.tsx
··· 1 - import { ClerkProvider } from "@clerk/nextjs"; 1 + import { SessionProvider } from "next-auth/react"; 2 2 3 3 export default function AuthLayout({ 4 4 children, // will be a page or nested layout 5 5 }: { 6 6 children: React.ReactNode; 7 7 }) { 8 - return <ClerkProvider>{children}</ClerkProvider>; 8 + return <SessionProvider>{children}</SessionProvider>; 9 9 }
-1
apps/web/src/app/layout.tsx
··· 38 38 }: { 39 39 children: React.ReactNode; 40 40 }) { 41 - // If you want to develop locally without Clerk, Comment the provider below 42 41 return ( 43 42 <html lang="en"> 44 43 <body className={`${inter.className} ${calSans.variable}`}>
-19
apps/web/src/app/status-page/[domain]/_components/user-button.tsx
··· 1 - "use client"; 2 - 3 - import Link from "next/link"; 4 - import { useUser } from "@clerk/nextjs"; 5 - 6 - import { Button } from "@openstatus/ui"; 7 - 8 - // Create a button only displayed if you are logged in and are the owner of the status page 9 - export function UserButton() { 10 - const { isSignedIn } = useUser(); 11 - if (isSignedIn) { 12 - return ( 13 - <Button asChild> 14 - <Link href="https://openstatus.dev/app">OpenStatus Dashboard</Link> 15 - </Button> 16 - ); 17 - } 18 - return null; 19 - }
+10
apps/web/src/components/icons.tsx
··· 45 45 ToyBrick, 46 46 Trash, 47 47 TwitterIcon, 48 + UserCircle, 48 49 Users, 49 50 Webhook, 50 51 Youtube, ··· 106 107 "hour-glass": Hourglass, 107 108 "candlestick-chart": CandlestickChart, 108 109 ratio: Ratio, 110 + user: UserCircle, 109 111 discord: ({ ...props }: LucideProps) => ( 110 112 <svg viewBox="0 0 640 512" {...props}> 111 113 <path 112 114 fill="currentColor" 113 115 d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z" 116 + /> 117 + </svg> 118 + ), 119 + google: (props: LucideProps) => ( 120 + <svg viewBox="0 0 24 24" {...props}> 121 + <path 122 + fill="currentColor" 123 + d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" 114 124 /> 115 125 </svg> 116 126 ),
+2 -3
apps/web/src/components/layout/header/app-header.tsx
··· 1 1 "use client"; 2 2 3 3 import Link from "next/link"; 4 - import { UserButton, useUser } from "@clerk/nextjs"; 5 4 import { allChangelogs } from "contentlayer/generated"; 6 5 import { ArrowUpRight } from "lucide-react"; 7 6 ··· 11 10 import { useCookieState } from "@/hooks/use-cookie-state"; 12 11 import { AppTabs } from "./app-tabs"; 13 12 import { Breadcrumbs } from "./breadcrumbs"; 13 + import { UserNav } from "./user-nav"; 14 14 15 15 const lastChangelog = allChangelogs 16 16 .sort( ··· 20 20 .pop(); 21 21 22 22 export function AppHeader() { 23 - const { isLoaded, isSignedIn } = useUser(); 24 23 const [lastViewed, setLastViewed] = useCookieState( 25 24 "last-viewed-changelog", 26 25 new Date(0).toISOString(), ··· 67 66 <div className="relative"> 68 67 <Skeleton className="h-8 w-8 rounded-full" /> 69 68 <div className="absolute inset-0"> 70 - {isLoaded && isSignedIn && <UserButton />} 69 + <UserNav /> 71 70 </div> 72 71 </div> 73 72 </div>
+70
apps/web/src/components/layout/header/user-nav.tsx
··· 1 + import Link from "next/link"; 2 + import { useParams } from "next/navigation"; 3 + import { signOut, useSession } from "next-auth/react"; 4 + 5 + import { 6 + Avatar, 7 + AvatarFallback, 8 + AvatarImage, 9 + Button, 10 + DropdownMenu, 11 + DropdownMenuContent, 12 + DropdownMenuGroup, 13 + DropdownMenuItem, 14 + DropdownMenuLabel, 15 + DropdownMenuSeparator, 16 + DropdownMenuTrigger, 17 + Skeleton, 18 + } from "@openstatus/ui"; 19 + 20 + export function UserNav() { 21 + const session = useSession(); 22 + const { workspaceSlug } = useParams<{ workspaceSlug: string }>(); 23 + 24 + if (session.status !== "authenticated") { 25 + return <Skeleton className="h-8 w-8 rounded-full" />; 26 + } 27 + 28 + return ( 29 + <DropdownMenu> 30 + <DropdownMenuTrigger asChild> 31 + <Button variant="ghost" className="relative h-8 w-8 rounded-full"> 32 + <Avatar className="h-8 w-8"> 33 + <AvatarImage 34 + src={session.data.user?.photoUrl || undefined} 35 + alt={ 36 + session.data.user?.name || 37 + `${session.data.user?.firstName} ${session.data.user?.lastName}` 38 + } 39 + /> 40 + <AvatarFallback></AvatarFallback> 41 + </Avatar> 42 + </Button> 43 + </DropdownMenuTrigger> 44 + <DropdownMenuContent className="w-56" align="end" forceMount> 45 + <DropdownMenuLabel className="font-normal"> 46 + <div className="flex flex-col space-y-1"> 47 + <p className="truncate text-sm font-medium leading-none"> 48 + {session.data.user?.name || 49 + `${session.data.user?.firstName} ${session.data.user?.lastName}`} 50 + </p> 51 + <p className="text-muted-foreground truncate text-xs leading-none"> 52 + {session.data.user?.email} 53 + </p> 54 + </div> 55 + </DropdownMenuLabel> 56 + <DropdownMenuSeparator /> 57 + <DropdownMenuGroup> 58 + <DropdownMenuItem asChild> 59 + <Link href={`/app/${workspaceSlug}/settings/billing`}>Billing</Link> 60 + </DropdownMenuItem> 61 + <DropdownMenuItem asChild> 62 + <Link href={`/app/${workspaceSlug}/settings/user`}>Profile</Link> 63 + </DropdownMenuItem> 64 + </DropdownMenuGroup> 65 + <DropdownMenuSeparator /> 66 + <DropdownMenuItem onClick={() => signOut()}>Log out</DropdownMenuItem> 67 + </DropdownMenuContent> 68 + </DropdownMenu> 69 + ); 70 + }
+4 -4
apps/web/src/components/layout/login-button.tsx
··· 1 1 "use client"; 2 2 3 3 import Link from "next/link"; 4 - import { useUser } from "@clerk/nextjs"; 4 + import { useSession } from "next-auth/react"; 5 5 6 6 import type { ButtonProps } from "@openstatus/ui"; 7 7 import { Button } from "@openstatus/ui"; ··· 9 9 import { cn } from "@/lib/utils"; 10 10 11 11 export function LoginButton({ className, ...props }: ButtonProps) { 12 - const { isSignedIn } = useUser(); 12 + const session = useSession(); 13 13 14 14 return ( 15 15 <Button asChild className={cn("rounded-full", className)} {...props}> 16 - {isSignedIn ? ( 16 + {session.status === "authenticated" ? ( 17 17 <Link href="/app">Dashboard</Link> 18 18 ) : ( 19 - <Link href="/app/sign-up">Sign Up</Link> 19 + <Link href="/app/login">Sign In</Link> 20 20 )} 21 21 </Button> 22 22 );
+3 -3
apps/web/src/components/layout/marketing-layout.tsx
··· 1 - import { ClerkProvider } from "@clerk/nextjs"; 1 + import { SessionProvider } from "next-auth/react"; 2 2 import PlausibleProvider from "next-plausible"; 3 3 4 4 import { MarketingFooter } from "./marketing-footer"; ··· 7 7 export function MarketingLayout({ children }: { children: React.ReactNode }) { 8 8 return ( 9 9 <PlausibleProvider domain="openstatus.dev"> 10 - <ClerkProvider> 10 + <SessionProvider> 11 11 <main className="flex min-h-screen w-full flex-col items-center justify-center gap-8 p-4 md:p-8"> 12 12 <MarketingHeader className="mx-auto w-full max-w-4xl" /> 13 13 <div className="mx-auto flex w-full max-w-4xl flex-1 flex-col items-start justify-center"> ··· 15 15 </div> 16 16 <MarketingFooter className="mx-auto w-full max-w-4xl" /> 17 17 </main> 18 - </ClerkProvider> 18 + </SessionProvider> 19 19 </PlausibleProvider> 20 20 ); 21 21 }
+3 -3
apps/web/src/components/layout/public-layout.tsx
··· 1 - import { ClerkProvider } from "@clerk/nextjs"; 1 + import { SessionProvider } from "next-auth/react"; 2 2 3 3 import { MarketingFooter } from "./marketing-footer"; 4 4 import { PublicHeader } from "./public-header"; 5 5 6 6 export function PublicLayout({ children }: { children: React.ReactNode }) { 7 7 return ( 8 - <ClerkProvider> 8 + <SessionProvider> 9 9 <main className="flex min-h-screen w-full flex-col items-center justify-center gap-8 p-4 md:p-8"> 10 10 <PublicHeader className="mx-auto w-full max-w-4xl" /> 11 11 <div className="mx-auto flex w-full max-w-4xl flex-1 flex-col items-start justify-center"> ··· 13 13 </div> 14 14 <MarketingFooter className="mx-auto w-full max-w-4xl" /> 15 15 </main> 16 - </ClerkProvider> 16 + </SessionProvider> 17 17 ); 18 18 }
+1 -1
apps/web/src/components/monitor-dashboard/response-details.tsx
··· 60 60 <div> 61 61 <pre 62 62 className="bg-muted text-wrap rounded-md p-4 text-sm" 63 - // @ts-expect-error textWrap is not a valid prop even though it is 63 + // @ts-expect-error some issues with types 64 64 style={{ textWrap: "wrap" }} 65 65 > 66 66 {message}
+1 -1
apps/web/src/components/ping-response-analysis/response-detail-tabs.tsx
··· 53 53 <div> 54 54 <pre 55 55 className="bg-muted text-wrap rounded-md p-4 text-sm" 56 - // @ts-expect-error textWrap is not a valid prop even though it is 56 + // @ts-expect-error some issues with types 57 57 style={{ textWrap: "wrap" }} 58 58 > 59 59 {message}
+7
apps/web/src/config/pages.ts
··· 46 46 icon: "sun", 47 47 segment: "appearance", 48 48 }, 49 + { 50 + title: "User", 51 + description: "Profile settings for the user.", 52 + href: "/settings/user", 53 + icon: "user", 54 + segment: "user", 55 + }, 49 56 ]; 50 57 51 58 export const monitorPagesConfig: Page[] = [
-17
apps/web/src/env.ts
··· 6 6 7 7 export const env = createEnv({ 8 8 server: { 9 - CLERK_SECRET_KEY: z.string().min(1), 10 9 TINY_BIRD_API_KEY: z.string().min(1), 11 10 RESEND_API_KEY: z.string().min(1), 12 - CLERK_WEBHOOK_SECRET: z.string().min(1), 13 11 QSTASH_CURRENT_SIGNING_KEY: z.string().min(1), 14 12 QSTASH_NEXT_SIGNING_KEY: z.string().min(1), 15 13 QSTASH_TOKEN: z.string().min(1), ··· 27 25 CLICKHOUSE_PASSWORD: z.string(), 28 26 }, 29 27 client: { 30 - NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1), 31 - NEXT_PUBLIC_CLERK_SIGN_IN_URL: z.string().min(1), 32 - NEXT_PUBLIC_CLERK_SIGN_UP_URL: z.string().min(1), 33 - NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL: z.string().min(1), 34 - NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL: z.string().min(1), 35 28 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string(), 36 29 NEXT_PUBLIC_URL: z.string(), 37 30 NEXT_PUBLIC_SENTRY_DSN: z.string(), 38 31 }, 39 32 runtimeEnv: { 40 - CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY, 41 33 TINY_BIRD_API_KEY: process.env.TINY_BIRD_API_KEY, 42 34 RESEND_API_KEY: process.env.RESEND_API_KEY, 43 - CLERK_WEBHOOK_SECRET: process.env.CLERK_WEBHOOK_SECRET, 44 - NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: 45 - process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, 46 - NEXT_PUBLIC_CLERK_SIGN_IN_URL: process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL, 47 - NEXT_PUBLIC_CLERK_SIGN_UP_URL: process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL, 48 - NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL: 49 - process.env.NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL, 50 - NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL: 51 - process.env.NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL, 52 35 QSTASH_CURRENT_SIGNING_KEY: process.env.QSTASH_CURRENT_SIGNING_KEY, 53 36 QSTASH_NEXT_SIGNING_KEY: process.env.QSTASH_NEXT_SIGNING_KEY, 54 37 QSTASH_TOKEN: process.env.QSTASH_TOKEN,
+36
apps/web/src/lib/auth/adapter.ts
··· 1 + import { DrizzleAdapter } from "@auth/drizzle-adapter"; 2 + import type { DefaultSession } from "next-auth"; 3 + import type { Adapter } from "next-auth/adapters"; 4 + 5 + import { db } from "@openstatus/db"; 6 + import { 7 + account, 8 + session, 9 + user, 10 + verificationToken, 11 + } from "@openstatus/db/src/schema"; 12 + 13 + import { createUser, getUser } from "./helper"; 14 + 15 + export type { DefaultSession }; 16 + 17 + export const adapter: Adapter = { 18 + ...DrizzleAdapter( 19 + // @ts-expect-error some issues with types 20 + db, 21 + { 22 + usersTable: user, 23 + accountsTable: account, 24 + sessionsTable: session, 25 + verificationTokensTable: verificationToken, 26 + }, 27 + ), 28 + // @ts-expect-error some issues with types 29 + createUser: async (data) => { 30 + return await createUser(data); 31 + }, 32 + // @ts-expect-error some issues with types 33 + getUser: async (id) => { 34 + return await getUser(id); 35 + }, 36 + };
+69
apps/web/src/lib/auth/helper.ts
··· 1 + import type { AdapterUser } from "next-auth/adapters"; 2 + import * as randomWordSlugs from "random-word-slugs"; 3 + 4 + import { db, eq } from "@openstatus/db"; 5 + import { user, usersToWorkspaces, workspace } from "@openstatus/db/src/schema"; 6 + 7 + export async function createUser(data: AdapterUser) { 8 + const { id, ...rest } = data; 9 + 10 + const newUser = await db 11 + .insert(user) 12 + .values({ email: rest.email, photoUrl: rest.image, name: rest.name }) 13 + .returning({ 14 + id: user.id, 15 + email: user.email, 16 + emailVerified: user.emailVerified, 17 + }) 18 + .get(); 19 + 20 + let slug: string | undefined = undefined; 21 + 22 + while (!slug) { 23 + slug = randomWordSlugs.generateSlug(2); 24 + const slugAlreadyExists = await db 25 + .select() 26 + .from(workspace) 27 + .where(eq(workspace.slug, slug)) 28 + .get(); 29 + 30 + if (slugAlreadyExists) { 31 + console.log(`slug already exists: '${slug}'`); 32 + slug = undefined; 33 + } 34 + } 35 + 36 + const newWorkspace = await db 37 + .insert(workspace) 38 + .values({ slug, name: "" }) 39 + .returning({ id: workspace.id }) 40 + .get(); 41 + 42 + await db 43 + .insert(usersToWorkspaces) 44 + .values({ 45 + userId: newUser.id, 46 + workspaceId: newWorkspace.id, 47 + role: "owner", 48 + }) 49 + .returning() 50 + .get(); 51 + 52 + return newUser; 53 + } 54 + 55 + export async function getUser(id: string) { 56 + const _user = await db 57 + .select({ 58 + id: user.id, 59 + email: user.email, 60 + firstName: user.firstName, 61 + lastName: user.lastName, 62 + photoUrl: user.photoUrl, 63 + }) 64 + .from(user) 65 + .where(eq(user.id, Number(id))) 66 + .get(); 67 + 68 + return _user || null; 69 + }
+117
apps/web/src/lib/auth/index.ts
··· 1 + import type { DefaultSession } from "next-auth"; 2 + import NextAuth from "next-auth"; 3 + import GitHub from "next-auth/providers/github"; 4 + import Google from "next-auth/providers/google"; 5 + 6 + import { analytics, trackAnalytics } from "@openstatus/analytics"; 7 + // import Credentials from "next-auth/providers/credentials"; 8 + 9 + import { db, eq } from "@openstatus/db"; 10 + import { user } from "@openstatus/db/src/schema"; 11 + import { sendEmail, WelcomeEmail } from "@openstatus/emails"; 12 + 13 + import { adapter } from "./adapter"; 14 + 15 + export type { DefaultSession }; 16 + 17 + export const { handlers, signIn, signOut, auth } = NextAuth({ 18 + // debug: true, 19 + adapter, 20 + providers: [ 21 + GitHub({ allowDangerousEmailAccountLinking: true }), 22 + Google({ 23 + allowDangerousEmailAccountLinking: true, 24 + authorization: { 25 + params: { 26 + // See https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest 27 + prompt: "select_account", 28 + // scope: 29 + // "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email", 30 + }, 31 + }, 32 + }), 33 + ], 34 + callbacks: { 35 + async signIn(params) { 36 + // We keep updating the user info when we loggin in 37 + 38 + if (params.account?.provider === "google") { 39 + if (!params.profile) return true; 40 + if (Number.isNaN(Number(params.user.id))) return true; 41 + 42 + console.log(params.profile); 43 + 44 + await db 45 + .update(user) 46 + .set({ 47 + firstName: params.profile.given_name, 48 + lastName: params.profile.family_name, 49 + photoUrl: params.profile.picture, 50 + // keep the name in sync 51 + name: `${params.profile.given_name} ${params.profile.family_name}`, 52 + }) 53 + .where(eq(user.id, Number(params.user.id))) 54 + .run(); 55 + } 56 + if (params.account?.provider === "github") { 57 + if (!params.profile) return true; 58 + if (Number.isNaN(Number(params.user.id))) return true; 59 + 60 + console.log(params.profile); 61 + 62 + await db 63 + .update(user) 64 + .set({ 65 + name: params.profile.name, 66 + photoUrl: String(params.profile.avatar_url), 67 + }) 68 + .where(eq(user.id, Number(params.user.id))) 69 + .run(); 70 + } 71 + 72 + return true; 73 + }, 74 + async session(params) { 75 + return params.session; 76 + }, 77 + }, 78 + events: { 79 + // That should probably done in the callback method instead 80 + async createUser(params) { 81 + if (!params.user.id || !params.user.email) { 82 + throw new Error("User id & email is required"); 83 + } 84 + 85 + // this means the user has already been created with clerk 86 + if (params.user.tenantId) return; 87 + 88 + await sendEmail({ 89 + from: "Thibault Le Ouay Ducasse <thibault@openstatus.dev>", 90 + subject: "Level up your website and API monitoring.", 91 + to: [params.user.email], 92 + react: WelcomeEmail(), 93 + }); 94 + 95 + const { id: userId, email } = params.user; 96 + 97 + await analytics.identify(userId, { email, userId }); 98 + await trackAnalytics({ event: "User Created", userId, email }); 99 + }, 100 + 101 + async signIn(params) { 102 + if (params.isNewUser) return; 103 + if (!params.user.id || !params.user.email) return; 104 + 105 + const { id: userId, email } = params.user; 106 + 107 + await analytics.identify(userId, { userId, email }); 108 + await trackAnalytics({ event: "User Signed In" }); 109 + }, 110 + }, 111 + pages: { 112 + signIn: "/app/login", 113 + // newUser: "/app/onboarding", // TODO: rethink this as we still have the `slug` to use 114 + }, 115 + // basePath: "/api/auth", // default is `/api/auth` 116 + // secret: process.env.AUTH_SECRET, // default is `AUTH_SECRET` 117 + });
+90 -117
apps/web/src/middleware.ts
··· 1 - import type { NextRequest } from "next/server"; 2 1 import { NextResponse } from "next/server"; 3 - import { authMiddleware, redirectToSignIn } from "@clerk/nextjs"; 4 2 5 3 import { db, eq } from "@openstatus/db"; 6 - import { 7 - monitor, 8 - user, 9 - usersToWorkspaces, 10 - workspace, 11 - } from "@openstatus/db/src/schema"; 4 + import { user, usersToWorkspaces, workspace } from "@openstatus/db/src/schema"; 12 5 6 + import { auth } from "@/lib/auth"; 13 7 import { env } from "./env"; 14 8 15 - const before = (req: NextRequest) => { 16 - const url = req.nextUrl.clone(); 17 - 18 - if (url.pathname.includes("api/trpc")) { 19 - return NextResponse.next(); 20 - } 21 - 22 - const host = req.headers.get("host"); 23 - const subdomain = getValidSubdomain(host); 24 - if (subdomain) { 25 - // Subdomain available, rewriting 26 - console.log( 27 - `>>> Rewriting: ${url.pathname} to /status-page/${subdomain}${url.pathname}`, 28 - ); 29 - url.pathname = `/status-page/${subdomain}${url.pathname}`; 30 - return NextResponse.rewrite(url); 31 - } 32 - 33 - return NextResponse.next(); 34 - }; 35 - 36 9 export const getValidSubdomain = (host?: string | null) => { 37 10 let subdomain: string | null = null; 38 11 if (!host && typeof window !== "undefined") { ··· 60 33 return subdomain; 61 34 }; 62 35 63 - export default authMiddleware({ 64 - publicRoutes: [ 65 - "/", 66 - "/play", 67 - "/play/(.*)", 68 - "/monitor/(.*)", 69 - "/api/(.*)", 70 - "/api/webhook/clerk", 71 - "/api/checker/regions/(.*)", 72 - "/api/checker/cron/10m", 73 - "/blog", 74 - "/blog/(.*)", 75 - "/status", 76 - "/status/(.*)", 77 - "/changelog", 78 - "/changelog/(.*)", 79 - "/legal/(.*)", 80 - "/about", 81 - "/cal", 82 - "/discord", 83 - "/github", 84 - "/pricing", 85 - "/oss-friends", 86 - "/status-page/(.*)", 87 - "/incidents", // used when trying subdomain slug via status.documenso.com/incidents 88 - "/incidents/(.*)", // used when trying subdomain slug via status.documenso.com/incidents/123 89 - "/monitors", // used when trying subdomain slug via status.documenso.com/monitors 90 - "/monitors/(.*)", // used when trying subdomain slug via status.documenso.com/monitors/123 91 - "/verify/(.*)", // used when trying subdomain slug via status.documenso.com/incidents 92 - "/public/(.*)", 93 - "/badge", // used when trying subdomain slug via status.documenso.com/badge to get the badge 94 - ], 95 - ignoredRoutes: ["/api/og", "/discord", "/github", "/status-page/(.*)"], // FIXME: we should check the `publicRoutes` 96 - beforeAuth: before, 97 - debug: true, // FIXME: status.revert.dev 98 - async afterAuth(auth, req) { 99 - // handle users who aren't authenticated 100 - if (!auth.userId && !auth.isPublicRoute) { 101 - return redirectToSignIn({ returnBackUrl: req.url }); 102 - } 36 + const publicAppPaths = [ 37 + "/app/sign-in", 38 + "/app/sign-up", 39 + "/app/login", 40 + "/app/invite", 41 + ]; 103 42 104 - if (auth.userId) { 105 - const pathname = req.nextUrl.pathname; 106 - if (pathname.startsWith("/app") && !pathname.startsWith("/app/invite")) { 107 - const workspaceSlug = req.nextUrl.pathname.split("/")?.[2]; 108 - const hasWorkspaceSlug = !!workspaceSlug && workspaceSlug.trim() !== ""; 43 + // remove auth middleware if needed 44 + // export const middleware = () => NextResponse.next(); 45 + 46 + export default auth(async (req) => { 47 + const url = req.nextUrl.clone(); 48 + 49 + if (url.pathname.includes("api/trpc")) { 50 + return NextResponse.next(); 51 + } 52 + 53 + const host = req.headers.get("host"); 54 + const subdomain = getValidSubdomain(host); 55 + 56 + // Rewriting to status page! 57 + if (subdomain) { 58 + url.pathname = `/status-page/${subdomain}${url.pathname}`; 59 + return NextResponse.rewrite(url); 60 + } 61 + 62 + const pathname = req.nextUrl.pathname; 63 + 64 + const isPublicAppPath = publicAppPaths.some((path) => 65 + pathname.startsWith(path), 66 + ); 109 67 110 - const allowedWorkspaces = await db 111 - .select() 112 - .from(usersToWorkspaces) 113 - .innerJoin(user, eq(user.id, usersToWorkspaces.userId)) 114 - .innerJoin(workspace, eq(workspace.id, usersToWorkspaces.workspaceId)) 115 - .where(eq(user.tenantId, auth.userId)) 116 - .all(); 68 + if (!req.auth && pathname.startsWith("/app") && !isPublicAppPath) { 69 + return NextResponse.redirect( 70 + new URL(`/app/login?redirectTo=${encodeURIComponent(pathname)}`, req.url), 71 + ); 72 + } 117 73 118 - // means, we are "not only on `/app` or `/app/`" 119 - if (hasWorkspaceSlug) { 120 - console.log(">>> Workspace slug", workspaceSlug); 121 - const hasAccessToWorkspace = allowedWorkspaces.find( 122 - ({ workspace }) => workspace.slug === workspaceSlug, 123 - ); 124 - if (hasAccessToWorkspace) { 125 - console.log(">>> Allowed! Attaching to cookie", workspaceSlug); 126 - req.cookies.set("workspace-slug", workspaceSlug); 127 - } else { 128 - console.log(">>> Not allowed, redirecting to /app", workspaceSlug); 129 - const appURL = new URL("/app", req.url); 130 - return NextResponse.redirect(appURL); 131 - } 132 - } else { 133 - console.log(">>> No workspace slug available"); 134 - if (allowedWorkspaces.length > 0) { 135 - const firstWorkspace = allowedWorkspaces[0].workspace; 136 - const { id, slug } = firstWorkspace; 137 - console.log(">>> Redirecting to first related workspace", slug); 138 - const firstMonitor = await db 139 - .select() 140 - .from(monitor) 141 - .where(eq(monitor.workspaceId, firstWorkspace.id)) 142 - .get(); 74 + if (req.auth && req.auth.user?.id) { 75 + if (pathname.startsWith("/app") && !isPublicAppPath) { 76 + const workspaceSlug = req.nextUrl.pathname.split("/")?.[2]; 77 + const hasWorkspaceSlug = !!workspaceSlug && workspaceSlug.trim() !== ""; 143 78 144 - if (!firstMonitor) { 145 - console.log(`>>> Redirecting to onboarding`, slug); 146 - const onboardingURL = new URL(`/app/${slug}/onboarding`, req.url); 147 - return NextResponse.redirect(onboardingURL); 148 - } 79 + const allowedWorkspaces = await db 80 + .select() 81 + .from(usersToWorkspaces) 82 + .innerJoin(user, eq(user.id, usersToWorkspaces.userId)) 83 + .innerJoin(workspace, eq(workspace.id, usersToWorkspaces.workspaceId)) 84 + .where(eq(user.id, parseInt(req.auth.user.id))) 85 + .all(); 149 86 150 - console.log(">>> Redirecting to workspace", slug); 151 - const monitorURL = new URL(`/app/${slug}/monitors`, req.url); 152 - return NextResponse.redirect(monitorURL); 153 - } 154 - console.log(">>> No action taken"); 87 + if (hasWorkspaceSlug) { 88 + const hasAccessToWorkspace = allowedWorkspaces.find( 89 + ({ workspace }) => workspace.slug === workspaceSlug, 90 + ); 91 + if (hasAccessToWorkspace) { 92 + const response = NextResponse.next(); 93 + response.cookies.set("workspace-slug", workspaceSlug); 94 + return response; 95 + } else { 96 + return NextResponse.redirect(new URL("/app", req.url)); 97 + } 98 + } else { 99 + if (allowedWorkspaces.length > 0) { 100 + const firstWorkspace = allowedWorkspaces[0].workspace; 101 + const { slug } = firstWorkspace; 102 + return NextResponse.redirect( 103 + new URL(`/app/${slug}/monitors`, req.url), 104 + ); 155 105 } 156 106 } 157 107 } 158 - }, 108 + } 109 + 110 + // reset workspace slug cookie if no auth 111 + if (!req.auth && req.cookies.has("workspace-slug")) { 112 + const response = NextResponse.next(); 113 + response.cookies.delete("workspace-slug"); 114 + return response; 115 + } 159 116 }); 160 117 161 118 export const config = { ··· 164 121 "/", 165 122 "/(api/webhook|api/trpc)(.*)", 166 123 "/(!api/checker/:path*|!api/og|!api/ping)", 124 + ], 125 + unstable_allowDynamic: [ 126 + // use a glob to allow anything in the function-bind 3rd party module 127 + // "**/packages/analytics/src/**", 128 + // // "@jitsu/js/**", 129 + // "**/node_modules/@jitsu/**", 130 + // "**/node_modules/**/@jitsu/**", 131 + // "**/node_modules/@openstatus/analytics/**", 132 + // "@openstatus/analytics/**", 133 + // "@jitsu/js/dist/jitsu.es.js", 134 + // "**/analytics/src/**", 135 + // "**/node_modules/.pnpm/@jitsu/**", 136 + // "/node_modules/function-bind/**", 137 + // "**/node_modules/.pnpm/**/function-bind/**", 138 + // "../../packages/analytics/src/index.ts", 139 + "**/node_modules/.pnpm/@jitsu*/**", 167 140 ], 168 141 };
+11
apps/web/src/next-auth.d.ts
··· 1 + import type { DefaultUser } from "next-auth"; 2 + 3 + // FIXME: this is very wrong - no type `DefaultUser` exists 4 + // also doenst provide autocomplete and type safety-ness 5 + 6 + declare module "next-auth" { 7 + interface User extends Omit<DefaultUser, "id"> { 8 + id: number; 9 + email: string; 10 + } 11 + }
+1 -1
apps/web/src/trpc/shared.ts
··· 10 10 return `http://localhost:3000`; 11 11 }; 12 12 13 - const lambdas = ["clerkRouter", "stripeRouter", "rumRouter"]; 13 + const lambdas = ["stripeRouter", "rumRouter"]; 14 14 15 15 export const endingLink = (opts?: { 16 16 headers?: HTTPHeaders | (() => HTTPHeaders);
+1 -1
packages/analytics/package.json
··· 4 4 "description": "", 5 5 "main": "src/index.ts", 6 6 "dependencies": { 7 - "@jitsu/js": "1.3.0", 7 + "@jitsu/js": "1.9.2", 8 8 "@t3-oss/env-core": "0.7.0", 9 9 "zod": "3.22.4" 10 10 },
+1 -2
packages/api/package.json
··· 7 7 "test": "bun test" 8 8 }, 9 9 "dependencies": { 10 - "@clerk/nextjs": "4.29.9", 11 10 "@openstatus/analytics": "workspace:*", 12 11 "@openstatus/assertions": "workspace:*", 13 12 "@openstatus/db": "workspace:*", ··· 19 18 "@trpc/server": "10.45.1", 20 19 "nanoid": "5.0.7", 21 20 "nanoid-dictionary": "5.0.0-beta.1", 22 - "next": "14.2.1", 21 + "next": "14.2.3", 23 22 "random-word-slugs": "0.1.7", 24 23 "stripe": "13.8.0", 25 24 "superjson": "1.13.3",
-2
packages/api/src/lambda.ts
··· 1 - import { clerkRouter } from "./router/clerk/webhook"; 2 1 import { rumRouter } from "./router/rum"; 3 2 import { stripeRouter } from "./router/stripe"; 4 3 import { createTRPCRouter } from "./trpc"; 5 4 6 5 // Deployed to /trpc/lambda/** 7 6 export const lambdaRouter = createTRPCRouter({ 8 - clerkRouter: clerkRouter, 9 7 stripeRouter: stripeRouter, 10 8 rumRouter: rumRouter, 11 9 });
-85
packages/api/src/router/clerk/type.ts
··· 1 - import { z } from "zod"; 2 - 3 - export const clerkEvent = z.discriminatedUnion("type", [ 4 - z.object({ 5 - type: z.literal("user.created"), 6 - data: z.object({ 7 - id: z.string(), 8 - // username: z.string(), 9 - created_at: z.number(), 10 - email_addresses: z.array( 11 - z.object({ 12 - email_address: z.string(), 13 - }), 14 - ), 15 - first_name: z.string().nullable(), 16 - last_name: z.string().nullable(), 17 - }), 18 - }), 19 - z.object({ 20 - type: z.literal("user.updated"), 21 - data: z.object({ 22 - id: z.string(), 23 - updated_at: z.number(), 24 - }), 25 - }), 26 - z.object({ 27 - type: z.literal("user.deleted"), 28 - data: z.object({ 29 - id: z.string(), 30 - }), 31 - }), 32 - z.object({ 33 - type: z.literal("organization.created"), 34 - data: z.object({ 35 - id: z.string(), 36 - slug: z.string(), 37 - name: z.string(), 38 - created_at: z.number(), 39 - }), 40 - }), 41 - z.object({ 42 - type: z.literal("session.created"), 43 - data: z.object({ 44 - id: z.string(), 45 - user_id: z.string(), 46 - created_at: z.number(), 47 - expire_at: z.number(), 48 - }), 49 - }), 50 - z.object({ 51 - type: z.literal("session.revoked"), 52 - data: z.object({ 53 - id: z.string(), 54 - user_id: z.string(), 55 - }), 56 - }), 57 - z.object({ 58 - type: z.literal("session.removed"), 59 - data: z.object({ 60 - id: z.string(), 61 - user_id: z.string(), 62 - }), 63 - }), 64 - z.object({ 65 - type: z.literal("session.ended"), 66 - data: z.object({ 67 - id: z.string(), 68 - user_id: z.string(), 69 - }), 70 - }), 71 - z.object({ 72 - type: z.literal("organizationMembership.created"), 73 - data: z.object({ 74 - created_at: z.number(), 75 - organization: z.object({ 76 - id: z.string(), 77 - slug: z.string(), 78 - name: z.string(), 79 - }), 80 - public_user_data: z.object({ 81 - user_id: z.string(), 82 - }), 83 - }), 84 - }), 85 - ]);
-114
packages/api/src/router/clerk/webhook.ts
··· 1 - import * as randomWordSlugs from "random-word-slugs"; 2 - import * as z from "zod"; 3 - 4 - import { analytics, trackAnalytics } from "@openstatus/analytics"; 5 - import { eq } from "@openstatus/db"; 6 - import { user, usersToWorkspaces, workspace } from "@openstatus/db/src/schema"; 7 - import { sendEmail, WelcomeEmail } from "@openstatus/emails"; 8 - 9 - import { createTRPCRouter, publicProcedure } from "../../trpc"; 10 - import { clerkEvent } from "./type"; 11 - 12 - export const webhookProcedure = publicProcedure.input( 13 - z.object({ 14 - data: clerkEvent, 15 - }), 16 - ); 17 - 18 - export const webhookRouter = createTRPCRouter({ 19 - userCreated: webhookProcedure.mutation(async (opts) => { 20 - if (opts.input.data.type === "user.created") { 21 - // There's no primary key with drizzle I checked the tennant is not already in the database 22 - const alreadyExists = await opts.ctx.db 23 - .select({ id: user.id }) 24 - .from(user) 25 - .where(eq(user.tenantId, opts.input.data.data.id)) 26 - .get(); 27 - if (alreadyExists) return; 28 - const userResult = await opts.ctx.db 29 - .insert(user) 30 - .values({ 31 - email: opts.input.data.data.email_addresses[0].email_address, 32 - tenantId: opts.input.data.data.id, 33 - firstName: opts.input.data.data.first_name, 34 - lastName: opts.input.data.data.last_name || "", 35 - }) 36 - .returning() 37 - .get(); 38 - 39 - // guarantee the slug is unique accross our workspace entries 40 - let slug: string | undefined = undefined; 41 - 42 - while (!slug) { 43 - slug = randomWordSlugs.generateSlug(2); 44 - const slugAlreadyExists = await opts.ctx.db 45 - .select() 46 - .from(workspace) 47 - .where(eq(workspace.slug, slug)) 48 - .get(); 49 - if (slugAlreadyExists) { 50 - console.log(`slug already exists: '${slug}'`); 51 - slug = undefined; 52 - } 53 - } 54 - 55 - const workspaceResult = await opts.ctx.db 56 - .insert(workspace) 57 - .values({ slug, name: "" }) 58 - .returning({ id: workspace.id }) 59 - .get(); 60 - await opts.ctx.db 61 - .insert(usersToWorkspaces) 62 - .values({ 63 - userId: userResult.id, 64 - workspaceId: workspaceResult.id, 65 - role: "owner", 66 - }) 67 - .returning() 68 - .get(); 69 - 70 - await sendEmail({ 71 - from: "Thibault Le Ouay Ducasse <thibault@openstatus.dev>", 72 - subject: "Level up your website and API monitoring.", 73 - to: [opts.input.data.data.email_addresses[0].email_address], 74 - react: WelcomeEmail(), 75 - }); 76 - 77 - await analytics.identify(String(userResult.id), { 78 - email: opts.input.data.data.email_addresses[0].email_address, 79 - userId: userResult.id, 80 - }); 81 - await trackAnalytics({ 82 - event: "User Created", 83 - userId: String(userResult.id), 84 - email: opts.input.data.data.email_addresses[0].email_address, 85 - }); 86 - } 87 - }), 88 - userUpdated: webhookProcedure.mutation(async (opts) => { 89 - if (opts.input.data.type === "user.updated") { 90 - // We should do something 91 - } 92 - }), 93 - userSignedIn: webhookProcedure.mutation(async (opts) => { 94 - if (opts.input.data.type === "session.created") { 95 - const currentUser = await opts.ctx.db 96 - .select({ id: user.id, email: user.email }) 97 - .from(user) 98 - .where(eq(user.tenantId, opts.input.data.data.user_id)) 99 - .get(); 100 - // Then it's the new user it might be null 101 - if (!currentUser) return; 102 - 103 - await analytics.identify(String(currentUser.id), { 104 - userId: currentUser.id, 105 - email: currentUser.email, 106 - }); 107 - await trackAnalytics({ event: "User Signed In" }); 108 - } 109 - }), 110 - }); 111 - 112 - export const clerkRouter = createTRPCRouter({ 113 - webhooks: webhookRouter, 114 - });
+3 -1
packages/api/src/router/invitation.ts
··· 132 132 }, 133 133 }); 134 134 135 + if (!opts.ctx.user?.id) return "Missing user"; 136 + 135 137 const _user = await opts.ctx.db.query.user.findFirst({ 136 - where: eq(user.tenantId, opts.ctx.auth?.userId || ""), 138 + where: eq(user.id, opts.ctx.user.id), 137 139 }); 138 140 139 141 if (!_user) return "Invalid user";
+3 -3
packages/api/src/router/stripe/index.ts
··· 35 35 const currentUser = opts.ctx.db 36 36 .select() 37 37 .from(user) 38 - .where(eq(user.tenantId, opts.ctx.auth.userId)) 38 + .where(eq(user.id, opts.ctx.user.id)) 39 39 .as("currentUser"); 40 40 const userHasAccess = await opts.ctx.db 41 41 .select() ··· 97 97 const currentUser = opts.ctx.db 98 98 .select() 99 99 .from(user) 100 - .where(eq(user.tenantId, opts.ctx.auth.userId)) 100 + .where(eq(user.id, opts.ctx.user.id)) 101 101 .as("currentUser"); 102 102 const userHasAccess = await opts.ctx.db 103 103 .select() ··· 112 112 const currentUser = await opts.ctx.db 113 113 .select() 114 114 .from(user) 115 - .where(eq(user.tenantId, opts.ctx.auth.userId)) 115 + .where(eq(user.id, opts.ctx.user.id)) 116 116 .get(); 117 117 const customerData: { 118 118 metadata: { workspaceId: string };
+1 -1
packages/api/src/router/user.ts
··· 10 10 const currentUser = await opts.ctx.db 11 11 .select() 12 12 .from(user) 13 - .where(eq(user.tenantId, opts.ctx.auth.userId)) 13 + .where(eq(user.id, opts.ctx.user.id)) 14 14 .get(); 15 15 return currentUser; 16 16 }),
+15 -12
packages/api/src/router/workspace.test.ts
··· 6 6 test("Get Test Workspace", async () => { 7 7 const ctx = createInnerTRPCContext({ 8 8 req: undefined, 9 - // @ts-expect-error 10 - auth: { 11 - userId: "1", 12 - sessionId: "1", 9 + // @ts-expect-error some issues with types 10 + session: { 11 + user: { 12 + id: "1", 13 + }, 13 14 }, 14 15 //@ts-expect-error 15 16 workspace: { ··· 37 38 test("by default we get the first workspace", async () => { 38 39 const ctx = createInnerTRPCContext({ 39 40 req: undefined, 40 - // @ts-expect-error 41 - auth: { 42 - userId: "1", 43 - sessionId: "1", 41 + // @ts-expect-error some issues with types 42 + session: { 43 + user: { 44 + id: "1", 45 + }, 44 46 }, 45 47 workspace: undefined, 46 48 }); ··· 65 67 test("All workspaces", async () => { 66 68 const ctx = createInnerTRPCContext({ 67 69 req: undefined, 68 - // @ts-expect-error 69 - auth: { 70 - userId: "1", 71 - sessionId: "1", 70 + // @ts-expect-error some issues with types 71 + session: { 72 + user: { 73 + id: "1", 74 + }, 72 75 }, 73 76 }); 74 77
+39 -13
packages/api/src/router/workspace.ts
··· 1 1 import { TRPCError } from "@trpc/server"; 2 2 import { generateSlug } from "random-word-slugs"; 3 + import * as randomWordSlugs from "random-word-slugs"; 3 4 import { z } from "zod"; 4 5 5 6 import { and, eq, sql } from "@openstatus/db"; ··· 18 19 import { createTRPCRouter, protectedProcedure } from "../trpc"; 19 20 20 21 export const workspaceRouter = createTRPCRouter({ 22 + createWorkspace: protectedProcedure 23 + .input(z.object({ userId: z.string() })) 24 + .mutation(async (opts) => { 25 + // guarantee the slug is unique accross our workspace entries 26 + let slug: string | undefined = undefined; 27 + 28 + while (!slug) { 29 + slug = randomWordSlugs.generateSlug(2); 30 + const slugAlreadyExists = await opts.ctx.db 31 + .select() 32 + .from(workspace) 33 + .where(eq(workspace.slug, slug)) 34 + .get(); 35 + if (slugAlreadyExists) { 36 + console.log(`slug already exists: '${slug}'`); 37 + slug = undefined; 38 + } 39 + } 40 + 41 + const _workspace = await opts.ctx.db 42 + .insert(workspace) 43 + .values({ slug, name: "" }) 44 + .returning({ id: workspace.id }) 45 + .get(); 46 + 47 + await opts.ctx.db 48 + .insert(usersToWorkspaces) 49 + .values({ 50 + userId: opts.ctx.user.id, 51 + workspaceId: _workspace.id, 52 + role: "owner", 53 + }) 54 + .returning() 55 + .get(); 56 + }), 21 57 getUserWithWorkspace: protectedProcedure.query(async (opts) => { 22 58 return await opts.ctx.db.query.user.findMany({ 23 59 with: { ··· 27 63 }, 28 64 }, 29 65 }, 30 - where: eq(user.tenantId, opts.ctx.auth.userId), 66 + where: eq(user.id, opts.ctx.user.id), 31 67 }); 32 68 }), 33 69 ··· 40 76 }), 41 77 42 78 getUserWorkspaces: protectedProcedure.query(async (opts) => { 79 + console.log(opts.ctx.user); 80 + 43 81 const result = await opts.ctx.db.query.usersToWorkspaces.findMany({ 44 82 where: eq(usersToWorkspaces.userId, opts.ctx.user.id), 45 83 with: { ··· 145 183 .update(workspace) 146 184 .set({ plan: opts.input.plan }) 147 185 .where(eq(workspace.id, opts.ctx.workspace.id)); 148 - }), 149 - 150 - createWorkspace: protectedProcedure 151 - .input(z.object({ name: z.string() })) 152 - .mutation(async (opts) => { 153 - const slug = generateSlug(2); 154 - 155 - return opts.ctx.db 156 - .insert(workspace) 157 - .values({ slug: slug, name: opts.input.name }) 158 - .returning() 159 - .get(); 160 186 }), 161 187 162 188 getCurrentWorkspaceNumbers: protectedProcedure.query(async (opts) => {
+12 -15
packages/api/src/trpc.ts
··· 1 1 import type { NextRequest } from "next/server"; 2 - import type { 3 - SignedInAuthObject, 4 - SignedOutAuthObject, 5 - } from "@clerk/nextjs/api"; 6 - import { getAuth } from "@clerk/nextjs/server"; 7 2 import { inferAsyncReturnType, initTRPC, TRPCError } from "@trpc/server"; 8 3 import superjson from "superjson"; 9 4 import { ZodError } from "zod"; ··· 11 6 import { clickhouseClient, db, eq, schema } from "@openstatus/db"; 12 7 import type { User, Workspace } from "@openstatus/db/src/schema"; 13 8 9 + // TODO: create a package for this 10 + import { 11 + auth, 12 + DefaultSession as Session, 13 + } from "../../../apps/web/src/lib/auth"; 14 + 14 15 /** 15 16 * 1. CONTEXT 16 17 * ··· 21 22 * 22 23 */ 23 24 type CreateContextOptions = { 24 - auth: SignedInAuthObject | SignedOutAuthObject | null; 25 + session: Session | null; 25 26 workspace?: Workspace | null; 26 27 user?: User | null; 27 28 req?: NextRequest; ··· 49 50 * process every request that goes through your tRPC endpoint 50 51 * @link https://trpc.io/docs/context 51 52 */ 52 - export const createTRPCContext = (opts: { 53 + export const createTRPCContext = async (opts: { 53 54 req: NextRequest; 54 55 serverSideCall?: boolean; 55 56 }) => { 56 - const auth = !opts.serverSideCall ? getAuth(opts.req) : null; 57 + const session = await auth(); 57 58 const workspace = null; 58 59 const user = null; 59 60 60 61 return createInnerTRPCContext({ 61 - auth, 62 + session, 62 63 workspace, 63 64 user, 64 65 req: opts.req, ··· 115 116 * procedure 116 117 */ 117 118 const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => { 118 - if (!ctx.auth?.userId) { 119 + if (!ctx.session?.user?.id) { 119 120 throw new TRPCError({ code: "UNAUTHORIZED" }); 120 121 } 121 122 ··· 124 125 // * comparing the `user.tenantId` to clerk's `auth.userId` 125 126 // */ 126 127 const userAndWorkspace = await db.query.user.findFirst({ 127 - where: eq(schema.user.tenantId, ctx.auth.userId), 128 + where: eq(schema.user.id, Number(ctx.session.user.id)), 128 129 with: { 129 130 usersToWorkspaces: { 130 131 with: { ··· 176 177 return next({ 177 178 ctx: { 178 179 ...ctx, 179 - auth: { 180 - ...ctx.auth, 181 - userId: ctx.auth.userId, 182 - }, 183 180 user, 184 181 workspace, 185 182 },
+1 -1
packages/config/eslint/package.json
··· 7 7 "@types/eslint": "8.44.3", 8 8 "@typescript-eslint/eslint-plugin": "6.7.3", 9 9 "@typescript-eslint/parser": "6.7.3", 10 - "eslint-config-next": "14.2.1", 10 + "eslint-config-next": "14.2.3", 11 11 "eslint-config-prettier": "9.0.0", 12 12 "eslint-config-turbo": "1.10.14", 13 13 "eslint-plugin-import": "2.28.1",
+5
packages/db/.env.example
··· 1 1 DATABASE_URL=http://127.0.0.1:8080 2 2 DATABASE_AUTH_TOKEN=any-token 3 + 4 + 5 + CLICKHOUSE_URL=http://localhost:8123 6 + CLICKHOUSE_USERNAME=default 7 + CLICKHOUSE_PASSWORD=
+32
packages/db/drizzle/0028_thin_power_pack.sql
··· 1 + CREATE TABLE `account` ( 2 + `user_id` integer NOT NULL, 3 + `type` text NOT NULL, 4 + `provider` text NOT NULL, 5 + `provider_account_id` text NOT NULL, 6 + `refresh_token` text, 7 + `access_token` text, 8 + `expires_at` integer, 9 + `token_type` text, 10 + `scope` text, 11 + `id_token` text, 12 + `session_state` text, 13 + PRIMARY KEY(`provider`, `provider_account_id`), 14 + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade 15 + ); 16 + --> statement-breakpoint 17 + CREATE TABLE `session` ( 18 + `session_token` text PRIMARY KEY NOT NULL, 19 + `user_id` integer NOT NULL, 20 + `expires` integer NOT NULL, 21 + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade 22 + ); 23 + --> statement-breakpoint 24 + CREATE TABLE `verification_token` ( 25 + `identifier` text NOT NULL, 26 + `token` text NOT NULL, 27 + `expires` integer NOT NULL, 28 + PRIMARY KEY(`identifier`, `token`) 29 + ); 30 + --> statement-breakpoint 31 + ALTER TABLE user ADD `name` text;--> statement-breakpoint 32 + ALTER TABLE user ADD `emailVerified` integer;
+1875
packages/db/drizzle/meta/0028_snapshot.json
··· 1 + { 2 + "version": "5", 3 + "dialect": "sqlite", 4 + "id": "715da58c-9c0f-42fe-920a-46f8c03c92ba", 5 + "prevId": "4488e03b-52ea-45eb-aac9-7d263c8f2e43", 6 + "tables": { 7 + "status_report_to_monitors": { 8 + "name": "status_report_to_monitors", 9 + "columns": { 10 + "monitor_id": { 11 + "name": "monitor_id", 12 + "type": "integer", 13 + "primaryKey": false, 14 + "notNull": true, 15 + "autoincrement": false 16 + }, 17 + "status_report_id": { 18 + "name": "status_report_id", 19 + "type": "integer", 20 + "primaryKey": false, 21 + "notNull": true, 22 + "autoincrement": false 23 + }, 24 + "created_at": { 25 + "name": "created_at", 26 + "type": "integer", 27 + "primaryKey": false, 28 + "notNull": false, 29 + "autoincrement": false, 30 + "default": "(strftime('%s', 'now'))" 31 + } 32 + }, 33 + "indexes": {}, 34 + "foreignKeys": { 35 + "status_report_to_monitors_monitor_id_monitor_id_fk": { 36 + "name": "status_report_to_monitors_monitor_id_monitor_id_fk", 37 + "tableFrom": "status_report_to_monitors", 38 + "tableTo": "monitor", 39 + "columnsFrom": [ 40 + "monitor_id" 41 + ], 42 + "columnsTo": [ 43 + "id" 44 + ], 45 + "onDelete": "cascade", 46 + "onUpdate": "no action" 47 + }, 48 + "status_report_to_monitors_status_report_id_status_report_id_fk": { 49 + "name": "status_report_to_monitors_status_report_id_status_report_id_fk", 50 + "tableFrom": "status_report_to_monitors", 51 + "tableTo": "status_report", 52 + "columnsFrom": [ 53 + "status_report_id" 54 + ], 55 + "columnsTo": [ 56 + "id" 57 + ], 58 + "onDelete": "cascade", 59 + "onUpdate": "no action" 60 + } 61 + }, 62 + "compositePrimaryKeys": { 63 + "status_report_to_monitors_monitor_id_status_report_id_pk": { 64 + "columns": [ 65 + "monitor_id", 66 + "status_report_id" 67 + ], 68 + "name": "status_report_to_monitors_monitor_id_status_report_id_pk" 69 + } 70 + }, 71 + "uniqueConstraints": {} 72 + }, 73 + "status_reports_to_pages": { 74 + "name": "status_reports_to_pages", 75 + "columns": { 76 + "page_id": { 77 + "name": "page_id", 78 + "type": "integer", 79 + "primaryKey": false, 80 + "notNull": true, 81 + "autoincrement": false 82 + }, 83 + "status_report_id": { 84 + "name": "status_report_id", 85 + "type": "integer", 86 + "primaryKey": false, 87 + "notNull": true, 88 + "autoincrement": false 89 + }, 90 + "created_at": { 91 + "name": "created_at", 92 + "type": "integer", 93 + "primaryKey": false, 94 + "notNull": false, 95 + "autoincrement": false, 96 + "default": "(strftime('%s', 'now'))" 97 + } 98 + }, 99 + "indexes": {}, 100 + "foreignKeys": { 101 + "status_reports_to_pages_page_id_page_id_fk": { 102 + "name": "status_reports_to_pages_page_id_page_id_fk", 103 + "tableFrom": "status_reports_to_pages", 104 + "tableTo": "page", 105 + "columnsFrom": [ 106 + "page_id" 107 + ], 108 + "columnsTo": [ 109 + "id" 110 + ], 111 + "onDelete": "cascade", 112 + "onUpdate": "no action" 113 + }, 114 + "status_reports_to_pages_status_report_id_status_report_id_fk": { 115 + "name": "status_reports_to_pages_status_report_id_status_report_id_fk", 116 + "tableFrom": "status_reports_to_pages", 117 + "tableTo": "status_report", 118 + "columnsFrom": [ 119 + "status_report_id" 120 + ], 121 + "columnsTo": [ 122 + "id" 123 + ], 124 + "onDelete": "cascade", 125 + "onUpdate": "no action" 126 + } 127 + }, 128 + "compositePrimaryKeys": { 129 + "status_reports_to_pages_page_id_status_report_id_pk": { 130 + "columns": [ 131 + "page_id", 132 + "status_report_id" 133 + ], 134 + "name": "status_reports_to_pages_page_id_status_report_id_pk" 135 + } 136 + }, 137 + "uniqueConstraints": {} 138 + }, 139 + "status_report": { 140 + "name": "status_report", 141 + "columns": { 142 + "id": { 143 + "name": "id", 144 + "type": "integer", 145 + "primaryKey": true, 146 + "notNull": true, 147 + "autoincrement": false 148 + }, 149 + "status": { 150 + "name": "status", 151 + "type": "text", 152 + "primaryKey": false, 153 + "notNull": true, 154 + "autoincrement": false 155 + }, 156 + "title": { 157 + "name": "title", 158 + "type": "text(256)", 159 + "primaryKey": false, 160 + "notNull": true, 161 + "autoincrement": false 162 + }, 163 + "workspace_id": { 164 + "name": "workspace_id", 165 + "type": "integer", 166 + "primaryKey": false, 167 + "notNull": false, 168 + "autoincrement": false 169 + }, 170 + "created_at": { 171 + "name": "created_at", 172 + "type": "integer", 173 + "primaryKey": false, 174 + "notNull": false, 175 + "autoincrement": false, 176 + "default": "(strftime('%s', 'now'))" 177 + }, 178 + "updated_at": { 179 + "name": "updated_at", 180 + "type": "integer", 181 + "primaryKey": false, 182 + "notNull": false, 183 + "autoincrement": false, 184 + "default": "(strftime('%s', 'now'))" 185 + } 186 + }, 187 + "indexes": {}, 188 + "foreignKeys": { 189 + "status_report_workspace_id_workspace_id_fk": { 190 + "name": "status_report_workspace_id_workspace_id_fk", 191 + "tableFrom": "status_report", 192 + "tableTo": "workspace", 193 + "columnsFrom": [ 194 + "workspace_id" 195 + ], 196 + "columnsTo": [ 197 + "id" 198 + ], 199 + "onDelete": "no action", 200 + "onUpdate": "no action" 201 + } 202 + }, 203 + "compositePrimaryKeys": {}, 204 + "uniqueConstraints": {} 205 + }, 206 + "status_report_update": { 207 + "name": "status_report_update", 208 + "columns": { 209 + "id": { 210 + "name": "id", 211 + "type": "integer", 212 + "primaryKey": true, 213 + "notNull": true, 214 + "autoincrement": false 215 + }, 216 + "status": { 217 + "name": "status", 218 + "type": "text(4)", 219 + "primaryKey": false, 220 + "notNull": true, 221 + "autoincrement": false 222 + }, 223 + "date": { 224 + "name": "date", 225 + "type": "integer", 226 + "primaryKey": false, 227 + "notNull": true, 228 + "autoincrement": false 229 + }, 230 + "message": { 231 + "name": "message", 232 + "type": "text", 233 + "primaryKey": false, 234 + "notNull": true, 235 + "autoincrement": false 236 + }, 237 + "status_report_id": { 238 + "name": "status_report_id", 239 + "type": "integer", 240 + "primaryKey": false, 241 + "notNull": true, 242 + "autoincrement": false 243 + }, 244 + "created_at": { 245 + "name": "created_at", 246 + "type": "integer", 247 + "primaryKey": false, 248 + "notNull": false, 249 + "autoincrement": false, 250 + "default": "(strftime('%s', 'now'))" 251 + }, 252 + "updated_at": { 253 + "name": "updated_at", 254 + "type": "integer", 255 + "primaryKey": false, 256 + "notNull": false, 257 + "autoincrement": false, 258 + "default": "(strftime('%s', 'now'))" 259 + } 260 + }, 261 + "indexes": {}, 262 + "foreignKeys": { 263 + "status_report_update_status_report_id_status_report_id_fk": { 264 + "name": "status_report_update_status_report_id_status_report_id_fk", 265 + "tableFrom": "status_report_update", 266 + "tableTo": "status_report", 267 + "columnsFrom": [ 268 + "status_report_id" 269 + ], 270 + "columnsTo": [ 271 + "id" 272 + ], 273 + "onDelete": "cascade", 274 + "onUpdate": "no action" 275 + } 276 + }, 277 + "compositePrimaryKeys": {}, 278 + "uniqueConstraints": {} 279 + }, 280 + "integration": { 281 + "name": "integration", 282 + "columns": { 283 + "id": { 284 + "name": "id", 285 + "type": "integer", 286 + "primaryKey": true, 287 + "notNull": true, 288 + "autoincrement": false 289 + }, 290 + "name": { 291 + "name": "name", 292 + "type": "text(256)", 293 + "primaryKey": false, 294 + "notNull": true, 295 + "autoincrement": false 296 + }, 297 + "workspace_id": { 298 + "name": "workspace_id", 299 + "type": "integer", 300 + "primaryKey": false, 301 + "notNull": false, 302 + "autoincrement": false 303 + }, 304 + "credential": { 305 + "name": "credential", 306 + "type": "text", 307 + "primaryKey": false, 308 + "notNull": false, 309 + "autoincrement": false 310 + }, 311 + "external_id": { 312 + "name": "external_id", 313 + "type": "text", 314 + "primaryKey": false, 315 + "notNull": true, 316 + "autoincrement": false 317 + }, 318 + "created_at": { 319 + "name": "created_at", 320 + "type": "integer", 321 + "primaryKey": false, 322 + "notNull": false, 323 + "autoincrement": false, 324 + "default": "(strftime('%s', 'now'))" 325 + }, 326 + "updated_at": { 327 + "name": "updated_at", 328 + "type": "integer", 329 + "primaryKey": false, 330 + "notNull": false, 331 + "autoincrement": false, 332 + "default": "(strftime('%s', 'now'))" 333 + }, 334 + "data": { 335 + "name": "data", 336 + "type": "text", 337 + "primaryKey": false, 338 + "notNull": true, 339 + "autoincrement": false 340 + } 341 + }, 342 + "indexes": {}, 343 + "foreignKeys": { 344 + "integration_workspace_id_workspace_id_fk": { 345 + "name": "integration_workspace_id_workspace_id_fk", 346 + "tableFrom": "integration", 347 + "tableTo": "workspace", 348 + "columnsFrom": [ 349 + "workspace_id" 350 + ], 351 + "columnsTo": [ 352 + "id" 353 + ], 354 + "onDelete": "no action", 355 + "onUpdate": "no action" 356 + } 357 + }, 358 + "compositePrimaryKeys": {}, 359 + "uniqueConstraints": {} 360 + }, 361 + "page": { 362 + "name": "page", 363 + "columns": { 364 + "id": { 365 + "name": "id", 366 + "type": "integer", 367 + "primaryKey": true, 368 + "notNull": true, 369 + "autoincrement": false 370 + }, 371 + "workspace_id": { 372 + "name": "workspace_id", 373 + "type": "integer", 374 + "primaryKey": false, 375 + "notNull": true, 376 + "autoincrement": false 377 + }, 378 + "title": { 379 + "name": "title", 380 + "type": "text", 381 + "primaryKey": false, 382 + "notNull": true, 383 + "autoincrement": false 384 + }, 385 + "description": { 386 + "name": "description", 387 + "type": "text", 388 + "primaryKey": false, 389 + "notNull": true, 390 + "autoincrement": false 391 + }, 392 + "icon": { 393 + "name": "icon", 394 + "type": "text(256)", 395 + "primaryKey": false, 396 + "notNull": false, 397 + "autoincrement": false, 398 + "default": "''" 399 + }, 400 + "slug": { 401 + "name": "slug", 402 + "type": "text(256)", 403 + "primaryKey": false, 404 + "notNull": true, 405 + "autoincrement": false 406 + }, 407 + "custom_domain": { 408 + "name": "custom_domain", 409 + "type": "text(256)", 410 + "primaryKey": false, 411 + "notNull": true, 412 + "autoincrement": false 413 + }, 414 + "published": { 415 + "name": "published", 416 + "type": "integer", 417 + "primaryKey": false, 418 + "notNull": false, 419 + "autoincrement": false, 420 + "default": false 421 + }, 422 + "password": { 423 + "name": "password", 424 + "type": "text(256)", 425 + "primaryKey": false, 426 + "notNull": false, 427 + "autoincrement": false 428 + }, 429 + "password_protected": { 430 + "name": "password_protected", 431 + "type": "integer", 432 + "primaryKey": false, 433 + "notNull": false, 434 + "autoincrement": false, 435 + "default": false 436 + }, 437 + "created_at": { 438 + "name": "created_at", 439 + "type": "integer", 440 + "primaryKey": false, 441 + "notNull": false, 442 + "autoincrement": false, 443 + "default": "(strftime('%s', 'now'))" 444 + }, 445 + "updated_at": { 446 + "name": "updated_at", 447 + "type": "integer", 448 + "primaryKey": false, 449 + "notNull": false, 450 + "autoincrement": false, 451 + "default": "(strftime('%s', 'now'))" 452 + } 453 + }, 454 + "indexes": { 455 + "page_slug_unique": { 456 + "name": "page_slug_unique", 457 + "columns": [ 458 + "slug" 459 + ], 460 + "isUnique": true 461 + } 462 + }, 463 + "foreignKeys": { 464 + "page_workspace_id_workspace_id_fk": { 465 + "name": "page_workspace_id_workspace_id_fk", 466 + "tableFrom": "page", 467 + "tableTo": "workspace", 468 + "columnsFrom": [ 469 + "workspace_id" 470 + ], 471 + "columnsTo": [ 472 + "id" 473 + ], 474 + "onDelete": "cascade", 475 + "onUpdate": "no action" 476 + } 477 + }, 478 + "compositePrimaryKeys": {}, 479 + "uniqueConstraints": {} 480 + }, 481 + "monitor": { 482 + "name": "monitor", 483 + "columns": { 484 + "id": { 485 + "name": "id", 486 + "type": "integer", 487 + "primaryKey": true, 488 + "notNull": true, 489 + "autoincrement": false 490 + }, 491 + "job_type": { 492 + "name": "job_type", 493 + "type": "text", 494 + "primaryKey": false, 495 + "notNull": true, 496 + "autoincrement": false, 497 + "default": "'other'" 498 + }, 499 + "periodicity": { 500 + "name": "periodicity", 501 + "type": "text", 502 + "primaryKey": false, 503 + "notNull": true, 504 + "autoincrement": false, 505 + "default": "'other'" 506 + }, 507 + "status": { 508 + "name": "status", 509 + "type": "text", 510 + "primaryKey": false, 511 + "notNull": true, 512 + "autoincrement": false, 513 + "default": "'active'" 514 + }, 515 + "active": { 516 + "name": "active", 517 + "type": "integer", 518 + "primaryKey": false, 519 + "notNull": false, 520 + "autoincrement": false, 521 + "default": false 522 + }, 523 + "regions": { 524 + "name": "regions", 525 + "type": "text", 526 + "primaryKey": false, 527 + "notNull": true, 528 + "autoincrement": false, 529 + "default": "''" 530 + }, 531 + "url": { 532 + "name": "url", 533 + "type": "text(2048)", 534 + "primaryKey": false, 535 + "notNull": true, 536 + "autoincrement": false 537 + }, 538 + "name": { 539 + "name": "name", 540 + "type": "text(256)", 541 + "primaryKey": false, 542 + "notNull": true, 543 + "autoincrement": false, 544 + "default": "''" 545 + }, 546 + "description": { 547 + "name": "description", 548 + "type": "text", 549 + "primaryKey": false, 550 + "notNull": true, 551 + "autoincrement": false, 552 + "default": "''" 553 + }, 554 + "headers": { 555 + "name": "headers", 556 + "type": "text", 557 + "primaryKey": false, 558 + "notNull": false, 559 + "autoincrement": false, 560 + "default": "''" 561 + }, 562 + "body": { 563 + "name": "body", 564 + "type": "text", 565 + "primaryKey": false, 566 + "notNull": false, 567 + "autoincrement": false, 568 + "default": "''" 569 + }, 570 + "method": { 571 + "name": "method", 572 + "type": "text", 573 + "primaryKey": false, 574 + "notNull": false, 575 + "autoincrement": false, 576 + "default": "'GET'" 577 + }, 578 + "workspace_id": { 579 + "name": "workspace_id", 580 + "type": "integer", 581 + "primaryKey": false, 582 + "notNull": false, 583 + "autoincrement": false 584 + }, 585 + "assertions": { 586 + "name": "assertions", 587 + "type": "text", 588 + "primaryKey": false, 589 + "notNull": false, 590 + "autoincrement": false 591 + }, 592 + "public": { 593 + "name": "public", 594 + "type": "integer", 595 + "primaryKey": false, 596 + "notNull": false, 597 + "autoincrement": false, 598 + "default": false 599 + }, 600 + "created_at": { 601 + "name": "created_at", 602 + "type": "integer", 603 + "primaryKey": false, 604 + "notNull": false, 605 + "autoincrement": false, 606 + "default": "(strftime('%s', 'now'))" 607 + }, 608 + "updated_at": { 609 + "name": "updated_at", 610 + "type": "integer", 611 + "primaryKey": false, 612 + "notNull": false, 613 + "autoincrement": false, 614 + "default": "(strftime('%s', 'now'))" 615 + }, 616 + "deleted_at": { 617 + "name": "deleted_at", 618 + "type": "integer", 619 + "primaryKey": false, 620 + "notNull": false, 621 + "autoincrement": false 622 + } 623 + }, 624 + "indexes": {}, 625 + "foreignKeys": { 626 + "monitor_workspace_id_workspace_id_fk": { 627 + "name": "monitor_workspace_id_workspace_id_fk", 628 + "tableFrom": "monitor", 629 + "tableTo": "workspace", 630 + "columnsFrom": [ 631 + "workspace_id" 632 + ], 633 + "columnsTo": [ 634 + "id" 635 + ], 636 + "onDelete": "no action", 637 + "onUpdate": "no action" 638 + } 639 + }, 640 + "compositePrimaryKeys": {}, 641 + "uniqueConstraints": {} 642 + }, 643 + "monitors_to_pages": { 644 + "name": "monitors_to_pages", 645 + "columns": { 646 + "monitor_id": { 647 + "name": "monitor_id", 648 + "type": "integer", 649 + "primaryKey": false, 650 + "notNull": true, 651 + "autoincrement": false 652 + }, 653 + "page_id": { 654 + "name": "page_id", 655 + "type": "integer", 656 + "primaryKey": false, 657 + "notNull": true, 658 + "autoincrement": false 659 + }, 660 + "created_at": { 661 + "name": "created_at", 662 + "type": "integer", 663 + "primaryKey": false, 664 + "notNull": false, 665 + "autoincrement": false, 666 + "default": "(strftime('%s', 'now'))" 667 + } 668 + }, 669 + "indexes": {}, 670 + "foreignKeys": { 671 + "monitors_to_pages_monitor_id_monitor_id_fk": { 672 + "name": "monitors_to_pages_monitor_id_monitor_id_fk", 673 + "tableFrom": "monitors_to_pages", 674 + "tableTo": "monitor", 675 + "columnsFrom": [ 676 + "monitor_id" 677 + ], 678 + "columnsTo": [ 679 + "id" 680 + ], 681 + "onDelete": "cascade", 682 + "onUpdate": "no action" 683 + }, 684 + "monitors_to_pages_page_id_page_id_fk": { 685 + "name": "monitors_to_pages_page_id_page_id_fk", 686 + "tableFrom": "monitors_to_pages", 687 + "tableTo": "page", 688 + "columnsFrom": [ 689 + "page_id" 690 + ], 691 + "columnsTo": [ 692 + "id" 693 + ], 694 + "onDelete": "cascade", 695 + "onUpdate": "no action" 696 + } 697 + }, 698 + "compositePrimaryKeys": { 699 + "monitors_to_pages_monitor_id_page_id_pk": { 700 + "columns": [ 701 + "monitor_id", 702 + "page_id" 703 + ], 704 + "name": "monitors_to_pages_monitor_id_page_id_pk" 705 + } 706 + }, 707 + "uniqueConstraints": {} 708 + }, 709 + "account": { 710 + "name": "account", 711 + "columns": { 712 + "user_id": { 713 + "name": "user_id", 714 + "type": "integer", 715 + "primaryKey": false, 716 + "notNull": true, 717 + "autoincrement": false 718 + }, 719 + "type": { 720 + "name": "type", 721 + "type": "text", 722 + "primaryKey": false, 723 + "notNull": true, 724 + "autoincrement": false 725 + }, 726 + "provider": { 727 + "name": "provider", 728 + "type": "text", 729 + "primaryKey": false, 730 + "notNull": true, 731 + "autoincrement": false 732 + }, 733 + "provider_account_id": { 734 + "name": "provider_account_id", 735 + "type": "text", 736 + "primaryKey": false, 737 + "notNull": true, 738 + "autoincrement": false 739 + }, 740 + "refresh_token": { 741 + "name": "refresh_token", 742 + "type": "text", 743 + "primaryKey": false, 744 + "notNull": false, 745 + "autoincrement": false 746 + }, 747 + "access_token": { 748 + "name": "access_token", 749 + "type": "text", 750 + "primaryKey": false, 751 + "notNull": false, 752 + "autoincrement": false 753 + }, 754 + "expires_at": { 755 + "name": "expires_at", 756 + "type": "integer", 757 + "primaryKey": false, 758 + "notNull": false, 759 + "autoincrement": false 760 + }, 761 + "token_type": { 762 + "name": "token_type", 763 + "type": "text", 764 + "primaryKey": false, 765 + "notNull": false, 766 + "autoincrement": false 767 + }, 768 + "scope": { 769 + "name": "scope", 770 + "type": "text", 771 + "primaryKey": false, 772 + "notNull": false, 773 + "autoincrement": false 774 + }, 775 + "id_token": { 776 + "name": "id_token", 777 + "type": "text", 778 + "primaryKey": false, 779 + "notNull": false, 780 + "autoincrement": false 781 + }, 782 + "session_state": { 783 + "name": "session_state", 784 + "type": "text", 785 + "primaryKey": false, 786 + "notNull": false, 787 + "autoincrement": false 788 + } 789 + }, 790 + "indexes": {}, 791 + "foreignKeys": { 792 + "account_user_id_user_id_fk": { 793 + "name": "account_user_id_user_id_fk", 794 + "tableFrom": "account", 795 + "tableTo": "user", 796 + "columnsFrom": [ 797 + "user_id" 798 + ], 799 + "columnsTo": [ 800 + "id" 801 + ], 802 + "onDelete": "cascade", 803 + "onUpdate": "no action" 804 + } 805 + }, 806 + "compositePrimaryKeys": { 807 + "account_provider_provider_account_id_pk": { 808 + "columns": [ 809 + "provider", 810 + "provider_account_id" 811 + ], 812 + "name": "account_provider_provider_account_id_pk" 813 + } 814 + }, 815 + "uniqueConstraints": {} 816 + }, 817 + "session": { 818 + "name": "session", 819 + "columns": { 820 + "session_token": { 821 + "name": "session_token", 822 + "type": "text", 823 + "primaryKey": true, 824 + "notNull": true, 825 + "autoincrement": false 826 + }, 827 + "user_id": { 828 + "name": "user_id", 829 + "type": "integer", 830 + "primaryKey": false, 831 + "notNull": true, 832 + "autoincrement": false 833 + }, 834 + "expires": { 835 + "name": "expires", 836 + "type": "integer", 837 + "primaryKey": false, 838 + "notNull": true, 839 + "autoincrement": false 840 + } 841 + }, 842 + "indexes": {}, 843 + "foreignKeys": { 844 + "session_user_id_user_id_fk": { 845 + "name": "session_user_id_user_id_fk", 846 + "tableFrom": "session", 847 + "tableTo": "user", 848 + "columnsFrom": [ 849 + "user_id" 850 + ], 851 + "columnsTo": [ 852 + "id" 853 + ], 854 + "onDelete": "cascade", 855 + "onUpdate": "no action" 856 + } 857 + }, 858 + "compositePrimaryKeys": {}, 859 + "uniqueConstraints": {} 860 + }, 861 + "user": { 862 + "name": "user", 863 + "columns": { 864 + "id": { 865 + "name": "id", 866 + "type": "integer", 867 + "primaryKey": true, 868 + "notNull": true, 869 + "autoincrement": false 870 + }, 871 + "tenant_id": { 872 + "name": "tenant_id", 873 + "type": "text(256)", 874 + "primaryKey": false, 875 + "notNull": false, 876 + "autoincrement": false 877 + }, 878 + "first_name": { 879 + "name": "first_name", 880 + "type": "text", 881 + "primaryKey": false, 882 + "notNull": false, 883 + "autoincrement": false, 884 + "default": "''" 885 + }, 886 + "last_name": { 887 + "name": "last_name", 888 + "type": "text", 889 + "primaryKey": false, 890 + "notNull": false, 891 + "autoincrement": false, 892 + "default": "''" 893 + }, 894 + "photo_url": { 895 + "name": "photo_url", 896 + "type": "text", 897 + "primaryKey": false, 898 + "notNull": false, 899 + "autoincrement": false, 900 + "default": "''" 901 + }, 902 + "name": { 903 + "name": "name", 904 + "type": "text", 905 + "primaryKey": false, 906 + "notNull": false, 907 + "autoincrement": false 908 + }, 909 + "email": { 910 + "name": "email", 911 + "type": "text", 912 + "primaryKey": false, 913 + "notNull": false, 914 + "autoincrement": false, 915 + "default": "''" 916 + }, 917 + "emailVerified": { 918 + "name": "emailVerified", 919 + "type": "integer", 920 + "primaryKey": false, 921 + "notNull": false, 922 + "autoincrement": false 923 + }, 924 + "created_at": { 925 + "name": "created_at", 926 + "type": "integer", 927 + "primaryKey": false, 928 + "notNull": false, 929 + "autoincrement": false, 930 + "default": "(strftime('%s', 'now'))" 931 + }, 932 + "updated_at": { 933 + "name": "updated_at", 934 + "type": "integer", 935 + "primaryKey": false, 936 + "notNull": false, 937 + "autoincrement": false, 938 + "default": "(strftime('%s', 'now'))" 939 + } 940 + }, 941 + "indexes": { 942 + "user_tenant_id_unique": { 943 + "name": "user_tenant_id_unique", 944 + "columns": [ 945 + "tenant_id" 946 + ], 947 + "isUnique": true 948 + } 949 + }, 950 + "foreignKeys": {}, 951 + "compositePrimaryKeys": {}, 952 + "uniqueConstraints": {} 953 + }, 954 + "users_to_workspaces": { 955 + "name": "users_to_workspaces", 956 + "columns": { 957 + "user_id": { 958 + "name": "user_id", 959 + "type": "integer", 960 + "primaryKey": false, 961 + "notNull": true, 962 + "autoincrement": false 963 + }, 964 + "workspace_id": { 965 + "name": "workspace_id", 966 + "type": "integer", 967 + "primaryKey": false, 968 + "notNull": true, 969 + "autoincrement": false 970 + }, 971 + "role": { 972 + "name": "role", 973 + "type": "text", 974 + "primaryKey": false, 975 + "notNull": true, 976 + "autoincrement": false, 977 + "default": "'member'" 978 + }, 979 + "created_at": { 980 + "name": "created_at", 981 + "type": "integer", 982 + "primaryKey": false, 983 + "notNull": false, 984 + "autoincrement": false, 985 + "default": "(strftime('%s', 'now'))" 986 + } 987 + }, 988 + "indexes": {}, 989 + "foreignKeys": { 990 + "users_to_workspaces_user_id_user_id_fk": { 991 + "name": "users_to_workspaces_user_id_user_id_fk", 992 + "tableFrom": "users_to_workspaces", 993 + "tableTo": "user", 994 + "columnsFrom": [ 995 + "user_id" 996 + ], 997 + "columnsTo": [ 998 + "id" 999 + ], 1000 + "onDelete": "no action", 1001 + "onUpdate": "no action" 1002 + }, 1003 + "users_to_workspaces_workspace_id_workspace_id_fk": { 1004 + "name": "users_to_workspaces_workspace_id_workspace_id_fk", 1005 + "tableFrom": "users_to_workspaces", 1006 + "tableTo": "workspace", 1007 + "columnsFrom": [ 1008 + "workspace_id" 1009 + ], 1010 + "columnsTo": [ 1011 + "id" 1012 + ], 1013 + "onDelete": "no action", 1014 + "onUpdate": "no action" 1015 + } 1016 + }, 1017 + "compositePrimaryKeys": { 1018 + "users_to_workspaces_user_id_workspace_id_pk": { 1019 + "columns": [ 1020 + "user_id", 1021 + "workspace_id" 1022 + ], 1023 + "name": "users_to_workspaces_user_id_workspace_id_pk" 1024 + } 1025 + }, 1026 + "uniqueConstraints": {} 1027 + }, 1028 + "verification_token": { 1029 + "name": "verification_token", 1030 + "columns": { 1031 + "identifier": { 1032 + "name": "identifier", 1033 + "type": "text", 1034 + "primaryKey": false, 1035 + "notNull": true, 1036 + "autoincrement": false 1037 + }, 1038 + "token": { 1039 + "name": "token", 1040 + "type": "text", 1041 + "primaryKey": false, 1042 + "notNull": true, 1043 + "autoincrement": false 1044 + }, 1045 + "expires": { 1046 + "name": "expires", 1047 + "type": "integer", 1048 + "primaryKey": false, 1049 + "notNull": true, 1050 + "autoincrement": false 1051 + } 1052 + }, 1053 + "indexes": {}, 1054 + "foreignKeys": {}, 1055 + "compositePrimaryKeys": { 1056 + "verification_token_identifier_token_pk": { 1057 + "columns": [ 1058 + "identifier", 1059 + "token" 1060 + ], 1061 + "name": "verification_token_identifier_token_pk" 1062 + } 1063 + }, 1064 + "uniqueConstraints": {} 1065 + }, 1066 + "page_subscriber": { 1067 + "name": "page_subscriber", 1068 + "columns": { 1069 + "id": { 1070 + "name": "id", 1071 + "type": "integer", 1072 + "primaryKey": true, 1073 + "notNull": true, 1074 + "autoincrement": false 1075 + }, 1076 + "email": { 1077 + "name": "email", 1078 + "type": "text", 1079 + "primaryKey": false, 1080 + "notNull": true, 1081 + "autoincrement": false 1082 + }, 1083 + "page_id": { 1084 + "name": "page_id", 1085 + "type": "integer", 1086 + "primaryKey": false, 1087 + "notNull": true, 1088 + "autoincrement": false 1089 + }, 1090 + "token": { 1091 + "name": "token", 1092 + "type": "text", 1093 + "primaryKey": false, 1094 + "notNull": false, 1095 + "autoincrement": false 1096 + }, 1097 + "accepted_at": { 1098 + "name": "accepted_at", 1099 + "type": "integer", 1100 + "primaryKey": false, 1101 + "notNull": false, 1102 + "autoincrement": false 1103 + }, 1104 + "expires_at": { 1105 + "name": "expires_at", 1106 + "type": "integer", 1107 + "primaryKey": false, 1108 + "notNull": false, 1109 + "autoincrement": false 1110 + }, 1111 + "created_at": { 1112 + "name": "created_at", 1113 + "type": "integer", 1114 + "primaryKey": false, 1115 + "notNull": false, 1116 + "autoincrement": false, 1117 + "default": "(strftime('%s', 'now'))" 1118 + }, 1119 + "updated_at": { 1120 + "name": "updated_at", 1121 + "type": "integer", 1122 + "primaryKey": false, 1123 + "notNull": false, 1124 + "autoincrement": false, 1125 + "default": "(strftime('%s', 'now'))" 1126 + } 1127 + }, 1128 + "indexes": {}, 1129 + "foreignKeys": { 1130 + "page_subscriber_page_id_page_id_fk": { 1131 + "name": "page_subscriber_page_id_page_id_fk", 1132 + "tableFrom": "page_subscriber", 1133 + "tableTo": "page", 1134 + "columnsFrom": [ 1135 + "page_id" 1136 + ], 1137 + "columnsTo": [ 1138 + "id" 1139 + ], 1140 + "onDelete": "no action", 1141 + "onUpdate": "no action" 1142 + } 1143 + }, 1144 + "compositePrimaryKeys": {}, 1145 + "uniqueConstraints": {} 1146 + }, 1147 + "workspace": { 1148 + "name": "workspace", 1149 + "columns": { 1150 + "id": { 1151 + "name": "id", 1152 + "type": "integer", 1153 + "primaryKey": true, 1154 + "notNull": true, 1155 + "autoincrement": false 1156 + }, 1157 + "slug": { 1158 + "name": "slug", 1159 + "type": "text", 1160 + "primaryKey": false, 1161 + "notNull": true, 1162 + "autoincrement": false 1163 + }, 1164 + "name": { 1165 + "name": "name", 1166 + "type": "text", 1167 + "primaryKey": false, 1168 + "notNull": false, 1169 + "autoincrement": false 1170 + }, 1171 + "stripe_id": { 1172 + "name": "stripe_id", 1173 + "type": "text(256)", 1174 + "primaryKey": false, 1175 + "notNull": false, 1176 + "autoincrement": false 1177 + }, 1178 + "subscription_id": { 1179 + "name": "subscription_id", 1180 + "type": "text", 1181 + "primaryKey": false, 1182 + "notNull": false, 1183 + "autoincrement": false 1184 + }, 1185 + "plan": { 1186 + "name": "plan", 1187 + "type": "text", 1188 + "primaryKey": false, 1189 + "notNull": false, 1190 + "autoincrement": false 1191 + }, 1192 + "ends_at": { 1193 + "name": "ends_at", 1194 + "type": "integer", 1195 + "primaryKey": false, 1196 + "notNull": false, 1197 + "autoincrement": false 1198 + }, 1199 + "paid_until": { 1200 + "name": "paid_until", 1201 + "type": "integer", 1202 + "primaryKey": false, 1203 + "notNull": false, 1204 + "autoincrement": false 1205 + }, 1206 + "created_at": { 1207 + "name": "created_at", 1208 + "type": "integer", 1209 + "primaryKey": false, 1210 + "notNull": false, 1211 + "autoincrement": false, 1212 + "default": "(strftime('%s', 'now'))" 1213 + }, 1214 + "updated_at": { 1215 + "name": "updated_at", 1216 + "type": "integer", 1217 + "primaryKey": false, 1218 + "notNull": false, 1219 + "autoincrement": false, 1220 + "default": "(strftime('%s', 'now'))" 1221 + }, 1222 + "dsn": { 1223 + "name": "dsn", 1224 + "type": "text", 1225 + "primaryKey": false, 1226 + "notNull": false, 1227 + "autoincrement": false 1228 + } 1229 + }, 1230 + "indexes": { 1231 + "workspace_slug_unique": { 1232 + "name": "workspace_slug_unique", 1233 + "columns": [ 1234 + "slug" 1235 + ], 1236 + "isUnique": true 1237 + }, 1238 + "workspace_stripe_id_unique": { 1239 + "name": "workspace_stripe_id_unique", 1240 + "columns": [ 1241 + "stripe_id" 1242 + ], 1243 + "isUnique": true 1244 + }, 1245 + "workspace_id_dsn_unique": { 1246 + "name": "workspace_id_dsn_unique", 1247 + "columns": [ 1248 + "id", 1249 + "dsn" 1250 + ], 1251 + "isUnique": true 1252 + } 1253 + }, 1254 + "foreignKeys": {}, 1255 + "compositePrimaryKeys": {}, 1256 + "uniqueConstraints": {} 1257 + }, 1258 + "notification": { 1259 + "name": "notification", 1260 + "columns": { 1261 + "id": { 1262 + "name": "id", 1263 + "type": "integer", 1264 + "primaryKey": true, 1265 + "notNull": true, 1266 + "autoincrement": false 1267 + }, 1268 + "name": { 1269 + "name": "name", 1270 + "type": "text", 1271 + "primaryKey": false, 1272 + "notNull": true, 1273 + "autoincrement": false 1274 + }, 1275 + "provider": { 1276 + "name": "provider", 1277 + "type": "text", 1278 + "primaryKey": false, 1279 + "notNull": true, 1280 + "autoincrement": false 1281 + }, 1282 + "data": { 1283 + "name": "data", 1284 + "type": "text", 1285 + "primaryKey": false, 1286 + "notNull": false, 1287 + "autoincrement": false, 1288 + "default": "'{}'" 1289 + }, 1290 + "workspace_id": { 1291 + "name": "workspace_id", 1292 + "type": "integer", 1293 + "primaryKey": false, 1294 + "notNull": false, 1295 + "autoincrement": false 1296 + }, 1297 + "created_at": { 1298 + "name": "created_at", 1299 + "type": "integer", 1300 + "primaryKey": false, 1301 + "notNull": false, 1302 + "autoincrement": false, 1303 + "default": "(strftime('%s', 'now'))" 1304 + }, 1305 + "updated_at": { 1306 + "name": "updated_at", 1307 + "type": "integer", 1308 + "primaryKey": false, 1309 + "notNull": false, 1310 + "autoincrement": false, 1311 + "default": "(strftime('%s', 'now'))" 1312 + } 1313 + }, 1314 + "indexes": {}, 1315 + "foreignKeys": { 1316 + "notification_workspace_id_workspace_id_fk": { 1317 + "name": "notification_workspace_id_workspace_id_fk", 1318 + "tableFrom": "notification", 1319 + "tableTo": "workspace", 1320 + "columnsFrom": [ 1321 + "workspace_id" 1322 + ], 1323 + "columnsTo": [ 1324 + "id" 1325 + ], 1326 + "onDelete": "no action", 1327 + "onUpdate": "no action" 1328 + } 1329 + }, 1330 + "compositePrimaryKeys": {}, 1331 + "uniqueConstraints": {} 1332 + }, 1333 + "notifications_to_monitors": { 1334 + "name": "notifications_to_monitors", 1335 + "columns": { 1336 + "monitor_id": { 1337 + "name": "monitor_id", 1338 + "type": "integer", 1339 + "primaryKey": false, 1340 + "notNull": true, 1341 + "autoincrement": false 1342 + }, 1343 + "notification_id": { 1344 + "name": "notification_id", 1345 + "type": "integer", 1346 + "primaryKey": false, 1347 + "notNull": true, 1348 + "autoincrement": false 1349 + }, 1350 + "created_at": { 1351 + "name": "created_at", 1352 + "type": "integer", 1353 + "primaryKey": false, 1354 + "notNull": false, 1355 + "autoincrement": false, 1356 + "default": "(strftime('%s', 'now'))" 1357 + } 1358 + }, 1359 + "indexes": {}, 1360 + "foreignKeys": { 1361 + "notifications_to_monitors_monitor_id_monitor_id_fk": { 1362 + "name": "notifications_to_monitors_monitor_id_monitor_id_fk", 1363 + "tableFrom": "notifications_to_monitors", 1364 + "tableTo": "monitor", 1365 + "columnsFrom": [ 1366 + "monitor_id" 1367 + ], 1368 + "columnsTo": [ 1369 + "id" 1370 + ], 1371 + "onDelete": "cascade", 1372 + "onUpdate": "no action" 1373 + }, 1374 + "notifications_to_monitors_notification_id_notification_id_fk": { 1375 + "name": "notifications_to_monitors_notification_id_notification_id_fk", 1376 + "tableFrom": "notifications_to_monitors", 1377 + "tableTo": "notification", 1378 + "columnsFrom": [ 1379 + "notification_id" 1380 + ], 1381 + "columnsTo": [ 1382 + "id" 1383 + ], 1384 + "onDelete": "cascade", 1385 + "onUpdate": "no action" 1386 + } 1387 + }, 1388 + "compositePrimaryKeys": { 1389 + "notifications_to_monitors_monitor_id_notification_id_pk": { 1390 + "columns": [ 1391 + "monitor_id", 1392 + "notification_id" 1393 + ], 1394 + "name": "notifications_to_monitors_monitor_id_notification_id_pk" 1395 + } 1396 + }, 1397 + "uniqueConstraints": {} 1398 + }, 1399 + "monitor_status": { 1400 + "name": "monitor_status", 1401 + "columns": { 1402 + "monitor_id": { 1403 + "name": "monitor_id", 1404 + "type": "integer", 1405 + "primaryKey": false, 1406 + "notNull": true, 1407 + "autoincrement": false 1408 + }, 1409 + "region": { 1410 + "name": "region", 1411 + "type": "text", 1412 + "primaryKey": false, 1413 + "notNull": true, 1414 + "autoincrement": false, 1415 + "default": "''" 1416 + }, 1417 + "status": { 1418 + "name": "status", 1419 + "type": "text", 1420 + "primaryKey": false, 1421 + "notNull": true, 1422 + "autoincrement": false, 1423 + "default": "'active'" 1424 + }, 1425 + "created_at": { 1426 + "name": "created_at", 1427 + "type": "integer", 1428 + "primaryKey": false, 1429 + "notNull": false, 1430 + "autoincrement": false, 1431 + "default": "(strftime('%s', 'now'))" 1432 + }, 1433 + "updated_at": { 1434 + "name": "updated_at", 1435 + "type": "integer", 1436 + "primaryKey": false, 1437 + "notNull": false, 1438 + "autoincrement": false, 1439 + "default": "(strftime('%s', 'now'))" 1440 + } 1441 + }, 1442 + "indexes": { 1443 + "monitor_status_idx": { 1444 + "name": "monitor_status_idx", 1445 + "columns": [ 1446 + "monitor_id", 1447 + "region" 1448 + ], 1449 + "isUnique": false 1450 + } 1451 + }, 1452 + "foreignKeys": { 1453 + "monitor_status_monitor_id_monitor_id_fk": { 1454 + "name": "monitor_status_monitor_id_monitor_id_fk", 1455 + "tableFrom": "monitor_status", 1456 + "tableTo": "monitor", 1457 + "columnsFrom": [ 1458 + "monitor_id" 1459 + ], 1460 + "columnsTo": [ 1461 + "id" 1462 + ], 1463 + "onDelete": "cascade", 1464 + "onUpdate": "no action" 1465 + } 1466 + }, 1467 + "compositePrimaryKeys": { 1468 + "monitor_status_monitor_id_region_pk": { 1469 + "columns": [ 1470 + "monitor_id", 1471 + "region" 1472 + ], 1473 + "name": "monitor_status_monitor_id_region_pk" 1474 + } 1475 + }, 1476 + "uniqueConstraints": {} 1477 + }, 1478 + "invitation": { 1479 + "name": "invitation", 1480 + "columns": { 1481 + "id": { 1482 + "name": "id", 1483 + "type": "integer", 1484 + "primaryKey": true, 1485 + "notNull": true, 1486 + "autoincrement": false 1487 + }, 1488 + "email": { 1489 + "name": "email", 1490 + "type": "text", 1491 + "primaryKey": false, 1492 + "notNull": true, 1493 + "autoincrement": false 1494 + }, 1495 + "role": { 1496 + "name": "role", 1497 + "type": "text", 1498 + "primaryKey": false, 1499 + "notNull": true, 1500 + "autoincrement": false, 1501 + "default": "'member'" 1502 + }, 1503 + "workspace_id": { 1504 + "name": "workspace_id", 1505 + "type": "integer", 1506 + "primaryKey": false, 1507 + "notNull": true, 1508 + "autoincrement": false 1509 + }, 1510 + "token": { 1511 + "name": "token", 1512 + "type": "text", 1513 + "primaryKey": false, 1514 + "notNull": true, 1515 + "autoincrement": false 1516 + }, 1517 + "expires_at": { 1518 + "name": "expires_at", 1519 + "type": "integer", 1520 + "primaryKey": false, 1521 + "notNull": true, 1522 + "autoincrement": false 1523 + }, 1524 + "created_at": { 1525 + "name": "created_at", 1526 + "type": "integer", 1527 + "primaryKey": false, 1528 + "notNull": false, 1529 + "autoincrement": false, 1530 + "default": "(strftime('%s', 'now'))" 1531 + }, 1532 + "accepted_at": { 1533 + "name": "accepted_at", 1534 + "type": "integer", 1535 + "primaryKey": false, 1536 + "notNull": false, 1537 + "autoincrement": false 1538 + } 1539 + }, 1540 + "indexes": {}, 1541 + "foreignKeys": {}, 1542 + "compositePrimaryKeys": {}, 1543 + "uniqueConstraints": {} 1544 + }, 1545 + "incident": { 1546 + "name": "incident", 1547 + "columns": { 1548 + "id": { 1549 + "name": "id", 1550 + "type": "integer", 1551 + "primaryKey": true, 1552 + "notNull": true, 1553 + "autoincrement": false 1554 + }, 1555 + "title": { 1556 + "name": "title", 1557 + "type": "text", 1558 + "primaryKey": false, 1559 + "notNull": true, 1560 + "autoincrement": false, 1561 + "default": "''" 1562 + }, 1563 + "summary": { 1564 + "name": "summary", 1565 + "type": "text", 1566 + "primaryKey": false, 1567 + "notNull": true, 1568 + "autoincrement": false, 1569 + "default": "''" 1570 + }, 1571 + "status": { 1572 + "name": "status", 1573 + "type": "text", 1574 + "primaryKey": false, 1575 + "notNull": true, 1576 + "autoincrement": false, 1577 + "default": "'triage'" 1578 + }, 1579 + "monitor_id": { 1580 + "name": "monitor_id", 1581 + "type": "integer", 1582 + "primaryKey": false, 1583 + "notNull": false, 1584 + "autoincrement": false 1585 + }, 1586 + "workspace_id": { 1587 + "name": "workspace_id", 1588 + "type": "integer", 1589 + "primaryKey": false, 1590 + "notNull": false, 1591 + "autoincrement": false 1592 + }, 1593 + "started_at": { 1594 + "name": "started_at", 1595 + "type": "integer", 1596 + "primaryKey": false, 1597 + "notNull": true, 1598 + "autoincrement": false, 1599 + "default": "(strftime('%s', 'now'))" 1600 + }, 1601 + "acknowledged_at": { 1602 + "name": "acknowledged_at", 1603 + "type": "integer", 1604 + "primaryKey": false, 1605 + "notNull": false, 1606 + "autoincrement": false 1607 + }, 1608 + "acknowledged_by": { 1609 + "name": "acknowledged_by", 1610 + "type": "integer", 1611 + "primaryKey": false, 1612 + "notNull": false, 1613 + "autoincrement": false 1614 + }, 1615 + "resolved_at": { 1616 + "name": "resolved_at", 1617 + "type": "integer", 1618 + "primaryKey": false, 1619 + "notNull": false, 1620 + "autoincrement": false 1621 + }, 1622 + "resolved_by": { 1623 + "name": "resolved_by", 1624 + "type": "integer", 1625 + "primaryKey": false, 1626 + "notNull": false, 1627 + "autoincrement": false 1628 + }, 1629 + "incident_screenshot_url": { 1630 + "name": "incident_screenshot_url", 1631 + "type": "text", 1632 + "primaryKey": false, 1633 + "notNull": false, 1634 + "autoincrement": false 1635 + }, 1636 + "recovery_screenshot_url": { 1637 + "name": "recovery_screenshot_url", 1638 + "type": "text", 1639 + "primaryKey": false, 1640 + "notNull": false, 1641 + "autoincrement": false 1642 + }, 1643 + "auto_resolved": { 1644 + "name": "auto_resolved", 1645 + "type": "integer", 1646 + "primaryKey": false, 1647 + "notNull": false, 1648 + "autoincrement": false, 1649 + "default": false 1650 + }, 1651 + "created_at": { 1652 + "name": "created_at", 1653 + "type": "integer", 1654 + "primaryKey": false, 1655 + "notNull": false, 1656 + "autoincrement": false, 1657 + "default": "(strftime('%s', 'now'))" 1658 + }, 1659 + "updated_at": { 1660 + "name": "updated_at", 1661 + "type": "integer", 1662 + "primaryKey": false, 1663 + "notNull": false, 1664 + "autoincrement": false, 1665 + "default": "(strftime('%s', 'now'))" 1666 + } 1667 + }, 1668 + "indexes": { 1669 + "incident_monitor_id_started_at_unique": { 1670 + "name": "incident_monitor_id_started_at_unique", 1671 + "columns": [ 1672 + "monitor_id", 1673 + "started_at" 1674 + ], 1675 + "isUnique": true 1676 + } 1677 + }, 1678 + "foreignKeys": { 1679 + "incident_monitor_id_monitor_id_fk": { 1680 + "name": "incident_monitor_id_monitor_id_fk", 1681 + "tableFrom": "incident", 1682 + "tableTo": "monitor", 1683 + "columnsFrom": [ 1684 + "monitor_id" 1685 + ], 1686 + "columnsTo": [ 1687 + "id" 1688 + ], 1689 + "onDelete": "set default", 1690 + "onUpdate": "no action" 1691 + }, 1692 + "incident_workspace_id_workspace_id_fk": { 1693 + "name": "incident_workspace_id_workspace_id_fk", 1694 + "tableFrom": "incident", 1695 + "tableTo": "workspace", 1696 + "columnsFrom": [ 1697 + "workspace_id" 1698 + ], 1699 + "columnsTo": [ 1700 + "id" 1701 + ], 1702 + "onDelete": "no action", 1703 + "onUpdate": "no action" 1704 + }, 1705 + "incident_acknowledged_by_user_id_fk": { 1706 + "name": "incident_acknowledged_by_user_id_fk", 1707 + "tableFrom": "incident", 1708 + "tableTo": "user", 1709 + "columnsFrom": [ 1710 + "acknowledged_by" 1711 + ], 1712 + "columnsTo": [ 1713 + "id" 1714 + ], 1715 + "onDelete": "no action", 1716 + "onUpdate": "no action" 1717 + }, 1718 + "incident_resolved_by_user_id_fk": { 1719 + "name": "incident_resolved_by_user_id_fk", 1720 + "tableFrom": "incident", 1721 + "tableTo": "user", 1722 + "columnsFrom": [ 1723 + "resolved_by" 1724 + ], 1725 + "columnsTo": [ 1726 + "id" 1727 + ], 1728 + "onDelete": "no action", 1729 + "onUpdate": "no action" 1730 + } 1731 + }, 1732 + "compositePrimaryKeys": {}, 1733 + "uniqueConstraints": {} 1734 + }, 1735 + "monitor_tag": { 1736 + "name": "monitor_tag", 1737 + "columns": { 1738 + "id": { 1739 + "name": "id", 1740 + "type": "integer", 1741 + "primaryKey": true, 1742 + "notNull": true, 1743 + "autoincrement": false 1744 + }, 1745 + "workspace_id": { 1746 + "name": "workspace_id", 1747 + "type": "integer", 1748 + "primaryKey": false, 1749 + "notNull": true, 1750 + "autoincrement": false 1751 + }, 1752 + "name": { 1753 + "name": "name", 1754 + "type": "text", 1755 + "primaryKey": false, 1756 + "notNull": true, 1757 + "autoincrement": false 1758 + }, 1759 + "color": { 1760 + "name": "color", 1761 + "type": "text", 1762 + "primaryKey": false, 1763 + "notNull": true, 1764 + "autoincrement": false 1765 + }, 1766 + "created_at": { 1767 + "name": "created_at", 1768 + "type": "integer", 1769 + "primaryKey": false, 1770 + "notNull": false, 1771 + "autoincrement": false, 1772 + "default": "(strftime('%s', 'now'))" 1773 + }, 1774 + "updated_at": { 1775 + "name": "updated_at", 1776 + "type": "integer", 1777 + "primaryKey": false, 1778 + "notNull": false, 1779 + "autoincrement": false, 1780 + "default": "(strftime('%s', 'now'))" 1781 + } 1782 + }, 1783 + "indexes": {}, 1784 + "foreignKeys": { 1785 + "monitor_tag_workspace_id_workspace_id_fk": { 1786 + "name": "monitor_tag_workspace_id_workspace_id_fk", 1787 + "tableFrom": "monitor_tag", 1788 + "tableTo": "workspace", 1789 + "columnsFrom": [ 1790 + "workspace_id" 1791 + ], 1792 + "columnsTo": [ 1793 + "id" 1794 + ], 1795 + "onDelete": "cascade", 1796 + "onUpdate": "no action" 1797 + } 1798 + }, 1799 + "compositePrimaryKeys": {}, 1800 + "uniqueConstraints": {} 1801 + }, 1802 + "monitor_tag_to_monitor": { 1803 + "name": "monitor_tag_to_monitor", 1804 + "columns": { 1805 + "monitor_id": { 1806 + "name": "monitor_id", 1807 + "type": "integer", 1808 + "primaryKey": false, 1809 + "notNull": true, 1810 + "autoincrement": false 1811 + }, 1812 + "monitor_tag_id": { 1813 + "name": "monitor_tag_id", 1814 + "type": "integer", 1815 + "primaryKey": false, 1816 + "notNull": true, 1817 + "autoincrement": false 1818 + }, 1819 + "created_at": { 1820 + "name": "created_at", 1821 + "type": "integer", 1822 + "primaryKey": false, 1823 + "notNull": false, 1824 + "autoincrement": false, 1825 + "default": "(strftime('%s', 'now'))" 1826 + } 1827 + }, 1828 + "indexes": {}, 1829 + "foreignKeys": { 1830 + "monitor_tag_to_monitor_monitor_id_monitor_id_fk": { 1831 + "name": "monitor_tag_to_monitor_monitor_id_monitor_id_fk", 1832 + "tableFrom": "monitor_tag_to_monitor", 1833 + "tableTo": "monitor", 1834 + "columnsFrom": [ 1835 + "monitor_id" 1836 + ], 1837 + "columnsTo": [ 1838 + "id" 1839 + ], 1840 + "onDelete": "cascade", 1841 + "onUpdate": "no action" 1842 + }, 1843 + "monitor_tag_to_monitor_monitor_tag_id_monitor_tag_id_fk": { 1844 + "name": "monitor_tag_to_monitor_monitor_tag_id_monitor_tag_id_fk", 1845 + "tableFrom": "monitor_tag_to_monitor", 1846 + "tableTo": "monitor_tag", 1847 + "columnsFrom": [ 1848 + "monitor_tag_id" 1849 + ], 1850 + "columnsTo": [ 1851 + "id" 1852 + ], 1853 + "onDelete": "cascade", 1854 + "onUpdate": "no action" 1855 + } 1856 + }, 1857 + "compositePrimaryKeys": { 1858 + "monitor_tag_to_monitor_monitor_id_monitor_tag_id_pk": { 1859 + "columns": [ 1860 + "monitor_id", 1861 + "monitor_tag_id" 1862 + ], 1863 + "name": "monitor_tag_to_monitor_monitor_id_monitor_tag_id_pk" 1864 + } 1865 + }, 1866 + "uniqueConstraints": {} 1867 + } 1868 + }, 1869 + "enums": {}, 1870 + "_meta": { 1871 + "schemas": {}, 1872 + "tables": {}, 1873 + "columns": {} 1874 + } 1875 + }
+7
packages/db/drizzle/meta/_journal.json
··· 197 197 "when": 1714586658374, 198 198 "tag": "0027_bizarre_bastion", 199 199 "breakpoints": true 200 + }, 201 + { 202 + "idx": 28, 203 + "version": "5", 204 + "when": 1715173356076, 205 + "tag": "0028_thin_power_pack", 206 + "breakpoints": true 200 207 } 201 208 ] 202 209 }
+1
packages/db/package.json
··· 28 28 "bufferutil": "4.0.7", 29 29 "drizzle-kit": "0.20.17", 30 30 "encoding": "0.1.13", 31 + "next-auth": "5.0.0-beta.17", 31 32 "typescript": "5.4.5", 32 33 "utf-8-validate": "6.0.3" 33 34 },
+1 -1
packages/db/src/db.ts
··· 1 - import { createClient } from "@libsql/client/http"; 1 + import { createClient } from "@libsql/client"; 2 2 import { drizzle } from "drizzle-orm/libsql"; 3 3 4 4 import { env } from "../env.mjs";
+54 -2
packages/db/src/schema/users/user.ts
··· 5 5 sqliteTable, 6 6 text, 7 7 } from "drizzle-orm/sqlite-core"; 8 + import type { AdapterAccount } from "next-auth/adapters"; 8 9 9 10 import { workspace, workspaceRole } from "../workspaces"; 10 11 11 12 export const user = sqliteTable("user", { 12 13 id: integer("id").primaryKey(), 14 + 15 + // clerk fields 13 16 tenantId: text("tenant_id", { length: 256 }).unique(), // the clerk User Id 14 - 15 17 firstName: text("first_name").default(""), 16 18 lastName: text("last_name").default(""), 17 - email: text("email").default(""), 18 19 photoUrl: text("photo_url").default(""), 20 + 21 + // next-auth fields 22 + name: text("name"), 23 + email: text("email").default(""), 24 + emailVerified: integer("emailVerified", { mode: "timestamp_ms" }), 19 25 20 26 createdAt: integer("created_at", { mode: "timestamp" }).default( 21 27 sql`(strftime('%s', 'now'))`, ··· 61 67 }), 62 68 }), 63 69 ); 70 + 71 + // NEXT AUTH TABLES 72 + 73 + export const account = sqliteTable( 74 + "account", 75 + { 76 + userId: integer("user_id") 77 + .notNull() 78 + .references(() => user.id, { onDelete: "cascade" }), 79 + type: text("type").$type<AdapterAccount["type"]>().notNull(), 80 + provider: text("provider").notNull(), 81 + providerAccountId: text("provider_account_id").notNull(), 82 + refresh_token: text("refresh_token"), 83 + access_token: text("access_token"), 84 + expires_at: integer("expires_at"), 85 + token_type: text("token_type"), 86 + scope: text("scope"), 87 + id_token: text("id_token"), 88 + session_state: text("session_state"), 89 + }, 90 + (account) => ({ 91 + compoundKey: primaryKey({ 92 + columns: [account.provider, account.providerAccountId], 93 + }), 94 + }), 95 + ); 96 + 97 + export const session = sqliteTable("session", { 98 + sessionToken: text("session_token").primaryKey(), 99 + userId: integer("user_id") 100 + .notNull() 101 + .references(() => user.id, { onDelete: "cascade" }), 102 + expires: integer("expires", { mode: "timestamp_ms" }).notNull(), 103 + }); 104 + 105 + export const verificationToken = sqliteTable( 106 + "verification_token", 107 + { 108 + identifier: text("identifier").notNull(), 109 + token: text("token").notNull(), 110 + expires: integer("expires", { mode: "timestamp_ms" }).notNull(), 111 + }, 112 + (vt) => ({ 113 + compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }), 114 + }), 115 + );
+1 -1
packages/notifications/discord/package.json
··· 10 10 "@types/node": "20.8.0", 11 11 "@types/react": "18.2.64", 12 12 "@types/react-dom": "18.2.21", 13 - "next": "14.2.1", 13 + "next": "14.2.3", 14 14 "typescript": "5.4.5" 15 15 } 16 16 }
+1 -1
packages/notifications/email/package.json
··· 18 18 "@types/node": "20.8.0", 19 19 "@types/react": "18.2.64", 20 20 "@types/react-dom": "18.2.21", 21 - "next": "14.2.1", 21 + "next": "14.2.3", 22 22 "typescript": "5.4.5" 23 23 } 24 24 }
+1 -1
packages/notifications/slack/package.json
··· 10 10 "@types/node": "20.8.0", 11 11 "@types/react": "18.2.64", 12 12 "@types/react-dom": "18.2.21", 13 - "next": "14.2.1", 13 + "next": "14.2.3", 14 14 "typescript": "5.4.5" 15 15 } 16 16 }
+1 -1
packages/notifications/twillio-sms/package.json
··· 14 14 "@types/node": "20.8.0", 15 15 "@types/react": "18.2.64", 16 16 "@types/react-dom": "18.2.21", 17 - "next": "14.2.1", 17 + "next": "14.2.3", 18 18 "typescript": "5.4.5" 19 19 } 20 20 }
+1 -1
packages/ui/package.json
··· 30 30 "@radix-ui/react-hover-card": "1.0.7", 31 31 "@radix-ui/react-label": "2.0.2", 32 32 "@radix-ui/react-popover": "1.0.7", 33 - "@radix-ui/react-progress": "^1.0.3", 33 + "@radix-ui/react-progress": "1.0.3", 34 34 "@radix-ui/react-radio-group": "1.1.3", 35 35 "@radix-ui/react-select": "2.0.0", 36 36 "@radix-ui/react-separator": "1.0.3",
+210 -469
pnpm-lock.yaml
··· 44 44 specifier: 0.2.1 45 45 version: 0.2.1(hono@4.1.4)(zod@3.22.4) 46 46 detect-browser: 47 - specifier: ^5.3.0 47 + specifier: 5.3.0 48 48 version: 5.3.0 49 49 hono: 50 50 specifier: 4.1.4 ··· 227 227 228 228 apps/web: 229 229 dependencies: 230 - '@clerk/nextjs': 231 - specifier: 4.29.9 232 - version: 4.29.9(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 230 + '@auth/core': 231 + specifier: 0.30.0 232 + version: 0.30.0 233 + '@auth/drizzle-adapter': 234 + specifier: 1.0.1 235 + version: 1.0.1 233 236 '@google-cloud/tasks': 234 237 specifier: 5.0.0 235 238 version: 5.0.0(encoding@0.1.13) ··· 239 242 '@hookform/resolvers': 240 243 specifier: 3.3.1 241 244 version: 3.3.1(react-hook-form@7.47.0(react@18.2.0)) 245 + '@libsql/client': 246 + specifier: 0.6.0 247 + version: 0.6.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) 242 248 '@openstatus/analytics': 243 249 specifier: workspace:* 244 250 version: link:../../packages/analytics ··· 256 262 version: link:../../packages/emails 257 263 '@openstatus/next-monitoring': 258 264 specifier: 0.0.2 259 - version: 0.0.2(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 265 + version: 0.0.2(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 260 266 '@openstatus/notification-discord': 261 267 specifier: workspace:* 262 268 version: link:../../packages/notifications/discord ··· 295 301 version: 7.100.1 296 302 '@sentry/nextjs': 297 303 specifier: 7.100.1 298 - version: 7.100.1(encoding@0.1.13)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 304 + version: 7.100.1(encoding@0.1.13)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 299 305 '@stripe/stripe-js': 300 306 specifier: 2.1.6 301 307 version: 2.1.6 ··· 319 325 version: 10.45.1(@trpc/server@10.45.1) 320 326 '@trpc/next': 321 327 specifier: 10.45.1 322 - version: 10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.45.1)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 328 + version: 10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.45.1)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 323 329 '@trpc/react-query': 324 330 specifier: 10.45.1 325 331 version: 10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) ··· 372 378 specifier: 5.0.1 373 379 version: 5.0.1 374 380 next: 375 - specifier: 14.2.1 376 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 381 + specifier: 14.2.3 382 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 383 + next-auth: 384 + specifier: 5.0.0-beta.17 385 + version: 5.0.0-beta.17(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 377 386 next-contentlayer: 378 387 specifier: 0.3.4 379 - version: 0.3.4(contentlayer@0.3.4(esbuild@0.19.12))(esbuild@0.19.12)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 388 + version: 0.3.4(contentlayer@0.3.4(esbuild@0.19.12))(esbuild@0.19.12)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 380 389 next-plausible: 381 390 specifier: 3.12.0 382 - version: 3.12.0(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 391 + version: 3.12.0(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 383 392 next-themes: 384 393 specifier: 0.2.1 385 - version: 0.2.1(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 394 + version: 0.2.1(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 395 + random-word-slugs: 396 + specifier: 0.1.7 397 + version: 0.1.7 386 398 react: 387 399 specifier: 18.2.0 388 400 version: 18.2.0 ··· 417 429 specifier: 1.1.0 418 430 version: 1.1.0 419 431 rss: 420 - specifier: ^1.2.2 432 + specifier: 1.2.2 421 433 version: 1.2.2 422 434 shiki: 423 435 specifier: 0.14.4 ··· 463 475 specifier: 18.2.21 464 476 version: 18.2.21 465 477 '@types/rss': 466 - specifier: ^0.0.32 478 + specifier: 0.0.32 467 479 version: 0.0.32 468 480 autoprefixer: 469 481 specifier: 10.4.16 ··· 493 505 packages/analytics: 494 506 dependencies: 495 507 '@jitsu/js': 496 - specifier: 1.3.0 497 - version: 1.3.0(@types/dlv@1.1.4) 508 + specifier: 1.9.2 509 + version: 1.9.2(@types/dlv@1.1.4) 498 510 '@t3-oss/env-core': 499 511 specifier: 0.7.0 500 512 version: 0.7.0(typescript@5.4.5)(zod@3.22.4) ··· 514 526 515 527 packages/api: 516 528 dependencies: 517 - '@clerk/nextjs': 518 - specifier: 4.29.9 519 - version: 4.29.9(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 520 529 '@openstatus/analytics': 521 530 specifier: workspace:* 522 531 version: link:../analytics ··· 551 560 specifier: 5.0.0-beta.1 552 561 version: 5.0.0-beta.1 553 562 next: 554 - specifier: 14.2.1 555 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 563 + specifier: 14.2.3 564 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 556 565 random-word-slugs: 557 566 specifier: 0.1.7 558 567 version: 0.1.7 ··· 603 612 specifier: 6.7.3 604 613 version: 6.7.3(eslint@8.50.0)(typescript@5.4.5) 605 614 eslint-config-next: 606 - specifier: 14.2.1 607 - version: 14.2.1(eslint@8.50.0)(typescript@5.4.5) 615 + specifier: 14.2.3 616 + version: 14.2.3(eslint@8.50.0)(typescript@5.4.5) 608 617 eslint-config-prettier: 609 618 specifier: 9.0.0 610 619 version: 9.0.0(eslint@8.50.0) ··· 670 679 encoding: 671 680 specifier: 0.1.13 672 681 version: 0.1.13 682 + next-auth: 683 + specifier: 5.0.0-beta.17 684 + version: 5.0.0-beta.17(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) 673 685 typescript: 674 686 specifier: 5.4.5 675 687 version: 5.4.5 ··· 742 754 specifier: 18.2.21 743 755 version: 18.2.21 744 756 next: 745 - specifier: 14.2.1 746 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 757 + specifier: 14.2.3 758 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 747 759 typescript: 748 760 specifier: 5.4.5 749 761 version: 5.4.5 ··· 788 800 specifier: 18.2.21 789 801 version: 18.2.21 790 802 next: 791 - specifier: 14.2.1 792 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 803 + specifier: 14.2.3 804 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 793 805 typescript: 794 806 specifier: 5.4.5 795 807 version: 5.4.5 ··· 813 825 specifier: 18.2.21 814 826 version: 18.2.21 815 827 next: 816 - specifier: 14.2.1 817 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 828 + specifier: 14.2.3 829 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 818 830 typescript: 819 831 specifier: 5.4.5 820 832 version: 5.4.5 ··· 850 862 specifier: 18.2.21 851 863 version: 18.2.21 852 864 next: 853 - specifier: 14.2.1 854 - version: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 865 + specifier: 14.2.3 866 + version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 855 867 typescript: 856 868 specifier: 5.4.5 857 869 version: 5.4.5 ··· 992 1004 specifier: 1.0.7 993 1005 version: 1.0.7(@types/react-dom@18.2.21)(@types/react@18.2.64)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 994 1006 '@radix-ui/react-progress': 995 - specifier: ^1.0.3 1007 + specifier: 1.0.3 996 1008 version: 1.0.3(@types/react-dom@18.2.21)(@types/react@18.2.64)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 997 1009 '@radix-ui/react-radio-group': 998 1010 specifier: 1.1.3 ··· 1038 1050 version: 3.3.0 1039 1051 next-themes: 1040 1052 specifier: 0.2.1 1041 - version: 0.2.1(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 1053 + version: 0.2.1(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 1042 1054 react: 1043 1055 specifier: 18.2.0 1044 1056 version: 18.2.0 ··· 1160 1172 peerDependencies: 1161 1173 zod: ^3.20.2 1162 1174 1175 + '@auth/core@0.30.0': 1176 + resolution: {integrity: sha512-8AE4m/nk+4EIiVCJwxZAsJeAQuzpEC8M8768mmKVn60CGDdupKQkVhxbRlm5Qh7eNRCoFFME+0DvtaX2aXrYaA==} 1177 + peerDependencies: 1178 + '@simplewebauthn/browser': ^9.0.1 1179 + '@simplewebauthn/server': ^9.0.2 1180 + nodemailer: ^6.8.0 1181 + peerDependenciesMeta: 1182 + '@simplewebauthn/browser': 1183 + optional: true 1184 + '@simplewebauthn/server': 1185 + optional: true 1186 + nodemailer: 1187 + optional: true 1188 + 1189 + '@auth/drizzle-adapter@1.0.1': 1190 + resolution: {integrity: sha512-E4np2F48p930q+YeQ5ipZPv/L+9gmQcB7g6NQQyux2wtanRNOXNW4TG8wMjSRfTzccNq161YZ8Fm5le/5snkGQ==} 1191 + 1163 1192 '@aws-crypto/crc32@3.0.0': 1164 1193 resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} 1165 1194 ··· 1489 1518 1490 1519 '@chronark/zod-bird@0.3.6': 1491 1520 resolution: {integrity: sha512-hE8kCGLJK5ncH8F7uPaqPiOOqo68vUI66nusg7HO5X9BcyN8lXfeQliu6Ou1kOSq95OYshf9nB2fk2+LEvF4ng==} 1492 - 1493 - '@clerk/backend@0.38.3': 1494 - resolution: {integrity: sha512-k14WRljVNETpIYrt99MBP/Zd7KEwkudQKSCEMatQbiRkWgrpwDWE8Czv+JzF1J7sdMiicBI+p2ph9biX1EOFzw==} 1495 - engines: {node: '>=14'} 1496 - 1497 - '@clerk/clerk-react@4.30.7': 1498 - resolution: {integrity: sha512-+6Q1hVteqn66gFLiCKSqqSdz2MBjsEjs1fkGLAEKZC1GdfOKrH6oWcLuSwUdyqRvJWuyjeIgwq15zoHtXKyztA==} 1499 - engines: {node: '>=14'} 1500 - peerDependencies: 1501 - react: '>=16' 1502 - 1503 - '@clerk/clerk-sdk-node@4.13.11': 1504 - resolution: {integrity: sha512-6CiRx61SW0B7i+4STlID537LvwFJvNGWxxQZY96OPHQnvYGYsp+9PdEyY4zaQiyLQBLYJt1+uc7VsdSYY5Omww==} 1505 - engines: {node: '>=14'} 1506 - 1507 - '@clerk/nextjs@4.29.9': 1508 - resolution: {integrity: sha512-RsOz+lxlPYJi9cBvhBRqAUVUOMBT20R3ppt3eof97DkqCT6YaHJx/S13XcYUuo6ojYRDDJ/nI6XiLcfpqIJO6g==} 1509 - engines: {node: '>=14'} 1510 - peerDependencies: 1511 - next: '>=10' 1512 - react: ^17.0.2 || ^18.0.0-0 1513 - react-dom: ^17.0.2 || ^18.0.0-0 1514 - 1515 - '@clerk/shared@1.3.3': 1516 - resolution: {integrity: sha512-Eein8cK72dlvY6Q1uFuw9K9MJH1OPjU8FzWloMTKklBo+iPiM6+uENGeGwlY5KId3q/kgPwRc2hBQnUoaijxCQ==} 1517 - peerDependencies: 1518 - react: '>=16' 1519 - peerDependenciesMeta: 1520 - react: 1521 - optional: true 1522 - 1523 - '@clerk/types@3.62.1': 1524 - resolution: {integrity: sha512-RmQhWB7EMZw2nE24viQG79VyEUULZYWndYew5oXiZx06DyvysMNCorDyEGRmgBbprv7bnbYhHdOtKmx8Wj0jug==} 1525 - engines: {node: '>=14'} 1526 1521 1527 1522 '@clickhouse/client-common@0.3.0': 1528 1523 resolution: {integrity: sha512-LcfJfyMglUTbGuDN/s6e/R3LwtbQXpv6juIJID+tVXxcGzPijhDB+XXQpqbprunqnm48vHmLfCB6/68Pgp5qvg==} ··· 2394 2389 resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} 2395 2390 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 2396 2391 2397 - '@jitsu/js@1.3.0': 2398 - resolution: {integrity: sha512-7k3dM84xqf6Ivaama8VWwGYOcmGI/WWQTUHmHNXao+M/tneU6L72SCNlUE587vgtaxvoN2oROo4sBGO+sTh4ZQ==} 2392 + '@jitsu/js@1.9.2': 2393 + resolution: {integrity: sha512-IFwVJczP/c9Lp5BFQZP5ebHgepbr5N1A+bE5m/CG1Sjekcr/oHuVtw1hjZFHJBa3eK6Gbn0Ax8Ih0LSPZkxiUg==} 2399 2394 2400 2395 '@jridgewell/gen-mapping@0.3.3': 2401 2396 resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} ··· 2506 2501 '@neon-rs/load@0.0.4': 2507 2502 resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} 2508 2503 2509 - '@next/env@14.2.1': 2510 - resolution: {integrity: sha512-qsHJle3GU3CmVx7pUoXcghX4sRN+vINkbLdH611T8ZlsP//grzqVW87BSUgOZeSAD4q7ZdZicdwNe/20U2janA==} 2504 + '@next/env@14.2.3': 2505 + resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} 2511 2506 2512 - '@next/eslint-plugin-next@14.2.1': 2513 - resolution: {integrity: sha512-Fp+mthEBjkn8r9qd6o4JgxKp0IDEzW0VYHD8ZC05xS5/lFNwHKuOdr2kVhWG7BQCO9L6eeepshM1Wbs2T+LgSg==} 2507 + '@next/eslint-plugin-next@14.2.3': 2508 + resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} 2514 2509 2515 - '@next/swc-darwin-arm64@14.2.1': 2516 - resolution: {integrity: sha512-kGjnjcIJehEcd3rT/3NAATJQndAEELk0J9GmGMXHSC75TMnvpOhONcjNHbjtcWE5HUQnIHy5JVkatrnYm1QhVw==} 2510 + '@next/swc-darwin-arm64@14.2.3': 2511 + resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} 2517 2512 engines: {node: '>= 10'} 2518 2513 cpu: [arm64] 2519 2514 os: [darwin] 2520 2515 2521 - '@next/swc-darwin-x64@14.2.1': 2522 - resolution: {integrity: sha512-dAdWndgdQi7BK2WSXrx4lae7mYcOYjbHJUhvOUnJjMNYrmYhxbbvJ2xElZpxNxdfA6zkqagIB9He2tQk+l16ew==} 2516 + '@next/swc-darwin-x64@14.2.3': 2517 + resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} 2523 2518 engines: {node: '>= 10'} 2524 2519 cpu: [x64] 2525 2520 os: [darwin] 2526 2521 2527 - '@next/swc-linux-arm64-gnu@14.2.1': 2528 - resolution: {integrity: sha512-2ZctfnyFOGvTkoD6L+DtQtO3BfFz4CapoHnyLTXkOxbZkVRgg3TQBUjTD/xKrO1QWeydeo8AWfZRg8539qNKrg==} 2522 + '@next/swc-linux-arm64-gnu@14.2.3': 2523 + resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} 2529 2524 engines: {node: '>= 10'} 2530 2525 cpu: [arm64] 2531 2526 os: [linux] 2532 2527 2533 - '@next/swc-linux-arm64-musl@14.2.1': 2534 - resolution: {integrity: sha512-jazZXctiaanemy4r+TPIpFP36t1mMwWCKMsmrTRVChRqE6putyAxZA4PDujx0SnfvZHosjdkx9xIq9BzBB5tWg==} 2528 + '@next/swc-linux-arm64-musl@14.2.3': 2529 + resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} 2535 2530 engines: {node: '>= 10'} 2536 2531 cpu: [arm64] 2537 2532 os: [linux] 2538 2533 2539 - '@next/swc-linux-x64-gnu@14.2.1': 2540 - resolution: {integrity: sha512-VjCHWCjsAzQAAo8lkBOLEIkBZFdfW+Z18qcQ056kL4KpUYc8o59JhLDCBlhg+hINQRgzQ2UPGma2AURGOH0+Qg==} 2534 + '@next/swc-linux-x64-gnu@14.2.3': 2535 + resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} 2541 2536 engines: {node: '>= 10'} 2542 2537 cpu: [x64] 2543 2538 os: [linux] 2544 2539 2545 - '@next/swc-linux-x64-musl@14.2.1': 2546 - resolution: {integrity: sha512-7HZKYKvAp4nAHiHIbY04finRqjeYvkITOGOurP1aLMexIFG/1+oCnqhGogBdc4lao/lkMW1c+AkwWSzSlLasqw==} 2540 + '@next/swc-linux-x64-musl@14.2.3': 2541 + resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} 2547 2542 engines: {node: '>= 10'} 2548 2543 cpu: [x64] 2549 2544 os: [linux] 2550 2545 2551 - '@next/swc-win32-arm64-msvc@14.2.1': 2552 - resolution: {integrity: sha512-YGHklaJ/Cj/F0Xd8jxgj2p8po4JTCi6H7Z3Yics3xJhm9CPIqtl8erlpK1CLv+HInDqEWfXilqatF8YsLxxA2Q==} 2546 + '@next/swc-win32-arm64-msvc@14.2.3': 2547 + resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} 2553 2548 engines: {node: '>= 10'} 2554 2549 cpu: [arm64] 2555 2550 os: [win32] 2556 2551 2557 - '@next/swc-win32-ia32-msvc@14.2.1': 2558 - resolution: {integrity: sha512-o+ISKOlvU/L43ZhtAAfCjwIfcwuZstiHVXq/BDsZwGqQE0h/81td95MPHliWCnFoikzWcYqh+hz54ZB2FIT8RA==} 2552 + '@next/swc-win32-ia32-msvc@14.2.3': 2553 + resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} 2559 2554 engines: {node: '>= 10'} 2560 2555 cpu: [ia32] 2561 2556 os: [win32] 2562 2557 2563 - '@next/swc-win32-x64-msvc@14.2.1': 2564 - resolution: {integrity: sha512-GmRoTiLcvCLifujlisknv4zu9/C4i9r0ktsA8E51EMqJL4bD4CpO7lDYr7SrUxCR0tS4RVcrqKmCak24T0ohaw==} 2558 + '@next/swc-win32-x64-msvc@14.2.3': 2559 + resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} 2565 2560 engines: {node: '>= 10'} 2566 2561 cpu: [x64] 2567 2562 os: [win32] ··· 2735 2730 resolution: {integrity: sha512-LMGqfSZkaMQXqewO0o1wvWr/2fQdCh4a3Sqlxka/UsJCe0cfLulh6x2aqnKLnsrSGiCq5rSCwvINd152i0nCqw==} 2736 2731 engines: {node: '>=14'} 2737 2732 2738 - '@peculiar/asn1-schema@2.3.8': 2739 - resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} 2740 - 2741 - '@peculiar/json-schema@1.1.12': 2742 - resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} 2743 - engines: {node: '>=8.0.0'} 2744 - 2745 - '@peculiar/webcrypto@1.4.1': 2746 - resolution: {integrity: sha512-eK4C6WTNYxoI7JOabMoZICiyqRRtJB220bh0Mbj5RwRycleZf9BPyZoxsTvpP0FpmVS2aS13NKOuh5/tN3sIRw==} 2747 - engines: {node: '>=10.12.0'} 2733 + '@panva/hkdf@1.1.1': 2734 + resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} 2748 2735 2749 2736 '@pkgjs/parseargs@0.11.0': 2750 2737 resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} ··· 3978 3965 '@types/acorn@4.0.6': 3979 3966 resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} 3980 3967 3981 - '@types/body-parser@1.19.4': 3982 - resolution: {integrity: sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==} 3983 - 3984 3968 '@types/caseless@0.12.4': 3985 3969 resolution: {integrity: sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==} 3986 3970 3987 - '@types/connect@3.4.37': 3988 - resolution: {integrity: sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==} 3989 - 3990 - '@types/cookies@0.7.7': 3991 - resolution: {integrity: sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==} 3971 + '@types/cookie@0.6.0': 3972 + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} 3992 3973 3993 3974 '@types/d3-array@3.0.9': 3994 3975 resolution: {integrity: sha512-mZowFN3p64ajCJJ4riVYlOjNlBJv3hctgAY01pjw3qTnJePD8s9DZmYDzhHKvzfCYvdjwylkU38+Vdt7Cu2FDA==} ··· 4032 4013 '@types/estree@1.0.3': 4033 4014 resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} 4034 4015 4035 - '@types/express-serve-static-core@4.17.39': 4036 - resolution: {integrity: sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==} 4037 - 4038 - '@types/express@4.17.14': 4039 - resolution: {integrity: sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==} 4040 - 4041 4016 '@types/glob@7.2.0': 4042 4017 resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} 4043 4018 ··· 4047 4022 '@types/hast@3.0.4': 4048 4023 resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} 4049 4024 4050 - '@types/http-errors@2.0.3': 4051 - resolution: {integrity: sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==} 4052 - 4053 4025 '@types/inquirer@6.5.0': 4054 4026 resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} 4055 4027 ··· 4074 4046 '@types/json5@0.0.29': 4075 4047 resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} 4076 4048 4077 - '@types/keygrip@1.0.4': 4078 - resolution: {integrity: sha512-/tjWYD8StMrINelsrHNmpXceo9s3/Y22AzePH1qCvXIgmz/aQp2YFFr6HqhNQVIOdcvaVyp5GS+yjHGuF7Rwsg==} 4079 - 4080 4049 '@types/long@4.0.2': 4081 4050 resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} 4082 4051 ··· 4089 4058 '@types/mdx@2.0.9': 4090 4059 resolution: {integrity: sha512-OKMdj17y8Cs+k1r0XFyp59ChSOwf8ODGtMQ4mnpfz5eFDk1aO41yN3pSKGuvVzmWAkFp37seubY1tzOVpwfWwg==} 4091 4060 4092 - '@types/mime@1.3.4': 4093 - resolution: {integrity: sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==} 4094 - 4095 - '@types/mime@3.0.3': 4096 - resolution: {integrity: sha512-i8MBln35l856k5iOhKk2XJ4SeAWg75mLIpZB4v6imOagKL6twsukBZGDMNhdOVk7yRFTMPpfILocMos59Q1otQ==} 4097 - 4098 4061 '@types/minimatch@5.1.2': 4099 4062 resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} 4100 4063 ··· 4104 4067 '@types/ms@0.7.33': 4105 4068 resolution: {integrity: sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==} 4106 4069 4107 - '@types/node-fetch@2.6.2': 4108 - resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} 4109 - 4110 4070 '@types/node-forge@1.3.11': 4111 4071 resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} 4112 - 4113 - '@types/node@16.18.6': 4114 - resolution: {integrity: sha512-vmYJF0REqDyyU0gviezF/KHq/fYaUbFhkcNbQCuPGFQj6VTbXuHZoxs/Y7mutWe73C8AC6l9fFu8mSYiBAqkGA==} 4115 4072 4116 4073 '@types/node@20.8.0': 4117 4074 resolution: {integrity: sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ==} ··· 4125 4082 '@types/prop-types@15.7.9': 4126 4083 resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==} 4127 4084 4128 - '@types/qs@6.9.9': 4129 - resolution: {integrity: sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==} 4130 - 4131 - '@types/range-parser@1.2.6': 4132 - resolution: {integrity: sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==} 4133 - 4134 4085 '@types/react-dom@18.2.21': 4135 4086 resolution: {integrity: sha512-gnvBA/21SA4xxqNXEwNiVcP0xSGHh/gi1VhWv9Bl46a0ItbTT5nFY+G9VSQpaG/8N/qdJpJ+vftQ4zflTtnjLw==} 4136 4087 ··· 4152 4103 '@types/semver@7.5.4': 4153 4104 resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} 4154 4105 4155 - '@types/send@0.17.3': 4156 - resolution: {integrity: sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==} 4157 - 4158 - '@types/serve-static@1.15.4': 4159 - resolution: {integrity: sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==} 4160 - 4161 4106 '@types/stack-utils@2.0.2': 4162 4107 resolution: {integrity: sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==} 4163 4108 ··· 4437 4382 as-table@1.0.55: 4438 4383 resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} 4439 4384 4440 - asn1js@3.0.5: 4441 - resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} 4442 - engines: {node: '>=12.0.0'} 4443 - 4444 4385 ast-types-flow@0.0.7: 4445 4386 resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} 4446 4387 ··· 4609 4550 caniuse-lite@1.0.30001551: 4610 4551 resolution: {integrity: sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==} 4611 4552 4612 - caniuse-lite@1.0.30001585: 4613 - resolution: {integrity: sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==} 4614 - 4615 4553 caniuse-lite@1.0.30001612: 4616 4554 resolution: {integrity: sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==} 4617 4555 ··· 4809 4747 resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} 4810 4748 engines: {node: '>= 0.6'} 4811 4749 4750 + cookie@0.6.0: 4751 + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} 4752 + engines: {node: '>= 0.6'} 4753 + 4812 4754 copy-anything@3.0.5: 4813 4755 resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} 4814 4756 engines: {node: '>=12.13'} ··· 4843 4785 cssstyle@2.3.0: 4844 4786 resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} 4845 4787 engines: {node: '>=8'} 4846 - 4847 - csstype@3.1.1: 4848 - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} 4849 4788 4850 4789 csstype@3.1.2: 4851 4790 resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} ··· 4969 4908 deep-is@0.1.4: 4970 4909 resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 4971 4910 4972 - deepmerge@4.2.2: 4973 - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} 4974 - engines: {node: '>=0.10.0'} 4975 - 4976 4911 deepmerge@4.3.1: 4977 4912 resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 4978 4913 engines: {node: '>=0.10.0'} ··· 5091 5026 dot-case@2.1.1: 5092 5027 resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} 5093 5028 5094 - dot-case@3.0.4: 5095 - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} 5096 - 5097 5029 dotenv@16.0.3: 5098 5030 resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} 5099 5031 engines: {node: '>=12'} ··· 5410 5342 engines: {node: '>=6.0'} 5411 5343 hasBin: true 5412 5344 5413 - eslint-config-next@14.2.1: 5414 - resolution: {integrity: sha512-BgD0kPCWMlqoItRf3xe9fG0MqwObKfVch+f2ccwDpZiCJA8ghkz2wrASH+bI6nLZzGcOJOpMm1v1Q1euhfpt4Q==} 5345 + eslint-config-next@14.2.3: 5346 + resolution: {integrity: sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==} 5415 5347 peerDependencies: 5416 5348 eslint: ^7.23.0 || ^8.0.0 5417 5349 typescript: '>=3.3.1' ··· 5677 5609 form-data@2.5.1: 5678 5610 resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} 5679 5611 engines: {node: '>= 0.12'} 5680 - 5681 - form-data@3.0.1: 5682 - resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} 5683 - engines: {node: '>= 6'} 5684 5612 5685 5613 form-data@4.0.0: 5686 5614 resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} ··· 6368 6296 jose@4.15.4: 6369 6297 resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==} 6370 6298 6299 + jose@5.2.4: 6300 + resolution: {integrity: sha512-6ScbIk2WWCeXkmzF6bRPmEuaqy1m8SbsRFMa/FLrSCkGIhj8OLVG/IH+XHVmNMx/KUo8cVWEE6oKR4dJ+S0Rkg==} 6301 + 6371 6302 joycon@3.1.1: 6372 6303 resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 6373 6304 engines: {node: '>=10'} ··· 6379 6310 resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} 6380 6311 engines: {node: '>=12'} 6381 6312 hasBin: true 6382 - 6383 - js-cookie@3.0.1: 6384 - resolution: {integrity: sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==} 6385 - engines: {node: '>=12'} 6386 6313 6387 6314 js-tokens@4.0.0: 6388 6315 resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} ··· 6950 6877 resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} 6951 6878 engines: {node: '>= 0.4.0'} 6952 6879 6880 + next-auth@5.0.0-beta.17: 6881 + resolution: {integrity: sha512-XA/7JtAjOgDfAeotJPFUsFZGGItZwzZrxLt9Gc9fE7EchLk6zydZfuZ22Vvwixs3IilkN644D5IoD5tEOAFGCQ==} 6882 + peerDependencies: 6883 + '@simplewebauthn/browser': ^9.0.1 6884 + '@simplewebauthn/server': ^9.0.2 6885 + next: ^14 6886 + nodemailer: ^6.6.5 6887 + react: ^18.2.0 6888 + peerDependenciesMeta: 6889 + '@simplewebauthn/browser': 6890 + optional: true 6891 + '@simplewebauthn/server': 6892 + optional: true 6893 + nodemailer: 6894 + optional: true 6895 + 6953 6896 next-contentlayer@0.3.4: 6954 6897 resolution: {integrity: sha512-UtUCwgAl159KwfhNaOwyiI7Lg6sdioyKMeh+E7jxx0CJ29JuXGxBEYmCI6+72NxFGIFZKx8lvttbbQhbnYWYSw==} 6955 6898 peerDependencies: ··· 6975 6918 next-tick@1.1.0: 6976 6919 resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} 6977 6920 6978 - next@14.2.1: 6979 - resolution: {integrity: sha512-SF3TJnKdH43PMkCcErLPv+x/DY1YCklslk3ZmwaVoyUfDgHKexuKlf9sEfBQ69w+ue8jQ3msLb+hSj1T19hGag==} 6921 + next@14.2.3: 6922 + resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} 6980 6923 engines: {node: '>=18.17.0'} 6981 6924 hasBin: true 6982 6925 peerDependencies: ··· 7006 6949 node-domexception@1.0.0: 7007 6950 resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} 7008 6951 engines: {node: '>=10.5.0'} 7009 - 7010 - node-fetch-native@1.0.1: 7011 - resolution: {integrity: sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==} 7012 6952 7013 6953 node-fetch@2.7.0: 7014 6954 resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} ··· 7063 7003 7064 7004 nwsapi@2.2.7: 7065 7005 resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} 7006 + 7007 + oauth4webapi@2.10.4: 7008 + resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} 7066 7009 7067 7010 object-assign@4.1.1: 7068 7011 resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} ··· 7342 7285 resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} 7343 7286 engines: {node: ^10 || ^12 || >=14} 7344 7287 7288 + preact-render-to-string@5.2.3: 7289 + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} 7290 + peerDependencies: 7291 + preact: '>=10' 7292 + 7293 + preact@10.11.3: 7294 + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} 7295 + 7345 7296 prebuild-install@7.1.1: 7346 7297 resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} 7347 7298 engines: {node: '>=10'} ··· 7412 7363 resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} 7413 7364 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} 7414 7365 7366 + pretty-format@3.8.0: 7367 + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} 7368 + 7415 7369 pretty@2.0.0: 7416 7370 resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} 7417 7371 engines: {node: '>=0.10.0'} ··· 7459 7413 punycode@2.3.0: 7460 7414 resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 7461 7415 engines: {node: '>=6'} 7462 - 7463 - pvtsutils@1.3.5: 7464 - resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} 7465 - 7466 - pvutils@1.1.3: 7467 - resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} 7468 - engines: {node: '>=6.0.0'} 7469 7416 7470 7417 qs@6.11.2: 7471 7418 resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} ··· 7922 7869 snake-case@2.1.0: 7923 7870 resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} 7924 7871 7925 - snake-case@3.0.4: 7926 - resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} 7927 - 7928 - snakecase-keys@3.2.1: 7929 - resolution: {integrity: sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==} 7930 - engines: {node: '>=8'} 7931 - 7932 - snakecase-keys@5.4.4: 7933 - resolution: {integrity: sha512-YTywJG93yxwHLgrYLZjlC75moVEX04LZM4FHfihjHe1FCXm+QaLOFfSf535aXOAd0ArVQMWUAe8ZPm4VtWyXaA==} 7934 - engines: {node: '>=12'} 7935 - 7936 7872 socks-proxy-agent@8.0.2: 7937 7873 resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} 7938 7874 engines: {node: '>= 14'} ··· 8157 8093 swap-case@1.1.2: 8158 8094 resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} 8159 8095 8160 - swr@2.2.0: 8161 - resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==} 8162 - peerDependencies: 8163 - react: ^16.11.0 || ^17.0.0 || ^18.0.0 8164 - 8165 8096 swr@2.2.4: 8166 8097 resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} 8167 8098 peerDependencies: ··· 8238 8169 resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 8239 8170 engines: {node: '>=4'} 8240 8171 8241 - to-no-case@1.0.2: 8242 - resolution: {integrity: sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==} 8243 - 8244 8172 to-regex-range@5.0.1: 8245 8173 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 8246 8174 engines: {node: '>=8.0'} 8247 - 8248 - to-snake-case@1.0.0: 8249 - resolution: {integrity: sha512-joRpzBAk1Bhi2eGEYBjukEWHOe/IvclOkiJl3DtA91jV6NwQ3MwXA4FHYeqk8BNp/D8bmi9tcNbRu/SozP0jbQ==} 8250 - 8251 - to-space-case@1.0.0: 8252 - resolution: {integrity: sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==} 8253 8175 8254 8176 toidentifier@1.0.0: 8255 8177 resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} ··· 8331 8253 tslib@1.14.1: 8332 8254 resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} 8333 8255 8334 - tslib@2.4.1: 8335 - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} 8336 - 8337 8256 tslib@2.6.2: 8338 8257 resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} 8339 8258 ··· 8432 8351 type-fest@1.4.0: 8433 8352 resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} 8434 8353 engines: {node: '>=10'} 8435 - 8436 - type-fest@2.19.0: 8437 - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} 8438 - engines: {node: '>=12.20'} 8439 8354 8440 8355 type-fest@3.13.0: 8441 8356 resolution: {integrity: sha512-Gur3yQGM9qiLNs0KPP7LPgeRbio2QTt4xXouobMCarR0/wyW3F+F/+OWwshg3NG0Adon7uQfSZBpB46NfhoF1A==} ··· 8691 8606 resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} 8692 8607 engines: {node: '>= 8'} 8693 8608 8694 - webcrypto-core@1.7.7: 8695 - resolution: {integrity: sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==} 8696 - 8697 8609 webidl-conversions@3.0.1: 8698 8610 resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 8699 8611 ··· 8921 8833 dependencies: 8922 8834 openapi3-ts: 4.1.2 8923 8835 zod: 3.22.4 8836 + 8837 + '@auth/core@0.30.0': 8838 + dependencies: 8839 + '@panva/hkdf': 1.1.1 8840 + '@types/cookie': 0.6.0 8841 + cookie: 0.6.0 8842 + jose: 5.2.4 8843 + oauth4webapi: 2.10.4 8844 + preact: 10.11.3 8845 + preact-render-to-string: 5.2.3(preact@10.11.3) 8846 + 8847 + '@auth/drizzle-adapter@1.0.1': 8848 + dependencies: 8849 + '@auth/core': 0.30.0 8850 + transitivePeerDependencies: 8851 + - '@simplewebauthn/browser' 8852 + - '@simplewebauthn/server' 8853 + - nodemailer 8924 8854 8925 8855 '@aws-crypto/crc32@3.0.0': 8926 8856 dependencies: ··· 9618 9548 dependencies: 9619 9549 zod: 3.22.4 9620 9550 9621 - '@clerk/backend@0.38.3(react@18.2.0)': 9622 - dependencies: 9623 - '@clerk/shared': 1.3.3(react@18.2.0) 9624 - '@clerk/types': 3.62.1 9625 - '@peculiar/webcrypto': 1.4.1 9626 - '@types/node': 16.18.6 9627 - cookie: 0.5.0 9628 - deepmerge: 4.2.2 9629 - node-fetch-native: 1.0.1 9630 - snakecase-keys: 5.4.4 9631 - tslib: 2.4.1 9632 - transitivePeerDependencies: 9633 - - react 9634 - 9635 - '@clerk/clerk-react@4.30.7(react@18.2.0)': 9636 - dependencies: 9637 - '@clerk/shared': 1.3.3(react@18.2.0) 9638 - '@clerk/types': 3.62.1 9639 - react: 18.2.0 9640 - tslib: 2.4.1 9641 - 9642 - '@clerk/clerk-sdk-node@4.13.11(react@18.2.0)': 9643 - dependencies: 9644 - '@clerk/backend': 0.38.3(react@18.2.0) 9645 - '@clerk/shared': 1.3.3(react@18.2.0) 9646 - '@clerk/types': 3.62.1 9647 - '@types/cookies': 0.7.7 9648 - '@types/express': 4.17.14 9649 - '@types/node-fetch': 2.6.2 9650 - camelcase-keys: 6.2.2 9651 - snakecase-keys: 3.2.1 9652 - tslib: 2.4.1 9653 - transitivePeerDependencies: 9654 - - react 9655 - 9656 - '@clerk/nextjs@4.29.9(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': 9657 - dependencies: 9658 - '@clerk/backend': 0.38.3(react@18.2.0) 9659 - '@clerk/clerk-react': 4.30.7(react@18.2.0) 9660 - '@clerk/clerk-sdk-node': 4.13.11(react@18.2.0) 9661 - '@clerk/shared': 1.3.3(react@18.2.0) 9662 - '@clerk/types': 3.62.1 9663 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 9664 - path-to-regexp: 6.2.1 9665 - react: 18.2.0 9666 - react-dom: 18.2.0(react@18.2.0) 9667 - tslib: 2.4.1 9668 - 9669 - '@clerk/shared@1.3.3(react@18.2.0)': 9670 - dependencies: 9671 - glob-to-regexp: 0.4.1 9672 - js-cookie: 3.0.1 9673 - swr: 2.2.0(react@18.2.0) 9674 - optionalDependencies: 9675 - react: 18.2.0 9676 - 9677 - '@clerk/types@3.62.1': 9678 - dependencies: 9679 - csstype: 3.1.1 9680 - 9681 9551 '@clickhouse/client-common@0.3.0': {} 9682 9552 9683 9553 '@clickhouse/client-common@1.0.1': {} ··· 10362 10232 '@types/yargs': 17.0.29 10363 10233 chalk: 4.1.2 10364 10234 10365 - '@jitsu/js@1.3.0(@types/dlv@1.1.4)': 10235 + '@jitsu/js@1.9.2(@types/dlv@1.1.4)': 10366 10236 dependencies: 10367 10237 analytics: 0.8.9(@types/dlv@1.1.4) 10368 10238 transitivePeerDependencies: ··· 10513 10383 10514 10384 '@neon-rs/load@0.0.4': {} 10515 10385 10516 - '@next/env@14.2.1': {} 10386 + '@next/env@14.2.3': {} 10517 10387 10518 - '@next/eslint-plugin-next@14.2.1': 10388 + '@next/eslint-plugin-next@14.2.3': 10519 10389 dependencies: 10520 10390 glob: 10.3.10 10521 10391 10522 - '@next/swc-darwin-arm64@14.2.1': 10392 + '@next/swc-darwin-arm64@14.2.3': 10523 10393 optional: true 10524 10394 10525 - '@next/swc-darwin-x64@14.2.1': 10395 + '@next/swc-darwin-x64@14.2.3': 10526 10396 optional: true 10527 10397 10528 - '@next/swc-linux-arm64-gnu@14.2.1': 10398 + '@next/swc-linux-arm64-gnu@14.2.3': 10529 10399 optional: true 10530 10400 10531 - '@next/swc-linux-arm64-musl@14.2.1': 10401 + '@next/swc-linux-arm64-musl@14.2.3': 10532 10402 optional: true 10533 10403 10534 - '@next/swc-linux-x64-gnu@14.2.1': 10404 + '@next/swc-linux-x64-gnu@14.2.3': 10535 10405 optional: true 10536 10406 10537 - '@next/swc-linux-x64-musl@14.2.1': 10407 + '@next/swc-linux-x64-musl@14.2.3': 10538 10408 optional: true 10539 10409 10540 - '@next/swc-win32-arm64-msvc@14.2.1': 10410 + '@next/swc-win32-arm64-msvc@14.2.3': 10541 10411 optional: true 10542 10412 10543 - '@next/swc-win32-ia32-msvc@14.2.1': 10413 + '@next/swc-win32-ia32-msvc@14.2.3': 10544 10414 optional: true 10545 10415 10546 - '@next/swc-win32-x64-msvc@14.2.1': 10416 + '@next/swc-win32-x64-msvc@14.2.3': 10547 10417 optional: true 10548 10418 10549 10419 '@nodelib/fs.scandir@2.1.5': ··· 10641 10511 10642 10512 '@one-ini/wasm@0.1.1': {} 10643 10513 10644 - '@openstatus/next-monitoring@0.0.2(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)': 10514 + '@openstatus/next-monitoring@0.0.2(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)': 10645 10515 dependencies: 10646 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 10516 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 10647 10517 react: 18.2.0 10648 10518 10649 10519 '@opentelemetry/api-logs@0.39.1': ··· 10743 10613 10744 10614 '@opentelemetry/semantic-conventions@1.13.0': {} 10745 10615 10746 - '@peculiar/asn1-schema@2.3.8': 10747 - dependencies: 10748 - asn1js: 3.0.5 10749 - pvtsutils: 1.3.5 10750 - tslib: 2.6.2 10751 - 10752 - '@peculiar/json-schema@1.1.12': 10753 - dependencies: 10754 - tslib: 2.6.2 10755 - 10756 - '@peculiar/webcrypto@1.4.1': 10757 - dependencies: 10758 - '@peculiar/asn1-schema': 2.3.8 10759 - '@peculiar/json-schema': 1.1.12 10760 - pvtsutils: 1.3.5 10761 - tslib: 2.6.2 10762 - webcrypto-core: 1.7.7 10616 + '@panva/hkdf@1.1.1': {} 10763 10617 10764 10618 '@pkgjs/parseargs@0.11.0': 10765 10619 optional: true ··· 11768 11622 localforage: 1.10.0 11769 11623 tslib: 2.6.2 11770 11624 11771 - '@sentry/nextjs@7.100.1(encoding@0.1.13)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)': 11625 + '@sentry/nextjs@7.100.1(encoding@0.1.13)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)': 11772 11626 dependencies: 11773 11627 '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) 11774 11628 '@sentry/core': 7.100.1 ··· 11780 11634 '@sentry/vercel-edge': 7.100.1 11781 11635 '@sentry/webpack-plugin': 1.21.0(encoding@0.1.13) 11782 11636 chalk: 3.0.0 11783 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 11637 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 11784 11638 react: 18.2.0 11785 11639 resolve: 1.22.8 11786 11640 rollup: 2.78.0 ··· 12266 12120 dependencies: 12267 12121 '@trpc/server': 10.45.1 12268 12122 12269 - '@trpc/next@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.45.1)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': 12123 + '@trpc/next@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/react-query@10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/server@10.45.1)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': 12270 12124 dependencies: 12271 12125 '@tanstack/react-query': 4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 12272 12126 '@trpc/client': 10.45.1(@trpc/server@10.45.1) 12273 12127 '@trpc/react-query': 10.45.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@trpc/client@10.45.1(@trpc/server@10.45.1))(@trpc/server@10.45.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 12274 12128 '@trpc/server': 10.45.1 12275 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 12129 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 12276 12130 react: 18.2.0 12277 12131 react-dom: 18.2.0(react@18.2.0) 12278 12132 ··· 12318 12172 dependencies: 12319 12173 '@types/estree': 1.0.3 12320 12174 12321 - '@types/body-parser@1.19.4': 12322 - dependencies: 12323 - '@types/connect': 3.4.37 12324 - '@types/node': 20.8.0 12325 - 12326 12175 '@types/caseless@0.12.4': {} 12327 12176 12328 - '@types/connect@3.4.37': 12329 - dependencies: 12330 - '@types/node': 20.8.0 12331 - 12332 - '@types/cookies@0.7.7': 12333 - dependencies: 12334 - '@types/connect': 3.4.37 12335 - '@types/express': 4.17.14 12336 - '@types/keygrip': 1.0.4 12337 - '@types/node': 20.8.0 12177 + '@types/cookie@0.6.0': {} 12338 12178 12339 12179 '@types/d3-array@3.0.9': {} 12340 12180 ··· 12377 12217 12378 12218 '@types/estree@1.0.3': {} 12379 12219 12380 - '@types/express-serve-static-core@4.17.39': 12381 - dependencies: 12382 - '@types/node': 20.8.0 12383 - '@types/qs': 6.9.9 12384 - '@types/range-parser': 1.2.6 12385 - '@types/send': 0.17.3 12386 - 12387 - '@types/express@4.17.14': 12388 - dependencies: 12389 - '@types/body-parser': 1.19.4 12390 - '@types/express-serve-static-core': 4.17.39 12391 - '@types/qs': 6.9.9 12392 - '@types/serve-static': 1.15.4 12393 - 12394 12220 '@types/glob@7.2.0': 12395 12221 dependencies: 12396 12222 '@types/minimatch': 5.1.2 ··· 12403 12229 '@types/hast@3.0.4': 12404 12230 dependencies: 12405 12231 '@types/unist': 2.0.9 12406 - 12407 - '@types/http-errors@2.0.3': {} 12408 12232 12409 12233 '@types/inquirer@6.5.0': 12410 12234 dependencies: ··· 12432 12256 '@types/json-schema@7.0.15': {} 12433 12257 12434 12258 '@types/json5@0.0.29': {} 12435 - 12436 - '@types/keygrip@1.0.4': {} 12437 12259 12438 12260 '@types/long@4.0.2': {} 12439 12261 ··· 12445 12267 12446 12268 '@types/mdx@2.0.9': {} 12447 12269 12448 - '@types/mime@1.3.4': {} 12449 - 12450 - '@types/mime@3.0.3': {} 12451 - 12452 12270 '@types/minimatch@5.1.2': {} 12453 12271 12454 12272 '@types/minimist@1.2.5': {} 12455 12273 12456 12274 '@types/ms@0.7.33': {} 12457 12275 12458 - '@types/node-fetch@2.6.2': 12459 - dependencies: 12460 - '@types/node': 20.8.0 12461 - form-data: 3.0.1 12462 - 12463 12276 '@types/node-forge@1.3.11': 12464 12277 dependencies: 12465 12278 '@types/node': 20.8.0 12466 12279 12467 - '@types/node@16.18.6': {} 12468 - 12469 12280 '@types/node@20.8.0': {} 12470 12281 12471 12282 '@types/normalize-package-data@2.4.3': {} ··· 12473 12284 '@types/parse5@6.0.3': {} 12474 12285 12475 12286 '@types/prop-types@15.7.9': {} 12476 - 12477 - '@types/qs@6.9.9': {} 12478 - 12479 - '@types/range-parser@1.2.6': {} 12480 12287 12481 12288 '@types/react-dom@18.2.21': 12482 12289 dependencies: ··· 12503 12310 12504 12311 '@types/semver@7.5.4': {} 12505 12312 12506 - '@types/send@0.17.3': 12507 - dependencies: 12508 - '@types/mime': 1.3.4 12509 - '@types/node': 20.8.0 12510 - 12511 - '@types/serve-static@1.15.4': 12512 - dependencies: 12513 - '@types/http-errors': 2.0.3 12514 - '@types/mime': 3.0.3 12515 - '@types/node': 20.8.0 12516 - 12517 12313 '@types/stack-utils@2.0.2': {} 12518 12314 12519 12315 '@types/through@0.0.32': ··· 12848 12644 dependencies: 12849 12645 printable-characters: 1.0.42 12850 12646 12851 - asn1js@3.0.5: 12852 - dependencies: 12853 - pvtsutils: 1.3.5 12854 - pvutils: 1.1.3 12855 - tslib: 2.6.2 12856 - 12857 12647 ast-types-flow@0.0.7: {} 12858 12648 12859 12649 ast-types@0.13.4: ··· 13013 12803 camelcase@7.0.1: {} 13014 12804 13015 12805 caniuse-lite@1.0.30001551: {} 13016 - 13017 - caniuse-lite@1.0.30001585: {} 13018 12806 13019 12807 caniuse-lite@1.0.30001612: {} 13020 12808 ··· 13233 13021 13234 13022 cookie@0.5.0: {} 13235 13023 13024 + cookie@0.6.0: {} 13025 + 13236 13026 copy-anything@3.0.5: 13237 13027 dependencies: 13238 13028 is-what: 4.1.15 ··· 13261 13051 dependencies: 13262 13052 cssom: 0.3.8 13263 13053 13264 - csstype@3.1.1: {} 13265 - 13266 13054 csstype@3.1.2: {} 13267 13055 13268 13056 d3-array@3.2.4: ··· 13360 13148 deep-extend@0.6.0: {} 13361 13149 13362 13150 deep-is@0.1.4: {} 13363 - 13364 - deepmerge@4.2.2: {} 13365 13151 13366 13152 deepmerge@4.3.1: {} 13367 13153 ··· 13483 13269 dot-case@2.1.1: 13484 13270 dependencies: 13485 13271 no-case: 2.3.2 13486 - 13487 - dot-case@3.0.4: 13488 - dependencies: 13489 - no-case: 3.0.4 13490 - tslib: 2.6.2 13491 13272 13492 13273 dotenv@16.0.3: {} 13493 13274 ··· 13832 13613 optionalDependencies: 13833 13614 source-map: 0.6.1 13834 13615 13835 - eslint-config-next@14.2.1(eslint@8.50.0)(typescript@5.4.5): 13616 + eslint-config-next@14.2.3(eslint@8.50.0)(typescript@5.4.5): 13836 13617 dependencies: 13837 - '@next/eslint-plugin-next': 14.2.1 13618 + '@next/eslint-plugin-next': 14.2.3 13838 13619 '@rushstack/eslint-patch': 1.5.1 13839 13620 '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.4.5) 13840 13621 eslint: 8.50.0 ··· 14197 13978 signal-exit: 4.1.0 14198 13979 14199 13980 form-data@2.5.1: 14200 - dependencies: 14201 - asynckit: 0.4.0 14202 - combined-stream: 1.0.8 14203 - mime-types: 2.1.35 14204 - 14205 - form-data@3.0.1: 14206 13981 dependencies: 14207 13982 asynckit: 0.4.0 14208 13983 combined-stream: 1.0.8 ··· 15069 14844 15070 14845 jose@4.15.4: {} 15071 14846 14847 + jose@5.2.4: {} 14848 + 15072 14849 joycon@3.1.1: {} 15073 14850 15074 14851 js-base64@3.7.5: {} ··· 15080 14857 glob: 8.1.0 15081 14858 nopt: 6.0.0 15082 14859 15083 - js-cookie@3.0.1: {} 15084 - 15085 14860 js-tokens@4.0.0: {} 15086 14861 15087 14862 js-yaml@3.14.1: ··· 15939 15714 15940 15715 netmask@2.0.2: {} 15941 15716 15942 - next-contentlayer@0.3.4(contentlayer@0.3.4(esbuild@0.19.12))(esbuild@0.19.12)(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15717 + next-auth@5.0.0-beta.17(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0): 15718 + dependencies: 15719 + '@auth/core': 0.30.0 15720 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15721 + react: 18.2.0 15722 + 15723 + next-contentlayer@0.3.4(contentlayer@0.3.4(esbuild@0.19.12))(esbuild@0.19.12)(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15943 15724 dependencies: 15944 15725 '@contentlayer/core': 0.3.4(esbuild@0.19.12) 15945 15726 '@contentlayer/utils': 0.3.4 15946 15727 contentlayer: 0.3.4(esbuild@0.19.12) 15947 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15728 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15948 15729 react: 18.2.0 15949 15730 react-dom: 18.2.0(react@18.2.0) 15950 15731 transitivePeerDependencies: ··· 15953 15734 - markdown-wasm 15954 15735 - supports-color 15955 15736 15956 - next-plausible@3.12.0(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15737 + next-plausible@3.12.0(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15957 15738 dependencies: 15958 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15739 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15959 15740 react: 18.2.0 15960 15741 react-dom: 18.2.0(react@18.2.0) 15961 15742 15962 - next-themes@0.2.1(next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15743 + next-themes@0.2.1(next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15963 15744 dependencies: 15964 - next: 14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15745 + next: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) 15965 15746 react: 18.2.0 15966 15747 react-dom: 18.2.0(react@18.2.0) 15967 15748 15968 15749 next-tick@1.1.0: {} 15969 15750 15970 - next@14.2.1(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15751 + next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.4.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): 15971 15752 dependencies: 15972 - '@next/env': 14.2.1 15753 + '@next/env': 14.2.3 15973 15754 '@swc/helpers': 0.5.5 15974 15755 busboy: 1.6.0 15975 - caniuse-lite: 1.0.30001585 15756 + caniuse-lite: 1.0.30001612 15976 15757 graceful-fs: 4.2.11 15977 15758 postcss: 8.4.31 15978 15759 react: 18.2.0 15979 15760 react-dom: 18.2.0(react@18.2.0) 15980 15761 styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.2.0) 15981 15762 optionalDependencies: 15982 - '@next/swc-darwin-arm64': 14.2.1 15983 - '@next/swc-darwin-x64': 14.2.1 15984 - '@next/swc-linux-arm64-gnu': 14.2.1 15985 - '@next/swc-linux-arm64-musl': 14.2.1 15986 - '@next/swc-linux-x64-gnu': 14.2.1 15987 - '@next/swc-linux-x64-musl': 14.2.1 15988 - '@next/swc-win32-arm64-msvc': 14.2.1 15989 - '@next/swc-win32-ia32-msvc': 14.2.1 15990 - '@next/swc-win32-x64-msvc': 14.2.1 15763 + '@next/swc-darwin-arm64': 14.2.3 15764 + '@next/swc-darwin-x64': 14.2.3 15765 + '@next/swc-linux-arm64-gnu': 14.2.3 15766 + '@next/swc-linux-arm64-musl': 14.2.3 15767 + '@next/swc-linux-x64-gnu': 14.2.3 15768 + '@next/swc-linux-x64-musl': 14.2.3 15769 + '@next/swc-win32-arm64-msvc': 14.2.3 15770 + '@next/swc-win32-ia32-msvc': 14.2.3 15771 + '@next/swc-win32-x64-msvc': 14.2.3 15991 15772 '@opentelemetry/api': 1.4.1 15992 15773 transitivePeerDependencies: 15993 15774 - '@babel/core' ··· 16007 15788 semver: 7.5.4 16008 15789 16009 15790 node-domexception@1.0.0: {} 16010 - 16011 - node-fetch-native@1.0.1: {} 16012 15791 16013 15792 node-fetch@2.7.0(encoding@0.1.13): 16014 15793 dependencies: ··· 16064 15843 path-key: 3.1.1 16065 15844 16066 15845 nwsapi@2.2.7: {} 15846 + 15847 + oauth4webapi@2.10.4: {} 16067 15848 16068 15849 object-assign@4.1.1: {} 16069 15850 ··· 16374 16155 picocolors: 1.0.0 16375 16156 source-map-js: 1.0.2 16376 16157 16158 + preact-render-to-string@5.2.3(preact@10.11.3): 16159 + dependencies: 16160 + preact: 10.11.3 16161 + pretty-format: 3.8.0 16162 + 16163 + preact@10.11.3: {} 16164 + 16377 16165 prebuild-install@7.1.1: 16378 16166 dependencies: 16379 16167 detect-libc: 2.0.2 ··· 16404 16192 '@jest/schemas': 29.6.3 16405 16193 ansi-styles: 5.2.0 16406 16194 react-is: 18.2.0 16195 + 16196 + pretty-format@3.8.0: {} 16407 16197 16408 16198 pretty@2.0.0: 16409 16199 dependencies: ··· 16469 16259 punycode@1.3.2: {} 16470 16260 16471 16261 punycode@2.3.0: {} 16472 - 16473 - pvtsutils@1.3.5: 16474 - dependencies: 16475 - tslib: 2.6.2 16476 - 16477 - pvutils@1.1.3: {} 16478 16262 16479 16263 qs@6.11.2: 16480 16264 dependencies: ··· 17025 16809 dependencies: 17026 16810 no-case: 2.3.2 17027 16811 17028 - snake-case@3.0.4: 17029 - dependencies: 17030 - dot-case: 3.0.4 17031 - tslib: 2.6.2 17032 - 17033 - snakecase-keys@3.2.1: 17034 - dependencies: 17035 - map-obj: 4.3.0 17036 - to-snake-case: 1.0.0 17037 - 17038 - snakecase-keys@5.4.4: 17039 - dependencies: 17040 - map-obj: 4.3.0 17041 - snake-case: 3.0.4 17042 - type-fest: 2.19.0 17043 - 17044 16812 socks-proxy-agent@8.0.2: 17045 16813 dependencies: 17046 16814 agent-base: 7.1.0 ··· 17284 17052 lower-case: 1.1.4 17285 17053 upper-case: 1.1.3 17286 17054 17287 - swr@2.2.0(react@18.2.0): 17288 - dependencies: 17289 - react: 18.2.0 17290 - use-sync-external-store: 1.2.0(react@18.2.0) 17291 - 17292 17055 swr@2.2.4(react@18.2.0): 17293 17056 dependencies: 17294 17057 client-only: 0.0.1 ··· 17419 17182 17420 17183 to-fast-properties@2.0.0: {} 17421 17184 17422 - to-no-case@1.0.2: {} 17423 - 17424 17185 to-regex-range@5.0.1: 17425 17186 dependencies: 17426 17187 is-number: 7.0.0 17427 17188 17428 - to-snake-case@1.0.0: 17429 - dependencies: 17430 - to-space-case: 1.0.0 17431 - 17432 - to-space-case@1.0.0: 17433 - dependencies: 17434 - to-no-case: 1.0.2 17435 - 17436 17189 toidentifier@1.0.0: {} 17437 17190 17438 17191 toml@3.0.0: {} ··· 17523 17276 17524 17277 tslib@1.14.1: {} 17525 17278 17526 - tslib@2.4.1: {} 17527 - 17528 17279 tslib@2.6.2: {} 17529 17280 17530 17281 tsup@7.2.0(postcss@8.4.31)(ts-node@10.9.1(@types/node@20.8.0)(typescript@5.4.5))(typescript@5.4.5): ··· 17610 17361 type-fest@0.8.1: {} 17611 17362 17612 17363 type-fest@1.4.0: {} 17613 - 17614 - type-fest@2.19.0: {} 17615 17364 17616 17365 type-fest@3.13.0: {} 17617 17366 ··· 17919 17668 web-namespaces@2.0.1: {} 17920 17669 17921 17670 web-streams-polyfill@3.2.1: {} 17922 - 17923 - webcrypto-core@1.7.7: 17924 - dependencies: 17925 - '@peculiar/asn1-schema': 2.3.8 17926 - '@peculiar/json-schema': 1.1.12 17927 - asn1js: 3.0.5 17928 - pvtsutils: 1.3.5 17929 - tslib: 2.6.2 17930 17671 17931 17672 webidl-conversions@3.0.1: {} 17932 17673
-6
turbo.json
··· 10 10 "!NEXT_PUBLIC_GIT_*", 11 11 "DATABASE_URL", 12 12 "TINY_BIRD_API_KEY", 13 - "CLERK_SECRET_KEY", 14 - "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY", 15 - "NEXT_PUBLIC_CLERK_SIGN_IN_URL", 16 - "NEXT_PUBLIC_CLERK_SIGN_UP_URL", 17 - "NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL", 18 - "NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL", 19 13 "NODE_ENV", 20 14 "VERCEL_URL" 21 15 ],