mirror of
https://github.com/Vb-Lg/class-history-template.git
synced 2026-11-03 18:46:40 +00:00
feat(api): auto-create and migrate messages table on first request
ensureSchema runs idempotent CREATE TABLE / ALTER TABLE (skipping duplicate-column errors), cached once per isolate with retry on failure; schema.sql becomes reference-only documentation
This commit is contained in:
1 parent
ca422df0c3
commit
4b489a3ebb
2 files changed
+46
-7
No files matched your search
@@ -2,7 +2,8 @@
|
|||||||
* Cloudflare Pages Functions
|
* Cloudflare Pages Functions
|
||||||
* GET /api/messages → 返回最新留言列表
|
* GET /api/messages → 返回最新留言列表
|
||||||
* POST /api/messages → 新增一条留言
|
* POST /api/messages → 新增一条留言
|
||||||
* 依赖绑定:环境变量 DB(D1 数据库,建表语句见 /schema.sql)
|
* 依赖绑定:环境变量 DB(D1 数据库)
|
||||||
|
* 表结构由 ensureSchema 在首次访问时自动创建/迁移,无需手动执行 SQL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const MAX_NAME = 12;
|
const MAX_NAME = 12;
|
||||||
@@ -40,6 +41,43 @@ function clean(str, max) {
|
|||||||
.slice(0, max);
|
.slice(0, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- 表结构:自动建表/迁移(幂等,旧表缺列时自动补齐) ---------- */
|
||||||
|
const SCHEMA_SQL = [
|
||||||
|
`CREATE TABLE IF NOT EXISTS messages (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
time TEXT NOT NULL,
|
||||||
|
ip TEXT,
|
||||||
|
ua TEXT,
|
||||||
|
country TEXT,
|
||||||
|
created_at INTEGER NOT NULL
|
||||||
|
)`,
|
||||||
|
'ALTER TABLE messages ADD COLUMN ua TEXT',
|
||||||
|
'ALTER TABLE messages ADD COLUMN country TEXT',
|
||||||
|
];
|
||||||
|
|
||||||
|
let schemaPromise = null; // 每个 isolate 只迁移一次;失败不缓存,下个请求重试
|
||||||
|
|
||||||
|
function ensureSchema(env) {
|
||||||
|
if (!schemaPromise) {
|
||||||
|
schemaPromise = (async () => {
|
||||||
|
for (const sql of SCHEMA_SQL) {
|
||||||
|
try {
|
||||||
|
await env.DB.prepare(sql).run();
|
||||||
|
} catch (err) {
|
||||||
|
// 列已存在时 SQLite 报 duplicate column name,属预期
|
||||||
|
if (!/duplicate column/i.test(String(err && err.message))) throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})().catch((err) => {
|
||||||
|
schemaPromise = null;
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return schemaPromise;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------- OPTIONS(预检) ---------- */
|
/* ---------- OPTIONS(预检) ---------- */
|
||||||
export async function onRequestOptions() {
|
export async function onRequestOptions() {
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
@@ -58,6 +96,8 @@ export async function onRequestGet({ env }) {
|
|||||||
if (!env.DB) return json({ ok: false, error: '数据库未绑定' }, 500);
|
if (!env.DB) return json({ ok: false, error: '数据库未绑定' }, 500);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await ensureSchema(env);
|
||||||
|
|
||||||
const { results } = await env.DB
|
const { results } = await env.DB
|
||||||
.prepare(
|
.prepare(
|
||||||
`SELECT id, name, text, time
|
`SELECT id, name, text, time
|
||||||
@@ -109,6 +149,8 @@ export async function onRequestPost({ request, env }) {
|
|||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await ensureSchema(env);
|
||||||
|
|
||||||
if (ip) {
|
if (ip) {
|
||||||
const last = await env.DB
|
const last = await env.DB
|
||||||
.prepare(
|
.prepare(
|
||||||
|
|||||||
+3
-6
@@ -1,7 +1,8 @@
|
|||||||
-- D1 数据库结构(留言墙 /api/messages 使用,绑定名 DB)
|
-- D1 数据库结构(留言墙 /api/messages 使用,绑定名 DB)
|
||||||
--
|
--
|
||||||
-- 全新部署:直接执行下面的 CREATE TABLE。
|
-- 无需手动执行:Functions 首次访问会自动建表并为旧表补齐缺失的列
|
||||||
-- 已有部署:老表缺少 ua / country 列时,执行文件末尾注释里的 ALTER TABLE。
|
-- (见 functions/api/messages.js 的 ensureSchema)。本文件仅作结构参考,
|
||||||
|
-- 需要手工干预(如排查问题)时再执行。
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS messages (
|
CREATE TABLE IF NOT EXISTS messages (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -13,7 +14,3 @@ CREATE TABLE IF NOT EXISTS messages (
|
|||||||
country TEXT, -- 国家/地区代码,来自 CF-IPCountry(审计)
|
country TEXT, -- 国家/地区代码,来自 CF-IPCountry(审计)
|
||||||
created_at INTEGER NOT NULL -- Unix 秒,排序与限流用
|
created_at INTEGER NOT NULL -- Unix 秒,排序与限流用
|
||||||
);
|
);
|
||||||
|
|
||||||
-- 已有部署的增量迁移:
|
|
||||||
-- ALTER TABLE messages ADD COLUMN ua TEXT;
|
|
||||||
-- ALTER TABLE messages ADD COLUMN country TEXT;
|
|
||||||
Reference in new issue
Block a user