将next-auth替换为better-auth

This commit is contained in:
2025-12-10 17:54:14 +08:00
parent db96b86e65
commit 881d9ca921
45 changed files with 2225 additions and 623 deletions

43
src/lib/actions/auth.ts Normal file
View File

@@ -0,0 +1,43 @@
"use server";
import { auth } from "@/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
export async function signUpAction(formData: FormData) {
const email = formData.get("email") as string;
const name = formData.get("name") as string;
const password = formData.get("password") as string;
await auth.api.signUpEmail({
body: {
email,
password,
name
}
});
redirect("/");
}
export async function signInAction(formData: FormData) {
const email = formData.get("email") as string;
const password = formData.get("password") as string;
await auth.api.signInEmail({
body: {
email,
password,
}
});
redirect("/");
}
export async function signOutAction() {
await auth.api.signOut({
headers: await headers()
});
redirect("/login");
}

5
src/lib/auth-client.ts Normal file
View File

@@ -0,0 +1,5 @@
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: process.env.BETTER_AUTH_URL as string
});

View File

@@ -16,7 +16,7 @@ export const getLocalStorageOperator = <T extends z.ZodTypeAny>(
try {
const item = globalThis.localStorage.getItem(key);
if (!item) return [];
if (!item) return [] as z.infer<T>;
const rawData = JSON.parse(item) as z.infer<T>;
const result = schema.safeParse(rawData);
@@ -28,11 +28,11 @@ export const getLocalStorageOperator = <T extends z.ZodTypeAny>(
"Invalid data structure in localStorage:",
result.error,
);
return [];
return [] as z.infer<T>;
}
} catch (e) {
console.error(`Failed to parse ${key} data:`, e);
return [];
return [] as z.infer<T>;
}
},
set: (data: z.infer<T>) => {

View File

@@ -3,7 +3,7 @@
import { FolderCreateInput, FolderUpdateInput } from "../../../../generated/prisma/models";
import prisma from "../../db";
export async function getFoldersByUserId(userId: number) {
export async function getFoldersByUserId(userId: string) {
const folders = await prisma.folder.findMany({
where: {
userId: userId,
@@ -23,7 +23,7 @@ export async function renameFolderById(id: number, newName: string) {
});
}
export async function getFoldersWithTotalPairsByUserId(userId: number) {
export async function getFoldersWithTotalPairsByUserId(userId: string) {
const folders = await prisma.folder.findMany({
where: { userId },
include: {

View File

@@ -20,3 +20,130 @@ export function shallowEqual<T extends object>(obj1: T, obj2: T): boolean {
return true;
}
export class SeededRandom {
private seed: number;
private readonly m: number = 0x80000000; // 2^31
private readonly a: number = 1103515245;
private readonly c: number = 12345;
constructor(seed?: number) {
this.seed = seed || Date.now();
}
/**
* 生成0-1之间的随机数
* @returns 0到1之间的随机浮点数
*/
next(): number {
this.seed = (this.a * this.seed + this.c) % this.m;
return this.seed / (this.m - 1);
}
/**
* 生成指定范围的随机整数
* @param min 最小值(包含)
* @param max 最大值(包含)
* @returns [min, max] 范围内的随机整数
*/
nextInt(min: number, max: number): number {
if (min > max) {
throw new Error('min must be less than or equal to max');
}
return Math.floor(this.next() * (max - min + 1)) + min;
}
/**
* 生成指定范围的随机浮点数
* @param min 最小值(包含)
* @param max 最大值(不包含)
* @returns [min, max) 范围内的随机浮点数
*/
nextFloat(min: number, max: number): number {
if (min >= max) {
throw new Error('min must be less than max');
}
return this.next() * (max - min) + min;
}
/**
* 生成固定长度的随机数序列
* @param length 序列长度
* @param min 最小值
* @param max 最大值
* @param type 生成类型:'integer' 或 'float'
* @returns 随机数数组
*/
generateSequence(
length: number,
min: number = 0,
max: number = 1,
type: 'integer' | 'float' = 'integer'
): number[] {
const sequence: number[] = [];
for (let i = 0; i < length; i++) {
if (type === 'integer') {
sequence.push(this.nextInt(min, max));
} else {
sequence.push(this.nextFloat(min, max));
}
}
return sequence;
}
/**
* 重置种子
* @param newSeed 新的种子值
*/
reset(newSeed?: number): void {
this.seed = newSeed || Date.now();
}
/**
* 获取当前种子值
* @returns 当前种子
*/
getSeed(): number {
return this.seed;
}
/**
* 生成随机布尔值
* @param probability 为 true 的概率,默认 0.5
* @returns 随机布尔值
*/
nextBoolean(probability: number = 0.5): boolean {
if (probability < 0 || probability > 1) {
throw new Error('probability must be between 0 and 1');
}
return this.next() < probability;
}
/**
* 从数组中随机选择元素
* @param array 源数组
* @returns 随机选择的元素
*/
choice<T>(array: T[]): T {
if (array.length === 0) {
throw new Error('array cannot be empty');
}
const index = this.nextInt(0, array.length - 1);
return array[index];
}
/**
* 打乱数组Fisher-Yates 洗牌算法)
* @param array 要打乱的数组
* @returns 打乱后的新数组
*/
shuffle<T>(array: T[]): T[] {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = this.nextInt(0, i);
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
}