Refactor authentication schema and database handling
- Updated SQLite journal metadata with new tag and timestamp. - Refactored account deletion API to utilize Better Auth's built-in user deletion method for cascading cleanup. - Enhanced database initialization to include authentication schemas for both SQLite and Postgres. - Removed user, session, account, and verification tables from the Drizzle schema, as they are now managed by Better Auth. - Created separate schema files for authentication in both Postgres and SQLite. - Added SQL migration scripts for creating necessary tables in both database systems.
This commit is contained in:
parent
f9366dbfa2
commit
bb853acaf6
17 changed files with 1046 additions and 753 deletions
|
|
@ -5,13 +5,12 @@ dotenv.config();
|
||||||
|
|
||||||
let url = process.env.POSTGRES_URL;
|
let url = process.env.POSTGRES_URL;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
//throw new Error('POSTGRES_URL is required for drizzle.config.pg.ts');
|
|
||||||
console.warn('[drizzle.config.pg.ts] POSTGRES_URL is not set; using a placeholder URL.');
|
console.warn('[drizzle.config.pg.ts] POSTGRES_URL is not set; using a placeholder URL.');
|
||||||
url = 'postgresql://placeholder:placeholder@localhost:5432/placeholder';
|
url = 'postgresql://placeholder:placeholder@localhost:5432/placeholder';
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
schema: './src/db/schema_postgres.ts',
|
schema: ['./src/db/schema_postgres.ts', './src/db/schema_auth_postgres.ts'],
|
||||||
out: './drizzle/postgres',
|
out: './drizzle/postgres',
|
||||||
dialect: 'postgresql',
|
dialect: 'postgresql',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import * as dotenv from 'dotenv';
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
schema: './src/db/schema_sqlite.ts',
|
schema: ['./src/db/schema_sqlite.ts', './src/db/schema_auth_sqlite.ts'],
|
||||||
out: './drizzle/sqlite',
|
out: './drizzle/sqlite',
|
||||||
dialect: 'sqlite',
|
dialect: 'sqlite',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,3 @@
|
||||||
CREATE TABLE "account" (
|
|
||||||
"id" text PRIMARY KEY NOT NULL,
|
|
||||||
"account_id" text NOT NULL,
|
|
||||||
"provider_id" text NOT NULL,
|
|
||||||
"user_id" text NOT NULL,
|
|
||||||
"access_token" text,
|
|
||||||
"refresh_token" text,
|
|
||||||
"id_token" text,
|
|
||||||
"access_token_expires_at" timestamp,
|
|
||||||
"refresh_token_expires_at" timestamp,
|
|
||||||
"scope" text,
|
|
||||||
"password" text,
|
|
||||||
"created_at" timestamp NOT NULL,
|
|
||||||
"updated_at" timestamp NOT NULL
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE "audiobook_chapters" (
|
CREATE TABLE "audiobook_chapters" (
|
||||||
"id" text NOT NULL,
|
"id" text NOT NULL,
|
||||||
"book_id" text NOT NULL,
|
"book_id" text NOT NULL,
|
||||||
|
|
@ -71,30 +55,6 @@ CREATE TABLE "documents" (
|
||||||
CONSTRAINT "documents_id_user_id_pk" PRIMARY KEY("id","user_id")
|
CONSTRAINT "documents_id_user_id_pk" PRIMARY KEY("id","user_id")
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
CREATE TABLE "session" (
|
|
||||||
"id" text PRIMARY KEY NOT NULL,
|
|
||||||
"expires_at" timestamp NOT NULL,
|
|
||||||
"token" text NOT NULL,
|
|
||||||
"created_at" timestamp NOT NULL,
|
|
||||||
"updated_at" timestamp NOT NULL,
|
|
||||||
"ip_address" text,
|
|
||||||
"user_agent" text,
|
|
||||||
"user_id" text NOT NULL,
|
|
||||||
CONSTRAINT "session_token_unique" UNIQUE("token")
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE "user" (
|
|
||||||
"id" text PRIMARY KEY NOT NULL,
|
|
||||||
"name" text NOT NULL,
|
|
||||||
"email" text NOT NULL,
|
|
||||||
"email_verified" boolean NOT NULL,
|
|
||||||
"image" text,
|
|
||||||
"created_at" timestamp NOT NULL,
|
|
||||||
"updated_at" timestamp NOT NULL,
|
|
||||||
"is_anonymous" boolean,
|
|
||||||
CONSTRAINT "user_email_unique" UNIQUE("email")
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE "user_document_progress" (
|
CREATE TABLE "user_document_progress" (
|
||||||
"user_id" text NOT NULL,
|
"user_id" text NOT NULL,
|
||||||
"document_id" text NOT NULL,
|
"document_id" text NOT NULL,
|
||||||
|
|
@ -124,11 +84,53 @@ CREATE TABLE "user_tts_chars" (
|
||||||
CONSTRAINT "user_tts_chars_user_id_date_pk" PRIMARY KEY("user_id","date")
|
CONSTRAINT "user_tts_chars_user_id_date_pk" PRIMARY KEY("user_id","date")
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "account" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"account_id" text NOT NULL,
|
||||||
|
"provider_id" text NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"access_token" text,
|
||||||
|
"refresh_token" text,
|
||||||
|
"id_token" text,
|
||||||
|
"access_token_expires_at" timestamp,
|
||||||
|
"refresh_token_expires_at" timestamp,
|
||||||
|
"scope" text,
|
||||||
|
"password" text,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "session" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"expires_at" timestamp NOT NULL,
|
||||||
|
"token" text NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp NOT NULL,
|
||||||
|
"ip_address" text,
|
||||||
|
"user_agent" text,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
CONSTRAINT "session_token_unique" UNIQUE("token")
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "user" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"email" text NOT NULL,
|
||||||
|
"email_verified" boolean DEFAULT false NOT NULL,
|
||||||
|
"image" text,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"is_anonymous" boolean DEFAULT false,
|
||||||
|
CONSTRAINT "user_email_unique" UNIQUE("email")
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
CREATE TABLE "verification" (
|
CREATE TABLE "verification" (
|
||||||
"id" text PRIMARY KEY NOT NULL,
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
"identifier" text NOT NULL,
|
"identifier" text NOT NULL,
|
||||||
"value" text NOT NULL,
|
"value" text NOT NULL,
|
||||||
"updated_at" timestamp
|
"expires_at" timestamp NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
|
@ -137,4 +139,7 @@ CREATE INDEX "idx_document_previews_status_lease" ON "document_previews" USING b
|
||||||
CREATE INDEX "idx_documents_user_id" ON "documents" USING btree ("user_id");--> statement-breakpoint
|
CREATE INDEX "idx_documents_user_id" ON "documents" USING btree ("user_id");--> statement-breakpoint
|
||||||
CREATE INDEX "idx_documents_user_id_last_modified" ON "documents" USING btree ("user_id","last_modified");--> statement-breakpoint
|
CREATE INDEX "idx_documents_user_id_last_modified" ON "documents" USING btree ("user_id","last_modified");--> statement-breakpoint
|
||||||
CREATE INDEX "idx_user_document_progress_user_id_updated_at" ON "user_document_progress" USING btree ("user_id","updated_at");--> statement-breakpoint
|
CREATE INDEX "idx_user_document_progress_user_id_updated_at" ON "user_document_progress" USING btree ("user_id","updated_at");--> statement-breakpoint
|
||||||
CREATE INDEX "idx_user_tts_chars_date" ON "user_tts_chars" USING btree ("date");
|
CREATE INDEX "idx_user_tts_chars_date" ON "user_tts_chars" USING btree ("date");--> statement-breakpoint
|
||||||
|
CREATE INDEX "account_userId_idx" ON "account" USING btree ("user_id");--> statement-breakpoint
|
||||||
|
CREATE INDEX "session_userId_idx" ON "session" USING btree ("user_id");--> statement-breakpoint
|
||||||
|
CREATE INDEX "verification_identifier_idx" ON "verification" USING btree ("identifier");
|
||||||
|
|
@ -1,114 +1,9 @@
|
||||||
{
|
{
|
||||||
"id": "161f4dc9-0c06-4d77-87e5-3496ffad1b97",
|
"id": "1c067f9b-aa2c-4099-a3b0-021e1a1c7ecb",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
"tables": {
|
"tables": {
|
||||||
"public.account": {
|
|
||||||
"name": "account",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"account_id": {
|
|
||||||
"name": "account_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"provider_id": {
|
|
||||||
"name": "provider_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"id_token": {
|
|
||||||
"name": "id_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"access_token_expires_at": {
|
|
||||||
"name": "access_token_expires_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token_expires_at": {
|
|
||||||
"name": "refresh_token_expires_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"scope": {
|
|
||||||
"name": "scope",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"name": "password",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"account_user_id_user_id_fk": {
|
|
||||||
"name": "account_user_id_user_id_fk",
|
|
||||||
"tableFrom": "account",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.audiobook_chapters": {
|
"public.audiobook_chapters": {
|
||||||
"name": "audiobook_chapters",
|
"name": "audiobook_chapters",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
|
|
@ -512,158 +407,6 @@
|
||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
"public.session": {
|
|
||||||
"name": "session",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"ip_address": {
|
|
||||||
"name": "ip_address",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"user_agent": {
|
|
||||||
"name": "user_agent",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"session_user_id_user_id_fk": {
|
|
||||||
"name": "session_user_id_user_id_fk",
|
|
||||||
"tableFrom": "session",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"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": true
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"email_verified": {
|
|
||||||
"name": "email_verified",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"is_anonymous": {
|
|
||||||
"name": "is_anonymous",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {
|
|
||||||
"user_email_unique": {
|
|
||||||
"name": "user_email_unique",
|
|
||||||
"nullsNotDistinct": false,
|
|
||||||
"columns": [
|
|
||||||
"email"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.user_document_progress": {
|
"public.user_document_progress": {
|
||||||
"name": "user_document_progress",
|
"name": "user_document_progress",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
|
|
@ -875,6 +618,301 @@
|
||||||
"checkConstraints": {},
|
"checkConstraints": {},
|
||||||
"isRLSEnabled": false
|
"isRLSEnabled": false
|
||||||
},
|
},
|
||||||
|
"public.account": {
|
||||||
|
"name": "account",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"account_id": {
|
||||||
|
"name": "account_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"provider_id": {
|
||||||
|
"name": "provider_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"access_token": {
|
||||||
|
"name": "access_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"refresh_token": {
|
||||||
|
"name": "refresh_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"id_token": {
|
||||||
|
"name": "id_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"access_token_expires_at": {
|
||||||
|
"name": "access_token_expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"refresh_token_expires_at": {
|
||||||
|
"name": "refresh_token_expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"name": "scope",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"name": "password",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"account_userId_idx": {
|
||||||
|
"name": "account_userId_idx",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"expression": "user_id",
|
||||||
|
"isExpression": false,
|
||||||
|
"asc": true,
|
||||||
|
"nulls": "last"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isUnique": false,
|
||||||
|
"concurrently": false,
|
||||||
|
"method": "btree",
|
||||||
|
"with": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"account_user_id_user_id_fk": {
|
||||||
|
"name": "account_user_id_user_id_fk",
|
||||||
|
"tableFrom": "account",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"name": "token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"ip_address": {
|
||||||
|
"name": "ip_address",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"user_agent": {
|
||||||
|
"name": "user_agent",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"session_userId_idx": {
|
||||||
|
"name": "session_userId_idx",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"expression": "user_id",
|
||||||
|
"isExpression": false,
|
||||||
|
"asc": true,
|
||||||
|
"nulls": "last"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isUnique": false,
|
||||||
|
"concurrently": false,
|
||||||
|
"method": "btree",
|
||||||
|
"with": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"session_user_id_user_id_fk": {
|
||||||
|
"name": "session_user_id_user_id_fk",
|
||||||
|
"tableFrom": "session",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"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": true
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"email_verified": {
|
||||||
|
"name": "email_verified",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"is_anonymous": {
|
||||||
|
"name": "is_anonymous",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
"public.verification": {
|
"public.verification": {
|
||||||
"name": "verification",
|
"name": "verification",
|
||||||
"schema": "",
|
"schema": "",
|
||||||
|
|
@ -897,14 +935,44 @@
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
"updated_at": {
|
"updated_at": {
|
||||||
"name": "updated_at",
|
"name": "updated_at",
|
||||||
"type": "timestamp",
|
"type": "timestamp",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": true,
|
||||||
|
"default": "now()"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"verification_identifier_idx": {
|
||||||
|
"name": "verification_identifier_idx",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"expression": "identifier",
|
||||||
|
"isExpression": false,
|
||||||
|
"asc": true,
|
||||||
|
"nulls": "last"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isUnique": false,
|
||||||
|
"concurrently": false,
|
||||||
|
"method": "btree",
|
||||||
|
"with": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
"foreignKeys": {},
|
||||||
"compositePrimaryKeys": {},
|
"compositePrimaryKeys": {},
|
||||||
"uniqueConstraints": {},
|
"uniqueConstraints": {},
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1770846273728,
|
"when": 1771184128245,
|
||||||
"tag": "0000_solid_colossus",
|
"tag": "0000_complex_ricochet",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,58 @@ function loadEnvFiles() {
|
||||||
|
|
||||||
loadEnvFiles();
|
loadEnvFiles();
|
||||||
|
|
||||||
// if (!process.env.POSTGRES_URL) {
|
// Ensure AUTH_SECRET and BASE_URL are set so Better Auth CLI can evaluate the config.
|
||||||
// console.error('[generate] POSTGRES_URL is required to generate postgres migrations.');
|
const env = { ...process.env };
|
||||||
// process.exit(1);
|
if (!env.AUTH_SECRET) env.AUTH_SECRET = 'generate-placeholder-secret-value-32chars!!';
|
||||||
// }
|
if (!env.BASE_URL) env.BASE_URL = 'http://localhost:3003';
|
||||||
|
|
||||||
const extraArgs = process.argv.slice(2);
|
const extraArgs = process.argv.slice(2);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Step 1: Generate Better Auth schema files (one per dialect).
|
||||||
|
//
|
||||||
|
// The Better Auth CLI reads our auth config and produces a Drizzle schema file
|
||||||
|
// matching the adapter in use. We run it twice:
|
||||||
|
// - Without POSTGRES_URL → SQLite schema
|
||||||
|
// - With POSTGRES_URL → Postgres schema
|
||||||
|
//
|
||||||
|
// These files are checked in and should NOT be hand-edited.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
console.log('\n--- Generating Better Auth schema (SQLite) ---');
|
||||||
|
{
|
||||||
|
const envSqlite = { ...env };
|
||||||
|
delete envSqlite.POSTGRES_URL; // force SQLite adapter
|
||||||
|
const result = spawnSync('npx', [
|
||||||
|
'@better-auth/cli', 'generate',
|
||||||
|
'--output', 'src/db/schema_auth_sqlite.ts',
|
||||||
|
'--yes',
|
||||||
|
], { stdio: 'inherit', env: envSqlite });
|
||||||
|
if ((result.status ?? 1) !== 0) process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n--- Generating Better Auth schema (Postgres) ---');
|
||||||
|
{
|
||||||
|
const envPg = { ...env };
|
||||||
|
// A placeholder URL is enough – the CLI doesn't connect, it just reads the config.
|
||||||
|
if (!envPg.POSTGRES_URL) {
|
||||||
|
envPg.POSTGRES_URL = 'postgresql://placeholder:placeholder@localhost:5432/placeholder';
|
||||||
|
}
|
||||||
|
const result = spawnSync('npx', [
|
||||||
|
'@better-auth/cli', 'generate',
|
||||||
|
'--output', 'src/db/schema_auth_postgres.ts',
|
||||||
|
'--yes',
|
||||||
|
], { stdio: 'inherit', env: envPg });
|
||||||
|
if ((result.status ?? 1) !== 0) process.exit(result.status ?? 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Step 2: Generate Drizzle migrations for both dialects.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
for (const configFile of ['drizzle.config.sqlite.ts', 'drizzle.config.pg.ts']) {
|
for (const configFile of ['drizzle.config.sqlite.ts', 'drizzle.config.pg.ts']) {
|
||||||
|
console.log(`\n--- Drizzle generate (${configFile}) ---`);
|
||||||
const result = spawnSync('drizzle-kit', ['generate', '--config', configFile, ...extraArgs], {
|
const result = spawnSync('drizzle-kit', ['generate', '--config', configFile, ...extraArgs], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: process.env,
|
env,
|
||||||
});
|
});
|
||||||
|
|
||||||
if ((result.status ?? 1) !== 0) {
|
if ((result.status ?? 1) !== 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,3 @@
|
||||||
CREATE TABLE `account` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`account_id` text NOT NULL,
|
|
||||||
`provider_id` text NOT NULL,
|
|
||||||
`user_id` text NOT NULL,
|
|
||||||
`access_token` text,
|
|
||||||
`refresh_token` text,
|
|
||||||
`id_token` text,
|
|
||||||
`access_token_expires_at` integer,
|
|
||||||
`refresh_token_expires_at` integer,
|
|
||||||
`scope` text,
|
|
||||||
`password` text,
|
|
||||||
`created_at` integer NOT NULL,
|
|
||||||
`updated_at` integer NOT NULL,
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE TABLE `audiobook_chapters` (
|
CREATE TABLE `audiobook_chapters` (
|
||||||
`id` text NOT NULL,
|
`id` text NOT NULL,
|
||||||
`book_id` text NOT NULL,
|
`book_id` text NOT NULL,
|
||||||
|
|
@ -75,31 +58,6 @@ CREATE TABLE `documents` (
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
CREATE INDEX `idx_documents_user_id` ON `documents` (`user_id`);--> statement-breakpoint
|
CREATE INDEX `idx_documents_user_id` ON `documents` (`user_id`);--> statement-breakpoint
|
||||||
CREATE INDEX `idx_documents_user_id_last_modified` ON `documents` (`user_id`,`last_modified`);--> statement-breakpoint
|
CREATE INDEX `idx_documents_user_id_last_modified` ON `documents` (`user_id`,`last_modified`);--> statement-breakpoint
|
||||||
CREATE TABLE `session` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`expires_at` integer NOT NULL,
|
|
||||||
`token` text NOT NULL,
|
|
||||||
`created_at` integer NOT NULL,
|
|
||||||
`updated_at` integer NOT NULL,
|
|
||||||
`ip_address` text,
|
|
||||||
`user_agent` text,
|
|
||||||
`user_id` text NOT NULL,
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
|
|
||||||
CREATE TABLE `user` (
|
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
|
||||||
`name` text NOT NULL,
|
|
||||||
`email` text NOT NULL,
|
|
||||||
`email_verified` integer NOT NULL,
|
|
||||||
`image` text,
|
|
||||||
`created_at` integer NOT NULL,
|
|
||||||
`updated_at` integer NOT NULL,
|
|
||||||
`is_anonymous` integer
|
|
||||||
);
|
|
||||||
--> statement-breakpoint
|
|
||||||
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
|
|
||||||
CREATE TABLE `user_document_progress` (
|
CREATE TABLE `user_document_progress` (
|
||||||
`user_id` text NOT NULL,
|
`user_id` text NOT NULL,
|
||||||
`document_id` text NOT NULL,
|
`document_id` text NOT NULL,
|
||||||
|
|
@ -131,9 +89,57 @@ CREATE TABLE `user_tts_chars` (
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
CREATE INDEX `idx_user_tts_chars_date` ON `user_tts_chars` (`date`);--> statement-breakpoint
|
CREATE INDEX `idx_user_tts_chars_date` ON `user_tts_chars` (`date`);--> statement-breakpoint
|
||||||
|
CREATE TABLE `account` (
|
||||||
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
|
`account_id` text NOT NULL,
|
||||||
|
`provider_id` text NOT NULL,
|
||||||
|
`user_id` text NOT NULL,
|
||||||
|
`access_token` text,
|
||||||
|
`refresh_token` text,
|
||||||
|
`id_token` text,
|
||||||
|
`access_token_expires_at` integer,
|
||||||
|
`refresh_token_expires_at` integer,
|
||||||
|
`scope` text,
|
||||||
|
`password` text,
|
||||||
|
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
|
||||||
|
`updated_at` integer NOT NULL,
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint
|
||||||
|
CREATE TABLE `session` (
|
||||||
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
|
`expires_at` integer NOT NULL,
|
||||||
|
`token` text NOT NULL,
|
||||||
|
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
|
||||||
|
`updated_at` integer NOT NULL,
|
||||||
|
`ip_address` text,
|
||||||
|
`user_agent` text,
|
||||||
|
`user_id` text NOT NULL,
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint
|
||||||
|
CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint
|
||||||
|
CREATE TABLE `user` (
|
||||||
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
|
`name` text NOT NULL,
|
||||||
|
`email` text NOT NULL,
|
||||||
|
`email_verified` integer DEFAULT false NOT NULL,
|
||||||
|
`image` text,
|
||||||
|
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
|
||||||
|
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
|
||||||
|
`is_anonymous` integer DEFAULT false
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint
|
||||||
CREATE TABLE `verification` (
|
CREATE TABLE `verification` (
|
||||||
`id` text PRIMARY KEY NOT NULL,
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
`identifier` text NOT NULL,
|
`identifier` text NOT NULL,
|
||||||
`value` text NOT NULL,
|
`value` text NOT NULL,
|
||||||
`updated_at` integer
|
`expires_at` integer NOT NULL,
|
||||||
|
`created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,
|
||||||
|
`updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL
|
||||||
);
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);
|
||||||
|
|
@ -1,124 +1,9 @@
|
||||||
{
|
{
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"id": "eb884adf-c9c7-494b-b0a1-3601f63bcbbe",
|
"id": "b45e86c4-7d98-4cfb-9b38-5d1423b17b5e",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"tables": {
|
"tables": {
|
||||||
"account": {
|
|
||||||
"name": "account",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"account_id": {
|
|
||||||
"name": "account_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"provider_id": {
|
|
||||||
"name": "provider_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"access_token": {
|
|
||||||
"name": "access_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"id_token": {
|
|
||||||
"name": "id_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"access_token_expires_at": {
|
|
||||||
"name": "access_token_expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"refresh_token_expires_at": {
|
|
||||||
"name": "refresh_token_expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"scope": {
|
|
||||||
"name": "scope",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"password": {
|
|
||||||
"name": "password",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"account_user_id_user_id_fk": {
|
|
||||||
"name": "account_user_id_user_id_fk",
|
|
||||||
"tableFrom": "account",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"checkConstraints": {}
|
|
||||||
},
|
|
||||||
"audiobook_chapters": {
|
"audiobook_chapters": {
|
||||||
"name": "audiobook_chapters",
|
"name": "audiobook_chapters",
|
||||||
"columns": {
|
"columns": {
|
||||||
|
|
@ -517,168 +402,6 @@
|
||||||
"uniqueConstraints": {},
|
"uniqueConstraints": {},
|
||||||
"checkConstraints": {}
|
"checkConstraints": {}
|
||||||
},
|
},
|
||||||
"session": {
|
|
||||||
"name": "session",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"expires_at": {
|
|
||||||
"name": "expires_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"token": {
|
|
||||||
"name": "token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"ip_address": {
|
|
||||||
"name": "ip_address",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"user_agent": {
|
|
||||||
"name": "user_agent",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"session_token_unique": {
|
|
||||||
"name": "session_token_unique",
|
|
||||||
"columns": [
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {
|
|
||||||
"session_user_id_user_id_fk": {
|
|
||||||
"name": "session_user_id_user_id_fk",
|
|
||||||
"tableFrom": "session",
|
|
||||||
"tableTo": "user",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"checkConstraints": {}
|
|
||||||
},
|
|
||||||
"user": {
|
|
||||||
"name": "user",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"email_verified": {
|
|
||||||
"name": "email_verified",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"autoincrement": false
|
|
||||||
},
|
|
||||||
"is_anonymous": {
|
|
||||||
"name": "is_anonymous",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"autoincrement": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {
|
|
||||||
"user_email_unique": {
|
|
||||||
"name": "user_email_unique",
|
|
||||||
"columns": [
|
|
||||||
"email"
|
|
||||||
],
|
|
||||||
"isUnique": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"checkConstraints": {}
|
|
||||||
},
|
|
||||||
"user_document_progress": {
|
"user_document_progress": {
|
||||||
"name": "user_document_progress",
|
"name": "user_document_progress",
|
||||||
"columns": {
|
"columns": {
|
||||||
|
|
@ -878,6 +601,304 @@
|
||||||
"uniqueConstraints": {},
|
"uniqueConstraints": {},
|
||||||
"checkConstraints": {}
|
"checkConstraints": {}
|
||||||
},
|
},
|
||||||
|
"account": {
|
||||||
|
"name": "account",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"account_id": {
|
||||||
|
"name": "account_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"provider_id": {
|
||||||
|
"name": "provider_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"access_token": {
|
||||||
|
"name": "access_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"refresh_token": {
|
||||||
|
"name": "refresh_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"id_token": {
|
||||||
|
"name": "id_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"access_token_expires_at": {
|
||||||
|
"name": "access_token_expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"refresh_token_expires_at": {
|
||||||
|
"name": "refresh_token_expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"name": "scope",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"name": "password",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"account_userId_idx": {
|
||||||
|
"name": "account_userId_idx",
|
||||||
|
"columns": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"isUnique": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"account_user_id_user_id_fk": {
|
||||||
|
"name": "account_user_id_user_id_fk",
|
||||||
|
"tableFrom": "account",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"session": {
|
||||||
|
"name": "session",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"name": "token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"ip_address": {
|
||||||
|
"name": "ip_address",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_agent": {
|
||||||
|
"name": "user_agent",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"session_token_unique": {
|
||||||
|
"name": "session_token_unique",
|
||||||
|
"columns": [
|
||||||
|
"token"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"session_userId_idx": {
|
||||||
|
"name": "session_userId_idx",
|
||||||
|
"columns": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"isUnique": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"session_user_id_user_id_fk": {
|
||||||
|
"name": "session_user_id_user_id_fk",
|
||||||
|
"tableFrom": "session",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email_verified": {
|
||||||
|
"name": "email_verified",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
},
|
||||||
|
"is_anonymous": {
|
||||||
|
"name": "is_anonymous",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"name": "verification",
|
"name": "verification",
|
||||||
"columns": {
|
"columns": {
|
||||||
|
|
@ -902,15 +923,39 @@
|
||||||
"notNull": true,
|
"notNull": true,
|
||||||
"autoincrement": false
|
"autoincrement": false
|
||||||
},
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
},
|
||||||
"updated_at": {
|
"updated_at": {
|
||||||
"name": "updated_at",
|
"name": "updated_at",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false,
|
"notNull": true,
|
||||||
"autoincrement": false
|
"autoincrement": false,
|
||||||
|
"default": "(cast(unixepoch('subsecond') * 1000 as integer))"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"verification_identifier_idx": {
|
||||||
|
"name": "verification_identifier_idx",
|
||||||
|
"columns": [
|
||||||
|
"identifier"
|
||||||
|
],
|
||||||
|
"isUnique": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
"foreignKeys": {},
|
||||||
"compositePrimaryKeys": {},
|
"compositePrimaryKeys": {},
|
||||||
"uniqueConstraints": {},
|
"uniqueConstraints": {},
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1770846273460,
|
"when": 1771184127967,
|
||||||
"tag": "0000_cool_gwen_stacy",
|
"tag": "0000_eager_rick_jones",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { auth } from '@/lib/server/auth';
|
import { auth } from '@/lib/server/auth';
|
||||||
import { db } from '@/db';
|
|
||||||
import { user } from '@/db/schema';
|
|
||||||
import { eq } from 'drizzle-orm';
|
|
||||||
import { isAuthEnabled } from '@/lib/server/auth-config';
|
import { isAuthEnabled } from '@/lib/server/auth-config';
|
||||||
|
|
||||||
export async function DELETE() {
|
export async function DELETE() {
|
||||||
|
|
@ -20,9 +17,11 @@ export async function DELETE() {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Directly delete user from database
|
// Use Better Auth's built-in deleteUser to handle cascading cleanup
|
||||||
// Drizzle will handle cascade if configured in foreign keys, but typical cascading happens in DB engine
|
await auth.api.deleteUser({
|
||||||
await db.delete(user).where(eq(user.id, session.user.id));
|
headers: await headers(),
|
||||||
|
body: {},
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,13 @@ import Database from 'better-sqlite3';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as schema from './schema';
|
import * as schema from './schema';
|
||||||
|
import * as authSchemaSqlite from './schema_auth_sqlite';
|
||||||
|
import * as authSchemaPostgres from './schema_auth_postgres';
|
||||||
|
|
||||||
// Singleton logic not strictly needed if Next.js handles module caching, but good for safety
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
let dbInstance: any = null;
|
let dbInstance: any = null;
|
||||||
|
|
||||||
export function getDrizzleDB() {
|
function getDrizzleDB() {
|
||||||
if (dbInstance) return dbInstance;
|
if (dbInstance) return dbInstance;
|
||||||
|
|
||||||
if (process.env.POSTGRES_URL) {
|
if (process.env.POSTGRES_URL) {
|
||||||
|
|
@ -18,7 +19,7 @@ export function getDrizzleDB() {
|
||||||
connectionString: process.env.POSTGRES_URL,
|
connectionString: process.env.POSTGRES_URL,
|
||||||
ssl: process.env.NODE_ENV === "production" ? { rejectUnauthorized: false } : false,
|
ssl: process.env.NODE_ENV === "production" ? { rejectUnauthorized: false } : false,
|
||||||
});
|
});
|
||||||
dbInstance = drizzlePg(pool, { schema });
|
dbInstance = drizzlePg(pool, { schema: { ...schema, ...authSchemaPostgres } });
|
||||||
} else {
|
} else {
|
||||||
// Fallback to SQLite
|
// Fallback to SQLite
|
||||||
const dbPath = path.join(process.cwd(), 'docstore', 'sqlite3.db');
|
const dbPath = path.join(process.cwd(), 'docstore', 'sqlite3.db');
|
||||||
|
|
@ -27,10 +28,20 @@ export function getDrizzleDB() {
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
const sqlite = new Database(dbPath);
|
const sqlite = new Database(dbPath);
|
||||||
dbInstance = drizzleSqlite(sqlite, { schema });
|
dbInstance = drizzleSqlite(sqlite, { schema: { ...schema, ...authSchemaSqlite } });
|
||||||
}
|
}
|
||||||
|
|
||||||
return dbInstance;
|
return dbInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const db = getDrizzleDB();
|
// Lazy proxy: the actual DB connection is only opened on first property access.
|
||||||
|
// This prevents side effects (e.g. creating an empty sqlite3.db) when modules
|
||||||
|
// import `db` but never use it, such as during Better Auth CLI schema generation.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
export const db: any = new Proxy({} as any, {
|
||||||
|
get(_target, prop, receiver) {
|
||||||
|
const instance = getDrizzleDB();
|
||||||
|
const value = Reflect.get(instance, prop, receiver);
|
||||||
|
return typeof value === 'function' ? value.bind(instance) : value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,12 @@ import * as postgresSchema from './schema_postgres';
|
||||||
|
|
||||||
const usePostgres = !!process.env.POSTGRES_URL;
|
const usePostgres = !!process.env.POSTGRES_URL;
|
||||||
|
|
||||||
// Export the correct table variants dynamically
|
// Auth tables (user, session, account, verification) are managed by Better Auth
|
||||||
|
// and are NOT part of the Drizzle schema. Only app-specific tables are exported here.
|
||||||
|
|
||||||
export const documents = usePostgres ? postgresSchema.documents : sqliteSchema.documents;
|
export const documents = usePostgres ? postgresSchema.documents : sqliteSchema.documents;
|
||||||
export const audiobooks = usePostgres ? postgresSchema.audiobooks : sqliteSchema.audiobooks;
|
export const audiobooks = usePostgres ? postgresSchema.audiobooks : sqliteSchema.audiobooks;
|
||||||
export const audiobookChapters = usePostgres ? postgresSchema.audiobookChapters : sqliteSchema.audiobookChapters;
|
export const audiobookChapters = usePostgres ? postgresSchema.audiobookChapters : sqliteSchema.audiobookChapters;
|
||||||
export const user = usePostgres ? postgresSchema.user : sqliteSchema.user;
|
|
||||||
export const session = usePostgres ? postgresSchema.session : sqliteSchema.session;
|
|
||||||
export const account = usePostgres ? postgresSchema.account : sqliteSchema.account;
|
|
||||||
export const verification = usePostgres ? postgresSchema.verification : sqliteSchema.verification;
|
|
||||||
export const userTtsChars = usePostgres ? postgresSchema.userTtsChars : sqliteSchema.userTtsChars;
|
export const userTtsChars = usePostgres ? postgresSchema.userTtsChars : sqliteSchema.userTtsChars;
|
||||||
export const userPreferences = usePostgres ? postgresSchema.userPreferences : sqliteSchema.userPreferences;
|
export const userPreferences = usePostgres ? postgresSchema.userPreferences : sqliteSchema.userPreferences;
|
||||||
export const userDocumentProgress = usePostgres ? postgresSchema.userDocumentProgress : sqliteSchema.userDocumentProgress;
|
export const userDocumentProgress = usePostgres ? postgresSchema.userDocumentProgress : sqliteSchema.userDocumentProgress;
|
||||||
|
|
|
||||||
94
src/db/schema_auth_postgres.ts
Normal file
94
src/db/schema_auth_postgres.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import { relations } from "drizzle-orm";
|
||||||
|
import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
|
export const user = pgTable("user", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: boolean("email_verified").default(false).notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
isAnonymous: boolean("is_anonymous").default(false),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const session = pgTable(
|
||||||
|
"session",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id, { onDelete: "cascade" }),
|
||||||
|
},
|
||||||
|
(table) => [index("session_userId_idx").on(table.userId)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const account = pgTable(
|
||||||
|
"account",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id, { onDelete: "cascade" }),
|
||||||
|
accessToken: text("access_token"),
|
||||||
|
refreshToken: text("refresh_token"),
|
||||||
|
idToken: text("id_token"),
|
||||||
|
accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
||||||
|
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
||||||
|
scope: text("scope"),
|
||||||
|
password: text("password"),
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index("account_userId_idx").on(table.userId)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const verification = pgTable(
|
||||||
|
"verification",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
identifier: text("identifier").notNull(),
|
||||||
|
value: text("value").notNull(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index("verification_identifier_idx").on(table.identifier)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const userRelations = relations(user, ({ many }) => ({
|
||||||
|
sessions: many(session),
|
||||||
|
accounts: many(account),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const sessionRelations = relations(session, ({ one }) => ({
|
||||||
|
user: one(user, {
|
||||||
|
fields: [session.userId],
|
||||||
|
references: [user.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const accountRelations = relations(account, ({ one }) => ({
|
||||||
|
user: one(user, {
|
||||||
|
fields: [account.userId],
|
||||||
|
references: [user.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
108
src/db/schema_auth_sqlite.ts
Normal file
108
src/db/schema_auth_sqlite.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
import { relations, sql } from "drizzle-orm";
|
||||||
|
import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const user = sqliteTable("user", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: integer("email_verified", { mode: "boolean" })
|
||||||
|
.default(false)
|
||||||
|
.notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
isAnonymous: integer("is_anonymous", { mode: "boolean" }).default(false),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const session = sqliteTable(
|
||||||
|
"session",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id, { onDelete: "cascade" }),
|
||||||
|
},
|
||||||
|
(table) => [index("session_userId_idx").on(table.userId)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const account = sqliteTable(
|
||||||
|
"account",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id, { onDelete: "cascade" }),
|
||||||
|
accessToken: text("access_token"),
|
||||||
|
refreshToken: text("refresh_token"),
|
||||||
|
idToken: text("id_token"),
|
||||||
|
accessTokenExpiresAt: integer("access_token_expires_at", {
|
||||||
|
mode: "timestamp_ms",
|
||||||
|
}),
|
||||||
|
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
|
||||||
|
mode: "timestamp_ms",
|
||||||
|
}),
|
||||||
|
scope: text("scope"),
|
||||||
|
password: text("password"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index("account_userId_idx").on(table.userId)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const verification = sqliteTable(
|
||||||
|
"verification",
|
||||||
|
{
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
identifier: text("identifier").notNull(),
|
||||||
|
value: text("value").notNull(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
|
||||||
|
.default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
},
|
||||||
|
(table) => [index("verification_identifier_idx").on(table.identifier)],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const userRelations = relations(user, ({ many }) => ({
|
||||||
|
sessions: many(session),
|
||||||
|
accounts: many(account),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const sessionRelations = relations(session, ({ one }) => ({
|
||||||
|
user: one(user, {
|
||||||
|
fields: [session.userId],
|
||||||
|
references: [user.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const accountRelations = relations(account, ({ one }) => ({
|
||||||
|
user: one(user, {
|
||||||
|
fields: [account.userId],
|
||||||
|
references: [user.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { pgTable, text, integer, real, boolean, timestamp, date, bigint, primaryKey, index, jsonb } from 'drizzle-orm/pg-core';
|
import { pgTable, text, integer, real, timestamp, date, bigint, primaryKey, index, jsonb } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
export const documents = pgTable('documents', {
|
export const documents = pgTable('documents', {
|
||||||
id: text('id').notNull(),
|
id: text('id').notNull(),
|
||||||
|
|
@ -41,50 +41,9 @@ export const audiobookChapters = pgTable('audiobook_chapters', {
|
||||||
pk: primaryKey({ columns: [table.id, table.userId] }),
|
pk: primaryKey({ columns: [table.id, table.userId] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const user = pgTable("user", {
|
// Auth tables (user, session, account, verification) are managed by Better Auth.
|
||||||
id: text("id").primaryKey(),
|
// They are created/migrated via `@better-auth/cli migrate` and should NOT be
|
||||||
name: text('name').notNull(),
|
// defined here. Only application-specific tables belong in this file.
|
||||||
email: text('email').notNull().unique(),
|
|
||||||
emailVerified: boolean('email_verified').notNull(),
|
|
||||||
image: text('image'),
|
|
||||||
createdAt: timestamp('created_at').notNull(),
|
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
|
||||||
isAnonymous: boolean('is_anonymous'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const session = pgTable("session", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
expiresAt: timestamp('expires_at').notNull(),
|
|
||||||
token: text('token').notNull().unique(),
|
|
||||||
createdAt: timestamp('created_at').notNull(),
|
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
|
||||||
ipAddress: text('ip_address'),
|
|
||||||
userAgent: text('user_agent'),
|
|
||||||
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' })
|
|
||||||
});
|
|
||||||
|
|
||||||
export const account = pgTable("account", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
accountId: text('account_id').notNull(),
|
|
||||||
providerId: text('provider_id').notNull(),
|
|
||||||
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
|
|
||||||
accessToken: text('access_token'),
|
|
||||||
refreshToken: text('refresh_token'),
|
|
||||||
idToken: text('id_token'),
|
|
||||||
accessTokenExpiresAt: timestamp('access_token_expires_at'),
|
|
||||||
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
|
|
||||||
scope: text('scope'),
|
|
||||||
password: text('password'),
|
|
||||||
createdAt: timestamp('created_at').notNull(),
|
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const verification = pgTable("verification", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
identifier: text('identifier').notNull(),
|
|
||||||
value: text('value').notNull(),
|
|
||||||
updatedAt: timestamp('updated_at'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const userTtsChars = pgTable("user_tts_chars", {
|
export const userTtsChars = pgTable("user_tts_chars", {
|
||||||
userId: text('user_id').notNull(),
|
userId: text('user_id').notNull(),
|
||||||
|
|
|
||||||
|
|
@ -42,50 +42,9 @@ export const audiobookChapters = sqliteTable('audiobook_chapters', {
|
||||||
pk: primaryKey({ columns: [table.id, table.userId] }),
|
pk: primaryKey({ columns: [table.id, table.userId] }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const user = sqliteTable("user", {
|
// Auth tables (user, session, account, verification) are managed by Better Auth.
|
||||||
id: text("id").primaryKey(),
|
// They are created/migrated via `@better-auth/cli migrate` and should NOT be
|
||||||
name: text('name').notNull(),
|
// defined here. Only application-specific tables belong in this file.
|
||||||
email: text('email').notNull().unique(),
|
|
||||||
emailVerified: integer('email_verified', { mode: 'boolean' }).notNull(),
|
|
||||||
image: text('image'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
isAnonymous: integer('is_anonymous', { mode: 'boolean' }),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const session = sqliteTable("session", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
token: text('token').notNull().unique(),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
ipAddress: text('ip_address'),
|
|
||||||
userAgent: text('user_agent'),
|
|
||||||
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' })
|
|
||||||
});
|
|
||||||
|
|
||||||
export const account = sqliteTable("account", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
accountId: text('account_id').notNull(),
|
|
||||||
providerId: text('provider_id').notNull(),
|
|
||||||
userId: text('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }),
|
|
||||||
accessToken: text('access_token'),
|
|
||||||
refreshToken: text('refresh_token'),
|
|
||||||
idToken: text('id_token'),
|
|
||||||
accessTokenExpiresAt: integer('access_token_expires_at', { mode: 'timestamp' }),
|
|
||||||
refreshTokenExpiresAt: integer('refresh_token_expires_at', { mode: 'timestamp' }),
|
|
||||||
scope: text('scope'),
|
|
||||||
password: text('password'),
|
|
||||||
createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const verification = sqliteTable("verification", {
|
|
||||||
id: text("id").primaryKey(),
|
|
||||||
identifier: text('identifier').notNull(),
|
|
||||||
value: text('value').notNull(),
|
|
||||||
updatedAt: integer('updated_at', { mode: 'timestamp' }),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const userTtsChars = sqliteTable("user_tts_chars", {
|
export const userTtsChars = sqliteTable("user_tts_chars", {
|
||||||
userId: text('user_id').notNull(),
|
userId: text('user_id').notNull(),
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import type { NextRequest } from 'next/server';
|
||||||
import { db } from "@/db";
|
import { db } from "@/db";
|
||||||
import { rateLimiter } from "@/lib/server/rate-limiter";
|
import { rateLimiter } from "@/lib/server/rate-limiter";
|
||||||
import { isAuthEnabled, isAnonymousAuthSessionsEnabled } from "@/lib/server/auth-config";
|
import { isAuthEnabled, isAnonymousAuthSessionsEnabled } from "@/lib/server/auth-config";
|
||||||
|
import * as authSchemaSqlite from "@/db/schema_auth_sqlite";
|
||||||
|
import * as authSchemaPostgres from "@/db/schema_auth_postgres";
|
||||||
import {
|
import {
|
||||||
transferUserAudiobooks,
|
transferUserAudiobooks,
|
||||||
transferUserDocuments,
|
transferUserDocuments,
|
||||||
|
|
@ -14,8 +16,6 @@ import {
|
||||||
transferUserProgress,
|
transferUserProgress,
|
||||||
} from "@/lib/server/claim-data";
|
} from "@/lib/server/claim-data";
|
||||||
|
|
||||||
import * as schema from "@/db/schema"; // Import the dynamic schema
|
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
function tryGetOrigin(url: string | undefined): string | null {
|
function tryGetOrigin(url: string | undefined): string | null {
|
||||||
|
|
@ -55,17 +55,13 @@ function envFlagEnabled(name: string, defaultValue: boolean): boolean {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const authSchema = process.env.POSTGRES_URL ? authSchemaPostgres : authSchemaSqlite;
|
||||||
|
|
||||||
const createAuth = () => betterAuth({
|
const createAuth = () => betterAuth({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
database: drizzleAdapter(db as any, {
|
database: drizzleAdapter(db as any, {
|
||||||
provider: process.env.POSTGRES_URL ? "pg" : "sqlite", // Dynamic provider
|
provider: process.env.POSTGRES_URL ? "pg" : "sqlite",
|
||||||
schema: {
|
schema: authSchema as Record<string, unknown>,
|
||||||
...schema,
|
|
||||||
user: schema.user,
|
|
||||||
session: schema.session,
|
|
||||||
account: schema.account,
|
|
||||||
verification: schema.verification,
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
secret: process.env.AUTH_SECRET!,
|
secret: process.env.AUTH_SECRET!,
|
||||||
baseURL: process.env.BASE_URL!,
|
baseURL: process.env.BASE_URL!,
|
||||||
|
|
@ -78,6 +74,11 @@ const createAuth = () => betterAuth({
|
||||||
console.log("Password reset requested for:", data.user.email);
|
console.log("Password reset requested for:", data.user.email);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
user: {
|
||||||
|
deleteUser: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
rateLimit: {
|
rateLimit: {
|
||||||
// Better Auth built-in rate limiting is enabled by default.
|
// Better Auth built-in rate limiting is enabled by default.
|
||||||
// Set DISABLE_AUTH_RATE_LIMIT=true to disable it.
|
// Set DISABLE_AUTH_RATE_LIMIT=true to disable it.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue