当然可以。让我们深入探讨更复杂的场景,并进一步细化上述内容。
- 高级类型定义
首先,让我们定义更复杂的类型结构:
enum UserRole {
Admin = 'admin',
User = 'user',
Guest = 'guest'
}
interface Address {
street: string;
city: string;
country: string;
postalCode: string;
}
interface UserDetails {
age: number;
email: string;
phone?: string;
address: Address;
}
interface ComplexParam {
id: number;
name: string;
role: UserRole;
details: UserDetails;
tags: string[];
preferences: Record<string, boolean>;
lastLogin: Date;
}- 高级后端路由处理
使用 Elysia 的高级特性来处理这个复杂结构:
import { Elysia, t } from 'elysia'
const addressSchema = t.Object({
street: t.String(),
city: t.String(),
country: t.String(),
postalCode: t.String()
})
const userDetailsSchema = t.Object({
age: t.Number(),
email: t.String(),
phone: t.Optional(t.String()),
address: addressSchema
})
const app = new Elysia()
.post('/process-complex', ({ body }) => {
const data = body as ComplexParam;
// 复杂处理逻辑
return `Processed: ${data.name}, role ${data.role}`;
}, {
body: t.Object({
id: t.Number(),
name: t.String(),
role: t.Enum(UserRole),
details: userDetailsSchema,
tags: t.Array(t.String()),
preferences: t.Record(t.String(), t.Boolean()),
lastLogin: t.String() // 将作为字符串接收,然后转换为Date
})
})- 高级前端 HTMX 实现
创建一个更复杂的表单,包含嵌套对象和数组:
<form hx-post="/process-complex" hx-trigger="submit" hx-target="#result">
<input type="hidden" name="id" value="1">
<input type="text" name="name" value="John Doe">
<select name="role">
<option value="admin">Admin</option>
<option value="user">User</option>
<option value="guest">Guest</option>
</select>
<fieldset>
<legend>Details</legend>
<input type="number" name="details.age" value="30">
<input type="email" name="details.email" value="john@example.com">
<input type="tel" name="details.phone" value="+1234567890">
<fieldset>
<legend>Address</legend>
<input type="text" name="details.address.street" value="123 Main St">
<input type="text" name="details.address.city" value="Anytown">
<input type="text" name="details.address.country" value="USA">
<input type="text" name="details.address.postalCode" value="12345">
</fieldset>
</fieldset>
<div id="tags-container">
<input type="text" name="tags[]" value="tag1">
<input type="text" name="tags[]" value="tag2">
</div>
<button type="button" onclick="addTag()">Add Tag</button>
<fieldset>
<legend>Preferences</legend>
<label><input type="checkbox" name="preferences.newsletter" value="true"> Newsletter</label>
<label><input type="checkbox" name="preferences.notifications" value="true"> Notifications</label>
</fieldset>
<input type="datetime-local" name="lastLogin">
<button type="submit">Submit</button>
</form>
<div id="result"></div>
<script>
function addTag() {
const container = document.getElementById('tags-container');
const input = document.createElement('input');
input.type = 'text';
input.name = 'tags[]';
container.appendChild(input);
}
</script>- 处理复杂数据转换
在后端,我们需要处理一些数据转换:
app.post('/process-complex', ({ body }) => {
const complexParam: ComplexParam = {
id: body.id,
name: body.name,
role: body.role as UserRole,
details: {
age: body.details.age,
email: body.details.email,
phone: body.details.phone,
address: body.details.address
},
tags: Array.isArray(body.tags) ? body.tags : [body.tags].filter(Boolean),
preferences: Object.entries(body.preferences || {}).reduce((acc, [key, value]) => {
acc[key] = value === 'true';
return acc;
}, {} as Record<string, boolean>),
lastLogin: new Date(body.lastLogin)
};
// 进一步处理逻辑
return JSON.stringify(complexParam);
})- 实现部分更新 (PATCH)
添加一个 PATCH 端点来处理部分更新:
App.Patch ('/update-complex/: id', ({ params, body }) => {
const id = parseInt(params.id);
// 假设我们有一个获取现有数据的函数
const existingData = getExistingData(id);
const updatedData: Partial<ComplexParam> = {
...existingData,
...body,
details: body.details ? { ...existingData.details, ...body.details } : existingData.details,
preferences: body.preferences ? { ...existingData.preferences, ...body.preferences } : existingData.preferences
};
// 更新逻辑
return `Updated: ${updatedData.name}`;
})- 实现文件上传
添加文件上传功能:
import { Elysia, t } from 'elysia'
import { multipart } from '@elysiajs/multipart'
app.use(multipart())
app.post('/upload', async ({ body }) => {
const file = body.file as File;
// 处理文件上传
await Bun.write(`uploads/${file.name}`, file);
return `File ${file.name} uploaded successfully`;
}, {
body: t.Object({
file: t.File()
})
})前端 HTMX 文件上传:
<form hx-post="/upload" hx-encoding="multipart/form-data" hx-target="#upload-result">
<input type="file" name="file">
<button type="submit">Upload</button>
</form>
<div id="upload-result"></div>- 实现分页和过滤
添加一个支持分页和过滤的 GET 端点:
app.get('/list-complex', ({ query }) => {
const page = parseInt(query.page as string) || 1;
const limit = parseInt(query.limit as string) || 10;
const filter = query.filter as string;
// 假设有一个获取数据的函数
const data = getComplexData(page, limit, filter);
return JSON.stringify(data);
})前端 HTMX 实现:
<div hx-get="/list-complex?page=1&limit=10" hx-trigger="load">
<!-- 数据将被加载到这里 -->
</div>
<input type="text" name="filter" hx-get="/list-complex" hx-trigger="keyup changed delay:500ms" hx-target="#data-container">
<div id="data-container"></div>- 使用 WebSocket 进行实时更新
使用 Elysia 的 WebSocket 支持实现实时更新:
import { Elysia, t } from 'elysia'
import { websocket } from '@elysiajs/websocket'
app.use(websocket())
app.ws('/realtime', {
message(ws, message) {
// 处理接收到的消息
console.log(message);
// 广播消息给所有连接的客户端
ws.send(`Received: ${message}`);
}
})前端 HTMX WebSocket 实现:
<div hx-ws="connect:/realtime">
<div id="messages"></div>
<form hx-ws="send:submit">
<input type="text" name="message">
<button type="submit">Send</button>
</form>
</div>- 错误处理和日志记录
实现全局错误处理和日志记录:
import { Elysia } from 'elysia'
import { logger } from '@elysiajs/logger'
const app = new Elysia()
.use(logger())
.onError(({ code, error, set }) => {
console.error(`Error ${code}: ${error.message}`);
set.status = code === 'NOT_FOUND' ? 404 : 500;
return { error: error.message };
})- 使用中间件进行认证
实现一个简单的 JWT 认证中间件:
import { Elysia } from 'elysia'
import { jwt } from '@elysiajs/jwt'
const app = new Elysia()
.use(jwt({
name: 'jwt',
secret: 'your-secret-key'
}))
.derive(({ jwt }) => ({
signToken: (payload: any) => jwt.sign(payload),
verifyToken: (token: string) => jwt.verify(token)
}))
.derive(({ request, verifyToken }) => ({
auth: async () => {
const token = request.headers.get('Authorization')?.split(' ')[1];
if (!token) throw new Error('No token provided');
const payload = await verifyToken(token);
if (!payload) throw new Error('Invalid token');
return payload;
}
}))
app.get('/protected', async ({ auth }) => {
const user = await auth();
return `Welcome, ${user.name}!`;
})这个扩展版本涵盖了更多高级主题,包括复杂的数据结构、文件上传、分页、实时通信、错误处理、认证等。它展示了如何在 Elysia 和 HTMX 的架构中处理各种复杂场景,同时保持代码的类型安全和可维护性。这种方法允许你构建功能丰富、响应迅速的全栈应用,充分利用 Bun 运行时的性能优势。