update dependencies, fix type issues in auth, add migrations for missing indexes

This commit is contained in:
Amruth Pillai
2026-03-18 10:42:08 +01:00
parent d8ffd00fa6
commit 1d7c4b2615
14 changed files with 3917 additions and 39 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
const nextPackages = ["@monaco-editor/react"];
const betaPackages = ["drizzle-orm", "drizzle-kit"];
const betaPackages = ["drizzle-orm", "drizzle-kit", "drizzle-zod"];
/** @type {import('npm-check-updates').RunOptions} */
module.exports = {
@@ -0,0 +1,2 @@
ALTER TABLE "user" ADD COLUMN "last_active_at" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "apikey" ALTER COLUMN "config_id" SET DEFAULT 'default';
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
ALTER TABLE "apikey" ALTER COLUMN "rate_limit_time_window" SET DEFAULT 86400000;--> statement-breakpoint
ALTER TABLE "apikey" ALTER COLUMN "rate_limit_max" SET DEFAULT 10;--> statement-breakpoint
ALTER TABLE "two_factor" ALTER COLUMN "secret" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "two_factor" ALTER COLUMN "backup_codes" SET NOT NULL;--> statement-breakpoint
CREATE INDEX "apikey_config_id_index" ON "apikey" ("config_id");--> statement-breakpoint
CREATE INDEX "verification_identifier_index" ON "verification" ("identifier");
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -81,7 +81,7 @@
"cmdk": "^1.1.1",
"dompurify": "^3.3.3",
"drizzle-orm": "1.0.0-beta.18-7eb39f0",
"drizzle-zod": "^0.8.3",
"drizzle-zod": "^1.0.0-beta.14-a36c63d",
"es-toolkit": "^1.45.1",
"fast-deep-equal": "^3.1.3",
"fast-json-patch": "^3.1.1",
+6 -6
View File
@@ -172,8 +172,8 @@ importers:
specifier: 1.0.0-beta.18-7eb39f0
version: 1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6)
drizzle-zod:
specifier: ^0.8.3
version: 0.8.3(drizzle-orm@1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6))(zod@4.3.6)
specifier: ^1.0.0-beta.14-a36c63d
version: 1.0.0-beta.9-e89174b(drizzle-orm@1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6))(zod@4.3.6)
es-toolkit:
specifier: ^1.45.1
version: 1.45.1
@@ -4520,10 +4520,10 @@ packages:
zod:
optional: true
drizzle-zod@0.8.3:
resolution: {integrity: sha512-66yVOuvGhKJnTdiqj1/Xaaz9/qzOdRJADpDa68enqS6g3t0kpNkwNYjUuaeXgZfO/UWuIM9HIhSlJ6C5ZraMww==}
drizzle-zod@1.0.0-beta.9-e89174b:
resolution: {integrity: sha512-dnEHqeFk5KHuC5sqYEbXxk0FXcijiYRtLwI2/p/z4AclfyGBOcnCAakoVwbOdNHrF0emlc6ufyRl0NffVP1XRw==}
peerDependencies:
drizzle-orm: '>=0.36.0'
drizzle-orm: '>=1.0.0-beta.2'
zod: ^3.25.0 || ^4.0.0
dunder-proto@1.0.1:
@@ -12228,7 +12228,7 @@ snapshots:
valibot: 1.2.0(typescript@5.9.3)
zod: 4.3.6
drizzle-zod@0.8.3(drizzle-orm@1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6))(zod@4.3.6):
drizzle-zod@1.0.0-beta.9-e89174b(drizzle-orm@1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6))(zod@4.3.6):
dependencies:
drizzle-orm: 1.0.0-beta.18-7eb39f0(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(@types/pg@8.18.0)(mssql@11.0.1(@azure/core-client@1.10.1))(mysql2@3.15.3)(pg@8.20.0)(postgres@3.4.7)(valibot@1.2.0(typescript@5.9.3))(zod@4.3.6)
zod: 4.3.6
+1 -1
View File
@@ -64,7 +64,7 @@ export function UserDropdownMenu({ children }: Props) {
return (
<DropdownMenu>
<DropdownMenuTrigger render={children({ session })} />
<DropdownMenuTrigger render={children({ session: session as AuthSession })} />
<DropdownMenuContent align="start" side="top">
<DropdownMenuGroup>
+2 -2
View File
@@ -1,5 +1,5 @@
import { apiKeyClient } from "@better-auth/api-key/client";
import { sentinelClient } from "@better-auth/infra/client";
import { dashClient } from "@better-auth/infra/client";
import { genericOAuthClient, inferAdditionalFields, twoFactorClient, usernameClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import type { auth } from "./config";
@@ -7,8 +7,8 @@ import type { auth } from "./config";
const getAuthClient = () => {
return createAuthClient({
plugins: [
dashClient(),
apiKeyClient(),
sentinelClient(),
usernameClient(),
twoFactorClient({
onTwoFactorRedirect() {
+3 -2
View File
@@ -8,11 +8,11 @@ import { genericOAuth } from "better-auth/plugins/generic-oauth";
import { twoFactor } from "better-auth/plugins/two-factor";
import { username } from "better-auth/plugins/username";
import { and, eq, or } from "drizzle-orm";
import { db } from "@/integrations/drizzle/client";
import { env } from "@/utils/env";
import { hashPassword, verifyPassword } from "@/utils/password";
import { generateId, toUsername } from "@/utils/string";
import { schema } from "../drizzle";
import { db } from "../drizzle/client";
import { sendEmail } from "../email/service";
function isCustomOAuthProviderEnabled() {
@@ -90,6 +90,7 @@ const getAuthConfig = () => {
telemetry: { enabled: false },
trustedOrigins: getTrustedOrigins(),
advanced: {
database: { generateId },
useSecureCookies: env.APP_URL.startsWith("https://"),
@@ -234,8 +235,8 @@ const getAuthConfig = () => {
openAPI(),
genericOAuth({ config: authConfigs }),
twoFactor({ issuer: "Reactive Resume" }),
dash({ apiKey: env.BETTER_AUTH_API_KEY }),
apiKey({ enableSessionForAPIKeys: true, rateLimit: { enabled: false } }),
dash({ apiKey: env.BETTER_AUTH_API_KEY, activityTracking: { enabled: true } }),
username({
minUsernameLength: 3,
maxUsernameLength: 64,
+1 -1
View File
@@ -8,7 +8,7 @@ export const getSession = createIsomorphicFn()
.client(async (): Promise<AuthSession | null> => {
const { data, error } = await authClient.getSession();
if (error) return null;
return data;
return data as AuthSession;
})
.server(async (): Promise<AuthSession | null> => {
const result = await auth.api.getSession({ headers: getRequestHeaders() });
+1 -3
View File
@@ -3,9 +3,7 @@ import type { auth } from "./config";
export type AuthSession = {
session: typeof auth.$Infer.Session.session;
user: typeof auth.$Infer.Session.user & {
name: string;
};
user: typeof auth.$Infer.Session.user;
};
const authProviderSchema = z.enum(["credential", "google", "github", "custom"]);
+1 -1
View File
@@ -1,8 +1,8 @@
import { createServerOnlyFn } from "@tanstack/react-start";
import { drizzle, type NodePgDatabase } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { schema } from "@/integrations/drizzle";
import { env } from "@/utils/env";
import * as schema from "./schema";
// During hot reload (i.e., in development), global assignment ensures the pool/client persist across reloads.
// This prevents exhausting connection limits due to re-creation on every reload.
+92 -21
View File
@@ -1,3 +1,4 @@
import { defineRelations } from "drizzle-orm";
import * as pg from "drizzle-orm/pg-core";
import { defaultResumeData, type ResumeData } from "../../schema/resume/data";
import { generateId } from "../../utils/string";
@@ -17,6 +18,7 @@ export const user = pg.pgTable(
username: pg.text("username").notNull().unique(),
displayUsername: pg.text("display_username").notNull().unique(),
twoFactorEnabled: pg.boolean("two_factor_enabled").notNull().default(false),
lastActiveAt: pg.timestamp("last_active_at", { withTimezone: true }),
createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: pg
.timestamp("updated_at", { withTimezone: true })
@@ -84,22 +86,26 @@ export const account = pg.pgTable(
(t) => [pg.index().on(t.userId)],
);
export const verification = pg.pgTable("verification", {
id: pg
.uuid("id")
.notNull()
.primaryKey()
.$defaultFn(() => generateId()),
identifier: pg.text("identifier").notNull().unique(),
value: pg.text("value").notNull(),
expiresAt: pg.timestamp("expires_at", { withTimezone: true }).notNull(),
createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: pg
.timestamp("updated_at", { withTimezone: true })
.notNull()
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date()),
});
export const verification = pg.pgTable(
"verification",
{
id: pg
.uuid("id")
.notNull()
.primaryKey()
.$defaultFn(() => generateId()),
identifier: pg.text("identifier").notNull().unique(),
value: pg.text("value").notNull(),
expiresAt: pg.timestamp("expires_at", { withTimezone: true }).notNull(),
createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: pg
.timestamp("updated_at", { withTimezone: true })
.notNull()
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date()),
},
(t) => [pg.index().on(t.identifier)],
);
export const twoFactor = pg.pgTable(
"two_factor",
@@ -113,8 +119,8 @@ export const twoFactor = pg.pgTable(
.uuid("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
secret: pg.text("secret"),
backupCodes: pg.text("backup_codes"),
secret: pg.text("secret").notNull(),
backupCodes: pg.text("backup_codes").notNull(),
createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
updatedAt: pg
.timestamp("updated_at", { withTimezone: true })
@@ -239,8 +245,8 @@ export const apikey = pg.pgTable(
lastRefillAt: pg.timestamp("last_refill_at", { withTimezone: true }),
enabled: pg.boolean("enabled").notNull().default(true),
rateLimitEnabled: pg.boolean("rate_limit_enabled").notNull().default(false),
rateLimitTimeWindow: pg.integer("rate_limit_time_window"),
rateLimitMax: pg.integer("rate_limit_max"),
rateLimitTimeWindow: pg.integer("rate_limit_time_window").default(86400000),
rateLimitMax: pg.integer("rate_limit_max").default(10),
requestCount: pg.integer("request_count").notNull().default(0),
remaining: pg.integer("remaining"),
lastRequest: pg.timestamp("last_request", { withTimezone: true }),
@@ -254,5 +260,70 @@ export const apikey = pg.pgTable(
permissions: pg.text("permissions"),
metadata: pg.jsonb("metadata"),
},
(t) => [pg.index().on(t.referenceId), pg.index().on(t.key), pg.index().on(t.enabled, t.referenceId)],
(t) => [
pg.index().on(t.referenceId),
pg.index().on(t.key),
pg.index().on(t.configId),
pg.index().on(t.enabled, t.referenceId),
],
);
export const relations = defineRelations(
{ user, session, account, verification, twoFactor, passkey, resume, resumeStatistics, apikey },
(r) => ({
user: {
sessions: r.many.session(),
accounts: r.many.account(),
twoFactors: r.many.twoFactor(),
passkeys: r.many.passkey(),
resumes: r.many.resume(),
apiKeys: r.many.apikey(),
},
session: {
user: r.one.user({
from: r.session.userId,
to: r.user.id,
}),
},
account: {
user: r.one.user({
from: r.account.userId,
to: r.user.id,
}),
},
twoFactor: {
user: r.one.user({
from: r.twoFactor.userId,
to: r.user.id,
}),
},
passkey: {
user: r.one.user({
from: r.passkey.userId,
to: r.user.id,
}),
},
resume: {
user: r.one.user({
from: r.resume.userId,
to: r.user.id,
}),
statistics: r.one.resumeStatistics({
from: r.resume.id,
to: r.resumeStatistics.resumeId,
}),
},
resumeStatistics: {
resume: r.one.resume({
from: r.resumeStatistics.resumeId,
to: r.resume.id,
}),
},
apikey: {
user: r.one.user({
from: r.apikey.referenceId,
to: r.user.id,
}),
},
}),
);