// Offline SQL-test helpers. No database access or command-line entry point. import { readFileSync } from 'node:fs' export function readInitialization(region = 'CN') { const name = region === 'CN' ? '头程数据库统一增量-MySQL8.sql' : '海外区域统一增量-MySQL8.sql' return readFileSync(new URL(`../deploy/sql/${name}`, import.meta.url), 'utf8') } export function tableDefinitions(sql) { const result = new Map() let schema for (const match of sql.matchAll(/^USE (\w+);|^CREATE TABLE (\w+) \([\s\S]*?^\) ENGINE=[^\n]+;/gm)) { if (match[1]) schema = match[1] else { const key = `${schema}.${match[2]}` if (result.has(key)) throw new Error(`Duplicate table definition: ${key}`) result.set(key, match[0]) } } return result } export function table(sql, schema, name) { const value = tableDefinitions(sql).get(`${schema}.${name}`) if (!value) throw new Error(`Missing table: ${schema}.${name}`) return value } function splitValues(value) { const items = [] let start = 0, depth = 0, quoted = false for (let i = 0; i < value.length; i++) { const c = value[i] if (quoted && c === '\\') { i++; continue } if (c === "'") { if (quoted && value[i + 1] === "'") { i++; continue } quoted = !quoted } if (quoted) continue if (c === '(') depth++ if (c === ')') depth-- if (c === ',' && depth === 0) { items.push(value.slice(start, i).trim()); start = i + 1 } } if (quoted || depth) throw new Error('Unbalanced SQL seed value') items.push(value.slice(start).trim()) return items.map(item => item === 'NULL' ? null : item.startsWith("'") ? item.slice(1, -1).replace(/''/g, "'").replace(/\\([\\'"nrt0])/g, (_, c) => ({ n: '\n', r: '\r', t: '\t', 0: '\0' }[c] ?? c)) : item) } export function seedRows(sql, name) { const pattern = new RegExp(`^INSERT INTO ${name} \\(([^\\n]+?)\\) VALUES \\(([^\\n]+)\\);$`, 'gm') return [...sql.matchAll(pattern)].map(match => { const keys = match[1].split(',').map(key => key.trim()) const values = splitValues(match[2]) if (keys.length !== values.length) throw new Error(`Invalid seed columns: ${name}`) return Object.fromEntries(keys.map((key, i) => [key, values[i]])) }) } export function roleAuthorities(sql, roleCode) { const role = seedRows(sql, 'iam_role').find(row => row.role_code === roleCode) if (!role) throw new Error(`Missing role: ${roleCode}`) const granted = new Set(seedRows(sql, 'iam_role_permission').filter(row => row.role_id === role.id).map(row => row.permission_id)) return new Set(seedRows(sql, 'iam_permission').filter(row => granted.has(row.id)).map(row => row.permission_code)) }