weifuwu 0.27.25 → 0.27.28

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
@@ -66,7 +66,7 @@ app.use(rateLimit({ window: 60 }))
66
66
  ## Full-stack SSR
67
67
 
68
68
  Server-rendered HTML with zero frontend build tools. Uses `html()` tagged templates
69
- for safe HTML rendering, and `weifuwu-ui.js` for client-side interactions.
69
+ for safe HTML rendering, and **HTMX + Alpine.js + weifuwu-ui** for client-side interactions.
70
70
 
71
71
  ```ts
72
72
  import { Router, serve, html, raw, layout, view, wfuwAssets, wfuwVersion, theme, i18n, flash } from 'weifuwu'
@@ -78,7 +78,7 @@ app.use(theme())
78
78
  app.use(i18n({ dir: './locales' }))
79
79
  app.use(flash())
80
80
 
81
- // weifuwu-ui frontend runtime
81
+ // HTMX + Alpine.js + weifuwu-ui frontend assets
82
82
  app.use('/', wfuwAssets())
83
83
 
84
84
  // Layout (wraps all pages)
@@ -134,8 +134,10 @@ export default function (body: string, ctx: any) {
134
134
  <head>
135
135
  <meta charset="utf-8" />
136
136
  <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
137
+ <script src="/__wfw/js/htmx.min.js?v=${wfuwVersion}"></script>
138
+ <script defer src="/__wfw/js/alpine.min.js?v=${wfuwVersion}"></script>
137
139
  <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
138
- <script id="__wfw-i18n" type="application/json">
140
+ <script id="__wf-i18n" type="application/json">
139
141
  ${raw(JSON.stringify(ctx.i18n?.messages || {}))}
140
142
  </script>
141
143
  </head>
@@ -160,16 +162,14 @@ export default function (ctx: any) {
160
162
  }
161
163
  ```
162
164
 
163
- ### UI frontend runtime (weifuwu-ui)
165
+ ### UI frontend runtime
164
166
 
165
- weifuwu-ui is a zero-dependency frontend runtime (~5KB) that ships with weifuwu.
166
- One `<script>` + `<link>` covers AJAX loading, state binding, SSE streaming,
167
- WebSocket, theme/i18n/flash integration, and UI components.
167
+ weifuwu ships with **HTMX** (AJAX, SSE, WebSocket, forms) + **Alpine.js** (state, DOM
168
+ binding, UI components) + **weifuwu-ui** (Alpine stores for theme/i18n/flash).
168
169
 
169
170
  ```ts
170
171
  import { wfuwAssets } from 'weifuwu'
171
-
172
- app.use(wfuwAssets()) // serve /__wfw/js/weifuwu-ui.js + /__wfw/css/weifuwu-ui.css
172
+ app.use(wfuwAssets()) // serve htmx.min.js + alpine.min.js + weifuwu-ui.js
173
173
  ```
174
174
 
175
175
  In your layout (with cache-busting via `wfuwVersion`):
@@ -179,6 +179,8 @@ import { wfuwVersion } from 'weifuwu'
179
179
  ```
180
180
 
181
181
  ```html
182
+ <script src="/__wfw/js/htmx.min.js?v=${wfuwVersion}"></script>
183
+ <script defer src="/__wfw/js/alpine.min.js?v=${wfuwVersion}"></script>
182
184
  <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
183
185
  <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
184
186
  ```
@@ -560,9 +562,7 @@ app.get('/', view('./ui/app/page.ts'))
560
562
 
561
563
  #### wfuwAssets()
562
564
 
563
- Serve weifuwu-ui.js and weifuwu-ui.css zero-dependency frontend runtime (~5KB total).
564
- Covers: AJAX loading, state binding, SSE streaming, WebSocket, theme/i18n/flash,
565
- modal/collapse/tabs/dropdown/toast components.
565
+ Serve HTMX, Alpine.js, and weifuwu-ui (Alpine stores for theme/i18n/flash).
566
566
 
567
567
  ```ts
568
568
  import { wfuwAssets } from 'weifuwu'
@@ -574,6 +574,8 @@ import { wfuwVersion } from 'weifuwu'
574
574
  ```
575
575
 
576
576
  ```html
577
+ <script src="/__wfw/js/htmx.min.js?v=${wfuwVersion}"></script>
578
+ <script defer src="/__wfw/js/alpine.min.js?v=${wfuwVersion}"></script>
577
579
  <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
578
580
  <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
579
581
  ```
@@ -702,9 +704,8 @@ Creates a minimal API project with `app.ts`, `index.ts`, and TypeScript config.
702
704
 
703
705
  ### Frontend
704
706
 
705
- - weifuwu-ui.js (~5KB) — built-in, zero external dependencies
706
-
707
- Covers: AJAX loading, state binding, SSE streaming, WebSocket, theme/i18n/flash,
708
- modal/collapse/tabs/dropdown/toast components.
707
+ - **HTMX** (~14KB) — AJAX loading, SSE, WebSocket, form submission
708
+ - **Alpine.js** (~15KB) — state management, DOM binding, UI components
709
+ - **weifuwu-ui** (~2KB) Alpine stores for theme/i18n/flash/toast
709
710
 
710
711
  Zero build tools. Zero frontend framework compilation.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // cli.ts
4
- import { mkdir, writeFile, readFile, cp } from "node:fs/promises";
4
+ import { mkdir, writeFile } from "node:fs/promises";
5
5
  import { existsSync } from "node:fs";
6
6
  import { execSync } from "node:child_process";
7
7
  import { join, dirname, resolve } from "node:path";
@@ -28,13 +28,10 @@ async function cmdInit(name, opts) {
28
28
  process.exit(1);
29
29
  }
30
30
  const pkg = await readPkg();
31
- if (opts.minimal) {
32
- await generateMinimal(targetDir, name, pkg.version, opts.skipInstall);
33
- } else {
34
- await generateFull(targetDir, name, pkg.version, opts.skipInstall);
35
- }
31
+ const typesNodeVersion = pkg.devDependencies?.["@types/node"] || "^22";
32
+ await generateMinimal(targetDir, name, pkg.version, typesNodeVersion, opts.skipInstall);
36
33
  }
37
- async function generateMinimal(targetDir, name, version, skipInstall) {
34
+ async function generateMinimal(targetDir, name, version, typesNodeVersion, skipInstall) {
38
35
  await mkdir(targetDir, { recursive: true });
39
36
  await writeFile(
40
37
  join(targetDir, "app.ts"),
@@ -60,22 +57,11 @@ async function generateMinimal(targetDir, name, version, skipInstall) {
60
57
  ``
61
58
  ].join("\n")
62
59
  );
63
- await writePackageJson(targetDir, name, version, {});
60
+ await writePackageJson(targetDir, name, version, typesNodeVersion, {});
64
61
  await writeCommonFiles(targetDir);
65
62
  await finishInit(targetDir, skipInstall);
66
63
  }
67
- async function generateFull(targetDir, name, version, skipInstall) {
68
- const templateDir = existsSync(join(__dirname, "cli", "template")) ? join(__dirname, "cli", "template") : join(__dirname, "template");
69
- await cp(templateDir, targetDir, { recursive: true });
70
- const pkgPath = join(targetDir, "package.json");
71
- const pkgContent = await readFile(pkgPath, "utf-8");
72
- await writeFile(
73
- pkgPath,
74
- pkgContent.replace("__PROJECT_NAME__", name).replace("__VERSION__", version)
75
- );
76
- await finishInit(targetDir, skipInstall);
77
- }
78
- async function writePackageJson(targetDir, name, version, extra) {
64
+ async function writePackageJson(targetDir, name, version, typesNodeVersion, _extra) {
79
65
  const pkg = {
80
66
  name,
81
67
  type: "module",
@@ -83,7 +69,12 @@ async function writePackageJson(targetDir, name, version, extra) {
83
69
  dev: "node --watch index.ts",
84
70
  start: "node index.ts"
85
71
  },
86
- ...extra
72
+ dependencies: {
73
+ weifuwu: "^" + version
74
+ },
75
+ devDependencies: {
76
+ "@types/node": typesNodeVersion
77
+ }
87
78
  };
88
79
  await writeFile(join(targetDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
89
80
  }
@@ -107,8 +98,7 @@ var HELP = `
107
98
  weifuwu \u2014 Web-standard HTTP microframework for Node.js
108
99
 
109
100
  Usage:
110
- npx weifuwu init <name> Create a new project (SSR + shadcn UI)
111
- npx weifuwu init <name> --minimal Create a minimal API-only project
101
+ npx weifuwu init <name> Create a new project
112
102
  npx weifuwu init <name> --skip-install Skip npm install
113
103
  npx weifuwu version Print version
114
104
  `;
@@ -118,18 +108,17 @@ if (cmd === "version" || cmd === "-v" || cmd === "--version") {
118
108
  const { values, positionals } = parseArgs({
119
109
  args: process.argv.slice(3),
120
110
  options: {
121
- "skip-install": { type: "boolean" },
122
- minimal: { type: "boolean" }
111
+ "skip-install": { type: "boolean" }
123
112
  },
124
113
  strict: false,
125
114
  allowPositionals: true
126
115
  });
127
116
  const name = positionals[0];
128
117
  if (!name) {
129
- console.error("Usage: npx weifuwu init <name> [--skip-install] [--minimal]");
118
+ console.error("Usage: npx weifuwu init <name> [--skip-install]");
130
119
  process.exit(1);
131
120
  }
132
- cmdInit(name, { skipInstall: !!values["skip-install"], minimal: !!values["minimal"] }).catch(
121
+ cmdInit(name, { skipInstall: !!values["skip-install"] }).catch(
133
122
  console.error
134
123
  );
135
124
  } else {
@@ -2,6 +2,22 @@ import type { WebSocket, Context, Handler, Middleware, ErrorHandler } from '../t
2
2
  import { type IncomingMessage } from 'node:http';
3
3
  import type { Duplex } from 'node:stream';
4
4
  import { type Hub } from '../hub.ts';
5
+ declare module '../types.ts' {
6
+ interface Context {
7
+ ws: {
8
+ /** Per-connection state object */
9
+ state: Record<string, unknown>;
10
+ /** Send JSON to this connection */
11
+ json(data: unknown): void;
12
+ /** Join a room */
13
+ join(room: string): void;
14
+ /** Leave a room */
15
+ leave(room: string): void;
16
+ /** Broadcast to a room */
17
+ sendRoom(room: string, data: unknown): void;
18
+ };
19
+ }
20
+ }
5
21
  export type WebSocketHandler = {
6
22
  open?: (ws: WebSocket, ctx: Context) => void | Promise<void>;
7
23
  message?: (ws: WebSocket, ctx: Context, data: string | Buffer) => void | Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { Context, Handler, Middleware, ErrorHandler } from './types.ts';
1
+ export type { Context, Handler, Middleware, ErrorHandler, WsContext } from './types.ts';
2
2
  export { HttpError } from './types.ts';
3
3
  export { currentTraceId, currentTrace, runWithTrace, traceElapsed, trace } from './core/trace.ts';
4
4
  export type { TraceContext, TraceInjected, TraceOptions } from './core/trace.ts';
@@ -49,21 +49,3 @@ export { queue } from './queue/index.ts';
49
49
  export type { QueueOptions, QueueJob, Queue, QueueInjected } from './queue/types.ts';
50
50
  export { health } from './middleware/health.ts';
51
51
  export type { HealthOptions } from './middleware/health.ts';
52
- export { theme } from './middleware/theme.ts';
53
- export type { ThemeOptions, ThemeInjected } from './middleware/theme.ts';
54
- export { i18n } from './middleware/i18n.ts';
55
- export type { I18nOptions, I18nInjected } from './middleware/i18n.ts';
56
- export { flash } from './middleware/flash.ts';
57
- export type { FlashOptions, FlashInjected, FlashModule } from './middleware/flash.ts';
58
- export { csrf } from './middleware/csrf.ts';
59
- export type { CsrfOptions, CsrfInjected, CsrfModule } from './middleware/csrf.ts';
60
- export { html, raw } from './ssr/html.ts';
61
- export type { RawString } from './ssr/html.ts';
62
- export { layout } from './ssr/layout.ts';
63
- export { view } from './ssr/view.ts';
64
- export type { ViewOptions } from './ssr/view.ts';
65
- export { loadModule, clearModuleCache } from './ssr/compile.ts';
66
- export { cssContext, cssRouter, clearCSSCache } from './ssr/css.ts';
67
- export type { CssAsset } from './ssr/css.ts';
68
- export { assetRouter, assetScripts } from './ssr/assets.ts';
69
- export { wfuwAssets, wfuwVersion } from './ssr/ui/assets.ts';