weifuwu 0.33.1 → 0.33.3

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,17 +1,19 @@
1
1
  # weifuwu
2
2
 
3
- **AI SaaS framework** — `(req, ctx) => Response`
3
+ **AI SaaS full-stack framework** — `(req, ctx) => Response` + `(props, ctx) => JSX`
4
4
 
5
5
  ```bash
6
6
  npm install weifuwu
7
7
  ```
8
8
 
9
- User system, instant messaging, RAG knowledge base, AI Agent, CMS, dynamic data storage. Configure environment variables and go.
9
+ One package. Backend + frontend. User system, instant messaging, RAG knowledge base, AI Agent, CMS, dynamic data storage, and a reactive frontend framework. Configure environment variables and go.
10
10
 
11
11
  ---
12
12
 
13
13
  ## Quick Start
14
14
 
15
+ ### Backend
16
+
15
17
  ```ts
16
18
  import { serve, Router, postgres, user, kb, agent, messager } from 'weifuwu'
17
19
  import { openai } from '@ai-sdk/openai'
@@ -34,6 +36,46 @@ app.post('/api/chat', async (req, ctx) => {
34
36
  serve(app, { port: 3000 })
35
37
  ```
36
38
 
39
+ ### Frontend
40
+
41
+ ```tsx
42
+ import { signal, Show, For, createApp, router, RouteView } from 'weifuwu/client'
43
+ import type { WfuiContext } from 'weifuwu/client'
44
+
45
+ function HomePage(_props: {}, ctx: WfuiContext) {
46
+ return (
47
+ <div>
48
+ <h1>Hello weifuwu</h1>
49
+ <p>当前路径: {ctx.route.path}</p>
50
+ </div>
51
+ )
52
+ }
53
+
54
+ const app = createApp()
55
+ app.use(router({
56
+ routes: [
57
+ { path: '/', component: HomePage, title: '首页' },
58
+ { path: '/chat/:id', component: ChatPage, title: '聊天' },
59
+ ],
60
+ }))
61
+ app.mount('#root', AppShell)
62
+ ```
63
+
64
+ ```json
65
+ // tsconfig.json
66
+ { "jsx": "react-jsx", "jsxImportSource": "weifuwu/client" }
67
+ ```
68
+
69
+ ```js
70
+ // build.mjs
71
+ esbuild.build({
72
+ entryPoints: ['src/main.tsx'],
73
+ jsx: 'automatic',
74
+ jsxImportSource: 'weifuwu/client',
75
+ bundle: true,
76
+ })
77
+ ```
78
+
37
79
  ### Environment Variables
38
80
 
39
81
  | Variable | Default | Used by |
@@ -49,6 +91,8 @@ serve(app, { port: 3000 })
49
91
 
50
92
  ## Modules
51
93
 
94
+ ### Backend
95
+
52
96
  | Module | Import | Dependency | Purpose |
53
97
  |--------|--------|-----------|---------|
54
98
  | User | `user()` | `postgres()` | Auth, JWT, roles |
@@ -84,6 +128,20 @@ serve(app, { port: 3000 })
84
128
  | `queue()` | Job queue + cron |
85
129
  | `createHub()` | WebSocket pub/sub |
86
130
 
131
+ ### Frontend (weifuwu/client)
132
+
133
+ | Import | Purpose |
134
+ |--------|---------|
135
+ | `signal()` | Reactive state |
136
+ | `computed()` | Derived signals |
137
+ | `effect()` | Auto-tracked side effects |
138
+ | `<Show>` | Conditional rendering |
139
+ | `<For>` | List rendering |
140
+ | `<RouteView>` | Route outlet |
141
+ | `createApp()` | App instance with middleware chain |
142
+ | `router()` | Hash/history router with params + query |
143
+ | `domMount()` | Direct DOM mounting |
144
+
87
145
  ### Utilities
88
146
 
89
147
  | Import | Purpose |
@@ -92,6 +150,92 @@ serve(app, { port: 3000 })
92
150
 
93
151
  ---
94
152
 
153
+ ## Frontend (weifuwu/client)
154
+
155
+ **weifuwu/client** is a reactive frontend framework built on Signal + TSX. Zero virtual DOM, zero dependencies, ~600 lines total.
156
+
157
+ ### Concepts
158
+
159
+ ```ts
160
+ // 1. Signal — reactive data
161
+ const count = signal(0)
162
+ count.value = count.value + 1 // DOM updates automatically
163
+
164
+ // 2. Computed — derived signals
165
+ const doubled = computed(() => count.value * 2)
166
+
167
+ // 3. Effect — auto-tracked side effects
168
+ effect(() => console.log('count:', count.value))
169
+
170
+ // 4. Component — (props, ctx) => JSX
171
+ function MyComponent({ name }: { name: string }, ctx: WfuiContext) {
172
+ return <div>Hello {name}</div>
173
+ }
174
+ ```
175
+
176
+ ### createApp + Middleware
177
+
178
+ ```tsx
179
+ import { createApp, router, RouteView } from 'weifuwu/client'
180
+ import type { WfuiContext, RouteDef } from 'weifuwu/client'
181
+
182
+ const app = createApp()
183
+ app.use(router({ routes, mode: 'hash' }))
184
+ app.mount('#root', AppShell)
185
+ ```
186
+
187
+ ### Router
188
+
189
+ ```tsx
190
+ const routes: RouteDef[] = [
191
+ { path: '/', component: HomePage, title: '首页' },
192
+ { path: '/chat/:id', component: ChatPage, title: '聊天' },
193
+ { path: '/user/:name', component: UserPage, title: '用户' },
194
+ ]
195
+
196
+ app.use(router({
197
+ routes,
198
+ notFound: NotFound,
199
+ mode: 'hash', // or 'history'
200
+ }))
201
+
202
+ // In layout:
203
+ function AppShell(_, ctx) {
204
+ return (
205
+ <div>
206
+ <nav>
207
+ <a onClick={() => ctx.app.navigate('/')}>首页</a>
208
+ <a onClick={() => ctx.app.navigate('/chat/123')}>聊天</a>
209
+ </nav>
210
+ <main>
211
+ <RouteView /> {/* ← renders matched route */}
212
+ </main>
213
+ </div>
214
+ )
215
+ }
216
+
217
+ // Route params and query:
218
+ ctx.route.path // "/chat/123"
219
+ ctx.route.params // { id: "123" }
220
+ ctx.route.query // { tab: "settings" }
221
+ ```
222
+
223
+ ### Show / For
224
+
225
+ ```tsx
226
+ // Conditional rendering (supports Signal)
227
+ <Show when={isLoggedIn} fallback={<LoginPage />}>
228
+ <Dashboard />
229
+ </Show>
230
+
231
+ // List rendering (supports Signal)
232
+ <For each={filteredItems}>
233
+ {(item) => <div>{item.name}</div>}
234
+ </For>
235
+ ```
236
+
237
+ ---
238
+
95
239
  ## user
96
240
 
97
241
  Auth, registration, JWT, password management, roles.
@@ -344,7 +488,7 @@ app.post('/api/chat/sync', async (req, ctx) => {
344
488
  ### ctx.agent API
345
489
 
346
490
  | Method | Description |
347
- |--------|-------------|
491
+ |-------------|-------------|
348
492
  | `chat(prompt, opts?)` | Non-streaming, returns text |
349
493
  | `chatStreamResponse({ messages })` | SSE stream (compatible with `useChat`) |
350
494
 
@@ -602,8 +746,21 @@ src/
602
746
  ├── queue/ ← Job queue + cron
603
747
  ├── graphql.ts ← GraphQL
604
748
  ├── hub.ts ← WebSocket hub
749
+ ├── client/ ← Frontend framework (signal, JSX, router)
750
+ │ ├── index.ts
751
+ │ ├── signal.ts
752
+ │ ├── jsx-runtime.ts
753
+ │ ├── app.ts
754
+ │ ├── router.ts
755
+ │ └── types.ts
605
756
  └── test/ ← 281 tests
606
757
 
758
+ apps/demo/ ← Full-stack demo
759
+ ├── src/main.tsx
760
+ ├── public/index.html
761
+ ├── tsconfig.json
762
+ └── scripts/build.mjs
763
+
607
764
  docker-compose.yml ← postgres (pgvector) + redis
608
765
  ```
609
766
 
@@ -0,0 +1,24 @@
1
+ /**
2
+ * weifuwu/client 应用 — 创建 ctx + 中间件链 + 挂载组件
3
+ *
4
+ * ```tsx
5
+ * import { createApp, api, auth, ws, router } from 'weifuwu/client'
6
+ *
7
+ * const app = createApp()
8
+ * app.use(api())
9
+ * app.use(auth())
10
+ * app.use(ws())
11
+ * app.use(router({ routes }))
12
+ * app.mount('#root', AppShell)
13
+ * ```
14
+ */
15
+ import type { WfuiContext, AppMiddleware } from './types.ts';
16
+ import type { Component } from './jsx-runtime.ts';
17
+ /**
18
+ * 创建 weifuwu/client 应用
19
+ */
20
+ export declare function createApp(): {
21
+ ctx: WfuiContext;
22
+ use: (mw: AppMiddleware) => any;
23
+ mount: (rootSelector: string, RootComponent: Component) => Promise<void>;
24
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Chat — 消息聊天组件
3
+ *
4
+ * 与 weifuwu 后端 messager + agent 模块对接。
5
+ *
6
+ * ```ts
7
+ * import { Chat } from 'weifuwu/client'
8
+ *
9
+ * function ChatPage(_, ctx) {
10
+ * return Chat({ conversationId: '123' }, ctx)
11
+ * }
12
+ * ```
13
+ */
14
+ import type { WfuiContext } from '../types.ts';
15
+ export declare function Chat({ conversationId }: {
16
+ conversationId: string;
17
+ }, ctx: WfuiContext): Node;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * LoginForm — 登录/注册组件
3
+ *
4
+ * ```ts
5
+ * import { LoginForm } from 'weifuwu/client'
6
+ *
7
+ * function LoginPage(_, ctx) {
8
+ * if (ctx.isAuthenticated) return ctx.app.navigate('/')
9
+ * return LoginForm({}, ctx)
10
+ * }
11
+ * ```
12
+ */
13
+ import type { WfuiContext } from '../types.ts';
14
+ export declare function LoginForm(_props: {}, ctx: WfuiContext): Node;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * weifuwu/client — 响应式前端框架,TSX + Signal
3
+ *
4
+ * ```tsx
5
+ * import { signal, createdApp, api, auth, ws, router, RouteView, Show, For } from 'weifuwu/client'
6
+ * import type { WfuiContext } from 'weifuwu/client'
7
+ *
8
+ * const app = createApp()
9
+ * app.use(api())
10
+ * app.use(auth())
11
+ * app.use(ws())
12
+ * app.use(router({ routes }))
13
+ * app.mount('#root', AppShell)
14
+ * ```
15
+ */
16
+ export { signal, computed, effect, isSignal } from './signal.ts';
17
+ export type { Signal } from './signal.ts';
18
+ export { jsx, jsxs, jsxDEV, Fragment, Show, For, domMount } from './jsx-runtime.ts';
19
+ export type { Component } from './jsx-runtime.ts';
20
+ export type { WfuiContext, AppMiddleware, RouteDef } from './types.ts';
21
+ export { createApp } from './app.ts';
22
+ export { router, RouteView } from './router.ts';
23
+ export { api, ApiClient, ApiError } from './middleware/api.ts';
24
+ export { auth } from './middleware/auth.ts';
25
+ export type { UserRecord } from './middleware/auth.ts';
26
+ export { ws } from './middleware/ws.ts';
27
+ export { LoginForm } from './components/LoginForm.ts';
28
+ export { Chat } from './components/Chat.ts';