feat: 添加数据库同步功能,创建版本表并处理版本迁移

This commit is contained in:
2026-03-30 02:30:58 +08:00
parent 50efd0ea41
commit d9442b9875
9 changed files with 3779 additions and 48 deletions

View File

@@ -32,6 +32,7 @@
"import-data": "bun run scripts/import-data.ts", "import-data": "bun run scripts/import-data.ts",
"studio": "npx drizzle-kit studio", "studio": "npx drizzle-kit studio",
"drizzle:migrate": "npx drizzle-kit migrate", "drizzle:migrate": "npx drizzle-kit migrate",
"drizzle:generate": "npx drizzle-kit generate",
"drizzle:push": "npx drizzle-kit push", "drizzle:push": "npx drizzle-kit push",
"pub": "envision pack -p -u -c" "pub": "envision pack -p -u -c"
}, },

View File

@@ -0,0 +1,24 @@
CREATE TABLE "cf_user_activity" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"userId" uuid,
"lastLoginAt" timestamp with time zone,
"lastActivityAt" timestamp with time zone,
"lastUsedAt" timestamp with time zone,
"createdAt" timestamp with time zone DEFAULT now() NOT NULL,
"updatedAt" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "mark_pod" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"title" text DEFAULT '',
"tags" jsonb DEFAULT '[]'::jsonb,
"link" text DEFAULT '',
"summary" text DEFAULT '',
"description" text DEFAULT '',
"data" jsonb DEFAULT '{}'::jsonb,
"uid" uuid,
"createdAt" timestamp with time zone DEFAULT now() NOT NULL,
"updatedAt" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "kv_app" ALTER COLUMN "proxy" SET DEFAULT true;

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,13 @@
"when": 1773148571509, "when": 1773148571509,
"tag": "0002_loving_lyja", "tag": "0002_loving_lyja",
"breakpoints": true "breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1774808985686,
"tag": "0003_shiny_venus",
"breakpoints": true
} }
] ]
} }

View File

@@ -1,3 +1,2 @@
import { relations } from "drizzle-orm/relations"; import { relations } from "drizzle-orm/relations";
import { } from "./schema";

View File

@@ -281,53 +281,7 @@ export const microAppsUpload = pgTable("micro_apps_upload", {
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(), updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
}); });
export const microMark = pgTable("micro_mark", {
id: uuid().primaryKey().defaultRandom(),
title: text().default(''),
tags: jsonb().default([]),
link: text().default(''),
summary: text().default(''),
description: text().default(''),
data: jsonb().default({}),
uname: varchar({ length: 255 }).default(''),
uid: uuid(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
cover: text().default(''),
thumbnail: text().default(''),
markType: text().default('md'),
config: jsonb().default({}),
puid: uuid(),
deletedAt: timestamp({ withTimezone: true, mode: 'string' }),
version: integer().default(1),
fileList: jsonb().default([]),
key: text().default(''),
});
export const workShareMark = pgTable("work_share_mark", {
id: uuid().primaryKey().defaultRandom(),
title: text().default(''),
key: text().default(''),
markType: text().default('md'),
description: text().default(''),
cover: text().default(''),
link: text().default(''),
tags: jsonb().default([]),
summary: text().default(''),
config: jsonb().default({}),
data: jsonb().default({}),
fileList: jsonb().default([]),
uname: varchar({ length: 255 }).default(''),
version: integer().default(1),
markedAt: timestamp({ withTimezone: true, mode: 'string' }),
uid: uuid(),
puid: uuid(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
deletedAt: timestamp({ withTimezone: true, mode: 'string' }),
});
export const prompts = pgTable('cf_prompts', { export const prompts = pgTable('cf_prompts', {

View File

@@ -6,4 +6,6 @@ export * from './schemas/n-code-schema.ts'
export * from './schemas/life-schema.ts' export * from './schemas/life-schema.ts'
export * from './schemas/user.ts' export * from './schemas/user.ts'
export * from './schemas/mark.ts'

65
src/db/schemas/mark.ts Normal file
View File

@@ -0,0 +1,65 @@
import { pgTable, serial, text, jsonb, varchar, timestamp, unique, uuid, doublePrecision, json, integer, boolean, index, uniqueIndex, pgEnum } from "drizzle-orm/pg-core"
import { sql, sum } from "drizzle-orm"
export const microMark = pgTable("micro_mark", {
id: uuid().primaryKey().defaultRandom(),
title: text().default(''),
tags: jsonb().default([]),
link: text().default(''),
summary: text().default(''),
description: text().default(''),
data: jsonb().default({}),
uname: varchar({ length: 255 }).default(''),
uid: uuid(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
cover: text().default(''),
thumbnail: text().default(''),
markType: text().default('md'),
config: jsonb().default({}),
puid: uuid(),
deletedAt: timestamp({ withTimezone: true, mode: 'string' }),
version: integer().default(1),
fileList: jsonb().default([]),
key: text().default(''),
});
export const workShareMark = pgTable("work_share_mark", {
id: uuid().primaryKey().defaultRandom(),
title: text().default(''),
key: text().default(''),
markType: text().default('md'),
description: text().default(''),
cover: text().default(''),
link: text().default(''),
tags: jsonb().default([]),
summary: text().default(''),
config: jsonb().default({}),
data: jsonb().default({}),
fileList: jsonb().default([]),
uname: varchar({ length: 255 }).default(''),
version: integer().default(1),
markedAt: timestamp({ withTimezone: true, mode: 'string' }),
uid: uuid(),
puid: uuid(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
deletedAt: timestamp({ withTimezone: true, mode: 'string' }),
});
export const markPod = pgTable("mark_pod", {
id: uuid().primaryKey().defaultRandom(),
title: text().default(''),
tags: jsonb().default([]),
link: text().default(''),
summary: text().default(''),
description: text().default(''),
data: jsonb().default({}),
uid: uuid(),
createdAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
});

60
src/db/sync.ts Normal file
View File

@@ -0,0 +1,60 @@
import { drizzle } from 'drizzle-orm/node-postgres';
import { sql } from 'drizzle-orm';
import { execSync } from 'child_process';
import { config } from '../modules/config.ts';
const VERSION_TABLE = '__db_version';
const CURRENT_VERSION = '0.1.0';
function getDb() {
return drizzle(config.DATABASE_URL || '');
}
export async function syncDatabase() {
const database = getDb();
try {
// 1. 确保版本表存在
await database.execute(sql`
CREATE TABLE IF NOT EXISTS ${VERSION_TABLE} (
id SERIAL PRIMARY KEY,
version VARCHAR(255) NOT NULL,
applied_at TIMESTAMP DEFAULT NOW()
)
`);
// 2. 获取当前数据库版本
const result = await database.execute(sql`
SELECT version FROM ${VERSION_TABLE} ORDER BY id DESC LIMIT 1
`);
const dbVersion = result.rows[0]?.version;
// 3. 版本对比
if (dbVersion === CURRENT_VERSION) {
console.log('[DB Sync] Version up to date:', CURRENT_VERSION);
return;
}
console.log(`[DB Sync] Version mismatch: DB=${dbVersion}, Code=${CURRENT_VERSION}`);
console.log('[DB Sync] Running drizzle-kit push...');
// 4. 执行 drizzle-kit push
execSync('npx drizzle-kit push --force', {
cwd: process.cwd(),
stdio: 'inherit',
env: { ...process.env, DATABASE_URL: config.DATABASE_URL },
});
// 5. 更新版本记录
await database.execute(sql`
INSERT INTO ${VERSION_TABLE} (version) VALUES (${CURRENT_VERSION})
`);
console.log('[DB Sync] Migration completed, version updated to:', CURRENT_VERSION);
} catch (error) {
console.error('[DB Sync] Migration failed:', error);
throw error;
}
}
export const sync = syncDatabase;