style: 统一代码风格 — 格式化 auth schema、修复 setup 页面 return 语句、规范 drizzle snapshot

This commit is contained in:
2026-03-31 22:46:47 +08:00
parent 9f39e7f7e8
commit dcccf6675f
4 changed files with 151 additions and 172 deletions
+13 -37
View File
@@ -110,12 +110,8 @@
"name": "account_user_id_user_id_fk", "name": "account_user_id_user_id_fk",
"tableFrom": "account", "tableFrom": "account",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -202,12 +198,8 @@
"name": "session_user_id_user_id_fk", "name": "session_user_id_user_id_fk",
"tableFrom": "session", "tableFrom": "session",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -217,9 +209,7 @@
"session_token_unique": { "session_token_unique": {
"name": "session_token_unique", "name": "session_token_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["token"]
"token"
]
} }
}, },
"policies": {}, "policies": {},
@@ -283,9 +273,7 @@
"user_email_unique": { "user_email_unique": {
"name": "user_email_unique", "name": "user_email_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["email"]
"email"
]
} }
}, },
"policies": {}, "policies": {},
@@ -434,12 +422,8 @@
"name": "bookmark_category_id_category_id_fk", "name": "bookmark_category_id_category_id_fk",
"tableFrom": "bookmark", "tableFrom": "bookmark",
"tableTo": "category", "tableTo": "category",
"columnsFrom": [ "columnsFrom": ["category_id"],
"category_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -447,12 +431,8 @@
"name": "bookmark_user_id_user_id_fk", "name": "bookmark_user_id_user_id_fk",
"tableFrom": "bookmark", "tableFrom": "bookmark",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -527,12 +507,8 @@
"name": "category_user_id_user_id_fk", "name": "category_user_id_user_id_fk",
"tableFrom": "category", "tableFrom": "category",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -555,4 +531,4 @@
"schemas": {}, "schemas": {},
"tables": {} "tables": {}
} }
} }
+1 -1
View File
@@ -10,4 +10,4 @@
"breakpoints": true "breakpoints": true
} }
] ]
} }
+85 -82
View File
@@ -52,90 +52,93 @@ function SetupPage() {
router.navigate({ to: '/' as never }) router.navigate({ to: '/' as never })
} }
;<div className="min-h-screen bg-slate-50 flex items-center justify-center px-4">
<div className="w-full max-w-md">
<div className="text-center mb-8">
<h1 className="text-4xl font-bold text-slate-900 tracking-tight">Kairos</h1>
<p className="text-slate-500 mt-2"></p>
</div>
<div className="bg-white rounded-2xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-slate-100 p-8"> return (
<form onSubmit={handleSubmit} className="space-y-5"> <div className="min-h-screen bg-slate-50 flex items-center justify-center px-4">
<div> <div className="w-full max-w-md">
<label htmlFor="name" className="block text-sm font-medium text-slate-700 mb-1.5"> <div className="text-center mb-8">
<h1 className="text-4xl font-bold text-slate-900 tracking-tight">Kairos</h1>
</label> <p className="text-slate-500 mt-2"></p>
<input </div>
id="name"
type="text" <div className="bg-white rounded-2xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-slate-100 p-8">
required <form onSubmit={handleSubmit} className="space-y-5">
value={name} <div>
onChange={(e) => setName(e.target.value)} <label htmlFor="name" className="block text-sm font-medium text-slate-700 mb-1.5">
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="你的名字" </label>
<input
id="name"
type="text"
required
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="你的名字"
disabled={loading}
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-slate-700 mb-1.5">
</label>
<input
id="email"
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="your@email.com"
disabled={loading}
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-slate-700 mb-1.5">
</label>
<input
id="password"
type="password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="至少 8 个字符"
disabled={loading}
/>
</div>
<div>
<label htmlFor="confirmPassword" className="block text-sm font-medium text-slate-700 mb-1.5">
</label>
<input
id="confirmPassword"
type="password"
required
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="再次输入密码"
disabled={loading}
/>
</div>
{error && <p className="text-sm text-red-600">{error}</p>}
<button
type="submit"
disabled={loading} disabled={loading}
/> className="w-full py-3 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-medium transition-all shadow-md shadow-indigo-200 disabled:opacity-50 disabled:shadow-none hover:shadow-lg hover:shadow-indigo-300 active:scale-[0.98]"
</div> >
{loading ? '初始化中...' : '开始使用 Kairos'}
<div> </button>
<label htmlFor="email" className="block text-sm font-medium text-slate-700 mb-1.5"> </form>
</div>
</label>
<input
id="email"
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="your@email.com"
disabled={loading}
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-slate-700 mb-1.5">
</label>
<input
id="password"
type="password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="至少 8 个字符"
disabled={loading}
/>
</div>
<div>
<label htmlFor="confirmPassword" className="block text-sm font-medium text-slate-700 mb-1.5">
</label>
<input
id="confirmPassword"
type="password"
required
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
placeholder="再次输入密码"
disabled={loading}
/>
</div>
{error && <p className="text-sm text-red-600">{error}</p>}
<button
type="submit"
disabled={loading}
className="w-full py-3 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-medium transition-all shadow-md shadow-indigo-200 disabled:opacity-50 disabled:shadow-none hover:shadow-lg hover:shadow-indigo-300 active:scale-[0.98]"
>
{loading ? '初始化中...' : '开始使用 Kairos'}
</button>
</form>
</div> </div>
</div> </div>
</div> )
} }
+52 -52
View File
@@ -1,93 +1,93 @@
import { relations } from "drizzle-orm"; import { relations } from 'drizzle-orm'
import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core"; import { boolean, index, pgTable, text, timestamp } from 'drizzle-orm/pg-core'
export const user = pgTable("user", { export const user = pgTable('user', {
id: text("id").primaryKey(), id: text('id').primaryKey(),
name: text("name").notNull(), name: text('name').notNull(),
email: text("email").notNull().unique(), email: text('email').notNull().unique(),
emailVerified: boolean("email_verified").default(false).notNull(), emailVerified: boolean('email_verified').default(false).notNull(),
image: text("image"), image: text('image'),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp("updated_at") updatedAt: timestamp('updated_at')
.defaultNow() .defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date()) .$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(), .notNull(),
}); })
export const session = pgTable( export const session = pgTable(
"session", 'session',
{ {
id: text("id").primaryKey(), id: text('id').primaryKey(),
expiresAt: timestamp("expires_at").notNull(), expiresAt: timestamp('expires_at').notNull(),
token: text("token").notNull().unique(), token: text('token').notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp("updated_at") updatedAt: timestamp('updated_at')
.$onUpdate(() => /* @__PURE__ */ new Date()) .$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(), .notNull(),
ipAddress: text("ip_address"), ipAddress: text('ip_address'),
userAgent: text("user_agent"), userAgent: text('user_agent'),
userId: text("user_id") userId: text('user_id')
.notNull() .notNull()
.references(() => user.id, { onDelete: "cascade" }), .references(() => user.id, { onDelete: 'cascade' }),
}, },
(table) => [index("session_userId_idx").on(table.userId)], (table) => [index('session_userId_idx').on(table.userId)],
); )
export const account = pgTable( export const account = pgTable(
"account", 'account',
{ {
id: text("id").primaryKey(), id: text('id').primaryKey(),
accountId: text("account_id").notNull(), accountId: text('account_id').notNull(),
providerId: text("provider_id").notNull(), providerId: text('provider_id').notNull(),
userId: text("user_id") userId: text('user_id')
.notNull() .notNull()
.references(() => user.id, { onDelete: "cascade" }), .references(() => user.id, { onDelete: 'cascade' }),
accessToken: text("access_token"), accessToken: text('access_token'),
refreshToken: text("refresh_token"), refreshToken: text('refresh_token'),
idToken: text("id_token"), idToken: text('id_token'),
accessTokenExpiresAt: timestamp("access_token_expires_at"), accessTokenExpiresAt: timestamp('access_token_expires_at'),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
scope: text("scope"), scope: text('scope'),
password: text("password"), password: text('password'),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp("updated_at") updatedAt: timestamp('updated_at')
.$onUpdate(() => /* @__PURE__ */ new Date()) .$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(), .notNull(),
}, },
(table) => [index("account_userId_idx").on(table.userId)], (table) => [index('account_userId_idx').on(table.userId)],
); )
export const verification = pgTable( export const verification = pgTable(
"verification", 'verification',
{ {
id: text("id").primaryKey(), id: text('id').primaryKey(),
identifier: text("identifier").notNull(), identifier: text('identifier').notNull(),
value: text("value").notNull(), value: text('value').notNull(),
expiresAt: timestamp("expires_at").notNull(), expiresAt: timestamp('expires_at').notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(), createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp("updated_at") updatedAt: timestamp('updated_at')
.defaultNow() .defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date()) .$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(), .notNull(),
}, },
(table) => [index("verification_identifier_idx").on(table.identifier)], (table) => [index('verification_identifier_idx').on(table.identifier)],
); )
export const userRelations = relations(user, ({ many }) => ({ export const userRelations = relations(user, ({ many }) => ({
sessions: many(session), sessions: many(session),
accounts: many(account), accounts: many(account),
})); }))
export const sessionRelations = relations(session, ({ one }) => ({ export const sessionRelations = relations(session, ({ one }) => ({
user: one(user, { user: one(user, {
fields: [session.userId], fields: [session.userId],
references: [user.id], references: [user.id],
}), }),
})); }))
export const accountRelations = relations(account, ({ one }) => ({ export const accountRelations = relations(account, ({ one }) => ({
user: one(user, { user: one(user, {
fields: [account.userId], fields: [account.userId],
references: [user.id], references: [user.id],
}), }),
})); }))