Merge branch 'fork' of 124-template-94/d8d-admin-mobile-starter-public into main
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
待实现
|
待实现
|
||||||
迁移管理页面,在正式环境中,需要验证env中配置的密码参数才能打开
|
迁移管理页面,在正式环境中,需要验证env中配置的密码参数才能打开
|
||||||
|
|
||||||
|
2025.05.14 0.1.2
|
||||||
|
将 server/migrations.ts 中的静态加载逻辑改为异步函数 loadMigrations()
|
||||||
|
|
||||||
2025.05.14 0.1.1
|
2025.05.14 0.1.1
|
||||||
创建 server/middlewares.ts - 集中管理所有中间件配置
|
创建 server/middlewares.ts - 集中管理所有中间件配置
|
||||||
创建 server/router.ts - 统一处理路由注册逻辑
|
创建 server/router.ts - 统一处理路由注册逻辑
|
||||||
|
|||||||
@@ -1,46 +1,50 @@
|
|||||||
import type { MigrationLiveDefinition } from '@d8d-appcontainer/types'
|
import type { MigrationLiveDefinition } from '@d8d-appcontainer/types'
|
||||||
|
|
||||||
// 动态加载迁移文件
|
/**
|
||||||
const migrations: MigrationLiveDefinition[] = [];
|
* 异步加载所有迁移文件
|
||||||
|
* @returns Promise<MigrationLiveDefinition[]> 返回加载并排序后的迁移数组
|
||||||
|
*/
|
||||||
|
export async function loadMigrations(): Promise<MigrationLiveDefinition[]> {
|
||||||
|
const migrations: MigrationLiveDefinition[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 读取并加载所有迁移文件
|
// 读取并加载所有迁移文件
|
||||||
const migrationsDir = import.meta.dirname + '/migrations';
|
const migrationsDir = import.meta.dirname + '/migrations';
|
||||||
|
|
||||||
for await (const entry of Deno.readDir(migrationsDir)) {
|
|
||||||
if (!entry.isFile || !entry.name.endsWith('.ts')) continue;
|
|
||||||
|
|
||||||
// 匹配文件名格式:数字前缀_描述.ts
|
for await (const entry of Deno.readDir(migrationsDir)) {
|
||||||
const match = entry.name.match(/^(\d+)_(.+)\.ts$/);
|
if (!entry.isFile || !entry.name.endsWith('.ts')) continue;
|
||||||
if (!match) continue;
|
|
||||||
|
|
||||||
const [_, prefix, name] = match;
|
|
||||||
try {
|
|
||||||
const migration = await import(`${migrationsDir}/${entry.name}`);
|
|
||||||
|
|
||||||
// 确保导出的迁移对象有效
|
// 匹配文件名格式:数字前缀_描述.ts
|
||||||
if (migration?.default?.name && migration?.default?.up && migration?.default?.down) {
|
const match = entry.name.match(/^(\d+)_(.+)\.ts$/);
|
||||||
migrations.push(migration.default);
|
if (!match) continue;
|
||||||
console.log(`✅ Loaded migration: ${entry.name}`);
|
|
||||||
} else {
|
const [_, prefix, name] = match;
|
||||||
console.warn(`⚠️ Invalid migration format in ${entry.name}`);
|
try {
|
||||||
|
const migration = await import(`${migrationsDir}/${entry.name}`);
|
||||||
|
|
||||||
|
// 确保导出的迁移对象有效
|
||||||
|
if (migration?.default?.name && migration?.default?.up && migration?.default?.down) {
|
||||||
|
migrations.push(migration.default);
|
||||||
|
console.log(`✅ Loaded migration: ${entry.name}`);
|
||||||
|
} else {
|
||||||
|
console.warn(`⚠️ Invalid migration format in ${entry.name}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ Failed to load migration ${entry.name}:`, err);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.error(`❌ Failed to load migration ${entry.name}:`, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按数字前缀排序
|
||||||
|
migrations.sort((a, b) => {
|
||||||
|
const aNum = parseInt(a.name.match(/^(\d+)_/)?.[1] || '0');
|
||||||
|
const bNum = parseInt(b.name.match(/^(\d+)_/)?.[1] || '0');
|
||||||
|
return aNum - bNum;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`🎉 Successfully loaded ${migrations.length} migrations`);
|
||||||
|
return migrations;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('❌ Failed to load migrations:', err);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 按数字前缀排序
|
|
||||||
migrations.sort((a, b) => {
|
|
||||||
const aNum = parseInt(a.name.match(/^(\d+)_/)?.[1] || '0');
|
|
||||||
const bNum = parseInt(b.name.match(/^(\d+)_/)?.[1] || '0');
|
|
||||||
return aNum - bNum;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`🎉 Successfully loaded ${migrations.length} migrations`);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('❌ Failed to load migrations:', err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出所有迁移
|
|
||||||
export { migrations };
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Hono } from 'hono'
|
import { Hono } from 'hono'
|
||||||
import { APIClient } from '@d8d-appcontainer/api'
|
import { APIClient } from '@d8d-appcontainer/api'
|
||||||
import type { Variables, WithAuth } from "./middlewares.ts";
|
import type { Variables, WithAuth } from "./middlewares.ts";
|
||||||
import { migrations } from './migrations.ts'
|
import { loadMigrations } from './migrations.ts'
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
const log = {
|
const log = {
|
||||||
api: debug("api:migrations"),
|
api: debug("api:migrations"),
|
||||||
@@ -13,6 +13,7 @@ export function createMigrationsRoutes(withAuth: WithAuth) {
|
|||||||
migrationsRoutes.get('/', async (c) => {
|
migrationsRoutes.get('/', async (c) => {
|
||||||
const apiClient = c.get('apiClient')
|
const apiClient = c.get('apiClient')
|
||||||
log.api('正在执行数据库迁移...')
|
log.api('正在执行数据库迁移...')
|
||||||
|
const migrations = await loadMigrations()
|
||||||
const migrationsResult = await apiClient.database.executeLiveMigrations(migrations)
|
const migrationsResult = await apiClient.database.executeLiveMigrations(migrations)
|
||||||
// log.app('数据库迁移完成 %O',migrationsResult)
|
// log.app('数据库迁移完成 %O',migrationsResult)
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ export function createMigrationsRoutes(withAuth: WithAuth) {
|
|||||||
const apiClient = c.get('apiClient')
|
const apiClient = c.get('apiClient')
|
||||||
const all = c.req.query('all') === 'true'
|
const all = c.req.query('all') === 'true'
|
||||||
log.api('正在执行数据库回滚...')
|
log.api('正在执行数据库回滚...')
|
||||||
|
const migrations = await loadMigrations()
|
||||||
const rollbackResult = await apiClient.database.rollbackLiveMigrations(migrations, all)
|
const rollbackResult = await apiClient.database.rollbackLiveMigrations(migrations, all)
|
||||||
|
|
||||||
const failedResult = rollbackResult?.find((migration) => migration.status === 'failed')
|
const failedResult = rollbackResult?.find((migration) => migration.status === 'failed')
|
||||||
|
|||||||
Reference in New Issue
Block a user