weifuwu 0.24.1 → 0.24.2

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.
Files changed (54) hide show
  1. package/README.md +818 -712
  2. package/cli/template/app.ts +5 -1
  3. package/cli/template/index.ts +4 -1
  4. package/cli/template/locales/en.json +6 -1
  5. package/cli/template/locales/zh-CN.json +6 -1
  6. package/cli/template/locales/zh-TW.json +6 -1
  7. package/cli/template/locales/zh.json +6 -1
  8. package/cli/template/ui/app/globals.css +1 -1
  9. package/cli/template/ui/app/page.tsx +55 -16
  10. package/cli.ts +148 -104
  11. package/dist/agent/rest.d.ts +1 -1
  12. package/dist/agent/run.d.ts +2 -2
  13. package/dist/ai/workflow.d.ts +1 -1
  14. package/dist/ai-sdk.d.ts +1 -1
  15. package/dist/cli.js +135 -97
  16. package/dist/cookie.d.ts +24 -0
  17. package/dist/fts.d.ts +5 -5
  18. package/dist/iii/index.d.ts +1 -1
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.js +787 -346
  21. package/dist/live.d.ts +2 -3
  22. package/dist/logdb/rest.d.ts +1 -1
  23. package/dist/mailer.d.ts +1 -1
  24. package/dist/messager/agent.d.ts +2 -2
  25. package/dist/messager/rest.d.ts +3 -3
  26. package/dist/messager/ws.d.ts +3 -3
  27. package/dist/opencode/index.d.ts +1 -1
  28. package/dist/opencode/permissions.d.ts +1 -1
  29. package/dist/opencode/run.d.ts +1 -1
  30. package/dist/opencode/session.d.ts +9 -9
  31. package/dist/opencode/tools/web.d.ts +1 -1
  32. package/dist/opencode/ws.d.ts +1 -2
  33. package/dist/permissions.d.ts +2 -2
  34. package/dist/postgres/module.d.ts +3 -3
  35. package/dist/postgres/schema/index.d.ts +1 -1
  36. package/dist/postgres/schema/table.d.ts +22 -20
  37. package/dist/postgres/types.d.ts +4 -4
  38. package/dist/queue/types.d.ts +1 -1
  39. package/dist/react.d.ts +1 -1
  40. package/dist/react.js +135 -90
  41. package/dist/router.d.ts +10 -10
  42. package/dist/session.d.ts +1 -2
  43. package/dist/tenant/graphql.d.ts +2 -2
  44. package/dist/tenant/index.d.ts +1 -1
  45. package/dist/tenant/rest.d.ts +2 -2
  46. package/dist/test-utils.d.ts +3 -3
  47. package/dist/user/index.d.ts +1 -1
  48. package/dist/user/oauth-login.d.ts +2 -2
  49. package/dist/vendor.d.ts +4 -0
  50. package/opencode/ui/app/globals.css +1 -1
  51. package/opencode/ui/app/layout.tsx +2 -3
  52. package/opencode/ui/app/page.tsx +302 -73
  53. package/package.json +26 -3
  54. package/cli/template/.weifuwu/ssr/2e3a7e60.js +0 -112
@@ -15,4 +15,8 @@ app.use(async (req, ctx, next) => {
15
15
  return next(req, ctx)
16
16
  })
17
17
  app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))
18
- app.ws('/ws/echo', { message(ws, _ctx, data) { ws.send(`echo: ${data}`) } })
18
+ app.ws('/ws/echo', {
19
+ message(ws, _ctx, data) {
20
+ ws.send(`echo: ${data}`)
21
+ },
22
+ })
@@ -4,4 +4,7 @@ import { app } from './app.ts'
4
4
  loadEnv()
5
5
  const port = Number(process.env.PORT) || 3000
6
6
  const srv = serve(app.handler(), { port, websocket: app.websocketHandler(), shutdown: false })
7
- process.on('SIGINT', () => { srv.stop(); process.exit(0) })
7
+ process.on('SIGINT', () => {
8
+ srv.stop()
9
+ process.exit(0)
10
+ })
@@ -2,7 +2,12 @@
2
2
  "nav": { "home": "Home", "docs": "Docs", "api": "API" },
3
3
  "hero": { "title": "Build Faster", "subtitle": "A modern web framework for Node.js" },
4
4
  "cta": { "start": "Get Started", "learn": "Learn More" },
5
- "demo": { "title": "WebSocket Demo", "placeholder": "Type a message...", "send": "Send", "echo": "Echo" },
5
+ "demo": {
6
+ "title": "WebSocket Demo",
7
+ "placeholder": "Type a message...",
8
+ "send": "Send",
9
+ "echo": "Echo"
10
+ },
6
11
  "ws": { "connected": "Connected", "connecting": "Connecting...", "disconnected": "Disconnected" },
7
12
  "footer": { "privacy": "Privacy", "terms": "Terms" }
8
13
  }
@@ -2,7 +2,12 @@
2
2
  "nav": { "home": "首页", "docs": "文档", "api": "API" },
3
3
  "hero": { "title": "更快地构建", "subtitle": "一个现代的 Node.js Web 框架" },
4
4
  "cta": { "start": "开始使用", "learn": "了解更多" },
5
- "demo": { "title": "WebSocket 演示", "placeholder": "输入消息...", "send": "发送", "echo": "回声" },
5
+ "demo": {
6
+ "title": "WebSocket 演示",
7
+ "placeholder": "输入消息...",
8
+ "send": "发送",
9
+ "echo": "回声"
10
+ },
6
11
  "ws": { "connected": "已连接", "connecting": "连接中...", "disconnected": "未连接" },
7
12
  "footer": { "privacy": "隐私", "terms": "条款" }
8
13
  }
@@ -2,7 +2,12 @@
2
2
  "nav": { "home": "首頁", "docs": "文件", "api": "API" },
3
3
  "hero": { "title": "更快構建", "subtitle": "一個現代的 Node.js Web 框架" },
4
4
  "cta": { "start": "開始使用", "learn": "了解更多" },
5
- "demo": { "title": "WebSocket 演示", "placeholder": "輸入訊息...", "send": "發送", "echo": "回聲" },
5
+ "demo": {
6
+ "title": "WebSocket 演示",
7
+ "placeholder": "輸入訊息...",
8
+ "send": "發送",
9
+ "echo": "回聲"
10
+ },
6
11
  "ws": { "connected": "已連線", "connecting": "連線中...", "disconnected": "未連線" },
7
12
  "footer": { "privacy": "隱私", "terms": "條款" }
8
13
  }
@@ -2,7 +2,12 @@
2
2
  "nav": { "home": "首页", "docs": "文档", "api": "API" },
3
3
  "hero": { "title": "更快地构建", "subtitle": "一个现代的 Node.js Web 框架" },
4
4
  "cta": { "start": "开始使用", "learn": "了解更多" },
5
- "demo": { "title": "WebSocket 演示", "placeholder": "输入消息...", "send": "发送", "echo": "回声" },
5
+ "demo": {
6
+ "title": "WebSocket 演示",
7
+ "placeholder": "输入消息...",
8
+ "send": "发送",
9
+ "echo": "回声"
10
+ },
6
11
  "ws": { "connected": "已连接", "connecting": "连接中...", "disconnected": "未连接" },
7
12
  "footer": { "privacy": "隐私", "terms": "条款" }
8
13
  }
@@ -1,2 +1,2 @@
1
- @import "tailwindcss";
1
+ @import 'tailwindcss';
2
2
  @variant dark (&:where([data-theme="dark"] *));
@@ -6,12 +6,11 @@ export default function Home() {
6
6
  const [input, setInput] = useState('')
7
7
  const { send, lastMessage, readyState } = useWebsocket('/ws/echo')
8
8
  const { locale, t, setLocale } = useLocale()
9
- const { theme, resolvedTheme, setTheme } = useTheme()
9
+ const { resolvedTheme, setTheme } = useTheme()
10
10
  const ld = useLoaderData<{ features?: { title: string; desc: string }[] }>()
11
11
 
12
12
  return (
13
13
  <div className="min-h-screen bg-white dark:bg-gray-950 text-gray-900 dark:text-gray-100">
14
-
15
14
  {/* Navbar */}
16
15
  <header className="border-b dark:border-gray-800">
17
16
  <div className="max-w-5xl mx-auto flex items-center justify-between h-14 px-4">
@@ -22,12 +21,16 @@ export default function Home() {
22
21
  <span className="hover:text-blue-600 transition cursor-pointer">{t('nav.api')}</span>
23
22
  </nav>
24
23
  <div className="flex items-center gap-2 text-sm">
25
- <button onClick={() => setLocale(locale === 'en' ? 'zh-CN' : 'en')}
26
- className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition">
24
+ <button
25
+ onClick={() => setLocale(locale === 'en' ? 'zh-CN' : 'en')}
26
+ className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
27
+ >
27
28
  {locale === 'en' ? '中文' : 'EN'}
28
29
  </button>
29
- <button onClick={() => setTheme(resolvedTheme === 'light' ? 'dark' : 'light')}
30
- className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition">
30
+ <button
31
+ onClick={() => setTheme(resolvedTheme === 'light' ? 'dark' : 'light')}
32
+ className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
33
+ >
31
34
  {resolvedTheme === 'light' ? '🌙' : '☀️'}
32
35
  </button>
33
36
  </div>
@@ -40,8 +43,18 @@ export default function Home() {
40
43
  <p className="text-xl text-gray-500 dark:text-gray-400 mb-8">{t('hero.subtitle')}</p>
41
44
  <Greeting name="Weifuwu" />
42
45
  <div className="flex justify-center gap-4 mt-8">
43
- <a href="#" className="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition font-medium">{t('cta.start')}</a>
44
- <a href="#" className="px-6 py-2.5 border dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition font-medium">{t('cta.learn')}</a>
46
+ <a
47
+ href="#"
48
+ className="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition font-medium"
49
+ >
50
+ {t('cta.start')}
51
+ </a>
52
+ <a
53
+ href="#"
54
+ className="px-6 py-2.5 border dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition font-medium"
55
+ >
56
+ {t('cta.learn')}
57
+ </a>
45
58
  </div>
46
59
  </section>
47
60
 
@@ -49,7 +62,10 @@ export default function Home() {
49
62
  {ld.features && (
50
63
  <section className="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 px-4 pb-20">
51
64
  {ld.features.map((f, i) => (
52
- <div key={i} className="p-6 rounded-xl border dark:border-gray-800 bg-gray-50 dark:bg-gray-900">
65
+ <div
66
+ key={i}
67
+ className="p-6 rounded-xl border dark:border-gray-800 bg-gray-50 dark:bg-gray-900"
68
+ >
53
69
  <h3 className="font-semibold mb-2">{f.title}</h3>
54
70
  <p className="text-sm text-gray-500 dark:text-gray-400">{f.desc}</p>
55
71
  </div>
@@ -62,17 +78,40 @@ export default function Home() {
62
78
  <div className="border dark:border-gray-800 rounded-xl p-6 bg-gray-50 dark:bg-gray-900 space-y-4">
63
79
  <h2 className="font-semibold">{t('demo.title')}</h2>
64
80
  <p className="text-sm text-gray-500 dark:text-gray-400">
65
- {readyState === 1 ? t('ws.connected') : readyState === 0 ? t('ws.connecting') : t('ws.disconnected')}
81
+ {readyState === 1
82
+ ? t('ws.connected')
83
+ : readyState === 0
84
+ ? t('ws.connecting')
85
+ : t('ws.disconnected')}
66
86
  </p>
67
87
  <div className="flex gap-2">
68
- <input value={input} onChange={e => setInput(e.target.value)}
69
- onKeyDown={e => { if (e.key === 'Enter') { send(input); setInput('') } }}
88
+ <input
89
+ value={input}
90
+ onChange={(e) => setInput(e.target.value)}
91
+ onKeyDown={(e) => {
92
+ if (e.key === 'Enter') {
93
+ send(input)
94
+ setInput('')
95
+ }
96
+ }}
70
97
  placeholder={t('demo.placeholder')}
71
- className="flex-1 border dark:border-gray-700 rounded px-3 py-2 text-sm bg-white dark:bg-gray-950 outline-none focus:border-blue-500 transition" />
72
- <button onClick={() => { send(input); setInput('') }}
73
- className="px-4 py-2 bg-blue-600 text-white rounded text-sm hover:bg-blue-700 transition font-medium">{t('demo.send')}</button>
98
+ className="flex-1 border dark:border-gray-700 rounded px-3 py-2 text-sm bg-white dark:bg-gray-950 outline-none focus:border-blue-500 transition"
99
+ />
100
+ <button
101
+ onClick={() => {
102
+ send(input)
103
+ setInput('')
104
+ }}
105
+ className="px-4 py-2 bg-blue-600 text-white rounded text-sm hover:bg-blue-700 transition font-medium"
106
+ >
107
+ {t('demo.send')}
108
+ </button>
74
109
  </div>
75
- {lastMessage && <p className="text-sm text-gray-600 dark:text-gray-400"><span className="font-medium">{t('demo.echo')}:</span> {lastMessage}</p>}
110
+ {lastMessage && (
111
+ <p className="text-sm text-gray-600 dark:text-gray-400">
112
+ <span className="font-medium">{t('demo.echo')}:</span> {lastMessage}
113
+ </p>
114
+ )}
76
115
  </div>
77
116
  </section>
78
117
 
package/cli.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
4
  import { mkdir, writeFile, copyFile, readFile, cp } from 'node:fs/promises'
3
5
  import { existsSync, readdirSync } from 'node:fs'
4
6
  import { execSync } from 'node:child_process'
@@ -33,8 +35,14 @@ async function cmdInit(name: string, opts: { minimal?: boolean; skipInstall?: bo
33
35
  const targetDir = resolve(process.cwd(), name)
34
36
  const pkg = await readPkg()
35
37
  const v = pkg.version
38
+ // Map of known type package versions that align with our runtime deps
39
+ const typeVersions: Record<string, string> = {
40
+ '@types/react': '^19',
41
+ '@types/react-dom': '^19',
42
+ '@types/node': '^22',
43
+ }
36
44
  const depVer = (depName: string) =>
37
- `^${(pkg.devDependencies?.[depName] || '0.0.0').replace(/^\^/, '')}`
45
+ typeVersions[depName] || `^${(pkg.devDependencies?.[depName] || '0.0.0').replace(/^\^/, '')}`
38
46
 
39
47
  await mkdir(targetDir, { recursive: true })
40
48
 
@@ -56,36 +64,45 @@ async function cmdInit(name: string, opts: { minimal?: boolean; skipInstall?: bo
56
64
  const uiPage = join(targetDir, 'ui', 'app', 'page.tsx')
57
65
  if (existsSync(uiPage)) {
58
66
  let content = await readFile(uiPage, 'utf-8')
59
- content = content
60
- .replace(/from '\.\.\/\.\.\/\.\.\/\.\.\/react\.ts'/g, "from 'weifuwu/react'")
67
+ content = content.replace(/from '\.\.\/\.\.\/\.\.\/\.\.\/react\.ts'/g, "from 'weifuwu/react'")
61
68
  await writeFile(uiPage, content)
62
69
  }
63
70
 
64
71
  // Minimal mode: strip SSR/i18n/theme, keep only HTTP core
65
72
  if (opts.minimal) {
66
- try { await rmrf(join(targetDir, 'ui')) } catch {}
67
- try { await rmrf(join(targetDir, 'locales')) } catch {}
73
+ try {
74
+ await rmrf(join(targetDir, 'ui'))
75
+ } catch {}
76
+ try {
77
+ await rmrf(join(targetDir, 'locales'))
78
+ } catch {}
68
79
 
69
80
  // Write minimal app.ts
70
- await writeFile(join(targetDir, 'app.ts'), [
71
- `import { Router } from 'weifuwu'`,
72
- ``,
73
- `export const app = new Router()`,
74
- ``,
75
- `app.get('/', () => new Response('Hello from ${name}!'))`,
76
- `app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))`,
77
- ``,
78
- ].join('\n'))
81
+ await writeFile(
82
+ join(targetDir, 'app.ts'),
83
+ [
84
+ `import { Router } from 'weifuwu'`,
85
+ ``,
86
+ `export const app = new Router()`,
87
+ ``,
88
+ `app.get('/', () => new Response('Hello from ${name}!'))`,
89
+ `app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))`,
90
+ ``,
91
+ ].join('\n'),
92
+ )
79
93
 
80
94
  // Write minimal index.ts
81
- await writeFile(join(targetDir, 'index.ts'), [
82
- `import { serve } from 'weifuwu'`,
83
- `import { app } from './app.ts'`,
84
- ``,
85
- `const port = Number(process.env.PORT) || 3000`,
86
- `serve(app.handler(), { port })`,
87
- ``,
88
- ].join('\n'))
95
+ await writeFile(
96
+ join(targetDir, 'index.ts'),
97
+ [
98
+ `import { serve } from 'weifuwu'`,
99
+ `import { app } from './app.ts'`,
100
+ ``,
101
+ `const port = Number(process.env.PORT) || 3000`,
102
+ `serve(app.handler(), { port })`,
103
+ ``,
104
+ ].join('\n'),
105
+ )
89
106
  }
90
107
 
91
108
  // Write package.json
@@ -100,64 +117,81 @@ async function cmdInit(name: string, opts: { minimal?: boolean; skipInstall?: bo
100
117
  }
101
118
  devDeps['@types/node'] = depVer('@types/node')
102
119
 
103
- await writeFile(join(targetDir, 'package.json'), JSON.stringify({
104
- name,
105
- type: 'module',
106
- scripts: {
107
- dev: 'NODE_ENV=development node --watch index.ts',
108
- start: 'node index.ts',
109
- },
110
- dependencies: deps,
111
- devDependencies: devDeps,
112
- }, null, 2) + '\n')
120
+ await writeFile(
121
+ join(targetDir, 'package.json'),
122
+ JSON.stringify(
123
+ {
124
+ name,
125
+ type: 'module',
126
+ scripts: {
127
+ dev: 'NODE_ENV=development node --watch index.ts',
128
+ start: 'node index.ts',
129
+ },
130
+ dependencies: deps,
131
+ devDependencies: devDeps,
132
+ },
133
+ null,
134
+ 2,
135
+ ) + '\n',
136
+ )
113
137
 
114
138
  // Write tsconfig.json
115
139
  const include = opts.minimal ? ['*.ts'] : ['*.ts', 'ui/**/*.ts', 'ui/**/*.tsx']
116
- await writeFile(join(targetDir, 'tsconfig.json'), JSON.stringify({
117
- compilerOptions: {
118
- target: 'ESNext',
119
- module: 'NodeNext',
120
- moduleResolution: 'NodeNext',
121
- strict: true,
122
- jsx: 'react-jsx',
123
- skipLibCheck: true,
124
- noEmit: true,
125
- allowImportingTsExtensions: true,
126
- },
127
- include,
128
- }, null, 2) + '\n')
140
+ await writeFile(
141
+ join(targetDir, 'tsconfig.json'),
142
+ JSON.stringify(
143
+ {
144
+ compilerOptions: {
145
+ target: 'ESNext',
146
+ module: 'NodeNext',
147
+ moduleResolution: 'NodeNext',
148
+ strict: true,
149
+ jsx: 'react-jsx',
150
+ skipLibCheck: true,
151
+ noEmit: true,
152
+ allowImportingTsExtensions: true,
153
+ },
154
+ include,
155
+ },
156
+ null,
157
+ 2,
158
+ ) + '\n',
159
+ )
129
160
 
130
161
  await writeFile(join(targetDir, '.gitignore'), 'node_modules\ndist\n.env\n.sessions\n.weifuwu\n')
131
162
  await writeFile(join(targetDir, '.env'), 'PORT=3000\n')
132
- await writeFile(join(targetDir, 'AGENTS.md'), [
133
- `# ${name}`,
134
- '',
135
- `This is a [weifuwu](https://weifuwu.io) application — pure Node.js, no build step.`,
136
- '',
137
- '## Commands',
138
- '',
139
- '- `npm run dev` — start dev server with hot reload',
140
- '- `npm start` — start production server',
141
- '- `npm install` — install dependencies',
142
- '- `npx tsc --noEmit` — type-check',
143
- '',
144
- '## API Reference',
145
- '',
146
- 'See `node_modules/weifuwu/README.md` for the full documentation.',
147
- '',
148
- ].join('\n'))
163
+ await writeFile(
164
+ join(targetDir, 'AGENTS.md'),
165
+ [
166
+ `# ${name}`,
167
+ '',
168
+ `This is a [weifuwu](https://weifuwu.io) application — pure Node.js, no build step.`,
169
+ '',
170
+ '## Commands',
171
+ '',
172
+ '- `npm run dev` — start dev server with hot reload',
173
+ '- `npm start` — start production server',
174
+ '- `npm install` — install dependencies',
175
+ '- `npx tsc --noEmit` — type-check',
176
+ '',
177
+ '## API Reference',
178
+ '',
179
+ 'See `node_modules/weifuwu/README.md` for the full documentation.',
180
+ '',
181
+ ].join('\n'),
182
+ )
149
183
 
150
184
  if (!opts.skipInstall) {
151
185
  console.log('\nInstalling dependencies...')
152
186
  execSync('npm install', { cwd: targetDir, stdio: 'inherit' })
153
187
  }
154
- console.log(`\n✅ Created ${name}/ — cd ${name} && ${opts.skipInstall ? 'npm install && ' : ''}npm run dev`)
188
+ console.log(
189
+ `\n✅ Created ${name}/ — cd ${name} && ${opts.skipInstall ? 'npm install && ' : ''}npm run dev`,
190
+ )
155
191
  }
156
192
 
157
193
  async function cmdDev() {
158
- const entry = existsSync('index.ts') ? 'index.ts'
159
- : existsSync('app.ts') ? 'app.ts'
160
- : null
194
+ const entry = existsSync('index.ts') ? 'index.ts' : existsSync('app.ts') ? 'app.ts' : null
161
195
 
162
196
  if (!entry) {
163
197
  console.error('No index.ts or app.ts found in current directory.')
@@ -182,44 +216,50 @@ async function cmdGenerate(type: string, name: string) {
182
216
  }
183
217
 
184
218
  await mkdir(dir, { recursive: true })
185
- await writeFile(join(dir, 'index.ts'), [
186
- `import type { Middleware } from 'weifuwu'`,
187
- ``,
188
- `export interface ${capitalize(name)}Options {`,
189
- ` // Add your options here`,
190
- `}`,
191
- ``,
192
- `export function ${name}(opts?: ${capitalize(name)}Options): Middleware {`,
193
- ` return async (req, ctx, next) => {`,
194
- ` // Your middleware logic here`,
195
- ` return next(req, ctx)`,
196
- ` }`,
197
- `}`,
198
- ``,
199
- ].join('\n'))
219
+ await writeFile(
220
+ join(dir, 'index.ts'),
221
+ [
222
+ `import type { Middleware } from 'weifuwu'`,
223
+ ``,
224
+ `export interface ${capitalize(name)}Options {`,
225
+ ` // Add your options here`,
226
+ `}`,
227
+ ``,
228
+ `export function ${name}(opts?: ${capitalize(name)}Options): Middleware {`,
229
+ ` return async (req, ctx, next) => {`,
230
+ ` // Your middleware logic here`,
231
+ ` return next(req, ctx)`,
232
+ ` }`,
233
+ `}`,
234
+ ``,
235
+ ].join('\n'),
236
+ )
200
237
 
201
238
  await mkdir(join(dir, '..', 'test'), { recursive: true })
202
- await writeFile(join(dir, '..', 'test', `${name}.test.ts`), [
203
- `import { describe, it } from 'node:test'`,
204
- `import assert from 'node:assert/strict'`,
205
- `import { ${name} } from '../${name}/index.ts'`,
206
- `import { Router } from 'weifuwu'`,
207
- ``,
208
- `describe('${name}', () => {`,
209
- ` it('works as middleware', async () => {`,
210
- ` const app = new Router()`,
211
- ` app.use(${name}())`,
212
- ` app.get('/', () => new Response('ok'))`,
213
- ``,
214
- ` const res = await app.handler()(`,
215
- ` new Request('http://localhost/'),`,
216
- ` { params: {}, query: {} } as any,`,
217
- ` )`,
218
- ` assert.equal(res.status, 200)`,
219
- ` })`,
220
- `})`,
221
- ``,
222
- ].join('\n'))
239
+ await writeFile(
240
+ join(dir, '..', 'test', `${name}.test.ts`),
241
+ [
242
+ `import { describe, it } from 'node:test'`,
243
+ `import assert from 'node:assert/strict'`,
244
+ `import { ${name} } from '../${name}/index.ts'`,
245
+ `import { Router } from 'weifuwu'`,
246
+ ``,
247
+ `describe('${name}', () => {`,
248
+ ` it('works as middleware', async () => {`,
249
+ ` const app = new Router()`,
250
+ ` app.use(${name}())`,
251
+ ` app.get('/', () => new Response('ok'))`,
252
+ ``,
253
+ ` const res = await app.handler()(`,
254
+ ` new Request('http://localhost/'),`,
255
+ ` { params: {}, query: {} } as any,`,
256
+ ` )`,
257
+ ` assert.equal(res.status, 200)`,
258
+ ` })`,
259
+ `})`,
260
+ ``,
261
+ ].join('\n'),
262
+ )
223
263
 
224
264
  console.log(`✅ Created module ${name}/ with index.ts and test/${name}.test.ts`)
225
265
  }
@@ -243,7 +283,9 @@ async function rmrf(dir: string) {
243
283
  }
244
284
  const { rmdir } = await import('node:fs/promises')
245
285
  await rmdir(dir)
246
- } catch { /* ignore */ }
286
+ } catch {
287
+ /* ignore */
288
+ }
247
289
  }
248
290
 
249
291
  import { parseArgs } from 'node:util'
@@ -283,7 +325,9 @@ if (cmd === 'version' || cmd === '-v' || cmd === '--version') {
283
325
  console.error('Usage: npx weifuwu init <name> [--minimal] [--skip-install]')
284
326
  process.exit(1)
285
327
  }
286
- cmdInit(name, { minimal: !!values.minimal, skipInstall: !!values['skip-install'] }).catch(console.error)
328
+ cmdInit(name, { minimal: !!values.minimal, skipInstall: !!values['skip-install'] }).catch(
329
+ console.error,
330
+ )
287
331
  } else if (cmd === 'dev') {
288
332
  cmdDev()
289
333
  } else if (cmd === 'generate' || cmd === 'g') {
@@ -1,5 +1,5 @@
1
1
  import { Router } from '../router.ts';
2
- import type { BoundTable } from '../postgres/schema/index.ts';
2
+ import { type BoundTable } from '../postgres/schema/index.ts';
3
3
  import type { RunParams } from './types.ts';
4
4
  interface RestDeps {
5
5
  agents: BoundTable<any>;
@@ -1,10 +1,10 @@
1
1
  import { type Tool } from 'ai';
2
- import type { Sql } from '../vendor.ts';
2
+ import type { SqlClient } from '../vendor.ts';
3
3
  import type { BoundTable } from '../postgres/schema/index.ts';
4
4
  import type { AIProvider } from '../ai/provider.ts';
5
5
  import type { RunParams, RunResult, KnowledgeDoc } from './types.ts';
6
6
  interface RunnerDeps {
7
- sql: Sql<{}>;
7
+ sql: SqlClient;
8
8
  agents: BoundTable<any>;
9
9
  runs: BoundTable<any>;
10
10
  knowledge: BoundTable<any>;
@@ -1,4 +1,4 @@
1
- import type { LanguageModel } from 'ai';
1
+ import { type LanguageModel } from 'ai';
2
2
  import type { AIProvider } from './provider.ts';
3
3
  export declare function runWorkflow(opts?: {
4
4
  tools?: Record<string, any>;
package/dist/ai-sdk.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { streamText, generateText, generateObject, streamObject, tool, embed, embedMany, smoothStream, } from 'ai';
2
- export { openai, createOpenAI, } from '@ai-sdk/openai';
2
+ export { openai, createOpenAI } from '@ai-sdk/openai';