From d88eae7230583c8f3a48d2dc1436c03adcf0b04a Mon Sep 17 00:00:00 2001 From: Jared Palmer Date: Mon, 22 May 2023 12:14:37 -0400 Subject: [PATCH] Try to use drizzle event though --- auth.ts | 16 + drizzle.config.ts | 6 + lib/db/db.ts | 4 + lib/db/index.ts | 270 +++++++ lib/db/migrate.ts | 18 + .../migrations/0000_flawless_moondragon.sql | 49 ++ lib/db/migrations/0001_colorful_spectrum.sql | 7 + lib/db/migrations/meta/0000_snapshot.json | 227 ++++++ lib/db/migrations/meta/0001_snapshot.json | 252 ++++++ lib/db/migrations/meta/_journal.json | 20 + lib/db/schema.ts | 353 +++++++++ package.json | 13 +- pnpm-lock.yaml | 744 +++++++++++++++++- tsconfig.migration.json | 11 + 14 files changed, 1978 insertions(+), 12 deletions(-) create mode 100644 drizzle.config.ts create mode 100644 lib/db/db.ts create mode 100644 lib/db/index.ts create mode 100644 lib/db/migrate.ts create mode 100644 lib/db/migrations/0000_flawless_moondragon.sql create mode 100644 lib/db/migrations/0001_colorful_spectrum.sql create mode 100644 lib/db/migrations/meta/0000_snapshot.json create mode 100644 lib/db/migrations/meta/0001_snapshot.json create mode 100644 lib/db/migrations/meta/_journal.json create mode 100644 lib/db/schema.ts create mode 100644 tsconfig.migration.json diff --git a/auth.ts b/auth.ts index 100244e..cab5ae5 100644 --- a/auth.ts +++ b/auth.ts @@ -1,11 +1,27 @@ import NextAuth from "@auth/nextjs"; import GitHub from "@auth/nextjs/providers/github"; import { NextResponse } from "next/server"; + +import { + db, + users, + accounts, + sessions, + verificationTokens, +} from "./lib/db/schema"; +import { DrizzleAdapterPg } from "./lib/db"; + export const { handlers: { GET, POST }, auth, CSRF_experimental, } = NextAuth({ + adapter: DrizzleAdapterPg(db, { + accounts, + users, + sessions, + verificationTokens, + }), // @ts-ignore providers: [GitHub], session: { strategy: "jwt" }, diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..422184e --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,6 @@ +import type { Config } from "drizzle-kit"; + +export default { + schema: "./lib/db/schema.ts", + out: "./lib/db/migrations", +} satisfies Config; diff --git a/lib/db/db.ts b/lib/db/db.ts new file mode 100644 index 0000000..066b295 --- /dev/null +++ b/lib/db/db.ts @@ -0,0 +1,4 @@ +import { drizzle } from "drizzle-orm/vercel-postgres"; +import { sql } from "@vercel/postgres"; + +export const db = drizzle(sql); diff --git a/lib/db/index.ts b/lib/db/index.ts new file mode 100644 index 0000000..c96d1c5 --- /dev/null +++ b/lib/db/index.ts @@ -0,0 +1,270 @@ +/** + *
+ *

Official Drizzle ORM adapter for Auth.js / NextAuth.js.

+ * + * + * + *
+ * + * ## Installation + * + * ```bash npm2yarn2pnpm + * npm install next-auth drizzle-orm @next-auth/drizzle-adapter + * npm install drizzle-kit --save-dev + * ``` + * + * @module @next-auth/drizzle-adapter + */ +import type { Adapter } from "@auth/nextjs/adapters"; +import { and, eq } from "drizzle-orm"; +import { v4 as uuid } from "uuid"; +import type { DbClient, Schema } from "./schema"; + +/** + * ## Setup + * + * Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object: + * + * ```js title="pages/api/auth/[...nextauth].js" + * import NextAuth from "next-auth" + * import GoogleProvider from "next-auth/providers/google" + * import { DrizzleAdapter } from "@next-auth/drizzle-adapter" + * import { db } from "./db-schema" + * + * export default NextAuth({ + * adapter: DrizzleAdapter(db), + * providers: [ + * GoogleProvider({ + * clientId: process.env.GOOGLE_CLIENT_ID, + * clientSecret: process.env.GOOGLE_CLIENT_SECRET, + * }), + * ], + * }) + * ``` + * + * ## Advanced usage + * + * ### Create the Drizzle schema from scratch + * + * You'll need to create a database schema that includes the minimal schema for a `next-auth` adapter. + * Be sure to use the Drizzle driver version that you're using for your project. + * + * > This schema is adapted for use in Drizzle and based upon our main [schema](https://authjs.dev/reference/adapters#models) + * + * + * ```json title="db-schema.ts" + * + * import { integer, pgTable, text, primaryKey } from 'drizzle-orm/pg-core'; + * import { drizzle } from 'drizzle-orm/node-postgres'; + * import { migrate } from 'drizzle-orm/node-postgres/migrator'; + * import { Pool } from 'pg' + * import { ProviderType } from 'next-auth/providers'; + * + * export const users = pgTable('users', { + * id: text('id').notNull().primaryKey(), + * name: text('name'), + * email: text("email").notNull(), + * emailVerified: integer("emailVerified"), + * image: text("image"), + * }); + * + * export const accounts = pgTable("accounts", { + * userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }), + * type: text("type").$type().notNull(), + * provider: text("provider").notNull(), + * providerAccountId: text("providerAccountId").notNull(), + * refresh_token: text("refresh_token"), + * access_token: text("access_token"), + * expires_at: integer("expires_at"), + * token_type: text("token_type"), + * scope: text("scope"), + * id_token: text("id_token"), + * session_state: text("session_state"), + * }, (account) => ({ + * _: primaryKey(account.provider, account.providerAccountId) + * })) + * + * export const sessions = pgTable("sessions", { + * userId: text("userId").notNull().references(() => users.id, { onDelete: "cascade" }), + * sessionToken: text("sessionToken").notNull().primaryKey(), + * expires: integer("expires").notNull(), + * }) + * + * export const verificationTokens = pgTable("verificationToken", { + * identifier: text("identifier").notNull(), + * token: text("token").notNull(), + * expires: integer("expires").notNull() + * }, (vt) => ({ + * _: primaryKey(vt.identifier, vt.token) + * })) + * + * const pool = new Pool({ + * connectionString: "YOUR_CONNECTION_STRING" + * }); + * + * export const db = drizzle(pool); + * + * migrate(db, { migrationsFolder: "./drizzle" }) + * + * ``` + * + **/ +export function DrizzleAdapterPg( + client: DbClient, + { users, sessions, verificationTokens, accounts }: Schema +): Adapter { + return { + createUser: async (data) => { + return client + .insert(users) + .values({ ...data, id: uuid() }) + .returning() + .then((res) => res[0]); + }, + getUser: async (data) => { + return ( + client + .select() + .from(users) + .where(eq(users.id, data)) + .then((res) => res[0]) ?? null + ); + }, + getUserByEmail: async (data) => { + return ( + client + .select() + .from(users) + .where(eq(users.email, data)) + .then((res) => res[0]) ?? null + ); + }, + createSession: async (data) => { + return client + .insert(sessions) + .values(data) + .returning() + .then((res) => res[0]); + }, + getSessionAndUser: async (data) => { + return ( + client + .select({ + session: sessions, + user: users, + }) + .from(sessions) + .where(eq(sessions.sessionToken, data)) + .innerJoin(users, eq(users.id, sessions.userId)) + .then((res) => res[0]) ?? null + ); + }, + updateUser: async (data) => { + if (!data.id) { + throw new Error("No user id."); + } + + return client + .update(users) + .set(data) + .where(eq(users.id, data.id)) + .returning() + .then((res) => res[0]); + }, + updateSession: async (data) => { + return client + .update(sessions) + .set(data) + .where(eq(sessions.sessionToken, data.sessionToken)) + .returning() + .then((res) => res[0]); + }, + linkAccount: async (rawAccount) => { + const updatedAccount = await client + .insert(accounts) + .values(rawAccount) + .returning() + .then((res) => res[0]); + + // Drizzle will return `null` for fields that are not defined. + // However, the return type is expecting `undefined`. + const account: ReturnType = { + ...updatedAccount, + access_token: updatedAccount.access_token ?? undefined, + token_type: updatedAccount.token_type ?? undefined, + id_token: updatedAccount.id_token ?? undefined, + refresh_token: updatedAccount.refresh_token ?? undefined, + scope: updatedAccount.scope ?? undefined, + expires_at: updatedAccount.expires_at ?? undefined, + session_state: updatedAccount.session_state ?? undefined, + }; + + return account; + }, + getUserByAccount: async (account) => { + const user = + (await client + .select() + .from(users) + .innerJoin( + accounts, + and( + eq(accounts.providerAccountId, account.providerAccountId), + eq(accounts.provider, account.provider) + ) + ) + .then((res) => res[0])) ?? null; + + return user.users; + }, + deleteSession: async (sessionToken) => { + await client + .delete(sessions) + .where(eq(sessions.sessionToken, sessionToken)); + }, + createVerificationToken: async (token) => { + return client + .insert(verificationTokens) + .values(token) + .returning() + .then((res) => res[0]); + }, + useVerificationToken: async (token) => { + try { + return ( + client + .delete(verificationTokens) + .where( + and( + eq(verificationTokens.identifier, token.identifier), + eq(verificationTokens.token, token.token) + ) + ) + .returning() + .then((res) => res[0]) ?? null + ); + } catch (err) { + throw new Error("No verification token found."); + } + }, + deleteUser: async (id) => { + await client + .delete(users) + .where(eq(users.id, id)) + .returning() + .then((res) => res[0]); + }, + unlinkAccount: async (account) => { + await client + .delete(accounts) + .where( + and( + eq(accounts.providerAccountId, account.providerAccountId), + eq(accounts.provider, account.provider) + ) + ); + + return undefined; + }, + }; +} diff --git a/lib/db/migrate.ts b/lib/db/migrate.ts new file mode 100644 index 0000000..cfbe862 --- /dev/null +++ b/lib/db/migrate.ts @@ -0,0 +1,18 @@ +import { migrate } from "drizzle-orm/vercel-postgres/migrator"; +import { db } from "./schema"; +import * as dotenv from "dotenv"; + +dotenv.config(); + +migrate(db, { + migrationsFolder: "lib/db/migrations", +}) + .then(() => { + console.log("Migration was succesfull!"); + }) + .catch((err) => { + console.error("Migration failed:", err); + }) + .finally(() => { + console.info("Migration finished"); + }); diff --git a/lib/db/migrations/0000_flawless_moondragon.sql b/lib/db/migrations/0000_flawless_moondragon.sql new file mode 100644 index 0000000..e634f49 --- /dev/null +++ b/lib/db/migrations/0000_flawless_moondragon.sql @@ -0,0 +1,49 @@ +CREATE TABLE IF NOT EXISTS "accounts" ( + "userId" text NOT NULL, + "type" text NOT NULL, + "provider" text NOT NULL, + "providerAccountId" text NOT NULL, + "refresh_token" text, + "access_token" text, + "expires_at" integer, + "token_type" text, + "scope" text, + "id_token" text, + "session_state" text +); +--> statement-breakpoint +ALTER TABLE "accounts" ADD CONSTRAINT "accounts_provider_providerAccountId" PRIMARY KEY("provider","providerAccountId"); + +CREATE TABLE IF NOT EXISTS "sessions" ( + "sessionToken" text PRIMARY KEY NOT NULL, + "userId" text NOT NULL, + "expires" timestamp NOT NULL +); + +CREATE TABLE IF NOT EXISTS "users" ( + "id" text PRIMARY KEY NOT NULL, + "name" text, + "email" text NOT NULL, + "emailVerified" timestamp, + "image" text +); + +CREATE TABLE IF NOT EXISTS "verificationToken" ( + "identifier" text NOT NULL, + "token" text NOT NULL, + "expires" timestamp NOT NULL +); +--> statement-breakpoint +ALTER TABLE "verificationToken" ADD CONSTRAINT "verificationToken_identifier_token" PRIMARY KEY("identifier","token"); + +DO $$ BEGIN + ALTER TABLE "accounts" ADD CONSTRAINT "accounts_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +DO $$ BEGIN + ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/lib/db/migrations/0001_colorful_spectrum.sql b/lib/db/migrations/0001_colorful_spectrum.sql new file mode 100644 index 0000000..5ff3ddb --- /dev/null +++ b/lib/db/migrations/0001_colorful_spectrum.sql @@ -0,0 +1,7 @@ +ALTER TABLE "accounts" DROP CONSTRAINT "accounts_provider_providerAccountId"; +ALTER TABLE "verificationToken" DROP CONSTRAINT "verificationToken_identifier_token"; +CREATE UNIQUE INDEX IF NOT EXISTS "Account_provider_providerAccountId_key" ON "accounts" ("provider","providerAccountId"); +CREATE UNIQUE INDEX IF NOT EXISTS "Session_sessionToken_key" ON "sessions" ("sessionToken"); +CREATE UNIQUE INDEX IF NOT EXISTS "User_email_key" ON "users" ("email"); +CREATE UNIQUE INDEX IF NOT EXISTS "VerificationToken_identifier_token_key" ON "verificationToken" ("identifier","token"); +CREATE UNIQUE INDEX IF NOT EXISTS "VerificationToken_token_key" ON "verificationToken" ("token"); \ No newline at end of file diff --git a/lib/db/migrations/meta/0000_snapshot.json b/lib/db/migrations/meta/0000_snapshot.json new file mode 100644 index 0000000..9bf3d1e --- /dev/null +++ b/lib/db/migrations/meta/0000_snapshot.json @@ -0,0 +1,227 @@ +{ + "version": "5", + "dialect": "pg", + "id": "ea430ef9-8e30-4cb6-9985-d03f43656cf8", + "prevId": "00000000-0000-0000-0000-000000000000", + "tables": { + "accounts": { + "name": "accounts", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "accounts_userId_users_id_fk": { + "name": "accounts_userId_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "accounts_provider_providerAccountId": { + "name": "accounts_provider_providerAccountId", + "columns": [ + "provider", + "providerAccountId" + ] + } + } + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_userId_users_id_fk": { + "name": "sessions_userId_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verificationToken_identifier_token": { + "name": "verificationToken_identifier_token", + "columns": [ + "identifier", + "token" + ] + } + } + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/lib/db/migrations/meta/0001_snapshot.json b/lib/db/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..9f8af6f --- /dev/null +++ b/lib/db/migrations/meta/0001_snapshot.json @@ -0,0 +1,252 @@ +{ + "version": "5", + "dialect": "pg", + "id": "34122d24-88e0-430e-862c-2168b0f866cb", + "prevId": "ea430ef9-8e30-4cb6-9985-d03f43656cf8", + "tables": { + "accounts": { + "name": "accounts", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "Account_provider_providerAccountId_key": { + "name": "Account_provider_providerAccountId_key", + "columns": [ + "provider", + "providerAccountId" + ], + "isUnique": true + } + }, + "foreignKeys": { + "accounts_userId_users_id_fk": { + "name": "accounts_userId_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {} + }, + "sessions": { + "name": "sessions", + "schema": "", + "columns": { + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "Session_sessionToken_key": { + "name": "Session_sessionToken_key", + "columns": [ + "sessionToken" + ], + "isUnique": true + } + }, + "foreignKeys": { + "sessions_userId_users_id_fk": { + "name": "sessions_userId_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {} + }, + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "emailVerified": { + "name": "emailVerified", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "User_email_key": { + "name": "User_email_key", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {} + }, + "verificationToken": { + "name": "verificationToken", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "VerificationToken_identifier_token_key": { + "name": "VerificationToken_identifier_token_key", + "columns": [ + "identifier", + "token" + ], + "isUnique": true + }, + "VerificationToken_token_key": { + "name": "VerificationToken_token_key", + "columns": [ + "token" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} \ No newline at end of file diff --git a/lib/db/migrations/meta/_journal.json b/lib/db/migrations/meta/_journal.json new file mode 100644 index 0000000..c023d95 --- /dev/null +++ b/lib/db/migrations/meta/_journal.json @@ -0,0 +1,20 @@ +{ + "version": "5", + "dialect": "pg", + "entries": [ + { + "idx": 0, + "version": "5", + "when": 1684771069602, + "tag": "0000_flawless_moondragon", + "breakpoints": false + }, + { + "idx": 1, + "version": "5", + "when": 1684771628481, + "tag": "0001_colorful_spectrum", + "breakpoints": false + } + ] +} \ No newline at end of file diff --git a/lib/db/schema.ts b/lib/db/schema.ts new file mode 100644 index 0000000..44be2d6 --- /dev/null +++ b/lib/db/schema.ts @@ -0,0 +1,353 @@ +import { + integer, + timestamp, + pgTable, + text, + primaryKey, + uniqueIndex, +} from "drizzle-orm/pg-core"; +import { drizzle } from "drizzle-orm/vercel-postgres"; +import { sql } from "@vercel/postgres"; +import { ProviderType } from "@auth/nextjs/providers"; + +export const users = pgTable( + "users", + { + id: text("id").notNull().primaryKey(), + name: text("name"), + email: text("email").notNull(), + emailVerified: timestamp("emailVerified", { mode: "date" }), + image: text("image"), + }, + (user) => ({ + emailKey: uniqueIndex("User_email_key").on(user.email), + }) +); + +export const accounts = pgTable( + "accounts", + { + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + type: text("type").$type().notNull(), + provider: text("provider").notNull(), + providerAccountId: text("providerAccountId").notNull(), + refresh_token: text("refresh_token"), + access_token: text("access_token"), + expires_at: integer("expires_at"), + token_type: text("token_type"), + scope: text("scope"), + id_token: text("id_token"), + session_state: text("session_state"), + }, + (table) => { + return { + providerProviderAccountIdKey: uniqueIndex( + "Account_provider_providerAccountId_key" + ).on(table.provider, table.providerAccountId), + }; + } +); + +export const sessions = pgTable( + "sessions", + { + sessionToken: text("sessionToken").notNull().primaryKey(), + userId: text("userId") + .notNull() + .references(() => users.id, { onDelete: "cascade" }), + expires: timestamp("expires", { mode: "date" }).notNull(), + }, + (table) => { + return { + sessionTokenKey: uniqueIndex("Session_sessionToken_key").on( + table.sessionToken + ), + }; + } +); + +export const verificationTokens = pgTable( + "verificationToken", + { + identifier: text("identifier").notNull(), + token: text("token").notNull(), + expires: timestamp("expires", { mode: "date" }).notNull(), + }, + (table) => ({ + identifierTokenKey: uniqueIndex( + "VerificationToken_identifier_token_key" + ).on(table.identifier, table.token), + tokenKey: uniqueIndex("VerificationToken_token_key").on(table.token), + }) +); + +// Connect to Vercel Postgres +export const db = drizzle(sql); + +export type DbClient = typeof db; + +export type Schema = { + users: typeof users; + accounts: typeof accounts; + sessions: typeof sessions; + verificationTokens: typeof verificationTokens; +}; +// import { sql, eq, and } from "drizzle-orm"; +// import { +// PgDatabase, +// QueryResultHKT, +// integer, +// pgTable, +// text, +// timestamp, +// uniqueIndex, +// uuid, +// } from "drizzle-orm/pg-core"; +// import { drizzle } from "drizzle-orm/vercel-postgres"; +// import { sql as c } from "@vercel/postgres"; +// import { Adapter, AdapterUser } from "@auth/nextjs/adapters"; + +// export const db = drizzle(c); + +// export const users = pgTable( +// "users", +// { +// id: uuid("id") +// .notNull() +// .primaryKey() +// .default(sql`gen_random_uuid()`), +// name: text("name"), +// email: text("email"), +// emailVerified: timestamp("emailVerified", { precision: 3 }), +// image: text("image"), +// }, +// (table) => { +// return { +// emailKey: uniqueIndex("User_email_key").on(table.email), +// }; +// } +// ); + +// export const verificationTokens = pgTable( +// "verification_tokens", +// { +// identifier: text("identifier").notNull(), +// token: text("token").notNull(), +// expires: timestamp("expires", { precision: 3 }).notNull(), +// }, +// (table) => { +// return { +// identifierTokenKey: uniqueIndex( +// "VerificationToken_identifier_token_key" +// ).on(table.identifier, table.token), +// tokenKey: uniqueIndex("VerificationToken_token_key").on(table.token), +// }; +// } +// ); + +// export const sessions = pgTable( +// "sessions", +// { +// id: uuid("id") +// .notNull() +// .primaryKey() +// .default(sql`gen_random_uuid()`), +// sessionToken: text("sessionToken").notNull(), +// userId: uuid("userId") +// .notNull() +// .references(() => users.id, { onDelete: "cascade", onUpdate: "cascade" }), +// expires: timestamp("expires", { precision: 3 }).notNull(), +// }, +// (table) => { +// return { +// sessionTokenKey: uniqueIndex("Session_sessionToken_key").on( +// table.sessionToken +// ), +// }; +// } +// ); + +// export const accounts = pgTable( +// "accounts", +// { +// id: uuid("id") +// .notNull() +// .primaryKey() +// .default(sql`gen_random_uuid()`), +// userId: uuid("userId") +// .notNull() +// .references(() => users.id, { onDelete: "cascade", onUpdate: "cascade" }), +// type: text("type").notNull(), +// provider: text("provider").notNull(), +// providerAccountId: text("providerAccountId").notNull(), +// refresh_token: text("refresh_token"), +// access_token: text("access_token"), +// expires_at: integer("expires_at"), +// token_type: text("token_type"), +// scope: text("scope"), +// id_token: text("id_token"), +// session_state: text("session_state"), +// }, +// (table) => { +// return { +// providerProviderAccountIdKey: uniqueIndex( +// "Account_provider_providerAccountId_key" +// ).on(table.provider, table.providerAccountId), +// }; +// } +// ); + +// type Users = typeof users; +// type Sessions = typeof sessions; +// type Accounts = typeof accounts; +// type VerificationTokens = typeof verificationTokens; + +// export function DrizzleAdapter< +// T extends PgDatabase, +// U extends QueryResultHKT +// >({ +// db, +// schema, +// }: { +// db: T; +// schema: { +// users: Users; +// sessions: Sessions; +// accounts: Accounts; +// verificationTokens: VerificationTokens; +// }; +// }): Adapter { +// return { +// async createUser(user) { +// const [newUser] = await db.insert(schema.users).values(user).returning(); + +// return newUser as AdapterUser; +// }, +// async getUser(id) { +// const [user] = await db +// .select() +// .from(schema.users) +// .where(eq(schema.users.id, id)); + +// return (user as AdapterUser) || null; +// }, +// async getUserByEmail(email) { +// const [user] = await db +// .select() +// .from(schema.users) +// .where(eq(schema.users.email, email)); + +// return (user as AdapterUser) || null; +// }, +// async getUserByAccount({ providerAccountId, provider }) { +// const results = await db +// .select() +// .from(schema.users) +// .leftJoin(schema.accounts, eq(schema.accounts.userId, schema.users.id)) +// .where( +// and( +// eq(schema.accounts.provider, provider), +// eq(schema.accounts.providerAccountId, providerAccountId) +// ) +// ); + +// if (results.length) { +// return results[0].users as AdapterUser; +// } + +// return null; +// }, +// async updateUser(user) { +// const userId = user.id; + +// if (!userId) { +// throw new Error("Cannot update user without id"); +// } + +// const [updatedUser] = await db +// .update(schema.users) +// .set(user) +// .where(eq(schema.users.id, userId)) +// .returning(); + +// return updatedUser as AdapterUser; +// }, +// async deleteUser(userId) { +// await db.delete(schema.users).where(eq(schema.users.id, userId)); +// }, +// async linkAccount(account) { +// await db.insert(schema.accounts).values(account); +// }, +// async unlinkAccount({ providerAccountId, provider }) { +// await db +// .delete(schema.accounts) +// .where( +// and( +// eq(schema.accounts.provider, provider), +// eq(schema.accounts.providerAccountId, providerAccountId) +// ) +// ); +// }, +// async createSession(session) { +// const [newSession] = await db +// .insert(schema.sessions) +// .values(session) +// .returning(); + +// return newSession; +// }, +// async getSessionAndUser(sessionToken) { +// const results = await db +// .select() +// .from(schema.sessions) +// .leftJoin(schema.users, eq(schema.users.id, schema.sessions.userId)) +// .where(eq(schema.sessions.sessionToken, sessionToken)); + +// if (results.length) { +// return { +// user: results[0].users! as AdapterUser, +// session: results[0].sessions, +// }; +// } + +// return null; +// }, +// async updateSession(session) { +// const [updatedSession] = await db +// .update(schema.sessions) +// .set(session) +// .where(eq(schema.sessions.sessionToken, session.sessionToken)) +// .returning(); + +// return updatedSession; +// }, +// async deleteSession(sessionToken) { +// await db +// .delete(schema.sessions) +// .where(eq(schema.sessions.sessionToken, sessionToken)); +// }, +// async createVerificationToken(token) { +// const [newVerificationToken] = await db +// .insert(schema.verificationTokens) +// .values(token) +// .returning(); + +// return newVerificationToken; +// }, +// async useVerificationToken({ identifier, token }) { +// const [deletedVerificationToken] = await db +// .delete(schema.verificationTokens) +// .where( +// and( +// eq(schema.verificationTokens.identifier, identifier), +// eq(schema.verificationTokens.token, token) +// ) +// ) +// .returning(); + +// return deletedVerificationToken || null; +// }, +// }; +// } diff --git a/package.json b/package.json index 48f3409..640b8e5 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "scripts": { "dev": "prisma generate && next dev", "build": "prisma generate && next build", - "studio": "prisma studio", + "db:mg:create": "drizzle-kit generate:pg --config=drizzle.config.ts", + "db:mg:apply": "ts-node --project tsconfig.migration.json ./lib/db/migrate --config=drizzle.config.ts", + "db:check": "drizzle-kit check:pg --config=drizzle.config.ts", + "db:up": "drizzle-kit up:pg --config=drizzle.config.ts", "start": "next start", "lint": "next lint", "lint:fix": "next lint --fix", @@ -21,11 +24,13 @@ "@radix-ui/react-dropdown-menu": "^2.0.4", "@vercel/analytics": "^1.0.0", "@vercel/kv": "^0.2.1", + "@vercel/postgres": "^0.3.0", "body-scroll-lock": "4.0.0-beta.0", "class-variance-authority": "^0.4.0", "clsx": "^1.2.1", "common-tags": "^1.8.2", "cookie": "^0.5.0", + "drizzle-orm": "^0.26.0", "eventsource-parser": "^1.0.0", "focus-trap-react": "^10.1.1", "framer-motion": "^10.12.4", @@ -45,7 +50,8 @@ "remark-gfm": "^3.0.1", "remark-math": "^5.1.1", "tailwind-merge": "^1.12.0", - "tailwindcss-animate": "^1.0.5" + "tailwindcss-animate": "^1.0.5", + "uuid": "^9.0.0" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^3.7.1", @@ -60,6 +66,8 @@ "@types/react-syntax-highlighter": "^15.5.6", "@typescript-eslint/parser": "^5.58.0", "autoprefixer": "^10.4.13", + "dotenv": "^16.0.3", + "drizzle-kit": "^0.18.0", "eslint": "^8.31.0", "eslint-config-next": "13.4.3-canary.3", "eslint-config-prettier": "^8.3.0", @@ -69,6 +77,7 @@ "prettier": "^2.7.1", "prisma": "^4.14.0", "tailwindcss": "^3.3.1", + "ts-node": "^10.9.1", "typescript": "^4.9.3" }, "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc1d6af..9ee82ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,9 @@ dependencies: '@vercel/kv': specifier: ^0.2.1 version: 0.2.1 + '@vercel/postgres': + specifier: ^0.3.0 + version: 0.3.0 body-scroll-lock: specifier: 4.0.0-beta.0 version: 4.0.0-beta.0 @@ -37,6 +40,9 @@ dependencies: cookie: specifier: ^0.5.0 version: 0.5.0 + drizzle-orm: + specifier: ^0.26.0 + version: 0.26.0(@vercel/postgres@0.3.0) eventsource-parser: specifier: ^1.0.0 version: 1.0.0 @@ -97,6 +103,9 @@ dependencies: tailwindcss-animate: specifier: ^1.0.5 version: 1.0.5(tailwindcss@3.3.2) + uuid: + specifier: ^9.0.0 + version: 9.0.0 devDependencies: '@ianvs/prettier-plugin-sort-imports': @@ -135,6 +144,12 @@ devDependencies: autoprefixer: specifier: ^10.4.13 version: 10.4.14(postcss@8.4.23) + dotenv: + specifier: ^16.0.3 + version: 16.0.3 + drizzle-kit: + specifier: ^0.18.0 + version: 0.18.0 eslint: specifier: ^8.31.0 version: 8.40.0 @@ -161,7 +176,10 @@ devDependencies: version: 4.14.0 tailwindcss: specifier: ^3.3.1 - version: 3.3.2 + version: 3.3.2(ts-node@10.9.1) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@17.0.45)(typescript@4.9.5) typescript: specifier: ^4.9.3 version: 4.9.5 @@ -388,6 +406,12 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + /@emotion/is-prop-valid@0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} requiresBuild: true @@ -401,6 +425,24 @@ packages: dev: false optional: true + /@esbuild/android-arm@0.15.18: + resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.15.18: + resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.40.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -532,6 +574,18 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@neondatabase/serverless@0.4.3: + resolution: {integrity: sha512-U8tpuF5f0R5WRsciR7iaJ5S2h54DWa6Z6CEW+J4KgwyvRN3q3qDz0MibdfFXU0WqnRoi/9RSf/2XN4TfeaOCbQ==} + dependencies: + '@types/pg': 8.6.6 + dev: false + /@next-auth/prisma-adapter@1.0.6(@prisma/client@4.14.0)(next-auth@4.22.1): resolution: {integrity: sha512-Z7agwfSZEeEcqKqrnisBun7VndRPshd6vyDsoRU68MXbkui8storkHgvN2hnNDrqr/hSCF9aRn56a1qpihaB4A==} peerDependencies: @@ -1022,9 +1076,21 @@ packages: lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.3.2 + tailwindcss: 3.3.2(ts-node@10.9.1) dev: true + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + /@types/common-tags@1.8.1: resolution: {integrity: sha512-20R/mDpKSPWdJs5TOpz3e7zqbeCNuMCPhV7Yndk9KU2Rbij2r5W4RzwDPkzC+2lzUqXYu9rFzTktCBnDjHuNQg==} dev: true @@ -1070,7 +1136,14 @@ packages: /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - dev: true + + /@types/pg@8.6.6: + resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==} + dependencies: + '@types/node': 17.0.45 + pg-protocol: 1.6.0 + pg-types: 2.2.0 + dev: false /@types/prop-types@15.7.5: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} @@ -1184,6 +1257,16 @@ packages: - encoding dev: false + /@vercel/postgres@0.3.0: + resolution: {integrity: sha512-cOC+x6qMnN54B4y0Fh0DV5LJQp2M7puIKbehQBMutY/8/zpzh+oKaQmnZb2QHn489MGOQKyRLJLgHa2P8M085Q==} + engines: {node: '>=14.6'} + dependencies: + '@neondatabase/serverless': 0.4.3 + bufferutil: 4.0.7 + utf-8-validate: 6.0.3 + ws: 8.13.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + dev: false + /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1192,11 +1275,14 @@ packages: acorn: 8.8.2 dev: true + /acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1235,6 +1321,9 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1377,6 +1466,12 @@ packages: balanced-match: 1.0.2 concat-map: 0.0.1 + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -1397,6 +1492,14 @@ packages: resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} dev: false + /bufferutil@4.0.7: + resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.6.0 + dev: false + /bundle-name@3.0.0: resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} engines: {node: '>=12'} @@ -1427,6 +1530,11 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true + /caniuse-lite@1.0.30001486: resolution: {integrity: sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==} @@ -1450,6 +1558,11 @@ packages: supports-color: 7.2.0 dev: true + /chalk@5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /character-entities-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} dev: false @@ -1491,6 +1604,17 @@ packages: typescript: 4.9.5 dev: false + /cli-color@2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true + /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false @@ -1536,6 +1660,11 @@ packages: engines: {node: '>= 12'} dev: false + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: true + /common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} @@ -1552,6 +1681,9 @@ packages: engines: {node: '>= 0.6'} dev: false + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1569,6 +1701,13 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true @@ -1671,11 +1810,21 @@ packages: /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} dev: false + /difflib@0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + dependencies: + heap: 0.2.7 + dev: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1700,6 +1849,98 @@ packages: esutils: 2.0.3 dev: true + /dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dev: true + + /dreamopt@0.8.0: + resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==} + engines: {node: '>=0.4.0'} + dependencies: + wordwrap: 1.0.0 + dev: true + + /drizzle-kit@0.18.0: + resolution: {integrity: sha512-43oH0XNWJDfMmVtDVnW8OV+tIs3xXDb1MjdsDiv0a7unQAylr0hpGG0HD5uEPWSbt7oxBots+hnYWxo98D0KAg==} + hasBin: true + dependencies: + camelcase: 7.0.1 + chalk: 5.2.0 + commander: 9.5.0 + esbuild: 0.15.18 + esbuild-register: 3.4.2(esbuild@0.15.18) + glob: 8.1.0 + hanji: 0.0.5 + json-diff: 0.9.0 + minimatch: 7.4.6 + zod: 3.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /drizzle-orm@0.26.0(@vercel/postgres@0.3.0): + resolution: {integrity: sha512-ztjhHehcuG5+lpGYxfT/L5I+yd/Z0dOf0fV3cS2ywBU01wkpxjwl4EJZVT7kVzjYfM8kwMGDghAPRPBCK0vULA==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@vercel/postgres': 0.3.0 + dev: false + /ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} dependencies: @@ -1799,6 +2040,261 @@ packages: is-symbol: 1.0.4 dev: true + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + + /esbuild-android-64@0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-android-arm64@0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-64@0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-arm64@0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-64@0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-arm64@0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-32@0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-64@0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm64@0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm@0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-mips64le@0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-ppc64le@0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-riscv64@0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-s390x@0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-netbsd-64@0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-openbsd-64@0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-register@3.4.2(esbuild@0.15.18): + resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} + peerDependencies: + esbuild: '>=0.12 <1' + dependencies: + debug: 4.3.4 + esbuild: 0.15.18 + transitivePeerDependencies: + - supports-color + dev: true + + /esbuild-sunos-64@0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-32@0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-64@0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-arm64@0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild@0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.15.18 + '@esbuild/linux-loong64': 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + dev: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -2014,7 +2510,7 @@ packages: dependencies: fast-glob: 3.2.12 postcss: 8.4.23 - tailwindcss: 3.3.2 + tailwindcss: 3.3.2(ts-node@10.9.1) dev: true /eslint-scope@7.2.0: @@ -2112,6 +2608,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + /eventsource-parser@1.0.0: resolution: {integrity: sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==} engines: {node: '>=14.18'} @@ -2147,6 +2650,12 @@ packages: strip-final-newline: 3.0.0 dev: true + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false @@ -2375,6 +2884,17 @@ packages: path-is-absolute: 1.0.1 dev: true + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -2438,6 +2958,13 @@ packages: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} dev: true + /hanji@0.0.5: + resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==} + dependencies: + lodash.throttle: 4.1.1 + sisteransi: 1.0.5 + dev: true + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -2498,6 +3025,10 @@ packages: space-separated-tokens: 1.1.5 dev: false + /heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + dev: true + /highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: false @@ -2695,6 +3226,10 @@ packages: engines: {node: '>=12'} dev: false + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -2820,6 +3355,15 @@ packages: engines: {node: '>=4'} hasBin: true + /json-diff@0.9.0: + resolution: {integrity: sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==} + hasBin: true + dependencies: + cli-color: 2.0.3 + difflib: 0.2.4 + dreamopt: 0.8.0 + dev: true + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -2937,6 +3481,10 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false @@ -2969,6 +3517,12 @@ packages: dependencies: yallist: 4.0.0 + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + /lucide-react@0.216.0(react@18.2.0): resolution: {integrity: sha512-PGWXs6JXI/08rhfkmj/joji0MAKDCcms44j0LYILO4J36AWqKhgjjaZ6WECRSyZ9TQe5gOrAR0g38O8cKrQngw==} peerDependencies: @@ -2977,6 +3531,9 @@ packages: react: 18.2.0 dev: false + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + /markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} dev: false @@ -3120,6 +3677,19 @@ packages: '@types/mdast': 3.0.11 dev: false + /memoizee@0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.7 + dev: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -3410,6 +3980,20 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true @@ -3484,6 +4068,10 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: true + /next@13.4.3-canary.3(@babel/core@7.21.8)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Fix/RAVHJHUpJZsvftaC5Pm8qGP7/NIitOBsKPozSPKIekCUWwKiaoLPY140taMgl9R+oW1nXKwYhAdjM8gSMg==} engines: {node: '>=16.8.0'} @@ -3541,6 +4129,11 @@ packages: whatwg-url: 5.0.0 dev: false + /node-gyp-build@4.6.0: + resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} + hasBin: true + dev: false + /node-releases@2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} @@ -3768,6 +4361,26 @@ packages: engines: {node: '>=8'} dev: true + /pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + dev: false + + /pg-protocol@1.6.0: + resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} + dev: false + + /pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -3803,7 +4416,7 @@ packages: camelcase-css: 2.0.1 postcss: 8.4.23 - /postcss-load-config@4.0.1(postcss@8.4.23): + /postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.1): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} peerDependencies: @@ -3817,6 +4430,7 @@ packages: dependencies: lilconfig: 2.1.0 postcss: 8.4.23 + ts-node: 10.9.1(@types/node@17.0.45)(typescript@4.9.5) yaml: 2.2.2 /postcss-nested@6.0.1(postcss@8.4.23): @@ -3863,6 +4477,28 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + dev: false + + /postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + dependencies: + xtend: 4.0.2 + dev: false + /preact-render-to-string@5.2.3(preact@10.11.3): resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} peerDependencies: @@ -4266,6 +4902,10 @@ packages: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -4440,10 +5080,10 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' dependencies: - tailwindcss: 3.3.2 + tailwindcss: 3.3.2(ts-node@10.9.1) dev: false - /tailwindcss@3.3.2: + /tailwindcss@3.3.2(ts-node@10.9.1): resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} engines: {node: '>=14.0.0'} hasBin: true @@ -4465,7 +5105,7 @@ packages: postcss: 8.4.23 postcss-import: 15.1.0(postcss@8.4.23) postcss-js: 4.0.1(postcss@8.4.23) - postcss-load-config: 4.0.1(postcss@8.4.23) + postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.1) postcss-nested: 6.0.1(postcss@8.4.23) postcss-selector-parser: 6.0.12 postcss-value-parser: 4.2.0 @@ -4494,6 +5134,13 @@ packages: dependencies: any-promise: 1.3.0 + /timers-ext@0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 + dev: true + /titleize@3.0.0: resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} engines: {node: '>=12'} @@ -4524,6 +5171,36 @@ packages: /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + /ts-node@10.9.1(@types/node@17.0.45)(typescript@4.9.5): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 17.0.45 + acorn: 8.8.2 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + /tsconfig-paths@3.14.2: resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} dependencies: @@ -4562,6 +5239,14 @@ packages: engines: {node: '>=10'} dev: true + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: @@ -4720,6 +5405,14 @@ packages: tslib: 2.5.0 dev: false + /utf-8-validate@6.0.3: + resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.6.0 + dev: false + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -4728,6 +5421,11 @@ packages: hasBin: true dev: false + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: false + /uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} engines: {node: '>=8'} @@ -4739,6 +5437,9 @@ packages: sade: 1.8.1 dev: false + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + /vfile-message@3.1.4: resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} dependencies: @@ -4814,9 +5515,29 @@ packages: engines: {node: '>=0.10.0'} dev: true + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + /ws@8.13.0(bufferutil@4.0.7)(utf-8-validate@6.0.3): + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dependencies: + bufferutil: 4.0.7 + utf-8-validate: 6.0.3 + dev: false + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -4832,6 +5553,10 @@ packages: resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} engines: {node: '>= 14'} + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -4839,7 +5564,6 @@ packages: /zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} - dev: false /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} diff --git a/tsconfig.migration.json b/tsconfig.migration.json new file mode 100644 index 0000000..f06016b --- /dev/null +++ b/tsconfig.migration.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "moduleResolution": "Node", + "target": "ES2020", + "jsx": "react", + "strictNullChecks": true, + "strictFunctionTypes": true + }, + "exclude": ["node_modules", "**/node_modules/*"] +}