Skip to content

Commit a0eddbc

Browse files
committed
refactor(server): replace typedi Container with native ElysiaJS dependency injection
Remove typedi dependency injection container Create context.ts for centralized type definitions (Env, DB) Update CacheImpl to receive dependencies via constructor instead of Container Rewrite setup.ts to use Elysia's decorate() and derive() for dependency injection Update all services to access dependencies via store instead of Container.get() Update _worker.ts to create and pass cache instances to createApp() Update server.ts to export createApp() function that accepts all dependencies Delete di.ts and db.ts (merged into context.ts) Update db-config.ts and ai.ts to receive db parameter explicitly This change removes the implicit dependency injection that added uncertainty to the codebase, replacing it with explicit dependency passing through ElysiaJS's native mechanisms.
1 parent 1acbcd6 commit a0eddbc

35 files changed

Lines changed: 12699 additions & 1821 deletions

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# 前端配置 (client/.env)
66
# ============================================
77
# 后端 API 地址
8+
FRONTEND_PORT=5173
89
API_URL=http://localhost:11498
910

1011
# 网站基本信息
@@ -23,6 +24,7 @@ RSS_ENABLE=false
2324
# ============================================
2425
# 前端地址(用于 Webhook 等)
2526
FRONTEND_URL=http://localhost:5173
27+
BACKEND_PORT=11498
2628

2729
# S3/R2 存储配置
2830
S3_FOLDER=images/

bun.lockb

-119 KB
Binary file not shown.

client/.env.example

Lines changed: 0 additions & 5 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,6 @@
2525
"release": "bun scripts/release.ts"
2626
},
2727
"devDependencies": {
28-
"autoprefixer": "^10.4.19",
29-
"i18next-parser": "^9.0.0",
30-
"postcss": "^8.4.38",
31-
"puppeteer": "^22.13.0",
32-
"tailwindcss": "^3.4.3",
33-
"turbo": "^1.13.3",
34-
"vitest": "1.6.1"
35-
},
36-
"dependencies": {
37-
"@types/lodash": "^4.17.7",
38-
"@types/react-syntax-highlighter": "^15.5.13",
39-
"fast-xml-parser": "^4.4.0",
40-
"html-to-md": "^0.8.5",
41-
"lodash": "^4.17.21",
42-
"mermaid": "^10.9.1",
43-
"react-markdown": "^9.0.1",
44-
"react-syntax-highlighter": "^15.5.0",
45-
"rehype-katex": "^7.0.0",
46-
"rehype-mathjax": "^6.0.0",
47-
"rehype-parse": "^9.0.0",
48-
"rehype-raw": "^7.0.0",
49-
"rehype-react": "^8.0.0",
50-
"rehype-sanitize": "^6.0.0",
51-
"remark-gfm": "^4.0.0",
52-
"remark-math": "^6.0.0",
53-
"remark-rehype": "^11.1.0"
28+
"turbo": "^1.13.3"
5429
}
5530
}

scripts/dev.ts

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,31 @@ import * as path from 'path';
1010
import * as net from 'net';
1111

1212
const ROOT_DIR = process.cwd();
13-
const FRONTEND_PORT = 5173;
14-
const BACKEND_PORT = 11498;
13+
const ENV_FILE = path.join(ROOT_DIR, '.env.local');
14+
const envContent = fs.readFileSync(ENV_FILE, 'utf-8');
15+
const env = parseEnv(envContent);
16+
const FRONTEND_PORT = env.FRONTEND_PORT ? parseInt(env.FRONTEND_PORT) : 5173;
17+
const BACKEND_PORT = env.BACKEND_PORT ? parseInt(env.BACKEND_PORT) : 11498;
18+
19+
function parseEnv(content: string): Record<string, string> {
20+
const env: Record<string, string> = {};
21+
const lines = content.split('\n');
22+
23+
for (const line of lines) {
24+
const trimmed = line.trim();
25+
// 跳过注释和空行
26+
if (!trimmed || trimmed.startsWith('#')) continue;
27+
28+
const equalIndex = trimmed.indexOf('=');
29+
if (equalIndex > 0) {
30+
const key = trimmed.substring(0, equalIndex).trim();
31+
const value = trimmed.substring(equalIndex + 1).trim();
32+
env[key] = value;
33+
}
34+
}
35+
36+
return env;
37+
}
1538

1639
// 颜色输出
1740
const colors = {
@@ -53,13 +76,13 @@ function checkPort(port: number): Promise<boolean> {
5376
// 检查配置文件
5477
if (!fs.existsSync(path.join(ROOT_DIR, '.env.local'))) {
5578
log('Setup', '首次运行,正在初始化配置...', colors.yellow);
56-
79+
5780
// 运行配置生成脚本
5881
const setupProcess = spawn('bun', ['scripts/setup-dev.ts'], {
5982
stdio: 'inherit',
6083
cwd: ROOT_DIR
6184
});
62-
85+
6386
setupProcess.on('exit', (code) => {
6487
if (code !== 0) {
6588
process.exit(code || 1);
@@ -69,17 +92,17 @@ if (!fs.existsSync(path.join(ROOT_DIR, '.env.local'))) {
6992
} else {
7093
// 检查是否需要重新生成配置
7194
const envStat = fs.statSync(path.join(ROOT_DIR, '.env.local'));
72-
const wranglerStat = fs.existsSync(path.join(ROOT_DIR, 'wrangler.toml'))
95+
const wranglerStat = fs.existsSync(path.join(ROOT_DIR, 'wrangler.toml'))
7396
? fs.statSync(path.join(ROOT_DIR, 'wrangler.toml'))
7497
: { mtime: new Date(0) };
75-
98+
7699
if (envStat.mtime > wranglerStat.mtime) {
77100
log('Setup', '检测到配置更新,正在重新生成...', colors.yellow);
78101
const setupProcess = spawn('bun', ['scripts/setup-dev.ts'], {
79102
stdio: 'inherit',
80103
cwd: ROOT_DIR
81104
});
82-
105+
83106
setupProcess.on('exit', (code) => {
84107
if (code !== 0) {
85108
process.exit(code || 1);
@@ -93,59 +116,60 @@ if (!fs.existsSync(path.join(ROOT_DIR, '.env.local'))) {
93116

94117
async function startDev() {
95118
log('Dev', '启动开发服务器...', colors.green);
96-
119+
120+
97121
// 检查端口占用
98122
const frontendAvailable = await checkPort(FRONTEND_PORT);
99123
const backendAvailable = await checkPort(BACKEND_PORT);
100-
124+
101125
if (!frontendAvailable) {
102126
log('Error', `端口 ${FRONTEND_PORT} 已被占用`, colors.red);
103127
log('Help', '请检查是否有其他进程占用了该端口,或修改 .env.local 中的 FRONTEND_URL', colors.yellow);
104128
process.exit(1);
105129
}
106-
130+
107131
if (!backendAvailable) {
108132
log('Error', `端口 ${BACKEND_PORT} 已被占用`, colors.red);
109133
log('Help', '请检查是否有其他 wrangler dev 进程在运行', colors.yellow);
110134
process.exit(1);
111135
}
112-
136+
113137
// 先运行数据库迁移
114138
log('DB', '检查数据库迁移...', colors.cyan);
115139
const migrateProcess = spawn('bun', ['scripts/db-migrate-local.ts'], {
116140
stdio: 'inherit',
117141
cwd: ROOT_DIR
118142
});
119-
143+
120144
migrateProcess.on('exit', (code) => {
121145
if (code !== 0) {
122146
log('DB', '数据库迁移失败', colors.red);
123147
process.exit(code || 1);
124148
}
125-
149+
126150
log('DB', '数据库迁移完成', colors.green);
127151
startServers();
128152
});
129153
}
130154

131155
function startServers() {
132156
log('Dev', '正在启动前端和后端服务...', colors.green);
133-
157+
134158
let backendReady = false;
135159
let frontendReady = false;
136-
160+
137161
// 启动后端
138162
const backend = spawn('bun', ['wrangler', 'dev', '--port', String(BACKEND_PORT)], {
139163
cwd: ROOT_DIR,
140164
env: { ...process.env }
141165
});
142-
166+
143167
// 启动前端
144-
const frontend = spawn('bun', ['--filter', './client', 'dev'], {
168+
const frontend = spawn('bun', ['--filter', './client', 'dev', '--port', String(FRONTEND_PORT)], {
145169
cwd: ROOT_DIR,
146170
env: { ...process.env }
147171
});
148-
172+
149173
// 输出处理
150174
backend.stdout.on('data', (data) => {
151175
const lines = data.toString().split('\n').filter((l: string) => l.trim());
@@ -163,12 +187,12 @@ function startServers() {
163187
}
164188
});
165189
});
166-
190+
167191
backend.stderr.on('data', (data) => {
168192
const lines = data.toString().split('\n').filter((l: string) => l.trim());
169193
lines.forEach((line: string) => log('Backend', line, colors.red));
170194
});
171-
195+
172196
frontend.stdout.on('data', (data) => {
173197
const lines = data.toString().split('\n').filter((l: string) => l.trim());
174198
lines.forEach((line: string) => {
@@ -185,44 +209,44 @@ function startServers() {
185209
}
186210
});
187211
});
188-
212+
189213
frontend.stderr.on('data', (data) => {
190214
const lines = data.toString().split('\n').filter((l: string) => l.trim());
191215
lines.forEach((line: string) => log('Frontend', line, colors.red));
192216
});
193-
217+
194218
// 进程退出处理
195219
backend.on('exit', (code) => {
196220
log('Backend', `进程退出,代码: ${code}`, colors.red);
197221
frontend.kill();
198222
process.exit(code || 0);
199223
});
200-
224+
201225
frontend.on('exit', (code) => {
202226
log('Frontend', `进程退出,代码: ${code}`, colors.red);
203227
backend.kill();
204228
process.exit(code || 0);
205229
});
206-
230+
207231
// 优雅退出
208232
process.on('SIGINT', () => {
209233
log('Dev', '正在关闭开发服务器...', colors.yellow);
210234
backend.kill('SIGINT');
211235
frontend.kill('SIGINT');
212236
});
213-
237+
214238
process.on('SIGTERM', () => {
215239
backend.kill('SIGTERM');
216240
frontend.kill('SIGTERM');
217241
});
218-
242+
219243
// 检查是否都准备好了
220244
function checkAllReady() {
221245
if (backendReady && frontendReady) {
222246
showReadyMessage();
223247
}
224248
}
225-
249+
226250
// 显示访问信息
227251
function showReadyMessage() {
228252
console.log('\n' + '='.repeat(60));
@@ -232,7 +256,7 @@ function startServers() {
232256
console.log(`${colors.blue}🔌 后端地址:${colors.reset} http://localhost:${BACKEND_PORT}`);
233257
console.log('='.repeat(60) + '\n');
234258
}
235-
259+
236260
// 超时显示(如果检测失败)
237261
setTimeout(() => {
238262
if (!backendReady || !frontendReady) {

scripts/setup-dev.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ const requiredVars = [
5555
'RIN_GITHUB_CLIENT_SECRET',
5656
'JWT_SECRET',
5757
'S3_ACCESS_KEY_ID',
58-
'S3_SECRET_ACCESS_KEY'
58+
'S3_SECRET_ACCESS_KEY',
59+
'BACKEND_PORT',
60+
'FRONTEND_PORT'
5961
];
6062

6163
const missingVars = requiredVars.filter(v => !env[v]);
@@ -70,8 +72,7 @@ if (missingVars.length > 0) {
7072
const wranglerContent = `#:schema node_modules/wrangler/config-schema.json
7173
name = "${env.WORKER_NAME || 'rin-server'}"
7274
main = "server/src/_worker.ts"
73-
compatibility_date = "2024-05-29"
74-
node_compat = true
75+
compatibility_date = "2026-01-20"
7576
7677
[triggers]
7778
crons = ["*/20 * * * *"]

server/package.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@
1414
"devDependencies": {
1515
"@types/bun": "^1.1.2",
1616
"drizzle-kit": "^0.21.2",
17-
"wrangler": "^3.63.1",
17+
"wrangler": "^4.61.1",
1818
"@cloudflare/vitest-pool-workers": "^0.1.0",
19-
"@cloudflare/workers-types": "^4.20240529.0",
2019
"typescript": "^5.0.4",
2120
"strip-indent": "^4.0.0"
2221
},
@@ -26,16 +25,18 @@
2625
"dependencies": {
2726
"@aws-sdk/client-s3": "^3.583.0",
2827
"@aws-sdk/s3-request-presigner": "^3.583.0",
29-
"@elysiajs/cors": "1.0.2",
30-
"@elysiajs/cron": "^1.0.3",
31-
"@elysiajs/eden": "^1.0.13",
32-
"@elysiajs/server-timing": "^1.0.2",
33-
"arctic": "^1.9.0",
28+
"@elysiajs/cors": "1.4.1",
29+
"@elysiajs/cron": "^1.4.1",
30+
"@elysiajs/eden": "^1.4.6",
31+
"@elysiajs/server-timing": "^1.4.0",
32+
"@sinclair/typebox": "^0.34.48",
33+
"arctic": "^3.7.0",
3434
"drizzle-orm": "^0.30.10",
35-
"elysia": "^1.0.21",
36-
"elysia-oauth2": "1.2.0",
35+
"elysia": "^1.4.22",
36+
"elysia-oauth2": "2.1.0",
3737
"feed": "^4.2.2",
3838
"jose": "^5.3.0",
39+
"openapi-types": "^12.1.3",
3940
"reflect-metadata": "^0.2.2",
4041
"rehype-stringify": "^10.0.0",
4142
"remark-gfm": "^4.0.0",
@@ -48,4 +49,4 @@
4849
"trustedDependencies": [
4950
"es5-ext"
5051
]
51-
}
52+
}

0 commit comments

Comments
 (0)