feat: add prisma
This commit is contained in:
@@ -22,10 +22,10 @@ src/server/
|
||||
|
||||
```typescript
|
||||
// src/server/functions/characters.ts
|
||||
import { createServerFn } from '@tanstack/react-start/server';
|
||||
import { z } from 'zod';
|
||||
import { db } from '@/lib/server/db';
|
||||
import { requireAuth } from '@/server/middleware/auth';
|
||||
import { createServerFn } from "@tanstack/react-start/server";
|
||||
import { z } from "zod";
|
||||
import { db } from "@/lib/server/db";
|
||||
import { requireAuth } from "@/server/middleware/auth";
|
||||
|
||||
// Schemas
|
||||
const createCharacterSchema = z.object({
|
||||
@@ -48,7 +48,7 @@ const characterFiltersSchema = z.object({
|
||||
});
|
||||
|
||||
// Functions
|
||||
export const getCharacters = createServerFn({ method: 'GET' })
|
||||
export const getCharacters = createServerFn({ method: "GET" })
|
||||
.validator((data: unknown) => characterFiltersSchema.parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
@@ -57,7 +57,7 @@ export const getCharacters = createServerFn({ method: 'GET' })
|
||||
const where = {
|
||||
account: { userId: session.userId },
|
||||
...(search && {
|
||||
name: { contains: search, mode: 'insensitive' as const },
|
||||
name: { contains: search, mode: "insensitive" as const },
|
||||
}),
|
||||
...(classIds?.length && { classId: { in: classIds } }),
|
||||
...(serverIds?.length && { serverId: { in: serverIds } }),
|
||||
@@ -70,7 +70,7 @@ export const getCharacters = createServerFn({ method: 'GET' })
|
||||
include: { account: { select: { id: true, name: true } } },
|
||||
skip: (page - 1) * limit,
|
||||
take: limit,
|
||||
orderBy: { name: 'asc' },
|
||||
orderBy: { name: "asc" },
|
||||
}),
|
||||
db.character.count({ where }),
|
||||
]);
|
||||
@@ -86,7 +86,7 @@ export const getCharacters = createServerFn({ method: 'GET' })
|
||||
};
|
||||
});
|
||||
|
||||
export const createCharacter = createServerFn({ method: 'POST' })
|
||||
export const createCharacter = createServerFn({ method: "POST" })
|
||||
.validator((data: unknown) => createCharacterSchema.parse(data))
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
@@ -97,14 +97,16 @@ export const createCharacter = createServerFn({ method: 'POST' })
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
throw new Error('Account not found');
|
||||
throw new Error("Account not found");
|
||||
}
|
||||
|
||||
return db.character.create({ data });
|
||||
});
|
||||
|
||||
export const bulkDeleteCharacters = createServerFn({ method: 'POST' })
|
||||
.validator((data: unknown) => z.object({ ids: z.array(z.string().cuid()) }).parse(data))
|
||||
export const bulkDeleteCharacters = createServerFn({ method: "POST" })
|
||||
.validator((data: unknown) =>
|
||||
z.object({ ids: z.array(z.string().cuid()) }).parse(data),
|
||||
)
|
||||
.handler(async ({ data }) => {
|
||||
const session = await requireAuth();
|
||||
|
||||
@@ -123,8 +125,8 @@ export const bulkDeleteCharacters = createServerFn({ method: 'POST' })
|
||||
|
||||
```typescript
|
||||
// src/server/middleware/auth.ts
|
||||
import { getWebRequest } from '@tanstack/react-start/server';
|
||||
import { db } from '@/lib/server/db';
|
||||
import { getWebRequest } from "@tanstack/react-start/server";
|
||||
import { db } from "@/lib/server/db";
|
||||
|
||||
interface Session {
|
||||
userId: string;
|
||||
@@ -133,13 +135,14 @@ interface Session {
|
||||
|
||||
export async function requireAuth(): Promise<Session> {
|
||||
const request = getWebRequest();
|
||||
const sessionId = request.headers.get('cookie')
|
||||
?.split(';')
|
||||
.find(c => c.trim().startsWith('session='))
|
||||
?.split('=')[1];
|
||||
const sessionId = request.headers
|
||||
.get("cookie")
|
||||
?.split(";")
|
||||
.find((c) => c.trim().startsWith("session="))
|
||||
?.split("=")[1];
|
||||
|
||||
if (!sessionId) {
|
||||
throw new Error('Unauthorized');
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
const session = await db.session.findUnique({
|
||||
@@ -148,7 +151,7 @@ export async function requireAuth(): Promise<Session> {
|
||||
});
|
||||
|
||||
if (!session || session.expiresAt < new Date()) {
|
||||
throw new Error('Session expired');
|
||||
throw new Error("Session expired");
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -170,7 +173,7 @@ export async function getOptionalAuth(): Promise<Session | null> {
|
||||
|
||||
```typescript
|
||||
// src/lib/server/cache.ts
|
||||
import NodeCache from 'node-cache';
|
||||
import NodeCache from "node-cache";
|
||||
|
||||
// Different TTLs for different data types
|
||||
const caches = {
|
||||
@@ -196,7 +199,9 @@ export const userCache = {
|
||||
|
||||
// Helper to invalidate all cache for a user
|
||||
invalidateUser: (userId: string): void => {
|
||||
const keys = caches.user.keys().filter(k => k.startsWith(`user:${userId}:`));
|
||||
const keys = caches.user
|
||||
.keys()
|
||||
.filter((k) => k.startsWith(`user:${userId}:`));
|
||||
caches.user.del(keys);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user