Files
a-share-analysis/tools/database/mysql2-schema-exporter.mjs
T

75 lines
2.6 KiB
JavaScript

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const mysql2Version = require('mysql2/package.json').version;
export const MYSQL2_EXPORTER_METADATA = Object.freeze({
name: 'mysql2-show-create',
version: '1.0.0',
driverName: 'mysql2',
driverVersion: mysql2Version,
});
export const DEFAULT_EXPORT_LIMITS = Object.freeze({
connectTimeoutMs: 5_000,
queryTimeoutMs: 5_000,
totalTimeoutMs: 30_000,
maxObjects: 5_000,
maxDefinitionBytes: 1_048_576,
});
export class SchemaExportError extends Error {
constructor(code, message) {
super(message);
this.name = 'SchemaExportError';
this.code = code;
}
}
/**
* 配置在 Schema 治理入口已完成 development、主机白名单和固定库名校验;这里仅映射
* 连接所需字段,固定禁用多语句以防止未来元数据查询被拼接为任意 SQL。
*/
export function buildConnectionOptions(config) {
return {
host: config.MYSQL_HOST,
port: Number(config.MYSQL_PORT),
user: config.MYSQL_USERNAME,
password: config.MYSQL_PASSWORD,
database: config.MYSQL_DATABASE,
charset: 'utf8mb4',
timezone: '+08:00',
connectTimeout: DEFAULT_EXPORT_LIMITS.connectTimeoutMs,
multipleStatements: false,
enableKeepAlive: true,
};
}
/**
* 元数据对象名仍需防御性转义,避免控制字符破坏 `SHOW CREATE` 查询边界;名称不合法时
* 不回显输入,确保异常路径不会把潜在敏感值写入日志。
*/
export function quoteIdentifier(identifier) {
if (typeof identifier !== 'string' || identifier.length === 0 || /[\u0000-\u001F\u007F]/.test(identifier)) {
throw new SchemaExportError('INVALID_IDENTIFIER', 'Schema 标识符不能为空且不得包含控制字符');
}
return `\`${identifier.replaceAll('`', '``')}\``;
}
/**
* 导出器只接受项目数据库兼容基线,拒绝 MariaDB 和 MySQL 5.7 之外的服务器,避免相同
* `SHOW CREATE` 文本在不兼容语义下被误认为可恢复的 Schema 快照。
*/
export function assertMysql57ServerMetadata(metadata) {
if (!/^5\.7\.\d+(?:[-+].*)?$/.test(metadata?.serverVersion ?? '')) {
throw new SchemaExportError('UNSUPPORTED_SERVER_VERSION', 'MySQL 服务端必须为 5.7.x');
}
if (metadata.databaseCharset !== 'utf8mb4') {
throw new SchemaExportError('INVALID_DATABASE_CHARSET', '数据库字符集必须为 utf8mb4');
}
if (metadata.databaseCollation !== 'utf8mb4_general_ci') {
throw new SchemaExportError('INVALID_DATABASE_COLLATION', '数据库排序规则必须为 utf8mb4_general_ci');
}
}