weifuwu 0.13.1 → 0.14.0
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 +7 -2
- package/README.zh.md +155 -0
- package/cli.ts +6 -2
- package/dist/agent/rest.d.ts +2 -0
- package/dist/agent/run.d.ts +3 -0
- package/dist/cli.js +6 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +597 -253
- package/dist/logdb/client.d.ts +2 -0
- package/dist/logdb/index.d.ts +2 -0
- package/dist/logdb/migrate.d.ts +5 -0
- package/dist/logdb/rest.d.ts +5 -0
- package/dist/logdb/types.d.ts +27 -0
- package/dist/messager/rest.d.ts +4 -0
- package/dist/postgres/schema/columns.d.ts +5 -0
- package/dist/postgres/schema/index.d.ts +4 -2
- package/dist/postgres/schema/table.d.ts +27 -10
- package/dist/postgres/schema/where.d.ts +15 -0
- package/docs/ai.md +1 -1
- package/docs/logdb.md +145 -0
- package/docs/opencode.md +17 -17
- package/docs/postgres.md +115 -20
- package/docs/tsx.md +2 -2
- package/docs/user.md +17 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Everything follows the same `(req, ctx) => Response` contract. The Router handle
|
|
|
21
21
|
- **Middleware** — global/path-scoped/route-level — onion model with short-circuit
|
|
22
22
|
- **Modules** — auth, validation, upload, compression, rate-limit, cookies, static files, CORS, logging
|
|
23
23
|
- **React SSR** — `tsx()` — pages, layouts, loaders, route handlers, Tailwind CSS, HMR
|
|
24
|
-
- **PostgreSQL** — schema builder with type-safe DDL
|
|
24
|
+
- **PostgreSQL** — schema builder with type-safe DDL, CRUD (`read`/`readMany`, `insertMany`, `update`/`updateMany`, `delete`/`deleteMany`), WHERE helpers (`eq`, `gte`, `contains`, `and`, `or`), transactions, vector search
|
|
25
25
|
- **Auth** — password + JWT + OAuth2 Server (authorization code / PKCE / client_credentials)
|
|
26
26
|
- **Real-time** — WebSocket, messaging channels with agent routing
|
|
27
27
|
- **AI** — streaming endpoint, DAG workflow tool, AI agents with RAG and tool-use
|
|
@@ -31,6 +31,7 @@ Everything follows the same `(req, ctx) => Response` contract. The Router handle
|
|
|
31
31
|
- **i18n** — locale detection, JSON translations, `ctx.t()`
|
|
32
32
|
- **Email** — SMTP or custom transport
|
|
33
33
|
- **Health check** — configurable `/health` endpoint
|
|
34
|
+
- **Environment** — `loadEnv()` — `.env` file loader into `process.env`
|
|
34
35
|
- **Test utilities** — `createTestServer()` — one-line test server setup
|
|
35
36
|
|
|
36
37
|
## Quick start
|
|
@@ -95,13 +96,14 @@ node app.ts
|
|
|
95
96
|
| **Messager** | [docs/messager.md](./docs/messager.md) | Real-time chat, channels, WebSocket, agent routing |
|
|
96
97
|
| **GraphQL** | [docs/graphql.md](./docs/graphql.md) | GraphQL endpoint with GraphiQL |
|
|
97
98
|
| **Tenant BaaS** | [docs/tenant.md](./docs/tenant.md) | Dynamic tables, auto REST + GraphQL, row isolation |
|
|
99
|
+
| **LogDB** | [docs/logdb.md](./docs/logdb.md) | Structured event logging with partitioning, metadata search, REST API |
|
|
98
100
|
| **Extra** | [docs/extra.md](./docs/extra.md) | Health check, i18n, email, test utilities |
|
|
99
101
|
|
|
100
102
|
### Infrastructure
|
|
101
103
|
|
|
102
104
|
| Module | Import | What it gives you |
|
|
103
105
|
|--------|--------|-------------------|
|
|
104
|
-
| PostgreSQL | `postgres(options?)` | Connection pool + schema builder + CRUD + transactions |
|
|
106
|
+
| PostgreSQL | `postgres(options?)` | Connection pool + schema builder + CRUD (`read`/`readMany`, `insertMany`, `update`/`updateMany`, `delete`/`deleteMany`) + where helpers (`eq`, `gte`, `contains`, `and`, `or`) + transactions |
|
|
105
107
|
| Redis | `redis(options?)` | ioredis client injected as `ctx.redis` |
|
|
106
108
|
| Queue | `queue(options?)` | Redis-backed job queue with cron scheduling |
|
|
107
109
|
| Deploy | `deploy(config)` | Self-hosted PaaS, see [deploy.md](./deploy.md) |
|
|
@@ -119,6 +121,7 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
119
121
|
| `messager(options)` | Real-time messaging | `migrate()`, `wsHandler()`, `send()`, `close()` |
|
|
120
122
|
| `aiStream(handler)` | AI streaming endpoint | — |
|
|
121
123
|
| `graphql(handler)` | GraphQL endpoint | — |
|
|
124
|
+
| `logdb(options)` | Structured event logging | `log()`, `migrate()`, `clean()`, `close()` |
|
|
122
125
|
| `health(options?)` | Health check | — |
|
|
123
126
|
|
|
124
127
|
### Middleware (all `(req, ctx, next) => Response`)
|
|
@@ -139,6 +142,7 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
139
142
|
| Function | Description |
|
|
140
143
|
|----------|-------------|
|
|
141
144
|
| `serveStatic(root, options?)` | Static file serving |
|
|
145
|
+
| `loadEnv(path?)` | Load `.env` file into `process.env` — no override, comments, quotes |
|
|
142
146
|
| `getCookies(req)` / `setCookie(res, ...)` / `deleteCookie(res, ...)` | Cookie helpers |
|
|
143
147
|
| `mailer(options)` | Email sender (SMTP or custom) |
|
|
144
148
|
| `createTestServer(handler)` | Start test server → `{ server, url }` |
|
|
@@ -146,6 +150,7 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
146
150
|
| `pgTable(name, columns)` | Type-safe table schema builder |
|
|
147
151
|
| `pg.table(name, columns)` | Pre-bound table (no `sql` param needed) |
|
|
148
152
|
| `serial()`, `uuid()`, `text()`, ... | Column type builders |
|
|
153
|
+
| `eq()`, `gte()`, `contains()`, `and()` ... | WHERE clause helpers — same API as Drizzle |
|
|
149
154
|
| `PgModule` | Base class for DB-backed modules |
|
|
150
155
|
|
|
151
156
|
## License
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: weifuwu
|
|
3
|
+
description: 面向 Node.js 的 Web 标准 HTTP 框架 — (req, ctx) => Response
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# weifuwu
|
|
7
|
+
|
|
8
|
+
**面向 Node.js 的 Web 标准 HTTP 框架。** `(req, ctx) => Response` — 没有框架特有的对象,只有浏览器原生支持的 Web API。
|
|
9
|
+
|
|
10
|
+
### 设计理念
|
|
11
|
+
|
|
12
|
+
weifuwu 不发明自己的请求/响应抽象。`Request` 和 `Response` 就是你在 `fetch()` 中使用的那套 API——你在浏览器中学到的知识可以直接用在服务端。`ctx` 是唯一的框架对象,它只携带路由解析的结果(`params`、`query`)。
|
|
13
|
+
|
|
14
|
+
所有功能遵循相同的 `(req, ctx) => Response` 约定。Router 负责 HTTP 路由和 WebSocket。其他所有功能——认证、校验、数据库、GraphQL、AI——都是独立的模块,通过 `app.use()` 挂载。
|
|
15
|
+
|
|
16
|
+
## 功能特性
|
|
17
|
+
|
|
18
|
+
- **Web 标准** — `Request` / `Response` / `ReadableStream`,零抽象
|
|
19
|
+
- **零构建** — Node.js v24+ 原生 TypeScript,核心零依赖
|
|
20
|
+
- **Trie 路由器** — 静态 > 参数 > 通配符,子路由挂载,WebSocket
|
|
21
|
+
- **中间件** — 全局/路径级/路由级 — 洋葱模型,支持短路
|
|
22
|
+
- **模块** — 认证、校验、上传、压缩、限流、Cookie、静态文件、CORS、日志
|
|
23
|
+
- **React SSR** — `tsx()` — 页面、布局、数据加载、路由处理、Tailwind CSS、HMR
|
|
24
|
+
- **PostgreSQL** — 类型安全 DDL + CRUD 的 schema 构建器,事务,向量搜索
|
|
25
|
+
- **认证** — 密码 + JWT + OAuth2 服务端(authorization code / PKCE / client_credentials)
|
|
26
|
+
- **实时** — WebSocket,带 agent 路由的消息频道
|
|
27
|
+
- **AI** — 流式端点,DAG 工作流工具,支持 RAG 和工具调用的 AI agent
|
|
28
|
+
- **数据** — Redis 客户端,支持 cron 调度的任务队列
|
|
29
|
+
- **多租户 BaaS** — 动态表,自动 REST + GraphQL,行级隔离
|
|
30
|
+
- **部署** — 自托管 PaaS:多应用代理,零停机更新,自动 SSL
|
|
31
|
+
- **国际化** — 语言检测,JSON 翻译,`ctx.t()`
|
|
32
|
+
- **邮件** — SMTP 或自定义传输
|
|
33
|
+
- **健康检查** — 可配置的 `/health` 端点
|
|
34
|
+
- **环境变量** — `loadEnv()` — 将 `.env` 文件加载到 `process.env`
|
|
35
|
+
- **测试工具** — `createTestServer()` — 一行代码搭建测试服务
|
|
36
|
+
|
|
37
|
+
## 快速开始
|
|
38
|
+
|
|
39
|
+
### Hello World
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { serve } from 'weifuwu'
|
|
43
|
+
serve((req, ctx) => new Response('Hello, World!'), { port: 3000 })
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 完整应用
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { serve, Router, postgres, user, aiStream, graphql } from 'weifuwu'
|
|
50
|
+
import { openai } from '@ai-sdk/openai'
|
|
51
|
+
|
|
52
|
+
const app = new Router()
|
|
53
|
+
const pg = postgres()
|
|
54
|
+
|
|
55
|
+
// 认证
|
|
56
|
+
const auth = user({ pg, jwtSecret: process.env.JWT_SECRET! })
|
|
57
|
+
await auth.migrate()
|
|
58
|
+
app.use('/auth', auth.router())
|
|
59
|
+
|
|
60
|
+
// AI 流式
|
|
61
|
+
const chat = await aiStream(async (req) => ({
|
|
62
|
+
model: openai('gpt-4o'),
|
|
63
|
+
messages: (await req.json()).messages,
|
|
64
|
+
}))
|
|
65
|
+
app.use('/chat', chat.router())
|
|
66
|
+
|
|
67
|
+
// GraphQL
|
|
68
|
+
const gql = graphql(() => ({
|
|
69
|
+
schema: `type Query { hello: String }`,
|
|
70
|
+
resolvers: { Query: { hello: () => 'world' } },
|
|
71
|
+
}))
|
|
72
|
+
app.use('/graphql', gql.router())
|
|
73
|
+
|
|
74
|
+
// 静态文件
|
|
75
|
+
app.get('/static/*', serveStatic('./public'))
|
|
76
|
+
|
|
77
|
+
serve(app.handler(), { port: 3000 })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
node app.ts
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 文档
|
|
85
|
+
|
|
86
|
+
| 模块 | 文档 | 说明 |
|
|
87
|
+
|--------|------|------|
|
|
88
|
+
| **Router** | [docs/router.md](./docs/router.md) | 路由、中间件、WebSocket、错误处理 |
|
|
89
|
+
| **Middleware** | [docs/middleware.md](./docs/middleware.md) | auth, cors, logger, rateLimit, compress, validate, upload, cookie, static |
|
|
90
|
+
| **PostgreSQL** | [docs/postgres.md](./docs/postgres.md) | Schema 构建器、CRUD、DDL、事务、PgModule |
|
|
91
|
+
| **Auth & User** | [docs/user.md](./docs/user.md) | 密码、JWT、OAuth2 服务端、社交登录示例 |
|
|
92
|
+
| **React SSR** | [docs/tsx.md](./docs/tsx.md) | 页面、布局、数据加载、Tailwind、shadcn/ui |
|
|
93
|
+
| **AI** | [docs/ai.md](./docs/ai.md) | `aiStream()`, `runWorkflow()` |
|
|
94
|
+
| **AI Agent** | [docs/agent.md](./docs/agent.md) | 对话、工具调用、RAG 知识库 |
|
|
95
|
+
| **Opencode** | [docs/opencode.md](./docs/opencode.md) | 编程助手、技能、会话、权限 |
|
|
96
|
+
| **Messager** | [docs/messager.md](./docs/messager.md) | 实时聊天、频道、WebSocket、agent 路由 |
|
|
97
|
+
| **GraphQL** | [docs/graphql.md](./docs/graphql.md) | 带 GraphiQL 的 GraphQL 端点 |
|
|
98
|
+
| **Tenant BaaS** | [docs/tenant.md](./docs/tenant.md) | 动态表、自动 REST + GraphQL、行隔离 |
|
|
99
|
+
| **Extra** | [docs/extra.md](./docs/extra.md) | 健康检查、国际化、邮件、测试工具 |
|
|
100
|
+
|
|
101
|
+
### 基础设施
|
|
102
|
+
|
|
103
|
+
| 模块 | 导入 | 功能 |
|
|
104
|
+
|--------|--------|-----------|
|
|
105
|
+
| PostgreSQL | `postgres(options?)` | 连接池 + schema 构建器 + CRUD + 事务 |
|
|
106
|
+
| Redis | `redis(options?)` | ioredis 客户端,注入为 `ctx.redis` |
|
|
107
|
+
| 队列 | `queue(options?)` | 基于 Redis 的任务队列,支持 cron 调度 |
|
|
108
|
+
| 部署 | `deploy(config)` | 自托管 PaaS,详见 [deploy.md](./deploy.md) |
|
|
109
|
+
|
|
110
|
+
### 可挂载模块
|
|
111
|
+
|
|
112
|
+
所有模块遵循相同模式 — `const m = module(options)` → `app.use('/path', m.router())`:
|
|
113
|
+
|
|
114
|
+
| 模块 | 用途 | 额外提供 |
|
|
115
|
+
|--------|---------|---------------|
|
|
116
|
+
| `user(options)` | 认证(密码 + JWT + OAuth2) | `migrate()`, `middleware()`, `register()`, `login()`, `verify()`, `close()` |
|
|
117
|
+
| `tenant(options)` | 多租户 BaaS | `migrate()`, `middleware()`, `graphql()`, `close()` |
|
|
118
|
+
| `agent(options)` | AI agents | `migrate()`, `run()`, `addKnowledge()`, `close()` |
|
|
119
|
+
| `opencode(options)` | 编程助手 | `migrate()`, `wsHandler()`, `close()` |
|
|
120
|
+
| `messager(options)` | 实时消息 | `migrate()`, `wsHandler()`, `send()`, `close()` |
|
|
121
|
+
| `aiStream(handler)` | AI 流式端点 | — |
|
|
122
|
+
| `graphql(handler)` | GraphQL 端点 | — |
|
|
123
|
+
| `health(options?)` | 健康检查 | — |
|
|
124
|
+
|
|
125
|
+
### 中间件(全部为 `(req, ctx, next) => Response`)
|
|
126
|
+
|
|
127
|
+
| 中间件 | 说明 |
|
|
128
|
+
|-----------|-------------|
|
|
129
|
+
| `auth(options)` | Bearer token / 自定义请求头 / 验证 / 代理 |
|
|
130
|
+
| `cors(options?)` | CORS,含预检请求、来源白名单、凭据 |
|
|
131
|
+
| `logger(options?)` | 带耗时的请求日志 |
|
|
132
|
+
| `rateLimit(options?)` | 基于内存的限流,带响应头 |
|
|
133
|
+
| `compress(options?)` | Brotli / Gzip / Deflate 压缩 |
|
|
134
|
+
| `validate(schemas)` | Zod 校验(body, query, params) |
|
|
135
|
+
| `upload(options?)` | 多部分文件上传 |
|
|
136
|
+
| `i18n(options)` | 国际化 — `ctx.t()`,语言检测 |
|
|
137
|
+
|
|
138
|
+
### 工具函数
|
|
139
|
+
|
|
140
|
+
| 函数 | 说明 |
|
|
141
|
+
|----------|-------------|
|
|
142
|
+
| `serveStatic(root, options?)` | 静态文件服务 |
|
|
143
|
+
| `loadEnv(path?)` | 加载 `.env` 文件到 `process.env` — 不覆盖、支持注释和引号 |
|
|
144
|
+
| `getCookies(req)` / `setCookie(res, ...)` / `deleteCookie(res, ...)` | Cookie 助手 |
|
|
145
|
+
| `mailer(options)` | 邮件发送(SMTP 或自定义) |
|
|
146
|
+
| `createTestServer(handler)` | 启动测试服务 → `{ server, url }` |
|
|
147
|
+
| `runWorkflow(options)` | 作为 AI SDK `Tool` 的 DAG 执行引擎 |
|
|
148
|
+
| `pgTable(name, columns)` | 类型安全的表 schema 构建器 |
|
|
149
|
+
| `pg.table(name, columns)` | 预绑定表(无需传 `sql` 参数) |
|
|
150
|
+
| `serial()`, `uuid()`, `text()`, ... | 列类型构建器 |
|
|
151
|
+
| `PgModule` | 数据库模块的基类 |
|
|
152
|
+
|
|
153
|
+
## 许可证
|
|
154
|
+
|
|
155
|
+
MIT
|
package/cli.ts
CHANGED
|
@@ -60,12 +60,16 @@ async function cmdInit(name: string) {
|
|
|
60
60
|
await writeFile(join(targetDir, '.env'), 'PORT=3000\n')
|
|
61
61
|
|
|
62
62
|
await writeFile(join(targetDir, 'app.ts'), [
|
|
63
|
-
"import { serve, loadEnv } from 'weifuwu'",
|
|
63
|
+
"import { serve, Router, loadEnv } from 'weifuwu'",
|
|
64
64
|
'',
|
|
65
65
|
"loadEnv()",
|
|
66
66
|
"const port = Number(process.env.PORT) || 3000",
|
|
67
67
|
'',
|
|
68
|
-
"
|
|
68
|
+
"const app = new Router()",
|
|
69
|
+
"app.get('/', (req, ctx) => new Response('Hello, Weifuwu!'))",
|
|
70
|
+
'',
|
|
71
|
+
"serve(app.handler(), { port })",
|
|
72
|
+
"console.log(`Listening on http://localhost:${port}`)",
|
|
69
73
|
'',
|
|
70
74
|
].join('\n'))
|
|
71
75
|
|
package/dist/agent/rest.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Sql } from '../vendor.ts';
|
|
2
2
|
import { Router } from '../router.ts';
|
|
3
|
+
import type { BoundTable } from '../postgres/schema/index.ts';
|
|
3
4
|
import type { RunParams } from './types.ts';
|
|
4
5
|
interface RestDeps {
|
|
5
6
|
sql: Sql<{}>;
|
|
7
|
+
agents: BoundTable<any>;
|
|
6
8
|
runner: {
|
|
7
9
|
run: (agentId: number, params: RunParams) => Promise<any>;
|
|
8
10
|
addKnowledge: (agentId: number, title: string, content: string) => Promise<any>;
|
package/dist/agent/run.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { type LanguageModel, type EmbeddingModel, type Tool } from 'ai';
|
|
2
2
|
import type { Sql } from '../vendor.ts';
|
|
3
|
+
import type { BoundTable } from '../postgres/schema/index.ts';
|
|
3
4
|
import type { RunParams, RunResult, KnowledgeDoc } from './types.ts';
|
|
4
5
|
interface RunnerDeps {
|
|
5
6
|
sql: Sql<{}>;
|
|
7
|
+
agents: BoundTable<any>;
|
|
8
|
+
knowledge: BoundTable<any>;
|
|
6
9
|
getModel: () => LanguageModel;
|
|
7
10
|
getEmbeddingModel: () => EmbeddingModel;
|
|
8
11
|
userTools?: Record<string, Tool>;
|
package/dist/cli.js
CHANGED
|
@@ -50,12 +50,16 @@ async function cmdInit(name) {
|
|
|
50
50
|
await writeFile(join(targetDir, ".gitignore"), "node_modules\ndist\n.env\n.sessions\n");
|
|
51
51
|
await writeFile(join(targetDir, ".env"), "PORT=3000\n");
|
|
52
52
|
await writeFile(join(targetDir, "app.ts"), [
|
|
53
|
-
"import { serve, loadEnv } from 'weifuwu'",
|
|
53
|
+
"import { serve, Router, loadEnv } from 'weifuwu'",
|
|
54
54
|
"",
|
|
55
55
|
"loadEnv()",
|
|
56
56
|
"const port = Number(process.env.PORT) || 3000",
|
|
57
57
|
"",
|
|
58
|
-
"
|
|
58
|
+
"const app = new Router()",
|
|
59
|
+
"app.get('/', (req, ctx) => new Response('Hello, Weifuwu!'))",
|
|
60
|
+
"",
|
|
61
|
+
"serve(app.handler(), { port })",
|
|
62
|
+
"console.log(`Listening on http://localhost:${port}`)",
|
|
59
63
|
""
|
|
60
64
|
].join("\n"));
|
|
61
65
|
console.log(`\u2705 Created ${name}/ \u2014 cd ${name} && npm install && npm run dev`);
|
package/dist/index.d.ts
CHANGED
|
@@ -49,3 +49,5 @@ export { i18n } from './i18n.ts';
|
|
|
49
49
|
export type { I18nOptions } from './i18n.ts';
|
|
50
50
|
export { mailer } from './mailer.ts';
|
|
51
51
|
export type { MailerOptions, MailOptions, Mailer } from './mailer.ts';
|
|
52
|
+
export { logdb } from './logdb/index.ts';
|
|
53
|
+
export type { LogdbOptions, LogdbModule, LogEntry, LogEntryInput } from './logdb/types.ts';
|