weifuwu 0.25.2 → 0.27.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.
Files changed (208) hide show
  1. package/README.md +291 -2489
  2. package/ai/provider.ts +129 -0
  3. package/ai/stream.ts +63 -0
  4. package/cli.ts +55 -257
  5. package/core/cookie.ts +114 -0
  6. package/core/env.ts +142 -0
  7. package/core/logger.ts +72 -0
  8. package/core/router.ts +795 -0
  9. package/core/serve.ts +294 -0
  10. package/core/sse.ts +85 -0
  11. package/core/trace.ts +146 -0
  12. package/graphql.ts +267 -0
  13. package/hub.ts +133 -0
  14. package/index.ts +71 -0
  15. package/mailer.ts +81 -0
  16. package/middleware/compress.ts +103 -0
  17. package/middleware/cors.ts +81 -0
  18. package/middleware/csrf.ts +112 -0
  19. package/middleware/flash.ts +144 -0
  20. package/middleware/health.ts +44 -0
  21. package/middleware/helmet.ts +98 -0
  22. package/middleware/i18n.ts +175 -0
  23. package/middleware/rate-limit.ts +167 -0
  24. package/middleware/request-id.ts +60 -0
  25. package/middleware/static.ts +149 -0
  26. package/middleware/theme.ts +84 -0
  27. package/middleware/upload.ts +168 -0
  28. package/middleware/validate.ts +186 -0
  29. package/package.json +14 -36
  30. package/postgres/client.ts +132 -0
  31. package/postgres/index.ts +4 -0
  32. package/postgres/module.ts +37 -0
  33. package/postgres/schema/columns.ts +186 -0
  34. package/postgres/schema/index.ts +36 -0
  35. package/postgres/schema/sql.ts +39 -0
  36. package/postgres/schema/table.ts +548 -0
  37. package/postgres/schema/where.ts +99 -0
  38. package/postgres/types.ts +48 -0
  39. package/queue/cron.ts +90 -0
  40. package/queue/index.ts +654 -0
  41. package/queue/types.ts +60 -0
  42. package/redis/client.ts +24 -0
  43. package/{dist/redis/index.d.ts → redis/index.ts} +2 -2
  44. package/redis/types.ts +28 -0
  45. package/types.ts +78 -0
  46. package/cli/template/app.ts +0 -22
  47. package/cli/template/index.ts +0 -10
  48. package/cli/template/locales/en.json +0 -13
  49. package/cli/template/locales/zh-CN.json +0 -13
  50. package/cli/template/locales/zh-TW.json +0 -13
  51. package/cli/template/locales/zh.json +0 -13
  52. package/cli/template/ui/app/globals.css +0 -2
  53. package/cli/template/ui/app/layout.tsx +0 -15
  54. package/cli/template/ui/app/page.tsx +0 -124
  55. package/cli/template/ui/components/Greeting.tsx +0 -3
  56. package/dist/agent/client.d.ts +0 -2
  57. package/dist/agent/index.d.ts +0 -2
  58. package/dist/agent/rest.d.ts +0 -14
  59. package/dist/agent/run.d.ts +0 -19
  60. package/dist/agent/types.d.ts +0 -55
  61. package/dist/ai/provider.d.ts +0 -45
  62. package/dist/ai/utils.d.ts +0 -5
  63. package/dist/ai/workflow.d.ts +0 -17
  64. package/dist/ai-sdk.d.ts +0 -2
  65. package/dist/ai.d.ts +0 -13
  66. package/dist/analytics.d.ts +0 -45
  67. package/dist/auth.d.ts +0 -22
  68. package/dist/cache.d.ts +0 -74
  69. package/dist/cli.d.ts +0 -2
  70. package/dist/cli.js +0 -302
  71. package/dist/client-locale.d.ts +0 -25
  72. package/dist/client-pref.d.ts +0 -3
  73. package/dist/client-router.d.ts +0 -300
  74. package/dist/client-state.d.ts +0 -22
  75. package/dist/client-theme.d.ts +0 -36
  76. package/dist/compile.d.ts +0 -15
  77. package/dist/compress.d.ts +0 -20
  78. package/dist/cookie.d.ts +0 -36
  79. package/dist/cors.d.ts +0 -25
  80. package/dist/cron-utils.d.ts +0 -73
  81. package/dist/csrf.d.ts +0 -47
  82. package/dist/deploy/config.d.ts +0 -2
  83. package/dist/deploy/gateway.d.ts +0 -2
  84. package/dist/deploy/index.d.ts +0 -4
  85. package/dist/deploy/manager.d.ts +0 -16
  86. package/dist/deploy/process.d.ts +0 -14
  87. package/dist/deploy/types.d.ts +0 -53
  88. package/dist/env.d.ts +0 -69
  89. package/dist/error-boundary.d.ts +0 -2
  90. package/dist/flash.d.ts +0 -90
  91. package/dist/fts.d.ts +0 -36
  92. package/dist/graphql.d.ts +0 -16
  93. package/dist/head.d.ts +0 -6
  94. package/dist/health.d.ts +0 -24
  95. package/dist/helmet.d.ts +0 -33
  96. package/dist/html-shell.d.ts +0 -1
  97. package/dist/hub.d.ts +0 -37
  98. package/dist/i18n.d.ts +0 -39
  99. package/dist/iii/client.d.ts +0 -2
  100. package/dist/iii/index.d.ts +0 -4
  101. package/dist/iii/register-worker.d.ts +0 -9
  102. package/dist/iii/rest.d.ts +0 -3
  103. package/dist/iii/stream.d.ts +0 -82
  104. package/dist/iii/types.d.ts +0 -121
  105. package/dist/iii/worker.d.ts +0 -2
  106. package/dist/iii/ws.d.ts +0 -22
  107. package/dist/index.d.ts +0 -101
  108. package/dist/index.js +0 -12752
  109. package/dist/kb/index.d.ts +0 -3
  110. package/dist/kb/types.d.ts +0 -72
  111. package/dist/layout.d.ts +0 -2
  112. package/dist/live.d.ts +0 -7
  113. package/dist/logdb/client.d.ts +0 -2
  114. package/dist/logdb/index.d.ts +0 -2
  115. package/dist/logdb/rest.d.ts +0 -5
  116. package/dist/logdb/types.d.ts +0 -27
  117. package/dist/logger.d.ts +0 -16
  118. package/dist/mailer.d.ts +0 -51
  119. package/dist/mcp.d.ts +0 -34
  120. package/dist/messager/agent.d.ts +0 -11
  121. package/dist/messager/client.d.ts +0 -2
  122. package/dist/messager/index.d.ts +0 -2
  123. package/dist/messager/rest.d.ts +0 -15
  124. package/dist/messager/types.d.ts +0 -57
  125. package/dist/messager/ws.d.ts +0 -14
  126. package/dist/module-server.d.ts +0 -9
  127. package/dist/not-found.d.ts +0 -2
  128. package/dist/notifier/client.d.ts +0 -2
  129. package/dist/notifier/index.d.ts +0 -2
  130. package/dist/notifier/types.d.ts +0 -105
  131. package/dist/opencode/client.d.ts +0 -2
  132. package/dist/opencode/index.d.ts +0 -2
  133. package/dist/opencode/permissions.d.ts +0 -5
  134. package/dist/opencode/prompt.d.ts +0 -8
  135. package/dist/opencode/rest.d.ts +0 -16
  136. package/dist/opencode/run.d.ts +0 -13
  137. package/dist/opencode/session.d.ts +0 -26
  138. package/dist/opencode/skills.d.ts +0 -4
  139. package/dist/opencode/tools/bash.d.ts +0 -6
  140. package/dist/opencode/tools/edit.d.ts +0 -19
  141. package/dist/opencode/tools/glob.d.ts +0 -9
  142. package/dist/opencode/tools/grep.d.ts +0 -17
  143. package/dist/opencode/tools/index.d.ts +0 -12
  144. package/dist/opencode/tools/question.d.ts +0 -5
  145. package/dist/opencode/tools/read.d.ts +0 -16
  146. package/dist/opencode/tools/skill.d.ts +0 -18
  147. package/dist/opencode/tools/web.d.ts +0 -18
  148. package/dist/opencode/tools/write.d.ts +0 -13
  149. package/dist/opencode/types.d.ts +0 -90
  150. package/dist/opencode/ws.d.ts +0 -21
  151. package/dist/permissions.d.ts +0 -51
  152. package/dist/postgres/client.d.ts +0 -4
  153. package/dist/postgres/index.d.ts +0 -4
  154. package/dist/postgres/module.d.ts +0 -17
  155. package/dist/postgres/schema/columns.d.ts +0 -99
  156. package/dist/postgres/schema/index.d.ts +0 -6
  157. package/dist/postgres/schema/sql.d.ts +0 -22
  158. package/dist/postgres/schema/table.d.ts +0 -141
  159. package/dist/postgres/schema/where.d.ts +0 -29
  160. package/dist/postgres/types.d.ts +0 -50
  161. package/dist/queue/index.d.ts +0 -2
  162. package/dist/queue/types.d.ts +0 -62
  163. package/dist/rate-limit.d.ts +0 -45
  164. package/dist/react.d.ts +0 -14
  165. package/dist/react.js +0 -751
  166. package/dist/redis/client.d.ts +0 -2
  167. package/dist/redis/types.d.ts +0 -18
  168. package/dist/request-id.d.ts +0 -40
  169. package/dist/router.d.ts +0 -73
  170. package/dist/s3.d.ts +0 -68
  171. package/dist/seo.d.ts +0 -104
  172. package/dist/serve.d.ts +0 -38
  173. package/dist/server-registry.d.ts +0 -10
  174. package/dist/session.d.ts +0 -117
  175. package/dist/sse.d.ts +0 -47
  176. package/dist/ssr-entries.d.ts +0 -4
  177. package/dist/ssr.d.ts +0 -11
  178. package/dist/static.d.ts +0 -23
  179. package/dist/stream.d.ts +0 -24
  180. package/dist/tailwind.d.ts +0 -15
  181. package/dist/tenant/client.d.ts +0 -2
  182. package/dist/tenant/graphql.d.ts +0 -3
  183. package/dist/tenant/index.d.ts +0 -2
  184. package/dist/tenant/rest.d.ts +0 -3
  185. package/dist/tenant/schema.d.ts +0 -5
  186. package/dist/tenant/types.d.ts +0 -48
  187. package/dist/tenant/utils.d.ts +0 -9
  188. package/dist/test-utils.d.ts +0 -194
  189. package/dist/theme.d.ts +0 -31
  190. package/dist/trace.d.ts +0 -95
  191. package/dist/tsx-context.d.ts +0 -32
  192. package/dist/types.d.ts +0 -47
  193. package/dist/upload.d.ts +0 -55
  194. package/dist/use-action.d.ts +0 -42
  195. package/dist/use-agent-stream.d.ts +0 -49
  196. package/dist/use-flash-message.d.ts +0 -17
  197. package/dist/use-websocket.d.ts +0 -42
  198. package/dist/user/client.d.ts +0 -30
  199. package/dist/user/index.d.ts +0 -2
  200. package/dist/user/oauth-login.d.ts +0 -21
  201. package/dist/user/oauth2.d.ts +0 -31
  202. package/dist/user/types.d.ts +0 -178
  203. package/dist/validate.d.ts +0 -32
  204. package/dist/vendor.d.ts +0 -7
  205. package/dist/webhook.d.ts +0 -79
  206. package/opencode/ui/app/globals.css +0 -1
  207. package/opencode/ui/app/layout.tsx +0 -13
  208. package/opencode/ui/app/page.tsx +0 -523
@@ -1,45 +0,0 @@
1
- import type { Middleware, Closeable } from './types.ts';
2
- import { Router } from './router.ts';
3
- /** Tagged-template SQL function from the postgres.js library. */
4
- type PgSql = (strings: TemplateStringsArray, ...values: unknown[]) => Promise<unknown[]>;
5
- /** Schema table builder callback. */
6
- type PgTable = (name: string, cols: Record<string, unknown>) => {
7
- create(): Promise<void>;
8
- createIndex(cols: string[], opts: {
9
- unique: boolean;
10
- }): Promise<void>;
11
- };
12
- /** Options for {@link analytics}. */
13
- export interface AnalyticsOptions {
14
- /** Path prefixes to exclude from analytics (default: `['/__analytics', '/__wfw', '/static']`). */
15
- excluded?: string[];
16
- /** PostgreSQL client for persistent storage. Required for production use. */
17
- pg?: {
18
- sql: PgSql;
19
- table: PgTable;
20
- };
21
- }
22
- /** Analytics module returned by {@link analytics}. */
23
- export interface AnalyticsModule extends Router, Closeable {
24
- /** Middleware that records page views. */
25
- middleware: () => Middleware;
26
- /** Create/update the analytics database tables. */
27
- migrate: () => Promise<void>;
28
- /** Close the in-memory store and any timers. */
29
- close: () => Promise<void>;
30
- }
31
- /**
32
- * Page view analytics module.
33
- *
34
- * Records page views with referrer and device type. Supports in-memory and PostgreSQL storage.
35
- * Provides a dashboard at `GET /__analytics`.
36
- *
37
- * ```ts
38
- * import { analytics, postgres } from 'weifuwu'
39
- *
40
- * const pg = postgres({ connection: DATABASE_URL })
41
- * app.use(analytics({ pg }).middleware())
42
- * ```
43
- */
44
- export declare function analytics(options?: AnalyticsOptions): AnalyticsModule;
45
- export {};
package/dist/auth.d.ts DELETED
@@ -1,22 +0,0 @@
1
- import type { Middleware } from './types.ts';
2
- export interface AuthOptions {
3
- token?: string;
4
- verify?: (token: string, req: Request) => unknown | Promise<unknown>;
5
- proxy?: string | URL;
6
- header?: string;
7
- /**
8
- * Enable session-based authentication.
9
- * When true, auth() checks `ctx.session.userId` first.
10
- * If found, the user is authenticated via session (no token required).
11
- * Falls back to header-based auth if no session userId is present.
12
- */
13
- session?: boolean;
14
- /**
15
- * Function to load user data from a user ID stored in the session.
16
- * Called when `session: true` and `ctx.session.userId` is present.
17
- * Return a falsy value to reject (e.g. if the user was deleted).
18
- * If not provided, `ctx.user` is set to `{ id: ctx.session.userId }`.
19
- */
20
- resolveUser?: (userId: unknown) => unknown | Promise<unknown>;
21
- }
22
- export declare function auth(options: AuthOptions): Middleware;
package/dist/cache.d.ts DELETED
@@ -1,74 +0,0 @@
1
- import type { Context, Middleware, Closeable } from './types.ts';
2
- import type { Redis } from './vendor.ts';
3
- export interface CachedResponse {
4
- status: number;
5
- statusText: string;
6
- headers: Record<string, string>;
7
- body: string;
8
- createdAt: number;
9
- tags: string[];
10
- }
11
- export interface CacheStore {
12
- get(key: string): Promise<CachedResponse | null>;
13
- set(key: string, entry: CachedResponse, ttl: number): Promise<void>;
14
- delete(key: string): Promise<void>;
15
- invalidate(tag: string): Promise<void>;
16
- flush(): Promise<void>;
17
- }
18
- export interface CacheOptions {
19
- /** TTL in milliseconds. Default: 300_000 (5 min). */
20
- ttl?: number;
21
- /** Cache store. 'memory' (default) or 'redis'. */
22
- store?: 'memory' | 'redis' | CacheStore;
23
- /** Redis client (required when store: 'redis'). */
24
- redis?: Redis;
25
- /** Custom cache key function. Default: SHA256 of method + URL. */
26
- key?: (req: Request) => string;
27
- /** Tag function for grouped invalidation. Called after handler runs (ctx available). */
28
- tag?: (req: Request, ctx: Context) => string | string[] | undefined;
29
- /** Whether to cache responses with Set-Cookie. Default: false. */
30
- cacheCookies?: boolean;
31
- /** Status codes to cache. Default: [200]. */
32
- cacheStatus?: number[];
33
- /** Maximum number of bytes per cached body. Default: 1MB. Larger bodies are skipped. */
34
- maxBodySize?: number;
35
- }
36
- export interface CacheMiddleware extends Middleware, Closeable {
37
- /** Invalidate all entries with a given tag. */
38
- invalidate(tag: string): Promise<void>;
39
- /** Flush all cached entries. */
40
- flush(): Promise<void>;
41
- /** Cleanup. */
42
- close(): Promise<void>;
43
- /** Store reference (for testing). */
44
- store: CacheStore;
45
- }
46
- export declare class MemoryCache implements CacheStore {
47
- private store;
48
- private tagIndex;
49
- private interval;
50
- constructor(cleanupMs?: number);
51
- get(key: string): Promise<CachedResponse | null>;
52
- set(key: string, data: CachedResponse, ttl: number): Promise<void>;
53
- delete(key: string): Promise<void>;
54
- invalidate(tag: string): Promise<void>;
55
- flush(): Promise<void>;
56
- private cleanup;
57
- close(): Promise<void>;
58
- /** Testing only. */
59
- get size(): number;
60
- }
61
- export declare class RedisCache implements CacheStore {
62
- private redis;
63
- private prefix;
64
- private tagPrefix;
65
- constructor(redis: Redis, prefix?: string);
66
- private key;
67
- private tagKey;
68
- get(key: string): Promise<CachedResponse | null>;
69
- set(key: string, entry: CachedResponse, ttl: number): Promise<void>;
70
- delete(key: string): Promise<void>;
71
- invalidate(tag: string): Promise<void>;
72
- flush(): Promise<void>;
73
- }
74
- export declare function cache(options?: CacheOptions): CacheMiddleware;
package/dist/cli.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/cli.js DELETED
@@ -1,302 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // cli.ts
4
- import { mkdir, writeFile, copyFile, readFile, cp } from "node:fs/promises";
5
- import { existsSync, readdirSync } from "node:fs";
6
- import { execSync } from "node:child_process";
7
- import { homedir } from "node:os";
8
- import { join, dirname, resolve } from "node:path";
9
- import { fileURLToPath } from "node:url";
10
- import { parseArgs } from "node:util";
11
- var __filename = fileURLToPath(import.meta.url);
12
- var __dirname = dirname(__filename);
13
- var pkgRoot = existsSync(join(__dirname, "package.json")) ? __dirname : resolve(__dirname, "..");
14
- async function readPkg() {
15
- return JSON.parse(await readFile(join(pkgRoot, "package.json"), "utf-8"));
16
- }
17
- async function cmdSkill() {
18
- const targetDir = join(homedir(), ".agents", "skills", "weifuwu");
19
- await mkdir(targetDir, { recursive: true });
20
- await copyFile(join(pkgRoot, "README.md"), join(targetDir, "SKILL.md"));
21
- console.log("\u2705 Installed weifuwu skill to ~/.agents/skills/weifuwu/");
22
- }
23
- async function cmdVersion() {
24
- const pkg = await readPkg();
25
- console.log(pkg.version);
26
- }
27
- async function cmdInit(name, opts) {
28
- const targetDir = resolve(process.cwd(), name);
29
- const pkg = await readPkg();
30
- const v = pkg.version;
31
- const typeVersions = {
32
- "@types/react": "^19",
33
- "@types/react-dom": "^19",
34
- "@types/node": "^22"
35
- };
36
- const depVer = (depName) => typeVersions[depName] || `^${(pkg.devDependencies?.[depName] || "0.0.0").replace(/^\^/, "")}`;
37
- await mkdir(targetDir, { recursive: true });
38
- const templateDir = join(pkgRoot, "cli", "template");
39
- await cp(templateDir, targetDir, { recursive: true });
40
- for (const file of ["app.ts", "index.ts"]) {
41
- const fp = join(targetDir, file);
42
- let content = await readFile(fp, "utf-8");
43
- content = content.replace(/from '\.\.\/\.\.\/index\.ts'/g, "from 'weifuwu'").replace(/from '\.\.\/\.\.\/\.\.\/react\.ts'/g, "from 'weifuwu/react'");
44
- await writeFile(fp, content);
45
- }
46
- const uiPage = join(targetDir, "ui", "app", "page.tsx");
47
- if (existsSync(uiPage)) {
48
- let content = await readFile(uiPage, "utf-8");
49
- content = content.replace(/from '\.\.\/\.\.\/\.\.\/\.\.\/react\.ts'/g, "from 'weifuwu/react'");
50
- await writeFile(uiPage, content);
51
- }
52
- if (opts.minimal) {
53
- try {
54
- await rmrf(join(targetDir, "ui"));
55
- } catch {
56
- }
57
- try {
58
- await rmrf(join(targetDir, "locales"));
59
- } catch {
60
- }
61
- await writeFile(
62
- join(targetDir, "app.ts"),
63
- [
64
- `import { Router } from 'weifuwu'`,
65
- ``,
66
- `export const app = new Router()`,
67
- ``,
68
- `app.get('/', () => new Response('Hello from ${name}!'))`,
69
- `app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))`,
70
- ``
71
- ].join("\n")
72
- );
73
- await writeFile(
74
- join(targetDir, "index.ts"),
75
- [
76
- `import { serve } from 'weifuwu'`,
77
- `import { app } from './app.ts'`,
78
- ``,
79
- `const port = Number(process.env.PORT) || 3000`,
80
- `serve(app.handler(), { port })`,
81
- ``
82
- ].join("\n")
83
- );
84
- }
85
- const deps = { weifuwu: `^${v}` };
86
- const devDeps = {};
87
- if (!opts.minimal) {
88
- deps["react"] = "^19";
89
- deps["react-dom"] = "^19";
90
- deps["tailwindcss"] = "^4";
91
- devDeps["@types/react"] = depVer("@types/react");
92
- devDeps["@types/react-dom"] = depVer("@types/react-dom");
93
- }
94
- devDeps["@types/node"] = depVer("@types/node");
95
- await writeFile(
96
- join(targetDir, "package.json"),
97
- JSON.stringify(
98
- {
99
- name,
100
- type: "module",
101
- scripts: {
102
- dev: "NODE_ENV=development node --watch index.ts",
103
- start: "node index.ts"
104
- },
105
- dependencies: deps,
106
- devDependencies: devDeps
107
- },
108
- null,
109
- 2
110
- ) + "\n"
111
- );
112
- const include = opts.minimal ? ["*.ts"] : ["*.ts", "ui/**/*.ts", "ui/**/*.tsx"];
113
- await writeFile(
114
- join(targetDir, "tsconfig.json"),
115
- JSON.stringify(
116
- {
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
- },
129
- null,
130
- 2
131
- ) + "\n"
132
- );
133
- await writeFile(join(targetDir, ".gitignore"), "node_modules\ndist\n.env\n.sessions\n.weifuwu\n");
134
- await writeFile(join(targetDir, ".env"), "PORT=3000\n");
135
- await writeFile(
136
- join(targetDir, "AGENTS.md"),
137
- [
138
- `# ${name}`,
139
- "",
140
- `This is a [weifuwu](https://weifuwu.io) application \u2014 pure Node.js, no build step.`,
141
- "",
142
- "## Commands",
143
- "",
144
- "- `npm run dev` \u2014 start dev server with hot reload",
145
- "- `npm start` \u2014 start production server",
146
- "- `npm install` \u2014 install dependencies",
147
- "- `npx tsc --noEmit` \u2014 type-check",
148
- "",
149
- "## API Reference",
150
- "",
151
- "See `node_modules/weifuwu/README.md` for the full documentation.",
152
- ""
153
- ].join("\n")
154
- );
155
- if (!opts.skipInstall) {
156
- console.log("\nInstalling dependencies...");
157
- execSync("npm install", { cwd: targetDir, stdio: "inherit" });
158
- }
159
- console.log(
160
- `
161
- \u2705 Created ${name}/ \u2014 cd ${name} && ${opts.skipInstall ? "npm install && " : ""}npm run dev`
162
- );
163
- }
164
- async function cmdDev() {
165
- const entry = existsSync("index.ts") ? "index.ts" : existsSync("app.ts") ? "app.ts" : null;
166
- if (!entry) {
167
- console.error("No index.ts or app.ts found in current directory.");
168
- console.error("Run `npx weifuwu init <name>` to create a new project.");
169
- process.exit(1);
170
- }
171
- console.log(`Starting dev server (${entry})...`);
172
- execSync(`NODE_ENV=development node --watch ${entry}`, { stdio: "inherit" });
173
- }
174
- async function cmdGenerate(type, name) {
175
- if (type !== "module") {
176
- console.error(`Unknown generate type: ${type}. Usage: npx weifuwu generate module <name>`);
177
- process.exit(1);
178
- }
179
- const dir = join(process.cwd(), name);
180
- if (existsSync(dir)) {
181
- console.error(`Directory ${name} already exists.`);
182
- process.exit(1);
183
- }
184
- await mkdir(dir, { recursive: true });
185
- await writeFile(
186
- join(dir, "index.ts"),
187
- [
188
- `import type { Middleware } from 'weifuwu'`,
189
- ``,
190
- `export interface ${capitalize(name)}Options {`,
191
- ` // Add your options here`,
192
- `}`,
193
- ``,
194
- `export function ${name}(opts?: ${capitalize(name)}Options): Middleware {`,
195
- ` return async (req, ctx, next) => {`,
196
- ` // Your middleware logic here`,
197
- ` return next(req, ctx)`,
198
- ` }`,
199
- `}`,
200
- ``
201
- ].join("\n")
202
- );
203
- await mkdir(join(dir, "..", "test"), { recursive: true });
204
- await writeFile(
205
- join(dir, "..", "test", `${name}.test.ts`),
206
- [
207
- `import { describe, it } from 'node:test'`,
208
- `import assert from 'node:assert/strict'`,
209
- `import { ${name} } from '../${name}/index.ts'`,
210
- `import { Router } from 'weifuwu'`,
211
- ``,
212
- `describe('${name}', () => {`,
213
- ` it('works as middleware', async () => {`,
214
- ` const app = new Router()`,
215
- ` app.use(${name}())`,
216
- ` app.get('/', () => new Response('ok'))`,
217
- ``,
218
- ` const res = await app.handler()(`,
219
- ` new Request('http://localhost/'),`,
220
- ` { params: {}, query: {} } as any,`,
221
- ` )`,
222
- ` assert.equal(res.status, 200)`,
223
- ` })`,
224
- `})`,
225
- ``
226
- ].join("\n")
227
- );
228
- console.log(`\u2705 Created module ${name}/ with index.ts and test/${name}.test.ts`);
229
- }
230
- function capitalize(s) {
231
- return s.charAt(0).toUpperCase() + s.slice(1);
232
- }
233
- async function rmrf(dir) {
234
- try {
235
- const entries = readdirSync(dir, { withFileTypes: true });
236
- for (const entry of entries) {
237
- const p = join(dir, entry.name);
238
- if (entry.isDirectory()) {
239
- await rmrf(p);
240
- } else {
241
- const { unlink } = await import("node:fs/promises");
242
- await unlink(p);
243
- }
244
- }
245
- const { rmdir } = await import("node:fs/promises");
246
- await rmdir(dir);
247
- } catch {
248
- }
249
- }
250
- var cmd = process.argv[2];
251
- var HELP = `
252
- weifuwu \u2014 Web-standard HTTP framework for Node.js
253
-
254
- Usage:
255
- npx weifuwu init <name> Create a new project (SSR + i18n + theme)
256
- npx weifuwu init <name> --minimal Create a minimal HTTP project
257
- npx weifuwu init <name> --skip-install Create project, skip npm install
258
- npx weifuwu dev Start dev server in current directory
259
- npx weifuwu generate module <name> Scaffold a new module
260
- npx weifuwu version Print version
261
- `;
262
- if (cmd === "version" || cmd === "-v" || cmd === "--version") {
263
- cmdVersion().catch(console.error);
264
- } else if (cmd === "skill") {
265
- cmdSkill().catch(console.error);
266
- } else if (cmd === "init") {
267
- const { values, positionals } = parseArgs({
268
- args: process.argv.slice(3),
269
- options: {
270
- minimal: { type: "boolean", short: "m" },
271
- "skip-install": { type: "boolean" }
272
- },
273
- strict: false,
274
- allowPositionals: true
275
- });
276
- const name = positionals[0];
277
- if (!name) {
278
- console.error("Usage: npx weifuwu init <name> [--minimal] [--skip-install]");
279
- process.exit(1);
280
- }
281
- cmdInit(name, { minimal: !!values.minimal, skipInstall: !!values["skip-install"] }).catch(
282
- console.error
283
- );
284
- } else if (cmd === "dev") {
285
- cmdDev();
286
- } else if (cmd === "generate" || cmd === "g") {
287
- const { positionals } = parseArgs({
288
- args: process.argv.slice(3),
289
- options: {},
290
- strict: false,
291
- allowPositionals: true
292
- });
293
- const type = positionals[0];
294
- const name = positionals[1];
295
- if (!type || !name) {
296
- console.error("Usage: npx weifuwu generate module <name>");
297
- process.exit(1);
298
- }
299
- cmdGenerate(type, name).catch(console.error);
300
- } else {
301
- console.log(HELP);
302
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * React hook to read and change the locale on the client side.
3
- *
4
- * Changes are made via SPA navigation to `/__lang/{locale}`, which is
5
- * intercepted by the client router and applied without a full page reload.
6
- *
7
- * ```tsx
8
- * import { useLocale } from 'weifuwu/react'
9
- *
10
- * function LangSwitcher() {
11
- * const { locale, setLocale, t } = useLocale()
12
- * return (
13
- * <>
14
- * <p>{t('greeting')}</p>
15
- * <button onClick={() => setLocale('zh')}>中文</button>
16
- * </>
17
- * )
18
- * }
19
- * ```
20
- */
21
- export declare function useLocale(): {
22
- locale: string | undefined;
23
- setLocale: (locale: string) => Promise<void>;
24
- t: (key: string, params?: Record<string, string>, fallback?: string) => string;
25
- };
@@ -1,3 +0,0 @@
1
- export type UrlInterceptor = (url: URL) => boolean | Promise<boolean>;
2
- export declare function addInterceptor(fn: UrlInterceptor): void;
3
- export declare function runInterceptors(url: URL): Promise<boolean>;