weifuwu 0.33.0 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # weifuwu
2
2
 
3
- **AI SaaS 框架** — `(req, ctx) => Response`
3
+ **AI SaaS framework** — `(req, ctx) => Response`
4
4
 
5
5
  ```bash
6
6
  npm install weifuwu
7
7
  ```
8
8
 
9
- 用户系统、即时消息、RAG 知识库、AI Agent、内容管理、动态数据存储。配好环境变量就能跑。
9
+ User system, instant messaging, RAG knowledge base, AI Agent, CMS, dynamic data storage. Configure environment variables and go.
10
10
 
11
11
  ---
12
12
 
@@ -34,7 +34,7 @@ app.post('/api/chat', async (req, ctx) => {
34
34
  serve(app, { port: 3000 })
35
35
  ```
36
36
 
37
- ### 环境变量
37
+ ### Environment Variables
38
38
 
39
39
  | Variable | Default | Used by |
40
40
  |----------|---------|---------|
@@ -51,12 +51,12 @@ serve(app, { port: 3000 })
51
51
 
52
52
  | Module | Import | Dependency | Purpose |
53
53
  |--------|--------|-----------|---------|
54
- | User | `user()` | `postgres()` | 注册、登录、JWT、角色 |
55
- | Messager | `messager()` | `postgres()`, `user()` | 即时消息、AI 对话交互层 |
56
- | KB | `kb()` | `postgres()` | RAG 知识库、分片、向量搜索 |
57
- | Agent | `agent()` | — | LLM 对话、工具调用、流式输出 |
58
- | CMS | `cms()` | `postgres()`, `user()` | 博客、文档、公告 |
59
- | Base | `base()` | `postgres()`, `user()` | 动态数据存储引擎 |
54
+ | User | `user()` | `postgres()` | Auth, JWT, roles |
55
+ | Messager | `messager()` | `postgres()`, `user()` | IM + AI conversation layer |
56
+ | KB | `kb()` | `postgres()` | RAG knowledge base |
57
+ | Agent | `agent()` | — | LLM chat, tool calling, streaming |
58
+ | CMS | `cms()` | `postgres()`, `user()` | Blog, docs, changelog |
59
+ | Base | `base()` | `postgres()`, `user()` | Dynamic data engine |
60
60
 
61
61
  ### Middleware
62
62
 
@@ -94,7 +94,7 @@ serve(app, { port: 3000 })
94
94
 
95
95
  ## user
96
96
 
97
- 身份认证、注册登录、JWT、密码管理。
97
+ Auth, registration, JWT, password management, roles.
98
98
 
99
99
  ```ts
100
100
  import { user, requireRole } from 'weifuwu'
@@ -102,24 +102,24 @@ import { user, requireRole } from 'weifuwu'
102
102
  app.use(postgres())
103
103
  app.use(user({ secret: process.env.JWT_SECRET }))
104
104
 
105
- // 注册
105
+ // Register
106
106
  app.post('/api/register', async (req, ctx) => {
107
107
  const result = await ctx.userModule.register(await req.json())
108
108
  return Response.json(result)
109
109
  })
110
- // 登录
110
+ // Login
111
111
  app.post('/api/login', async (req, ctx) => {
112
112
  const { email, password } = await req.json()
113
113
  const result = await ctx.userModule.login(email, password)
114
114
  if (!result) return new Response('Unauthorized', { status: 401 })
115
115
  return Response.json(result)
116
116
  })
117
- // 当前用户
117
+ // Current user
118
118
  app.get('/api/me', async (req, ctx) => {
119
119
  if (!ctx.user) return new Response('Unauthorized', { status: 401 })
120
120
  return Response.json(ctx.user)
121
121
  })
122
- // 仅管理员
122
+ // Admin only
123
123
  app.get('/api/admin/users', requireRole('admin'), async (req, ctx) => {
124
124
  return Response.json(await ctx.userModule.listUsers())
125
125
  })
@@ -129,28 +129,28 @@ app.get('/api/admin/users', requireRole('admin'), async (req, ctx) => {
129
129
 
130
130
  | Method | Returns | Description |
131
131
  |--------|---------|-------------|
132
- | `register(input)` | `{ user, token }` | 注册 |
133
- | `login(email, pw)` | `{ user, token } \| null` | 登录 |
134
- | `getUserById(id)` | `UserRecord \| null` | 查用户 |
135
- | `getUserByEmail(email)` | `UserRecord \| null` | 查邮箱 |
136
- | `updateUser(id, input)` | `UserRecord \| null` | 更新 |
137
- | `changePassword(id, oldPw, newPw)` | `boolean` | 改密码 |
138
- | `deleteUser(id)` | `boolean` | 软删除 |
139
- | `listUsers(inactive?)` | `UserRecord[]` | 用户列表 |
140
- | `generateToken(user)` | `string` | 签发 JWT |
141
- | `verifyToken(token)` | `TokenPayload \| null` | 验证 JWT |
142
- | `refreshToken(token)` | `string \| null` | 刷新 JWT |
132
+ | `register(input)` | `{ user, token }` | Register |
133
+ | `login(email, pw)` | `{ user, token } \| null` | Login |
134
+ | `getUserById(id)` | `UserRecord \| null` | Get by ID |
135
+ | `getUserByEmail(email)` | `UserRecord \| null` | Get by email |
136
+ | `updateUser(id, input)` | `UserRecord \| null` | Update |
137
+ | `changePassword(id, oldPw, newPw)` | `boolean` | Change password |
138
+ | `deleteUser(id)` | `boolean` | Soft delete |
139
+ | `listUsers(inactive?)` | `UserRecord[]` | List users |
140
+ | `generateToken(user)` | `string` | Issue JWT |
141
+ | `verifyToken(token)` | `TokenPayload \| null` | Verify JWT |
142
+ | `refreshToken(token)` | `string \| null` | Refresh JWT |
143
143
 
144
144
  ### ctx.user
145
145
 
146
- 由中间件自动从 `Authorization: Bearer` `token` cookie 解析。
146
+ Auto-resolved from `Authorization: Bearer` or `token` cookie.
147
147
 
148
148
  ```ts
149
149
  interface User {
150
150
  id: string
151
151
  name: string
152
152
  email: string
153
- role: string // 'user' | 'admin' | ...
153
+ role: string
154
154
  [key: string]: unknown
155
155
  }
156
156
  ```
@@ -159,19 +159,19 @@ interface User {
159
159
 
160
160
  ```ts
161
161
  app.get('/admin', requireRole('admin'), handler)
162
- // 未登录 → 401,角色不匹配 → 403
162
+ // No auth → 401, wrong role → 403
163
163
  ```
164
164
 
165
- ### 安全
165
+ ### Security
166
166
 
167
- - 密码:scrypt + 随机 32 字节盐
168
- - 令牌:HMAC SHA-2567 天过期
167
+ - Password: scrypt + 32-byte random salt
168
+ - Token: HMAC SHA-256, 7 day expiry
169
169
 
170
170
  ---
171
171
 
172
172
  ## messager
173
173
 
174
- 即时消息 + AI 对话交互层。单聊、群聊、消息持久化、WebSocket 实时推送。
174
+ Instant messaging + AI conversation layer. Direct/group chat, message persistence, WebSocket push.
175
175
 
176
176
  ```ts
177
177
  import { messager } from 'weifuwu'
@@ -180,7 +180,7 @@ app.use(postgres())
180
180
  app.use(user())
181
181
  app.use(messager())
182
182
 
183
- // WebSocket — 自动加入用户的所有会话
183
+ // WebSocket — auto-join all user conversations
184
184
  app.ws('/ws', {
185
185
  async open(ws, ctx) {
186
186
  for (const c of await ctx.messager.getConversations()) {
@@ -209,32 +209,32 @@ app.get('/api/conversations/:id/messages', async (req, ctx) => {
209
209
 
210
210
  | Method | Returns | Description |
211
211
  |--------|---------|-------------|
212
- | `createDirectConversation(userId)` | `Conversation` | 创建/复用私聊 |
213
- | `createGroupConversation(title, userIds)` | `Conversation` | 建群 |
214
- | `sendMessage(convId, body)` | `Message` | 发消息,自动广播到 `conversation:{id}` 房间 |
215
- | `getMessages(convId, opts?)` | `Message[]` | 游标分页 |
216
- | `editMessage(msgId, body)` | `Message \| null` | 编辑(24h 内) |
217
- | `deleteMessage(msgId)` | `boolean` | 软删除 |
218
- | `getConversations()` | `Conversation[]` | 会话列表(含未读、最后消息预览) |
219
- | `getConversation(id)` | `Conversation \| null` | 会话详情 |
220
- | `markRead(convId)` | `void` | 标记已读 |
221
- | `getUnreadCount()` | `{ total, byConversation }` | 未读统计 |
222
- | `addParticipants(convId, userIds)` | `void` | 加人 |
223
- | `removeParticipant(convId, userId?)` | `boolean` | 退出/踢出 |
212
+ | `createDirectConversation(userId)` | `Conversation` | Create/reuse DM |
213
+ | `createGroupConversation(title, userIds)` | `Conversation` | Create group |
214
+ | `sendMessage(convId, body)` | `Message` | Send, auto-broadcast to `conversation:{id}` room |
215
+ | `getMessages(convId, opts?)` | `Message[]` | Cursor pagination |
216
+ | `editMessage(msgId, body)` | `Message \| null` | Edit (24h window) |
217
+ | `deleteMessage(msgId)` | `boolean` | Soft delete |
218
+ | `getConversations()` | `Conversation[]` | List with unread + last message |
219
+ | `getConversation(id)` | `Conversation \| null` | Get detail |
220
+ | `markRead(convId)` | `void` | Mark as read |
221
+ | `getUnreadCount()` | `{ total, byConversation }` | Unread stats |
222
+ | `addParticipants(convId, userIds)` | `void` | Add members |
223
+ | `removeParticipant(convId, userId?)` | `boolean` | Leave / kick |
224
224
 
225
- ### 存储
225
+ ### Storage
226
226
 
227
- 3 张表:`conversations` / `participants` / `messages`。自动建表迁移。
227
+ 3 tables: `conversations` / `participants` / `messages`. Auto-migration.
228
228
 
229
- ### AI 对话
229
+ ### AI Conversations
230
230
 
231
- messager + agent 两个模块组合 = ChatGPT 基础架构。messager 管会话和推送,agent LLM 生成。
231
+ messager + agent = ChatGPT foundation. Messager handles sessions + push, agent handles LLM generation.
232
232
 
233
233
  ---
234
234
 
235
235
  ## kb
236
236
 
237
- RAG 知识库。文档导入自动分片 → DashScope embedding → pgvector 存储语义搜索。
237
+ RAG knowledge base. Import docs auto-chunk → DashScope embedding → pgvector storagesemantic search.
238
238
 
239
239
  ```ts
240
240
  import { kb } from 'weifuwu'
@@ -242,14 +242,14 @@ import { kb } from 'weifuwu'
242
242
  app.use(postgres())
243
243
  app.use(kb())
244
244
 
245
- // 导入
245
+ // Import
246
246
  app.post('/api/kb/import', async (req, ctx) => {
247
247
  const { title, content } = await req.json()
248
248
  const result = await ctx.kb.importText(title, content)
249
249
  return Response.json(result, { status: 201 })
250
250
  })
251
251
 
252
- // 搜索
252
+ // Search
253
253
  app.post('/api/kb/search', async (req, ctx) => {
254
254
  const { query } = await req.json()
255
255
  return Response.json(await ctx.kb.search(query, { limit: 5 }))
@@ -260,30 +260,30 @@ app.post('/api/kb/search', async (req, ctx) => {
260
260
 
261
261
  | Method | Returns | Description |
262
262
  |--------|---------|-------------|
263
- | `importText(title, text, opts?)` | `{ document, chunks }` | 导入分片embedding存储 |
264
- | `importDocuments(docs)` | `Document[]` | 批量导入 |
265
- | `search(query, opts?)` | `SearchResult[]` | 语义搜索(cosine 相似度) |
266
- | `list()` | `Document[]` | 文档列表 |
267
- | `get(id)` | `Document \| null` | 文档详情 |
268
- | `getChunks(documentId)` | `Chunk[]` | 分片列表 |
269
- | `delete(id)` | `boolean` | 删除文档 + 级联删除分片 |
263
+ | `importText(title, text, opts?)` | `{ document, chunks }` | Importchunkembedstore |
264
+ | `importDocuments(docs)` | `Document[]` | Batch import |
265
+ | `search(query, opts?)` | `SearchResult[]` | Semantic search (cosine) |
266
+ | `list()` | `Document[]` | List documents |
267
+ | `get(id)` | `Document \| null` | Get document |
268
+ | `getChunks(documentId)` | `Chunk[]` | Get chunks |
269
+ | `delete(id)` | `boolean` | Delete + cascade chunks |
270
270
 
271
- ### 配置
271
+ ### Configuration
272
272
 
273
273
  ```ts
274
- // 默认:DashScope text-embedding-v4(环境变量 DASHSCOPE_API_KEY
274
+ // Default: DashScope text-embedding-v4 (env: DASHSCOPE_API_KEY)
275
275
  app.use(kb())
276
276
 
277
- // 自定义 embedding
277
+ // Custom embedding
278
278
  app.use(kb({
279
- embed: async (text) => { /* 返回 number[] */ },
279
+ embed: async (text) => { /* return number[] */ },
280
280
  dimensions: 1536,
281
- chunkSize: 512, // 默认分片大小(tokens
282
- chunkOverlap: 64, // 分片重叠
281
+ chunkSize: 512, // tokens
282
+ chunkOverlap: 64,
283
283
  }))
284
284
  ```
285
285
 
286
- ### Agent 配合
286
+ ### Integration with Agent
287
287
 
288
288
  ```ts
289
289
  app.use(agent({
@@ -294,16 +294,16 @@ app.use(agent({
294
294
  }))
295
295
  ```
296
296
 
297
- ### 存储
297
+ ### Storage
298
298
 
299
- - `kb_documents` — 原始文档元数据
300
- - `kb_chunks` — 分片内容 + VECTOR(1536) + TSVECTOR GIN 索引
299
+ - `kb_documents` — document metadata
300
+ - `kb_chunks` — chunk content + VECTOR(1536) + TSVECTOR GIN index
301
301
 
302
302
  ---
303
303
 
304
304
  ## agent
305
305
 
306
- AI Agent — LLM 对话、工具调用、RAG、流式输出。
306
+ AI Agent — LLM chat, tool calling, RAG, streaming.
307
307
 
308
308
  ```ts
309
309
  import { agent } from 'weifuwu'
@@ -327,13 +327,13 @@ app.use(agent({
327
327
  maxSteps: 5,
328
328
  }))
329
329
 
330
- // 流式对话
330
+ // Streaming
331
331
  app.post('/api/chat', async (req, ctx) => {
332
332
  const { messages } = await req.json()
333
333
  return ctx.agent.chatStreamResponse({ messages })
334
334
  })
335
335
 
336
- // 非流式对话
336
+ // Non-streaming
337
337
  app.post('/api/chat/sync', async (req, ctx) => {
338
338
  const { prompt } = await req.json()
339
339
  const text = await ctx.agent.chat(prompt)
@@ -345,30 +345,30 @@ app.post('/api/chat/sync', async (req, ctx) => {
345
345
 
346
346
  | Method | Description |
347
347
  |--------|-------------|
348
- | `chat(prompt, opts?)` | 非流式对话,返回文本 |
349
- | `chatStreamResponse({ messages })` | SSE 流式回复(兼容 `useChat`) |
348
+ | `chat(prompt, opts?)` | Non-streaming, returns text |
349
+ | `chatStreamResponse({ messages })` | SSE stream (compatible with `useChat`) |
350
350
 
351
- ### 默认模型
351
+ ### Default Model
352
352
 
353
- - LLM: DeepSeek-V4-Flash(`@ai-sdk/openai` + `baseURL: 'https://api.deepseek.com/v1'`)
354
- - 环境变量 `DEEPSEEK_MODEL` 可覆盖模型名称
355
- - 环境变量 `DEEPSEEK_API_KEY` `OPENAI_API_KEY` 为 API 密钥
353
+ - LLM: DeepSeek-V4-Flash (via `@ai-sdk/openai` + `baseURL: 'https://api.deepseek.com/v1'`)
354
+ - Override with `DEEPSEEK_MODEL` env
355
+ - API key via `DEEPSEEK_API_KEY` or `OPENAI_API_KEY` env
356
356
 
357
357
  ### Features
358
358
 
359
359
  | Feature | Description |
360
360
  |---------|-------------|
361
- | `knowledge.search` | RAG 回调,自动注入 system prompt |
362
- | `tools` | 工具定义,自动循环调用(maxSteps |
363
- | `sandbox: true` | `ctx.sandbox` 集成(文件读写) |
364
- | `store` | 对话持久化(save/load |
365
- | `agents` | Agent 编排 |
361
+ | `knowledge.search` | RAG callback, auto-injected into system prompt |
362
+ | `tools` | Tool definitions, auto-loop (maxSteps) |
363
+ | `sandbox: true` | Integrates with `ctx.sandbox` |
364
+ | `store` | Session persistence (save/load) |
365
+ | `agents` | Multi-agent orchestration |
366
366
 
367
367
  ---
368
368
 
369
369
  ## cms
370
370
 
371
- 内容管理博客、文档、公告、更新日志。
371
+ Content management blog, docs, changelog.
372
372
 
373
373
  ```ts
374
374
  import { cms, requireRole } from 'weifuwu'
@@ -377,7 +377,7 @@ app.use(postgres())
377
377
  app.use(user())
378
378
  app.use(cms())
379
379
 
380
- // 公开:已发布的文章
380
+ // Public
381
381
  app.get('/api/posts', async (req, ctx) => {
382
382
  return Response.json(await ctx.cms.list({ type: 'post', status: 'published' }))
383
383
  })
@@ -387,7 +387,7 @@ app.get('/api/posts/:slug', async (req, ctx) => {
387
387
  return Response.json(post)
388
388
  })
389
389
 
390
- // 管理端
390
+ // Admin
391
391
  app.post('/api/admin/posts', requireRole('admin'), async (req, ctx) => {
392
392
  const post = await ctx.cms.create(await req.json())
393
393
  return Response.json(post, { status: 201 })
@@ -403,31 +403,31 @@ app.patch('/api/admin/posts/:id', requireRole('admin'), async (req, ctx) => {
403
403
 
404
404
  | Method | Returns | Description |
405
405
  |--------|---------|-------------|
406
- | `create(input)` | `Content` | 创建(admin |
407
- | `get(slug)` | `Content \| null` | slug 获取 |
408
- | `getById(id)` | `Content \| null` | id 获取 |
409
- | `update(id, input)` | `Content \| null` | 更新(admin |
410
- | `delete(id)` | `boolean` | 删除(admin |
411
- | `list(opts?)` | `Content[]` | 列表(游标分页) |
412
- | `publish(id)` | `Content \| null` | 发布(admin |
413
- | `unpublish(id)` | `Content \| null` | 下线(admin |
414
- | `listTags()` | `TagWithCount[]` | 标签列表 |
415
- | `createTag(name)` | `Tag` | 创建标签 |
406
+ | `create(input)` | `Content` | Create (admin) |
407
+ | `get(slug)` | `Content \| null` | Get by slug |
408
+ | `getById(id)` | `Content \| null` | Get by ID |
409
+ | `update(id, input)` | `Content \| null` | Update (admin) |
410
+ | `delete(id)` | `boolean` | Delete (admin) |
411
+ | `list(opts?)` | `Content[]` | List with cursor |
412
+ | `publish(id)` | `Content \| null` | Publish (admin) |
413
+ | `unpublish(id)` | `Content \| null` | Unpublish (admin) |
414
+ | `listTags()` | `TagWithCount[]` | List tags |
415
+ | `createTag(name)` | `Tag` | Create tag |
416
416
 
417
417
  ### Features
418
418
 
419
- - 内容类型:post / page / doc / changelog(任意字符串)
420
- - 状态:draft / published / archived
421
- - Slug:自动生成,同类型唯一
422
- - 标签:多对多,自动创建
423
- - 树形:parent_id 支持层级
424
- - 鉴权:非管理员只能读已发布
419
+ - Types: post / page / doc / changelog (any string)
420
+ - Status: draft / published / archived
421
+ - Slug: auto-generated, unique per type
422
+ - Tags: many-to-many, auto-created
423
+ - Tree: parent_id for hierarchy
424
+ - Auth: non-admin users see published only
425
425
 
426
426
  ---
427
427
 
428
428
  ## base
429
429
 
430
- 动态数据存储引擎让用户自定义数据结构(类似 Airtable)。
430
+ Dynamic data storage engine let users define their own data structures (like Airtable).
431
431
 
432
432
  ```ts
433
433
  import { base } from 'weifuwu'
@@ -436,13 +436,13 @@ app.use(postgres())
436
436
  app.use(user())
437
437
  app.use(base())
438
438
 
439
- // 定义数据结构
439
+ // Define schema
440
440
  app.post('/api/bases', async (req, ctx) => {
441
441
  const b = await ctx.base.create(await req.json())
442
442
  return Response.json(b, { status: 201 })
443
443
  })
444
444
 
445
- // 增删改查
445
+ // CRUD
446
446
  app.post('/api/bases/:id/:table', async (req, ctx) => {
447
447
  const row = await ctx.base.insert(ctx.params.id, ctx.params.table, await req.json())
448
448
  return Response.json(row, { status: 201 })
@@ -461,35 +461,37 @@ app.get('/api/bases/:id/:table', async (req, ctx) => {
461
461
 
462
462
  | Method | Returns | Description |
463
463
  |--------|---------|-------------|
464
- | `create({ name, tables })` | `BaseDef` | 创建数据库 |
465
- | `defineTable(baseId, schema)` | `BaseDef` | 加表 |
466
- | `updateTable(baseId, name, schema)` | `BaseDef \| null` | 改表 |
467
- | `removeTable(baseId, name)` | `BaseDef \| null` | 删表 |
468
- | `insert(baseId, table, data)` | `Row` | 插入行 |
469
- | `getRow(baseId, table, id)` | `Row \| null` | 查行 |
470
- | `updateRow(baseId, table, id, data)` | `Row \| null` | 改行 |
471
- | `deleteRow(baseId, table, id)` | `boolean` | 删行 |
472
- | `query(baseId, table, opts?)` | `Row[]` | 查询(filter/sort/limit/offset |
473
- | `search(baseId, table, field, query)` | `Row[]` | 全文搜索 |
474
- | `similaritySearch(baseId, table, field, vector)` | `Row[]` | 向量搜索 |
475
- | `list()` / `get(id)` / `getBySlug(slug)` / `delete(id)` | — | 数据库管理 |
476
-
477
- ### 架构
478
-
479
- Fixed Slot:一张 `base_data` 表,预分配 ~120 个物理列:
480
-
481
- | 类型 | 列数 | PG 类型 |
482
- |------|:----:|:--------:|
464
+ | `create({ name, tables })` | `BaseDef` | Create database |
465
+ | `defineTable(baseId, schema)` | `BaseDef` | Add table |
466
+ | `updateTable(baseId, name, schema)` | `BaseDef \| null` | Update table |
467
+ | `removeTable(baseId, name)` | `BaseDef \| null` | Remove table |
468
+ | `insert(baseId, table, data)` | `Row` | Insert row |
469
+ | `getRow(baseId, table, id)` | `Row \| null` | Get row |
470
+ | `updateRow(baseId, table, id, data)` | `Row \| null` | Update row |
471
+ | `deleteRow(baseId, table, id)` | `boolean` | Delete row |
472
+ | `query(baseId, table, opts?)` | `Row[]` | Query (filter/sort/limit/offset) |
473
+ | `search(baseId, table, field, query)` | `Row[]` | Full-text search |
474
+ | `similaritySearch(baseId, table, field, vector)` | `Row[]` | Vector search |
475
+ | `list()` / `get(id)` / `getBySlug(slug)` / `delete(id)` | — | Manage databases |
476
+
477
+ ### Architecture
478
+
479
+ Fixed Slot: a single `base_data` table with ~120 physical columns:
480
+
481
+ | Type | Count | PG Type |
482
+ |------|:-----:|:--------:|
483
483
  | text001..064 | 64 | TEXT |
484
484
  | number001..032 | 32 | DOUBLE PRECISION |
485
485
  | date001..008 | 8 | TIMESTAMPTZ |
486
486
  | vector001..004 | 4 | VECTOR(1536) |
487
487
  | search001..004 | 4 | TEXT |
488
- | ext | 1 | JSONB(溢出兜底) |
488
+ | ext | 1 | JSONB (overflow) |
489
489
 
490
- 字段名物理列号 的映射存储在 `base_column_map` 表。超出物理列的字段自动溢出到 ext JSONB
490
+ Field name physical column mapping stored in `base_column_map`. Fields beyond the physical columns overflow to ext JSONB.
491
491
 
492
- pgvector 自动检测:docker 镜像默认支持。
492
+ pgvector auto-detected (included in docker image).
493
+
494
+ ---
493
495
 
494
496
  ---
495
497
 
@@ -507,12 +509,12 @@ app.all(path, ...handlers)
507
509
  app.ws(path, ...middlewares, handler)
508
510
  // handler: { open?, message?, close?, error? }
509
511
 
510
- // 中间件 & 挂载
512
+ // Middleware & mounting
511
513
  app.use(middleware)
512
514
  app.mount(prefix, router)
513
515
  app.plugin(fn)
514
516
  app.onError(handler)
515
- app.routes() // 调试:列出所有路由
517
+ app.routes() // debug: list all routes
516
518
  ```
517
519
 
518
520
  ---
@@ -546,7 +548,7 @@ await sql.sql`SELECT * FROM users WHERE id = ${id}`
546
548
  await sql.sql.begin(async (sql) => { /* transaction */ })
547
549
  ```
548
550
 
549
- `DATABASE_URL` 环境变量。支持迁移、事务、连接池统计。
551
+ Reads `DATABASE_URL` env. Supports migrations, transactions, connection pool stats.
550
552
 
551
553
  ---
552
554
 
@@ -560,7 +562,7 @@ app.use(r) // → ctx.redis
560
562
  await r.redis.set('key', 'value')
561
563
  ```
562
564
 
563
- `REDIS_URL` 环境变量,默认 `redis://localhost:6379`。
565
+ Reads `REDIS_URL` env (default: `redis://localhost:6379`).
564
566
 
565
567
  ---
566
568
 
@@ -585,20 +587,19 @@ q.run()
585
587
 
586
588
  ```
587
589
  src/
588
- ├── index.ts ← 入口,导出所有模块
589
- ├── types.ts ← Context, Handler, Middleware 定义
590
+ ├── index.ts ← Entry, exports all modules
591
+ ├── types.ts ← Context, Handler, Middleware types
590
592
  ├── core/ ← serve, router, ws, trace, logger
591
593
  ├── middleware/ ← cors, helmet, compress, rate-limit, upload, static, sandbox
592
- ├── user/ ← 用户系统(CRUDJWTrequireRole
593
- ├── messager/ ← 即时消息 + AI 对话交互层
594
- ├── kb/ ← RAG 知识库(分片、embedding、向量搜索)
595
- ├── ai/ ← AI AgentLLMtoolsRAG
596
- ├── cms/ ← 内容管理(博客、文档、公告)
597
- ├── base/ ← 动态数据存储引擎(Fixed Slot
598
- ├── postgres/ ← PostgreSQL 客户端
599
- ├── redis/ ← Redis 客户端
600
- ├── queue/ ← 任务队列 + cron
601
- ├── react/ ← React SSR
594
+ ├── user/ ← User system (CRUD, JWT, requireRole)
595
+ ├── messager/ ← IM + AI conversation layer
596
+ ├── kb/ ← RAG knowledge base (chunking, embedding, vector search)
597
+ ├── ai/ ← AI Agent (LLM, tools, RAG)
598
+ ├── cms/ ← Content management (blog, docs, changelog)
599
+ ├── base/ ← Dynamic data engine (Fixed Slot)
600
+ ├── postgres/ ← PostgreSQL client
601
+ ├── redis/ ← Redis client
602
+ ├── queue/ ← Job queue + cron
602
603
  ├── graphql.ts ← GraphQL
603
604
  ├── hub.ts ← WebSocket hub
604
605
  └── test/ ← 281 tests
@@ -611,7 +612,7 @@ docker-compose.yml ← postgres (pgvector) + redis
611
612
  ## Development
612
613
 
613
614
  ```bash
614
- docker compose up -d # 启动 postgres + redis
615
+ docker compose up -d # Start postgres + redis
615
616
  npm run build # esbuild → dist/
616
617
  npm run typecheck # tsc --noEmit
617
618
  npm test # 281 tests
package/dist/index.d.ts CHANGED
@@ -37,9 +37,6 @@ export { createHub } from './hub.ts';
37
37
  export type { Hub, HubOptions } from './hub.ts';
38
38
  export { queue } from './queue/index.ts';
39
39
  export type { QueueOptions, QueueJob, Queue, QueueInjected } from './queue/types.ts';
40
- export { react, reactRouter } from './react/index.ts';
41
- export type { ReactOptions, RenderOptions, ReactRouterOptions, ReactAppOptions } from './react/types.ts';
42
- export { useServerData, ServerDataContext, Link, ErrorBoundary } from './react/index.ts';
43
40
  export { ai } from './ai/index.ts';
44
41
  export type { AiOptions, Ai } from './ai/index.ts';
45
42
  export { agent } from './ai/agent.ts';