Merge pull request #53 from Hureru/refactor/token-routes-page

refactor: 重构 TokenRoutes 页面,支持分层加载、网格布局和性能优化
This commit is contained in:
Cita
2026-03-11 16:14:25 +08:00
committed by GitHub
18 changed files with 3346 additions and 2406 deletions
@@ -0,0 +1,64 @@
export type AccountTokenSchemaDialect = 'sqlite' | 'mysql' | 'postgres';
export interface AccountTokenSchemaInspector {
dialect: AccountTokenSchemaDialect;
tableExists(table: string): Promise<boolean>;
columnExists(table: string, column: string): Promise<boolean>;
execute(sqlText: string): Promise<void>;
}
type AccountTokenColumnCompatibilitySpec = {
table: 'account_tokens';
column: string;
addSql: Record<AccountTokenSchemaDialect, string>;
};
const ACCOUNT_TOKEN_COLUMN_COMPATIBILITY_SPECS: AccountTokenColumnCompatibilitySpec[] = [
{
table: 'account_tokens',
column: 'token_group',
addSql: {
sqlite: 'ALTER TABLE account_tokens ADD COLUMN token_group text;',
mysql: 'ALTER TABLE `account_tokens` ADD COLUMN `token_group` TEXT NULL',
postgres: 'ALTER TABLE "account_tokens" ADD COLUMN "token_group" TEXT',
},
},
];
function normalizeSchemaErrorMessage(error: unknown): string {
if (typeof error === 'object' && error && 'message' in error) {
return String((error as { message?: unknown }).message || '');
}
return String(error || '');
}
function isDuplicateColumnError(error: unknown): boolean {
const lowered = normalizeSchemaErrorMessage(error).toLowerCase();
return lowered.includes('duplicate column')
|| lowered.includes('already exists')
|| lowered.includes('duplicate column name');
}
async function executeAddColumn(inspector: AccountTokenSchemaInspector, sqlText: string): Promise<void> {
try {
await inspector.execute(sqlText);
} catch (error) {
if (!isDuplicateColumnError(error)) {
throw error;
}
}
}
export async function ensureAccountTokenSchemaCompatibility(inspector: AccountTokenSchemaInspector): Promise<void> {
for (const spec of ACCOUNT_TOKEN_COLUMN_COMPATIBILITY_SPECS) {
const hasTable = await inspector.tableExists(spec.table);
if (!hasTable) {
continue;
}
const hasColumn = await inspector.columnExists(spec.table, spec.column);
if (!hasColumn) {
await executeAddColumn(inspector, spec.addSql[inspector.dialect]);
}
}
}
+2
View File
@@ -6,6 +6,7 @@ import { dirname, resolve } from 'node:path';
import { ensureSiteSchemaCompatibility, type SiteSchemaInspector } from './siteSchemaCompatibility.js';
import { ensureRouteGroupingSchemaCompatibility } from './routeGroupingSchemaCompatibility.js';
import { ensureProxyFileSchemaCompatibility } from './proxyFileSchemaCompatibility.js';
import { ensureAccountTokenSchemaCompatibility } from './accountTokenSchemaCompatibility.js';
export type RuntimeSchemaDialect = 'sqlite' | 'mysql' | 'postgres';
@@ -241,6 +242,7 @@ export async function ensureRuntimeDatabaseSchema(client: RuntimeSchemaClient):
await ensureSiteSchemaCompatibility(createSiteSchemaInspector(client));
await ensureRouteGroupingSchemaCompatibility(createSiteSchemaInspector(client));
await ensureProxyFileSchemaCompatibility(createSiteSchemaInspector(client));
await ensureAccountTokenSchemaCompatibility(createSiteSchemaInspector(client));
}
export async function bootstrapRuntimeDatabaseSchema(input: RuntimeSchemaConnectionInput): Promise<void> {