Commit 9bf2ef80 authored by 何 广一's avatar 何 广一
Browse files

some bugfixes & docker support

parent b5231b65
# write a dockerfile for a react app
# ---------- 基础 ----------
FROM node:20-alpine AS base
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile --shamefully-hoist
# ---------- Prisma + SQLite ----------
COPY prisma ./prisma
ENV DATABASE_URL=file:/app/data/db.sqlite
RUN mkdir -p /app/data
RUN pnpm prisma generate
RUN pnpm prisma migrate deploy --schema ./prisma/schema.prisma
# ---------- 构建 ----------
COPY . .
RUN pnpm build
# ---------- 运行时 ----------
FROM node:20-alpine AS runner
WORKDIR /app
RUN apk add --no-cache redis
COPY --from=base /app/.next ./.next
COPY --from=base /app/node_modules ./node_modules
COPY --from=base /app/package.json ./package.json
COPY --from=base /app/prisma ./prisma
COPY --from=base /app/.env.docker ./.env
# 启动脚本:后台起 Redis + Next.js
COPY <<EOF /app/start.sh
#!/bin/sh
redis-server --daemonize yes
exec node .next/standalone/server.js
EOF
RUN chmod +x /app/start.sh
EXPOSE 3000
CMD ["sh", "/app/start.sh"]
\ No newline at end of file
......@@ -10,6 +10,8 @@
"redis": "start redis-server --port 6379"
},
"dependencies": {
"@types/react": "^19",
"@types/react-dom": "^19",
"@prisma/client": "6.14.0",
"next": "15.4.6",
"rate-limiter-flexible": "^7.2.0",
......
......@@ -11,6 +11,12 @@ importers:
'@prisma/client':
specifier: 6.14.0
version: 6.14.0(prisma@6.14.0(typescript@5.9.2))(typescript@5.9.2)
'@types/react':
specifier: ^19
version: 19.1.9
'@types/react-dom':
specifier: ^19
version: 19.1.7(@types/react@19.1.9)
next:
specifier: 15.4.6
version: 15.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
......@@ -39,12 +45,6 @@ importers:
'@types/node':
specifier: ^20
version: 20.19.10
'@types/react':
specifier: ^19
version: 19.1.9
'@types/react-dom':
specifier: ^19
version: 19.1.7(@types/react@19.1.9)
concurrently:
specifier: ^9.2.0
version: 9.2.0
......
'use client';
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useLocalBackend } from '../interface';
import * as Auth from '../api/login-interface';
import * as Ty from '../interface';
......@@ -24,7 +23,7 @@ export default function AutoLoginProvider() {
router.push(`/chat?username=${encodeURIComponent(data.data.user)}`);
} catch (error) {
console.error(error);
alert(error.message);
alert((error as Error).message);
}
};
......@@ -32,5 +31,5 @@ export default function AutoLoginProvider() {
autoLogin();
}, [router]);
return <></>;
return null;
}
\ No newline at end of file
......@@ -142,7 +142,7 @@ function Home_Local(){
}
} catch (error) {
console.error(error);
setPageError((asLogin ? '登录错误!' : '注册错误!') + error.message);
setPageError((asLogin ? '登录错误!' : '注册错误!') + (error as Error).message);
setIsErrorInstant(false);
} finally {
setPending(false);
......
import { NextRequest, NextResponse } from 'next/server';
import * as Ty from '../../../interface'
import * as Db from '../../room-api';
import * as Auth from '../../login-interface';
/*
- url: /api/auth/logout
......
......@@ -7,7 +7,8 @@ import * as Auth from '../../login-interface';
- url: /api/auth/startSession
- method: GET
*/
export async function GET(req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.Session | null>>> {
export async function GET(_req: NextRequest): Promise<NextResponse<Ty.BackendResponse<Auth.Session | null>>> {
const result = await Db.StartAuthSession();
return NextResponse.json(result);
......
import {z} from 'zod';
import * as Ty from '../interface';
export const RoomAddArgsSchema = z.object({
user: z.string().min(2).max(100),
......
import { NextRequest, NextResponse } from 'next/server';
import { NextResponse } from 'next/server';
import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
import { createHash, randomBytes } from 'crypto';
import * as Ty from '../interface'
......@@ -22,7 +22,13 @@ const UserExists = async (name: string): Promise<boolean> => {
return user !== null;
};
const toFrontMsg = async (m: any) : Promise<Ty.Message | null> => {
const toFrontMsg = async (m: {
createdAt: Date;
id: number;
content: string;
roomId: number;
senderName: string;
}) : Promise<Ty.Message | null> => {
if(!m.senderName.length) return null;
if(!await UserExists(m.senderName)) return null;
return {
......@@ -174,7 +180,7 @@ export async function UpdateMessageList(data: Ty.RoomMessageGetUpdateArgs): Prom
}
export async function DeleteRoom(data: Ty.RoomDeleteArgs, operatorToken: String ): Promise<Ty.BackendResponse<null>> {
export async function DeleteRoom(data: Ty.RoomDeleteArgs, operatorToken: string ): Promise<Ty.BackendResponse<null>> {
const { user, roomId } = data;
const room = await prisma.room.findUnique({
......
'use client'
import { useEffect, useState } from 'react';
import { useRoom } from './room-context'
import { after } from 'node:test';
import { set } from 'zod';
export default function ConfirmModalProvider() {
......
'use client'
import { createContext, useContext, useState, ReactNode, useEffect } from 'react'
import { useRoom } from './room-context'
export default function RoomHeaderProvider() {
......
......@@ -3,7 +3,6 @@
import { useRoom } from './room-context'
import { useRouter } from 'next/navigation';
import * as Ty from '../interface'
import * as Auth from '../api/login-interface'
export default function PageHeaderProvider() {
......
import * as Ty from '../interface'
import RoomListProvider from './room-list';
import RoomHeaderProvider from './current-room';
import RoomMessageProvider from './room-message';
......
......@@ -262,7 +262,7 @@ export default function RoomListProvider() {
triggerErrorModal(roomsError);
setRoomsError('');
}
}, [roomsError]);
}, [roomsError, triggerErrorModal]);
return (
<div className="room-container">
......
'use client'
import { useState, useEffect, useRef, use } from 'react'
import { useState, useEffect, useRef } from 'react'
import * as Ty from '../interface'
import { useRoom } from './room-context'
import { reloginErrorCode } from '../api/login-interface'
......@@ -68,7 +68,7 @@ export default function RoomMessageProvider() {
} catch (error) {
console.error('房间列表获取失败:', error);
setMessagesError(error.message);
setMessagesError((error as Error).message);
} finally {
setMessagesLoading(false);
}
......@@ -125,7 +125,7 @@ export default function RoomMessageProvider() {
} catch (error) {
console.error('房间列表获取失败:', error);
setMessagesError(error.message);
setMessagesError((error as Error).message);
} finally {
setMessagesLoading(false);
}
......@@ -165,7 +165,7 @@ export default function RoomMessageProvider() {
triggerErrorModal(messagesError);
setMessagesError('');
}
}, [messagesError]);
}, [messagesError, triggerErrorModal]);
if(currentRoomInfo)
{
......@@ -174,6 +174,7 @@ export default function RoomMessageProvider() {
ref={scrollRef}
className="bg-white p-4 overflow-y-auto h-3/5"
>
{messagesLoading && <div>Loading...</div>}
<div className="bg-gray-100 min-h-full">
<ul className="mb-2">
{messages?.map((msg) => (
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment