好的,我们可以使用 Turso 数据库和 Drizzle ORM 来添加数据库管理功能。Turso 是一个分布式 SQLite 数据库,而 Drizzle ORM 是一个 TypeScript ORM,它们都可以很好地与 Bun 一起使用。
让我们更新我们的 Blog 系统以包含这些功能:
- 首先,安装必要的依赖:
bun add @libsql/client drizzle-orm drizzle-kit- 创建一个新的文件
src/db/schema.ts来定义数据库模式:
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey(),
title: text('title').notNull(),
content: text('content').notNull(),
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(sql`CURRENT_TIMESTAMP`),
});- 创建一个新的文件
src/db/index.ts来设置数据库连接:
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
import * as schema from './schema';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
export const db = drizzle(client, { schema });- 更新
src/index.ts文件以使用数据库:
import { Elysia } from 'elysia';
import { html } from '@elysiajs/html';
import { staticPlugin } from '@elysiajs/static';
import { renderToString } from 'react-dom/server';
import { Blog } from './components/Blog';
import { db } from './db';
import { posts } from './db/schema';
import { eq } from 'drizzle-orm';
const app = new Elysia()
.use(html())
.use(staticPlugin())
.get('/', async ({ html }) => {
const allPosts = await db.select().from(posts).all();
const blogHtml = renderToString(Blog({ posts: allPosts }));
return html(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Blog</title>
<link rel="stylesheet" href="/public/styles.css">
<script src="https://unpkg.com/htmx.org@1.9.0"></script>
</head>
<body>
<div id="root">${blogHtml}</div>
</body>
</html>
`);
})
.get('/api/post/:id', async ({ params }) => {
const post = await db.select().from(posts).where(eq(posts.id, parseInt(params.id))).get();
if (!post) {
return new Response('Post not found', { status: 404 });
}
return `
<article>
<h2>${post.title}</h2>
<p>${post.content}</p>
<small>Created at: ${new Date(post.createdAt).toLocaleString()}</small>
</article>
`;
})
.post('/api/post', async ({ body }) => {
const { title, content } = body as { title: string; content: string };
const newPost = await db.insert(posts).values({ title, content }).returning().get();
return newPost;
})
.put('/api/post/:id', async ({ params, body }) => {
const { title, content } = body as { title: string; content: string };
const updatedPost = await db.update(posts)
.set({ title, content })
.where(eq(posts.id, parseInt(params.id)))
.returning()
.get();
return updatedPost;
})
.delete('/api/post/:id', async ({ params }) => {
await db.delete(posts).where(eq(posts.id, parseInt(params.id))).run();
return { success: true };
})
.listen(3000);
console.log(`Server is running at http://localhost:${app.server?.port}`);- 更新
src/components/Blog.tsx以包含创建新文章的表单:
import React from 'react';
interface Post {
id: number;
title: string;
content: string;
createdAt: number;
}
interface BlogProps {
posts: Post[];
}
export const Blog: React.FC<BlogProps> = ({ posts }) => {
return (
<div>
<h1>My Blog</h1>
<form hx-post="/api/post" hx-swap="beforeend" hx-target="#posts">
<input type="text" name="title" placeholder="Title" required />
<textarea name="content" placeholder="Content" required></textarea>
<button type="submit">Create Post</button>
</form>
<div id="posts">
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
<small>Created at: {new Date(post.createdAt).toLocaleString()}</small>
<button hx-get={`/api/post/${post.id}`} hx-target="closest article" hx-swap="outerHTML">
Load Full Post
</button>
<button hx-delete={`/api/post/${post.id}`} hx-target="closest article" hx-swap="outerHTML">
Delete Post
</button>
</article>
))}
</div>
</div>
);
};- 创建一个新文件
drizzle.config.ts在项目根目录:
import type { Config } from 'drizzle-kit';
export default {
schema: './src/db/schema.ts',
out: './drizzle',
driver: 'turso',
dbCredentials: {
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
},
} satisfies Config;- 添加以下脚本到
package.json:
{
"scripts": {
"generate": "drizzle-kit generate:sqlite",
"push": "drizzle-kit push:sqlite"
}
}- 运行迁移:
bun run generate
bun run push- 确保在运行应用之前设置环境变量:
export TURSO_DATABASE_URL=your_database_url
export TURSO_AUTH_TOKEN=your_auth_token- 运行应用:
bun run src/index.ts这个更新后的 Blog 系统现在使用 Turso 数据库和 Drizzle ORM 来管理博客文章。它包括以下功能:
- 从数据库获取所有文章
- 创建新文章
- 获取单篇文章的完整内容
- 删除文章
你可以进一步扩展这个系统,例如:
- 添加文章编辑功能
- 实现用户认证和授权
- 添加评论系统
- 实现分页
- 添加搜索功能
记住,在实际部署时,你需要 properly 管理你的环境变量和数据库凭证。此外,你可能还需要添加错误处理和输入验证来使应用更加健壮。