数据库层架构

四层架构设计

HiDNS 实现了严格的四层数据库架构:

DSM层 → 业务适配器层 → 数据库抽象层 → 驱动层 → 数据库

第一层:业务适配器层

文件位置: server/src/db/bal/business-adapter.ts

职责: 提供函数式 API,所有数据库操作必须通过此层

核心函数

// 查询多行
export async function query<T = QueryResult>(sql: string, params?: unknown[]): Promise<T[]>

// 查询单行
export async function get<T = QueryResult>(sql: string, params?: unknown[]): Promise<T | undefined>

// 执行无返回
export async function execute(sql: string, params?: unknown[]): Promise<void>

// 插入返回ID
export async function insert(sql: string, params?: unknown[]): Promise<number>

// 执行返回影响行数
export async function run(sql: string, params?: unknown[]): Promise<{ changes: number }>

// 获取当前时间函数
export function now(): string

// 获取数据库类型
export function getDbType(): DatabaseType

// 检查是否已连接
export function isDbConnected(): boolean

// 事务支持
export async function withTransaction<T>(fn: (trx: TransactionOperations) => Promise<T>): Promise<T>

业务操作模块

// 用户操作
export const UserOperations = {
  async getById(id: number): Promise<User | undefined>,
  async getByUsername(username: string): Promise<User | undefined>,
  async getByEmail(email: string): Promise<User | undefined>,
  async create(user: Omit<User, 'id' | 'createdAt'>): Promise<number>,
  async update(id: number, updates: Partial<User>): Promise<void>,
  async delete(id: number): Promise<void>,
  async list(options?: ListOptions): Promise<PaginatedResult<User>>,
}

// DNS 账号操作
export const DnsAccountOperations = { ... }

// 域名操作
export const DomainOperations = { ... }

// 团队操作
export const TeamOperations = { ... }

// 设置操作
export const SettingsOperations = { ... }

// 审计操作
export const AuditOperations = { ... }

// Token 操作
export const TokenOperations = { ... }

// 密钥操作
export const SecretOperations = { ... }

// 安全策略操作
export const SecurityPolicyOperations = { ... }

// 设备信任操作
export const TrustedDeviceOperations = { ... }

// 用户偏好操作
export const UserPreferencesOperations = { ... }

// 会话操作
export const SessionOperations = { ... }

// 登录限制操作
export const LoginLimitOperations = { ... }

// 故障转移操作
export const FailoverOperations = { ... }

// 审计导出操作
export const AuditExportOperations = { ... }

// TOTP 操作
export const TOTPOperations = { ... }

// WebAuthn 操作
export const WebAuthnOperations = { ... }

// SMTP 操作
export const SmtpOperations = { ... }

// WHOIS 操作
export const WhoisOperations = { ... }

// 审计规则操作
export const AuditRulesOperations = { ... }

// 审计日志操作
export const AuditLogOperations = { ... }

// OAuth 操作
export const OAuthOperations = { ... }

// 双因素认证操作
export const TwoFAOperations = { ... }

// 事务操作
export class TransactionOperations { ... }

使用示例

import { query, get, execute, insert, run, now, UserOperations } from '../db';

// 查询单行
const user = await get<User>('SELECT * FROM users WHERE id = ?', [userId]);

// 查询多行
const users = await query<User>('SELECT * FROM users WHERE status = ?', ['active']);

// 插入数据
const id = await insert('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);

// 执行更新
await execute('UPDATE users SET last_login = ? WHERE id = ?', [now(), userId]);

// 使用业务操作模块
const user = await UserOperations.getById(1);

第二层:数据库抽象层

文件位置: server/src/db/core/

职责: 提供统一的数据库连接和类型系统

文件结构

db/core/
├── types.ts       # 统一类型定义
├── connection.ts  # 连接管理器(单例模式)
└── config.ts      # 配置管理

核心类型

// 数据库类型
type DatabaseType = 'sqlite' | 'mysql' | 'postgresql'

// 数据库连接接口
interface DatabaseConnection {
  readonly type: DatabaseType
  readonly isConnected: boolean
  
  query<T>(sql: string, params?: unknown[]): Promise<T[]>
  get<T>(sql: string, params?: unknown[]): Promise<T | undefined>
  execute(sql: string, params?: unknown[]): Promise<void>
  insert(sql: string, params?: unknown[]): Promise<number>
  run(sql: string, params?: unknown[]): Promise<{ changes: number }>
  
  beginTransaction(): Promise<Transaction>
  close(): Promise<void>
}

第三层:驱动层

文件位置: server/src/db/dl/

职责: 实现具体数据库的操作逻辑

文件结构

db/dl/
├── base.ts        # 基础驱动类(模板方法模式)
├── mysql.ts       # MySQL 驱动(连接池)
├── postgresql.ts  # PostgreSQL 驱动(连接池)
└── sqlite.ts      # SQLite 驱动(better-sqlite3)

驱动特性

第四层:声明式模式管理层 (DSM)

文件位置: server/src/db/dsm/

职责: 管理数据库表结构的声明式定义、自动调谐(reconciliation)、数据迁移及版本管理

文件结构

db/dsm/
├── index.ts               # 统一入口
├── init-dsm.ts            # DSM 初始化
├── schema-reconciler.ts   # Schema 调谐器(自动同步表结构)
├── migration-manager.ts   # 迁移管理器
├── data-migration-runner.ts # 数据迁移运行器
├── backup-manager.ts      # 备份管理器
├── sql-compat.ts          # SQL 兼容性层
├── column-validator.ts    # 列验证器
├── schema/
│   ├── registry.ts        # Schema 注册表
│   └── migration.ts       # 迁移定义
└── schemas/
    ├── index.ts           # Schema 入口
    ├── complete-schema.ts # 完整 Schema 定义
    ├── types/
    │   └── schema.ts      # Schema 类型定义
    └── dialects/
        ├── sqlite.ts      # SQLite 方言
        ├── mysql.ts       # MySQL 方言
        └── postgresql.ts  # PostgreSQL 方言

核心能力

数据库主入口

文件位置: server/src/db/index.ts

职责: 统一导出业务适配器函数和类型

// ==================== 业务适配器层(推荐)====================
export {
  // 核心函数
  query, get, execute, insert, run, now,
  getDbType, isDbConnected, withTransaction,

  // 业务操作模块
  UserOperations, DnsAccountOperations, DomainOperations,
  TeamOperations, SettingsOperations, AuditOperations,
  TokenOperations, SecretOperations,
  SecurityPolicyOperations, TrustedDeviceOperations,
  UserPreferencesOperations, SessionOperations,
  LoginLimitOperations, FailoverOperations,
  AuditExportOperations, TOTPOperations,
  WebAuthnOperations, SmtpOperations, WhoisOperations,
  AuditRulesOperations, AuditLogOperations,
  OAuthOperations, TwoFAOperations,

  // 类型
  type QueryResult, TransactionOperations,
} from './bal/business-adapter';

// ==================== 初始化函数 ====================
export { initSchema, initSchemaAsync } from './schema';

Schema 管理

职责: 定义和管理数据库表结构

多数据库 Schema

核心表

数据库初始化流程

app.ts:252  → createConnection()     → 创建数据库连接(传统层)
app.ts:255  → connect()              → 初始化业务适配器
app.ts:258  → initSchemaAsync(conn)  → 初始化数据库表结构

initSchemaAsync 函数

export async function initSchemaAsync(conn, reset = false): Promise<void> {
  if (conn.type === 'sqlite') {
    initSQLiteSchema(conn, reset);
  } else if (conn.type === 'mysql') {
    await initMySQLSchema(conn, reset);
  } else if (conn.type === 'postgresql') {
    await initPostgreSQLSchema(conn, reset);
  }
}

数据库调用规范

✅ 正确用法

// 使用业务适配器函数
import { query, get, execute, insert, UserOperations } from '../db';

const user = await get<User>('SELECT * FROM users WHERE id = ?', [userId]);
const users = await query<User>('SELECT * FROM users WHERE status = ?', ['active']);
const id = await insert('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);

❌ 错误用法

// 禁止直接使用兼容层
import { getAdapter } from '../db/adapter';  // 已废除
const db = getAdapter();

日志记录

业务适配器层自动记录所有数据库操作:

[BusinessAdapter] [DEBUG] Executing get {"sql":"SELECT * FROM users WHERE id = ?","params":[1]}
[BusinessAdapter] [ERROR] Get failed {"sql":"...","error":"...","duration":"44ms"}

数据库迁移

迁移脚本位置

server/scripts/
├── db-migrate.ts        # 数据库迁移主脚本
├── db-rollback.ts       # 回滚脚本
└── migrate-*.js         # 特定迁移脚本

迁移流程

  1. 检测数据库类型(SQLite/MySQL/PostgreSQL)
  2. 根据类型选择对应的 SQL 语法
  3. 执行迁移并记录版本
  4. 支持回滚操作

自动迁移