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 +34 -25
- package/dist/cli.js +6 -23
- package/dist/core/router.d.ts +16 -0
- package/dist/index.d.ts +1 -19
- package/dist/index.js +49 -600
- package/dist/types.d.ts +27 -7
- package/package.json +5 -9
- package/dist/docs/ssr/ui.md +0 -472
- package/dist/middleware/csrf.d.ts +0 -47
- package/dist/middleware/flash.d.ts +0 -90
- package/dist/middleware/i18n.d.ts +0 -39
- package/dist/middleware/theme.d.ts +0 -31
- package/dist/ssr/assets.d.ts +0 -5
- package/dist/ssr/compile.d.ts +0 -21
- package/dist/ssr/css.d.ts +0 -16
- package/dist/ssr/html.d.ts +0 -53
- package/dist/ssr/layout.d.ts +0 -2
- package/dist/ssr/ui/assets.d.ts +0 -4
- package/dist/ssr/view.d.ts +0 -36
- package/dist/template/AGENTS.md +0 -30
- package/dist/template/app.ts +0 -20
- package/dist/template/index.ts +0 -6
- package/dist/template/locales/en.json +0 -7
- package/dist/template/locales/zh-CN.json +0 -7
- package/dist/template/package.json +0 -11
- package/dist/template/tsconfig.json +0 -15
- package/dist/template/ui/app/globals.css +0 -2
- package/dist/template/ui/app/layout.ts +0 -39
- package/dist/template/ui/app/page.ts +0 -39
- package/dist/weifuwu-ui.css +0 -646
- package/dist/weifuwu-ui.js +0 -998
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
|
|
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
|
|
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/
|
|
138
|
-
<script
|
|
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
|
|
165
|
+
### UI frontend runtime
|
|
164
166
|
|
|
165
|
-
weifuwu
|
|
166
|
-
|
|
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/
|
|
179
|
-
<
|
|
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
|
|
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/
|
|
570
|
-
<
|
|
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
|
-
-
|
|
698
|
-
|
|
699
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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]
|
|
112
|
+
console.error("Usage: npx weifuwu init <name> [--skip-install]");
|
|
130
113
|
process.exit(1);
|
|
131
114
|
}
|
|
132
|
-
cmdInit(name, { skipInstall: !!values["skip-install"]
|
|
115
|
+
cmdInit(name, { skipInstall: !!values["skip-install"] }).catch(
|
|
133
116
|
console.error
|
|
134
117
|
);
|
|
135
118
|
} else {
|
package/dist/core/router.d.ts
CHANGED
|
@@ -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';
|