weifuwu 0.27.24 → 0.27.26

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,10 +66,10 @@ 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
- import { Router, serve, html, raw, layout, view, wfuwAssets, theme, i18n, flash } from 'weifuwu'
72
+ import { Router, serve, html, raw, layout, view, wfuwAssets, wfuwVersion, theme, i18n, flash } from 'weifuwu'
73
73
 
74
74
  const app = new Router()
75
75
 
@@ -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)
@@ -125,7 +125,7 @@ html`<div>${html`<span>nested</span>`}</div>`
125
125
  Wraps page HTML in a layout template. Multiple layouts nest naturally.
126
126
 
127
127
  ```ts
128
- import { html, raw } from 'weifuwu'
128
+ import { html, raw, wfuwVersion } from 'weifuwu'
129
129
 
130
130
  // ui/app/layout.ts
131
131
  export default function (body: string, ctx: any) {
@@ -133,9 +133,11 @@ export default function (body: string, ctx: any) {
133
133
  <html data-theme="${ctx.theme?.value || 'light'}">
134
134
  <head>
135
135
  <meta charset="utf-8" />
136
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
137
- <script src="/__wfw/js/weifuwu-ui.js"></script>
138
- <script id="__wfw-i18n" type="application/json">
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>
139
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
140
+ <script id="__wf-i18n" type="application/json">
139
141
  ${raw(JSON.stringify(ctx.i18n?.messages || {}))}
140
142
  </script>
141
143
  </head>
@@ -160,23 +162,27 @@ 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
- In your layout:
175
+ In your layout (with cache-busting via `wfuwVersion`):
176
+
177
+ ```ts
178
+ import { wfuwVersion } from 'weifuwu'
179
+ ```
176
180
 
177
181
  ```html
178
- <script src="/__wfw/js/weifuwu-ui.js"></script>
179
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
182
+ <script src="/__wfw/js/htmx.min.js?v=${wfuwVersion}"></script>
183
+ <script defer src="/__wfw/js/alpine.min.js?v=${wfuwVersion}"></script>
184
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
185
+ <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
180
186
  ```
181
187
 
182
188
  ---
@@ -556,18 +562,22 @@ app.get('/', view('./ui/app/page.ts'))
556
562
 
557
563
  #### wfuwAssets()
558
564
 
559
- Serve weifuwu-ui.js and weifuwu-ui.css zero-dependency frontend runtime (~5KB total).
560
- Covers: AJAX loading, state binding, SSE streaming, WebSocket, theme/i18n/flash,
561
- modal/collapse/tabs/dropdown/toast components.
565
+ Serve HTMX, Alpine.js, and weifuwu-ui (Alpine stores for theme/i18n/flash).
562
566
 
563
567
  ```ts
564
568
  import { wfuwAssets } from 'weifuwu'
565
569
  app.use(wfuwAssets())
566
570
  ```
567
571
 
572
+ ```ts
573
+ import { wfuwVersion } from 'weifuwu'
574
+ ```
575
+
568
576
  ```html
569
- <script src="/__wfw/js/weifuwu-ui.js"></script>
570
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
577
+ <script src="/__wfw/js/htmx.min.js?v=${wfuwVersion}"></script>
578
+ <script defer src="/__wfw/js/alpine.min.js?v=${wfuwVersion}"></script>
579
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
580
+ <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
571
581
  ```
572
582
 
573
583
  ### Standalone utilities
@@ -694,9 +704,8 @@ Creates a minimal API project with `app.ts`, `index.ts`, and TypeScript config.
694
704
 
695
705
  ### Frontend
696
706
 
697
- - weifuwu-ui.js (~5KB) — built-in, zero external dependencies
698
-
699
- Covers: AJAX loading, state binding, SSE streaming, WebSocket, theme/i18n/flash,
700
- 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
701
710
 
702
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,11 +28,7 @@ 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
+ await generateMinimal(targetDir, name, pkg.version, opts.skipInstall);
36
32
  }
37
33
  async function generateMinimal(targetDir, name, version, skipInstall) {
38
34
  await mkdir(targetDir, { recursive: true });
@@ -64,17 +60,6 @@ async function generateMinimal(targetDir, name, version, skipInstall) {
64
60
  await writeCommonFiles(targetDir);
65
61
  await finishInit(targetDir, skipInstall);
66
62
  }
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
63
  async function writePackageJson(targetDir, name, version, extra) {
79
64
  const pkg = {
80
65
  name,
@@ -107,8 +92,7 @@ var HELP = `
107
92
  weifuwu \u2014 Web-standard HTTP microframework for Node.js
108
93
 
109
94
  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
95
+ npx weifuwu init <name> Create a new project
112
96
  npx weifuwu init <name> --skip-install Skip npm install
113
97
  npx weifuwu version Print version
114
98
  `;
@@ -118,18 +102,17 @@ if (cmd === "version" || cmd === "-v" || cmd === "--version") {
118
102
  const { values, positionals } = parseArgs({
119
103
  args: process.argv.slice(3),
120
104
  options: {
121
- "skip-install": { type: "boolean" },
122
- minimal: { type: "boolean" }
105
+ "skip-install": { type: "boolean" }
123
106
  },
124
107
  strict: false,
125
108
  allowPositionals: true
126
109
  });
127
110
  const name = positionals[0];
128
111
  if (!name) {
129
- console.error("Usage: npx weifuwu init <name> [--skip-install] [--minimal]");
112
+ console.error("Usage: npx weifuwu init <name> [--skip-install]");
130
113
  process.exit(1);
131
114
  }
132
- cmdInit(name, { skipInstall: !!values["skip-install"], minimal: !!values["minimal"] }).catch(
115
+ cmdInit(name, { skipInstall: !!values["skip-install"] }).catch(
133
116
  console.error
134
117
  );
135
118
  } 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';