diff --git a/drizzle/0000_loose_catseye.sql b/drizzle/0000_loose_catseye.sql index e7d7fd7..35e5681 100644 --- a/drizzle/0000_loose_catseye.sql +++ b/drizzle/0000_loose_catseye.sql @@ -1,56 +1 @@ --- Current sql file was generated after introspecting the database --- If you want to run this migration please uncomment this code before executing migrations -/* -CREATE TABLE "session" ( - "sessionToken" text PRIMARY KEY NOT NULL, - "userId" text NOT NULL, - "expires" timestamp NOT NULL -); ---> statement-breakpoint -CREATE TABLE "user" ( - "id" text PRIMARY KEY NOT NULL, - "name" text, - "email" text NOT NULL, - "emailVerified" timestamp, - "image" text -); ---> statement-breakpoint -CREATE TABLE "verificationToken" ( - "identifier" text NOT NULL, - "token" text NOT NULL, - "expires" timestamp NOT NULL, - CONSTRAINT "verificationToken_identifier_token_pk" PRIMARY KEY("identifier","token") -); ---> statement-breakpoint -CREATE TABLE "authenticator" ( - "credentialID" text NOT NULL, - "userId" text NOT NULL, - "providerAccountId" text NOT NULL, - "credentialPublicKey" text NOT NULL, - "counter" integer NOT NULL, - "credentialDeviceType" text NOT NULL, - "credentialBackedUp" boolean NOT NULL, - "transports" text, - CONSTRAINT "authenticator_userId_credentialID_pk" PRIMARY KEY("credentialID","userId"), - CONSTRAINT "authenticator_credentialID_unique" UNIQUE("credentialID") -); ---> statement-breakpoint -CREATE TABLE "account" ( - "userId" text NOT NULL, - "type" text NOT NULL, - "provider" text NOT NULL, - "providerAccountId" text NOT NULL, - "refresh_token" text, - "access_token" text, - "expires_at" text, - "token_type" text, - "scope" text, - "id_token" text, - "session_state" text, - CONSTRAINT "account_provider_providerAccountId_pk" PRIMARY KEY("provider","providerAccountId") -); ---> statement-breakpoint -ALTER TABLE "session" ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "authenticator" ADD CONSTRAINT "authenticator_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint -ALTER TABLE "account" ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; -*/ \ No newline at end of file +-- Baseline snapshot: tables already exist in the database diff --git a/drizzle/0001_great_sentry.sql b/drizzle/0001_great_sentry.sql new file mode 100644 index 0000000..1a0bf22 --- /dev/null +++ b/drizzle/0001_great_sentry.sql @@ -0,0 +1,41 @@ +ALTER TABLE "authenticator" DISABLE ROW LEVEL SECURITY;--> statement-breakpoint +DROP TABLE "authenticator" CASCADE;--> statement-breakpoint +ALTER TABLE "verificationToken" RENAME TO "verification";--> statement-breakpoint +ALTER TABLE "session" RENAME COLUMN "expires" TO "expiresAt";--> statement-breakpoint +ALTER TABLE "session" RENAME COLUMN "sessionToken" TO "token";--> statement-breakpoint +ALTER TABLE "verification" RENAME COLUMN "token" TO "value";--> statement-breakpoint +ALTER TABLE "verification" RENAME COLUMN "expires" TO "expiresAt";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "providerAccountId" TO "accountId";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "provider" TO "providerId";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "access_token" TO "accessToken";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "refresh_token" TO "refreshToken";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "expires_at" TO "accessTokenExpiresAt";--> statement-breakpoint +ALTER TABLE "account" RENAME COLUMN "id_token" TO "idToken";--> statement-breakpoint +ALTER TABLE "verification" DROP CONSTRAINT "verificationToken_identifier_token_pk";--> statement-breakpoint +ALTER TABLE "account" DROP CONSTRAINT "account_provider_providerAccountId_pk";--> statement-breakpoint +ALTER TABLE "user" ALTER COLUMN "emailVerified" SET DATA TYPE boolean USING ("emailVerified" IS NOT NULL);--> statement-breakpoint +ALTER TABLE "session" DROP CONSTRAINT "session_pkey";--> statement-breakpoint +ALTER TABLE "session" ADD COLUMN "id" text PRIMARY KEY NOT NULL DEFAULT gen_random_uuid();--> statement-breakpoint +ALTER TABLE "session" ADD COLUMN "createdAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "session" ADD COLUMN "updatedAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "session" ADD COLUMN "ipAddress" text;--> statement-breakpoint +ALTER TABLE "session" ADD COLUMN "userAgent" text;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "createdAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "updatedAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "verification" ADD COLUMN "id" text PRIMARY KEY NOT NULL DEFAULT gen_random_uuid();--> statement-breakpoint +ALTER TABLE "verification" ADD COLUMN "createdAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "verification" ADD COLUMN "updatedAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "account" ADD COLUMN "id" text PRIMARY KEY NOT NULL DEFAULT gen_random_uuid();--> statement-breakpoint +ALTER TABLE "account" ADD COLUMN "refreshTokenExpiresAt" timestamp;--> statement-breakpoint +ALTER TABLE "account" ADD COLUMN "password" text;--> statement-breakpoint +ALTER TABLE "account" ADD COLUMN "createdAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "account" ADD COLUMN "updatedAt" timestamp DEFAULT now();--> statement-breakpoint +ALTER TABLE "account" DROP COLUMN "type";--> statement-breakpoint +ALTER TABLE "account" DROP COLUMN "token_type";--> statement-breakpoint +ALTER TABLE "account" DROP COLUMN "session_state";--> statement-breakpoint +ALTER TABLE "session" ADD CONSTRAINT "session_token_unique" UNIQUE("token");--> statement-breakpoint +ALTER TABLE "user" ADD CONSTRAINT "user_email_unique" UNIQUE("email"); +-- Drop the uuid defaults so future inserts rely on app-provided values +ALTER TABLE "session" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "verification" ALTER COLUMN "id" DROP DEFAULT;--> statement-breakpoint +ALTER TABLE "account" ALTER COLUMN "id" DROP DEFAULT; diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..ebaba7c --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,328 @@ +{ + "id": "69e7666b-0b8c-4658-906d-993870a0b539", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessToken": { + "name": "accessToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refreshToken": { + "name": "refreshToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessTokenExpiresAt": { + "name": "accessTokenExpiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refreshTokenExpiresAt": { + "name": "refreshTokenExpiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "idToken": { + "name": "idToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "account_userId_user_id_fk": { + "name": "account_userId_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "ipAddress": { + "name": "ipAddress", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userAgent": { + "name": "userAgent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_userId_user_id_fk": { + "name": "session_userId_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "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": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 612f104..353b4e2 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1755586325384, "tag": "0000_loose_catseye", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1775526538601, + "tag": "0001_great_sentry", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/db/schema.ts b/src/db/schema.ts index 08dbac6..421df04 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -1,55 +1,47 @@ -import { pgTable, text, timestamp, integer, boolean, primaryKey } from 'drizzle-orm/pg-core'; +import { pgTable, text, timestamp, boolean } from 'drizzle-orm/pg-core'; -export const users = pgTable('user', { +export const user = pgTable('user', { id: text('id').primaryKey(), name: text('name'), - email: text('email').notNull(), - emailVerified: timestamp('emailVerified', { mode: 'string' }), + email: text('email').notNull().unique(), + emailVerified: boolean('emailVerified').default(false), image: text('image'), + createdAt: timestamp('createdAt').defaultNow(), + updatedAt: timestamp('updatedAt').defaultNow(), }); -export const accounts = pgTable('account', { - userId: text('userId').notNull().references(() => users.id, { onDelete: '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: text('expires_at'), - token_type: text('token_type'), +export const session = pgTable('session', { + id: text('id').primaryKey(), + expiresAt: timestamp('expiresAt').notNull(), + token: text('token').notNull().unique(), + createdAt: timestamp('createdAt').defaultNow(), + updatedAt: timestamp('updatedAt').defaultNow(), + ipAddress: text('ipAddress'), + userAgent: text('userAgent'), + userId: text('userId').notNull().references(() => user.id, { onDelete: 'cascade' }), +}); + +export const account = pgTable('account', { + id: text('id').primaryKey(), + accountId: text('accountId').notNull(), + providerId: text('providerId').notNull(), + userId: text('userId').notNull().references(() => user.id, { onDelete: 'cascade' }), + accessToken: text('accessToken'), + refreshToken: text('refreshToken'), + accessTokenExpiresAt: timestamp('accessTokenExpiresAt'), + refreshTokenExpiresAt: timestamp('refreshTokenExpiresAt'), scope: text('scope'), - id_token: text('id_token'), - session_state: text('session_state'), -}, (account) => ({ - compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }) -})); - -export const sessions = pgTable('session', { - sessionToken: text().primaryKey().notNull(), - userId: text().notNull().references(() => users.id, { onDelete: 'cascade' }), - expires: timestamp({ mode: 'string' }).notNull(), + idToken: text('idToken'), + password: text('password'), + createdAt: timestamp('createdAt').defaultNow(), + updatedAt: timestamp('updatedAt').defaultNow(), }); -export const verificationTokens = pgTable('verificationToken', { +export const verification = pgTable('verification', { + id: text('id').primaryKey(), identifier: text('identifier').notNull(), - token: text('token').notNull(), - expires: timestamp('expires', { mode: 'string' }).notNull(), -}, (vt) => ({ - compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }) -})); - -export const authenticators = pgTable('authenticator', { - credentialID: text('credentialID').notNull().unique(), - userId: text('userId').notNull().references(() => users.id, { onDelete: 'cascade' }), - providerAccountId: text('providerAccountId').notNull(), - credentialPublicKey: text('credentialPublicKey').notNull(), - counter: integer('counter').notNull(), - credentialDeviceType: text('credentialDeviceType').notNull(), - credentialBackedUp: boolean('credentialBackedUp').notNull(), - transports: text('transports'), -}, (authenticator) => ({ - compositePK: primaryKey({ - columns: [authenticator.credentialID, authenticator.userId], - name: "authenticator_userId_credentialID_pk" - }) -})); \ No newline at end of file + value: text('value').notNull(), + expiresAt: timestamp('expiresAt').notNull(), + createdAt: timestamp('createdAt').defaultNow(), + updatedAt: timestamp('updatedAt').defaultNow(), +});