添加数据库自动初始化功能
- 创建 db/init.ts 脚本,可自动创建数据库和表 - 更新 db/index.ts,应用启动时自动检查并创建表结构 - 添加 bun run init-db 命令用于初始化数据库 - 更新 README.md 添加数据库初始化说明
This commit is contained in:
20
README.md
20
README.md
@@ -14,6 +14,24 @@ bun run dev
|
||||
bun run start
|
||||
```
|
||||
|
||||
## 数据库初始化
|
||||
|
||||
首次运行前,需要初始化数据库:
|
||||
|
||||
```bash
|
||||
# 方式一:使用初始化脚本(推荐,会自动创建数据库和表)
|
||||
bun run init-db
|
||||
|
||||
# 方式二:手动创建数据库和表
|
||||
# 1. 创建数据库
|
||||
createdb media
|
||||
# 或使用 psql
|
||||
psql -U postgres -c "CREATE DATABASE media;"
|
||||
|
||||
# 2. 创建表结构
|
||||
psql -U postgres -d media -f db/schema.sql
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
配置以下环境变量:
|
||||
@@ -27,3 +45,5 @@ bun run start
|
||||
- `DB_HOST`: 数据库主机(默认: localhost)
|
||||
- `DB_PORT`: 数据库端口(默认: 5432)
|
||||
- `DB_NAME`: 数据库名称(默认: media)
|
||||
|
||||
**注意**:应用启动时会自动检查并创建表结构(如果不存在),但不会自动创建数据库。请确保数据库已存在。
|
||||
|
||||
49
db/index.ts
49
db/index.ts
@@ -5,6 +5,13 @@
|
||||
* @FilePath: /my-score/honoback/db/index.ts
|
||||
*/
|
||||
import postgres from "postgres";
|
||||
import { readFileSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
|
||||
// 获取当前文件所在目录
|
||||
const __dirname = typeof import.meta.dir !== 'undefined'
|
||||
? import.meta.dir
|
||||
: dirname(new URL(import.meta.url).pathname);
|
||||
|
||||
// 从环境变量获取数据库连接信息
|
||||
const DATABASE_URL =
|
||||
@@ -18,6 +25,48 @@ const DATABASE_URL =
|
||||
// 初始化 PostgreSQL 连接
|
||||
const sql = postgres(DATABASE_URL);
|
||||
|
||||
// 自动初始化表结构(如果表不存在)
|
||||
async function initTables() {
|
||||
try {
|
||||
// 检查 media 表是否存在
|
||||
const tableExists = await sql`
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'media'
|
||||
)
|
||||
`;
|
||||
|
||||
// 如果表不存在,创建表
|
||||
if (!tableExists[0].exists) {
|
||||
console.log("Initializing database tables...");
|
||||
const schemaPath = join(__dirname, "schema.sql");
|
||||
const schema = readFileSync(schemaPath, "utf-8");
|
||||
await sql.unsafe(schema);
|
||||
console.log("Database tables initialized successfully");
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 如果是因为数据库不存在,尝试创建数据库
|
||||
if (
|
||||
error.message?.includes("database") &&
|
||||
error.message?.includes("does not exist")
|
||||
) {
|
||||
console.error("Database does not exist. Please create it first:");
|
||||
console.error(" createdb media");
|
||||
console.error(" or: psql -U postgres -c 'CREATE DATABASE media;'");
|
||||
throw error;
|
||||
}
|
||||
// 其他错误也抛出
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 在模块加载时初始化表(但不阻塞)
|
||||
initTables().catch((error) => {
|
||||
console.error("Failed to initialize tables:", error.message);
|
||||
// 不抛出错误,让应用继续运行,但会在第一次查询时失败
|
||||
});
|
||||
|
||||
// 将 SQLite 的 ? 占位符转换为 PostgreSQL 的 $1, $2, $3...
|
||||
function convertQuery(query: string, params: any[]): [string, any[]] {
|
||||
let pgQuery = query;
|
||||
|
||||
83
db/init.ts
Normal file
83
db/init.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 数据库初始化脚本
|
||||
* 自动创建数据库和表结构
|
||||
*/
|
||||
import postgres from "postgres";
|
||||
import { readFileSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
|
||||
// 获取当前文件所在目录
|
||||
const __dirname =
|
||||
typeof import.meta.dir !== "undefined"
|
||||
? import.meta.dir
|
||||
: dirname(new URL(import.meta.url).pathname);
|
||||
|
||||
// 从环境变量获取数据库连接信息(不包含数据库名)
|
||||
const getBaseConnection = () => {
|
||||
const user = process.env.DB_USER || "postgres";
|
||||
const password = process.env.DB_PASSWORD || "postgres";
|
||||
const host = process.env.DB_HOST || "localhost";
|
||||
const port = process.env.DB_PORT || "5432";
|
||||
return `postgresql://${user}:${password}@${host}:${port}`;
|
||||
};
|
||||
|
||||
// 初始化数据库
|
||||
export async function initDatabase() {
|
||||
const dbName = process.env.DB_NAME || "media";
|
||||
const baseUrl = getBaseConnection();
|
||||
|
||||
try {
|
||||
// 连接到 PostgreSQL 服务器(使用默认的 postgres 数据库)
|
||||
const adminSql = postgres(`${baseUrl}/postgres`);
|
||||
|
||||
// 检查数据库是否存在
|
||||
const dbExists = await adminSql`
|
||||
SELECT 1 FROM pg_database WHERE datname = ${dbName}
|
||||
`;
|
||||
|
||||
// 如果数据库不存在,创建它
|
||||
if (dbExists.length === 0) {
|
||||
console.log(`Creating database: ${dbName}`);
|
||||
await adminSql.unsafe(`CREATE DATABASE ${dbName}`);
|
||||
console.log(`Database ${dbName} created successfully`);
|
||||
} else {
|
||||
console.log(`Database ${dbName} already exists`);
|
||||
}
|
||||
|
||||
await adminSql.end();
|
||||
|
||||
// 连接到新创建的数据库
|
||||
const sql = postgres(`${baseUrl}/${dbName}`);
|
||||
|
||||
// 读取并执行 schema.sql
|
||||
const schemaPath = join(__dirname, "schema.sql");
|
||||
const schema = readFileSync(schemaPath, "utf-8");
|
||||
|
||||
// 执行 schema 中的 SQL 语句
|
||||
console.log("Creating tables...");
|
||||
await sql.unsafe(schema);
|
||||
console.log("Tables created successfully");
|
||||
|
||||
await sql.end();
|
||||
console.log("Database initialization completed");
|
||||
} catch (error: any) {
|
||||
console.error("Database initialization failed:", error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此文件,执行初始化
|
||||
if (
|
||||
import.meta.main ||
|
||||
(typeof Bun !== "undefined" && Bun.main === import.meta.path)
|
||||
) {
|
||||
initDatabase()
|
||||
.then(() => {
|
||||
console.log("Initialization complete");
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Initialization failed:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -6,7 +6,8 @@
|
||||
"main": "main.ts",
|
||||
"scripts": {
|
||||
"start": "bun run main.ts",
|
||||
"dev": "bun --watch main.ts"
|
||||
"dev": "bun --watch main.ts",
|
||||
"init-db": "bun run db/init.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@@ -18,4 +19,4 @@
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user