Try to use drizzle event though
This commit is contained in:
parent
f14e73ac8f
commit
d88eae7230
14 changed files with 1978 additions and 12 deletions
16
auth.ts
16
auth.ts
|
|
@ -1,11 +1,27 @@
|
||||||
import NextAuth from "@auth/nextjs";
|
import NextAuth from "@auth/nextjs";
|
||||||
import GitHub from "@auth/nextjs/providers/github";
|
import GitHub from "@auth/nextjs/providers/github";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
import {
|
||||||
|
db,
|
||||||
|
users,
|
||||||
|
accounts,
|
||||||
|
sessions,
|
||||||
|
verificationTokens,
|
||||||
|
} from "./lib/db/schema";
|
||||||
|
import { DrizzleAdapterPg } from "./lib/db";
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
handlers: { GET, POST },
|
handlers: { GET, POST },
|
||||||
auth,
|
auth,
|
||||||
CSRF_experimental,
|
CSRF_experimental,
|
||||||
} = NextAuth({
|
} = NextAuth({
|
||||||
|
adapter: DrizzleAdapterPg(db, {
|
||||||
|
accounts,
|
||||||
|
users,
|
||||||
|
sessions,
|
||||||
|
verificationTokens,
|
||||||
|
}),
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
providers: [GitHub],
|
providers: [GitHub],
|
||||||
session: { strategy: "jwt" },
|
session: { strategy: "jwt" },
|
||||||
|
|
|
||||||
6
drizzle.config.ts
Normal file
6
drizzle.config.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import type { Config } from "drizzle-kit";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
schema: "./lib/db/schema.ts",
|
||||||
|
out: "./lib/db/migrations",
|
||||||
|
} satisfies Config;
|
||||||
4
lib/db/db.ts
Normal file
4
lib/db/db.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { drizzle } from "drizzle-orm/vercel-postgres";
|
||||||
|
import { sql } from "@vercel/postgres";
|
||||||
|
|
||||||
|
export const db = drizzle(sql);
|
||||||
270
lib/db/index.ts
Normal file
270
lib/db/index.ts
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
/**
|
||||||
|
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}>
|
||||||
|
* <p style={{fontWeight: "normal"}}>Official <a href="https://github.com/drizzle-team/drizzle-orm">Drizzle ORM</a> adapter for Auth.js / NextAuth.js.</p>
|
||||||
|
* <a href="https://github.com/drizzle-team/drizzle-orm">
|
||||||
|
* <img style={{display: "block"}} src="https://pbs.twimg.com/profile_images/1598308842391179266/CtXrfLnk_400x400.jpg" width="38" />
|
||||||
|
* </a>
|
||||||
|
* </div>
|
||||||
|
*
|
||||||
|
* ## 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<ProviderType>().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<Adapter["linkAccount"]> = {
|
||||||
|
...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;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
18
lib/db/migrate.ts
Normal file
18
lib/db/migrate.ts
Normal file
|
|
@ -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");
|
||||||
|
});
|
||||||
49
lib/db/migrations/0000_flawless_moondragon.sql
Normal file
49
lib/db/migrations/0000_flawless_moondragon.sql
Normal file
|
|
@ -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 $$;
|
||||||
7
lib/db/migrations/0001_colorful_spectrum.sql
Normal file
7
lib/db/migrations/0001_colorful_spectrum.sql
Normal file
|
|
@ -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");
|
||||||
227
lib/db/migrations/meta/0000_snapshot.json
Normal file
227
lib/db/migrations/meta/0000_snapshot.json
Normal file
|
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
252
lib/db/migrations/meta/0001_snapshot.json
Normal file
252
lib/db/migrations/meta/0001_snapshot.json
Normal file
|
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
lib/db/migrations/meta/_journal.json
Normal file
20
lib/db/migrations/meta/_journal.json
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
353
lib/db/schema.ts
Normal file
353
lib/db/schema.ts
Normal file
|
|
@ -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<ProviderType>().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>,
|
||||||
|
// 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;
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// }
|
||||||
13
package.json
13
package.json
|
|
@ -5,7 +5,10 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "prisma generate && next dev",
|
"dev": "prisma generate && next dev",
|
||||||
"build": "prisma generate && next build",
|
"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",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"lint:fix": "next lint --fix",
|
"lint:fix": "next lint --fix",
|
||||||
|
|
@ -21,11 +24,13 @@
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
"@radix-ui/react-dropdown-menu": "^2.0.4",
|
||||||
"@vercel/analytics": "^1.0.0",
|
"@vercel/analytics": "^1.0.0",
|
||||||
"@vercel/kv": "^0.2.1",
|
"@vercel/kv": "^0.2.1",
|
||||||
|
"@vercel/postgres": "^0.3.0",
|
||||||
"body-scroll-lock": "4.0.0-beta.0",
|
"body-scroll-lock": "4.0.0-beta.0",
|
||||||
"class-variance-authority": "^0.4.0",
|
"class-variance-authority": "^0.4.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"common-tags": "^1.8.2",
|
"common-tags": "^1.8.2",
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.5.0",
|
||||||
|
"drizzle-orm": "^0.26.0",
|
||||||
"eventsource-parser": "^1.0.0",
|
"eventsource-parser": "^1.0.0",
|
||||||
"focus-trap-react": "^10.1.1",
|
"focus-trap-react": "^10.1.1",
|
||||||
"framer-motion": "^10.12.4",
|
"framer-motion": "^10.12.4",
|
||||||
|
|
@ -45,7 +50,8 @@
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
"tailwind-merge": "^1.12.0",
|
"tailwind-merge": "^1.12.0",
|
||||||
"tailwindcss-animate": "^1.0.5"
|
"tailwindcss-animate": "^1.0.5",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ianvs/prettier-plugin-sort-imports": "^3.7.1",
|
"@ianvs/prettier-plugin-sort-imports": "^3.7.1",
|
||||||
|
|
@ -60,6 +66,8 @@
|
||||||
"@types/react-syntax-highlighter": "^15.5.6",
|
"@types/react-syntax-highlighter": "^15.5.6",
|
||||||
"@typescript-eslint/parser": "^5.58.0",
|
"@typescript-eslint/parser": "^5.58.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
|
"dotenv": "^16.0.3",
|
||||||
|
"drizzle-kit": "^0.18.0",
|
||||||
"eslint": "^8.31.0",
|
"eslint": "^8.31.0",
|
||||||
"eslint-config-next": "13.4.3-canary.3",
|
"eslint-config-next": "13.4.3-canary.3",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
|
@ -69,6 +77,7 @@
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prisma": "^4.14.0",
|
"prisma": "^4.14.0",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.9.3"
|
"typescript": "^4.9.3"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|
|
||||||
744
pnpm-lock.yaml
generated
744
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
11
tsconfig.migration.json
Normal file
11
tsconfig.migration.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "CommonJS",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"target": "ES2020",
|
||||||
|
"jsx": "react",
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictFunctionTypes": true
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "**/node_modules/*"]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue