npm package: @lark-apaas/express-datapaas
Description: Drizzle ORM + PostgreSQL with RLS support for Express
Latest version: 0.0.4

# @lark-apaas/express-datapaas

基于 Drizzle ORM 封装的 PostgreSQL 数据库模块，为 Express 应用提供连接管理与 RLS（行级安全）支持。

## 功能特性

- 基于 Drizzle ORM + postgres-js 的数据库连接管理
- 自动在 pg session 层面注入用户上下文，无感支持 RLS
- 简洁的函数式 API，`createDatabase` 返回可直接使用的 `db` 实例
- Express 中间件形式的 RLS 上下文注入

## 安装

```bash
npm install @lark-apaas/express-datapaas
```

### Peer Dependencies

需要同时安装以下依赖：

```bash
npm install drizzle-orm@0.44.6 express
```

> **注意**: drizzle-orm 版本必须为 `0.44.6`，安装后会自动通过 postinstall 脚本打补丁以支持 RLS 功能。

## 快速开始

### 1. 创建数据库实例

```typescript
import { createDatabase } from '@lark-apaas/express-datapaas';
import * as schema from './schema';

const { db, close } = createDatabase({
  connectionString: process.env.DATABASE_URL!,
  schema,
  logger: false,
  maxConnections: 1,
  idleTimeout: 20,
  connectionTimeout: 10,
  ssl: false,
});

// 应用退出时关闭连接
process.on('SIGTERM', async () => {
  await close();
});
```

### 2. 注册 RLS 中间件

```typescript
import express from 'express';
import { createRlsMiddleware } from '@lark-apaas/express-datapaas';

const app = express();

// 在 userContext 中间件之后注册
app.use(createRlsMiddleware());
```

中间件会从 `req.userContext` 读取用户信息，自动为后续的数据库查询设置 RLS 上下文。

### 3. 使用数据库

```typescript
import { db } from './database';
import { users } from './schema';

app.get('/api/users', async (req, res) => {
  // db 查询自动携带 RLS 上下文
  const result = await db.select().from(users);
  res.json(result);
});
```

## API 参考

### createDatabase(config)

创建数据库连接实例。

**参数 `CreateDatabaseConfig`：**

| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `connectionString` | `string` | 是 | - | PostgreSQL 连接串 |
| `schema` | `object` | 否 | - | Drizzle schema 对象 |
| `logger` | `boolean \| Logger` | 否 | `false` | 是否启用 SQL 日志 |
| `maxConnections` | `number` | 否 | `1` | 最大连接数 |
| `idleTimeout` | `number` | 否 | `20` | 空闲连接超时（秒） |
| `connectionTimeout` | `number` | 否 | `10` | 连接超时（秒） |
| `ssl` | `string \| boolean \| object` | 否 | `false` | SSL 配置，连接串含 `sslmode=require` 时自动启用 |

**返回值 `DatabaseInstance`：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `db` | `PostgresJsDatabase` | Drizzle 数据库实例，可直接用于查询 |
| `close` | `() => Promise<void>` | 关闭数据库连接 |

### createRlsMiddleware(options?)

创建 Express RLS 中间件。

**参数 `RlsMiddlewareOptions`（可选）：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `roleSchema` | `string` | 角色 schema 标识。省略时自动使用 `createDatabase` 从连接串解析的值 |

**UserContext 结构：**

中间件从 `req.userContext` 读取以下字段：

```typescript
interface UserContext {
  userId?: string;        // 用户 ID
  tenantId?: number;      // 租户 ID
  appId?: string;         // 应用 ID
  roles?: string[];       // 用户角色列表
  isSystemAccount: boolean; // 是否系统账号
  userType?: string;      // 用户类型
}
```

**RLS 行为：**

| 场景 | 设置的 PostgreSQL 角色 |
|------|----------------------|
| 系统账号 (`isSystemAccount: true`) | `service_role_{schema}` |
| 已登录用户 (`userId` 存在) | `authenticated_{schema}` |
| 匿名用户 | `anon_{schema}` |

同时会设置 `app.user_id`、`app.role_ids`、`app.user_type` 等会话变量。

## 注意事项

1. **drizzle-orm 版本锁定**：必须使用 `drizzle-orm@0.44.6`，该版本已通过 patch-package 打补丁以支持 RLS 上下文注入
2. **应用层不要单独安装 drizzle-orm**：如果需要 drizzle-orm 的类型导出，直接从 `@lark-apaas/express-datapaas` 导入（如 `PostgresJsDatabase`）
3. **中间件顺序**：`createRlsMiddleware()` 必须在设置 `req.userContext` 的中间件之后注册
4. **连接关闭**：应用退出时务必调用 `close()` 释放连接资源

## License

MIT