mirror of
https://github.com/cita-777/metapi.git
synced 2026-10-31 19:47:31 +08:00
- Added support for specifying prefix lengths for live text-backed columns in MySQL upgrade SQL generation. - Introduced `mysqlIndexPrefixRequirements` option to `generateUpgradeSql` function. - Updated tests to validate the new functionality for MySQL upgrade generation. - Removed legacy shared index compatibility specifications to avoid duplication with runtime schema bootstrap. - Improved error handling and response structure in account token coverage refresh logic. - Added tests for coverage refresh failure scenarios to ensure proper handling of token persistence. # Conflicts: # src/server/db/sharedIndexSchemaCompatibility.test.ts # src/server/db/sharedIndexSchemaCompatibility.ts # src/server/index.ts
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
export type SharedIndexSchemaDialect = 'sqlite' | 'mysql' | 'postgres';
|
|
|
|
export interface SharedIndexSchemaInspector {
|
|
dialect: SharedIndexSchemaDialect;
|
|
tableExists(table: string): Promise<boolean>;
|
|
execute(sqlText: string): Promise<void>;
|
|
}
|
|
|
|
type SharedIndexCompatibilitySpec = {
|
|
table: string;
|
|
indexName: string;
|
|
createSql: Record<SharedIndexSchemaDialect, string>;
|
|
};
|
|
|
|
// Contract-defined indexes are owned by generated schema artifacts and
|
|
// runtimeSchemaBootstrap. This legacy hook is intentionally empty so startup
|
|
// does not maintain a second static source of index SQL.
|
|
export const SHARED_INDEX_COMPATIBILITY_SPECS: SharedIndexCompatibilitySpec[] = [];
|
|
|
|
function normalizeSchemaErrorMessage(error: unknown): string {
|
|
if (typeof error === 'object' && error && 'message' in error) {
|
|
return String((error as { message?: unknown }).message || '');
|
|
}
|
|
return String(error || '');
|
|
}
|
|
|
|
function isDuplicateSchemaError(error: unknown): boolean {
|
|
const lowered = normalizeSchemaErrorMessage(error).toLowerCase();
|
|
return lowered.includes('already exists')
|
|
|| lowered.includes('duplicate')
|
|
|| lowered.includes('relation') && lowered.includes('already exists');
|
|
}
|
|
|
|
async function executeIgnoreDuplicate(inspector: SharedIndexSchemaInspector, sqlText: string): Promise<void> {
|
|
try {
|
|
await inspector.execute(sqlText);
|
|
} catch (error) {
|
|
if (!isDuplicateSchemaError(error)) {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function ensureSharedIndexSchemaCompatibility(inspector: SharedIndexSchemaInspector): Promise<void> {
|
|
const tableExistsCache = new Map<string, boolean>();
|
|
|
|
for (const spec of SHARED_INDEX_COMPATIBILITY_SPECS) {
|
|
let hasTable = tableExistsCache.get(spec.table);
|
|
if (hasTable === undefined) {
|
|
hasTable = await inspector.tableExists(spec.table);
|
|
tableExistsCache.set(spec.table, hasTable);
|
|
}
|
|
if (!hasTable) {
|
|
continue;
|
|
}
|
|
|
|
await executeIgnoreDuplicate(inspector, spec.createSql[inspector.dialect]);
|
|
}
|
|
}
|