feat(M01-B): 建立核心迁移与MySQL连接池
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const backendRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
||||
const repoRoot = dirname(backendRoot);
|
||||
const read = (path) => readFileSync(join(repoRoot, path), 'utf8');
|
||||
|
||||
const upSql = read('database/migrations/2026061601_m01b_core_schema.up.sql');
|
||||
const downSql = read('database/migrations/2026061601_m01b_core_schema.down.sql');
|
||||
const verifySql = read('database/migrations/2026061601_m01b_core_schema.verify.sql');
|
||||
const seedSql = read('database/seeds/2026061601_m01b_minimal_seed.sql');
|
||||
|
||||
const coreTables = [
|
||||
'qipai_schema_migrations',
|
||||
'qipai_tenants',
|
||||
'qipai_stores',
|
||||
'qipai_rooms',
|
||||
'qipai_members',
|
||||
'qipai_orders',
|
||||
'qipai_payments',
|
||||
'qipai_devices',
|
||||
'qipai_audit_logs',
|
||||
'qipai_legacy_table_mappings'
|
||||
];
|
||||
|
||||
for (const table of coreTables) {
|
||||
assert.match(upSql, new RegExp(`CREATE TABLE IF NOT EXISTS ${table}\\b`));
|
||||
assert.match(downSql, new RegExp(`DROP TABLE IF EXISTS ${table}\\b`));
|
||||
assert.match(verifySql, new RegExp(`'${table}'`));
|
||||
}
|
||||
|
||||
for (const table of [
|
||||
'qipai_stores',
|
||||
'qipai_rooms',
|
||||
'qipai_members',
|
||||
'qipai_orders',
|
||||
'qipai_payments',
|
||||
'qipai_devices',
|
||||
'qipai_audit_logs'
|
||||
]) {
|
||||
const block = upSql.slice(upSql.indexOf(`CREATE TABLE IF NOT EXISTS ${table}`));
|
||||
assert.match(block, /\btenant_id BIGINT UNSIGNED NOT NULL\b/);
|
||||
}
|
||||
|
||||
for (const amountColumn of [
|
||||
'base_price_cents',
|
||||
'balance_cents',
|
||||
'total_amount_cents',
|
||||
'paid_amount_cents',
|
||||
'amount_cents'
|
||||
]) {
|
||||
assert.match(upSql, new RegExp(`\\b${amountColumn}\\b`));
|
||||
}
|
||||
|
||||
assert.doesNotMatch(upSql, /\bDECIMAL\b/i);
|
||||
assert.match(upSql, /DATETIME\(3\)/);
|
||||
assert.match(upSql, /legacy_store_id/);
|
||||
assert.match(upSql, /legacy_order_id/);
|
||||
assert.match(seedSql, /INSERT IGNORE INTO qipai_legacy_table_mappings/);
|
||||
assert.match(seedSql, /member_order_info/);
|
||||
|
||||
console.log('PASS: M01-B migration contract is present.');
|
||||
@@ -0,0 +1,29 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { loadConfig } from '../dist/config.js';
|
||||
import { toPoolOptions } from '../dist/db/mysql.js';
|
||||
|
||||
const config = loadConfig({
|
||||
NODE_ENV: 'test',
|
||||
QIPAI_MYSQL_HOST: 'db.internal',
|
||||
QIPAI_MYSQL_PORT: '3307',
|
||||
QIPAI_MYSQL_DATABASE: 'qipai_test',
|
||||
QIPAI_MYSQL_USER: 'qipai_test_user',
|
||||
QIPAI_MYSQL_PASSWORD: 'test-password',
|
||||
QIPAI_MYSQL_CONNECTION_LIMIT: '7',
|
||||
QIPAI_MQTT_URL: 'mqtt://127.0.0.1:1883'
|
||||
});
|
||||
|
||||
const poolOptions = toPoolOptions(config);
|
||||
|
||||
assert.equal(config.mysql.passwordConfigured, true);
|
||||
assert.equal(poolOptions.host, 'db.internal');
|
||||
assert.equal(poolOptions.port, 3307);
|
||||
assert.equal(poolOptions.database, 'qipai_test');
|
||||
assert.equal(poolOptions.user, 'qipai_test_user');
|
||||
assert.equal(poolOptions.password, 'test-password');
|
||||
assert.equal(poolOptions.connectionLimit, 7);
|
||||
assert.equal(poolOptions.waitForConnections, true);
|
||||
assert.equal(poolOptions.namedPlaceholders, true);
|
||||
assert.equal(poolOptions.timezone, 'Z');
|
||||
|
||||
console.log('PASS: MySQL pool contract is present.');
|
||||
Reference in New Issue
Block a user