weifuwu 0.2.4 → 0.3.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.
- package/README.md +26 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
**Web-standard HTTP framework for Node.js.** `(req, ctx) => Response` — no framework-specific objects, just the Web API your browser already speaks.
|
|
4
4
|
|
|
5
|
+
### Design
|
|
6
|
+
|
|
7
|
+
weifuwu doesn't invent its own request/response abstraction. `Request` and `Response` are the same objects you use in `fetch()` — what you learn in the browser applies directly on the server. `ctx` is the only framework object, and it only carries what the router parsed for you (`params`, `query`).
|
|
8
|
+
|
|
9
|
+
Features like `tsx()`, WebSocket, GraphQL, and AI streaming all follow the same `(req, ctx) => Response` contract. There is no separate concept for "page route" vs "API route" — everything is a handler that returns a `Response`. `tsx()` just generates a `Response` from a React component the same way `router.get()` returns a `Response` from a handler function.
|
|
10
|
+
|
|
5
11
|
## Features
|
|
6
12
|
|
|
7
13
|
- **Web Standard** — `Request` / `Response` / `ReadableStream`, zero abstractions
|
|
8
14
|
- **Trie router** — static > param > wildcard, sub-router mounting, path params
|
|
9
15
|
- **Middleware** — global, path-scoped, route-level — onion model, short-circuit
|
|
10
16
|
- **Built-in middleware** — `auth()`, `cors()`, `logger()`, `rateLimit()`, `compress()`
|
|
11
|
-
- **React SSR + Hydration** — `tsx({ dir })` — page.tsx / load.ts / layout.tsx / route.ts
|
|
17
|
+
- **React SSR + Hydration** — `tsx({ dir })` — page.tsx / load.ts / layout.tsx / route.ts / not-found.tsx
|
|
12
18
|
- **WebSocket** — `router.ws()` with upgrade middleware (auth before connect)
|
|
13
19
|
- **GraphQL** — `router.graphql()` with GraphiQL IDE
|
|
14
20
|
- **AI streaming** — `router.ai()` via Vercel AI SDK
|
|
@@ -46,12 +52,15 @@ serve(app.handler(), { port: 3000 })
|
|
|
46
52
|
pages/
|
|
47
53
|
page.tsx → GET / (React component, default export)
|
|
48
54
|
layout.tsx → root layout (HTML shell, receives req/ctx, NOT hydrated)
|
|
55
|
+
not-found.tsx → 404 error page (rendered for unmatched routes, wrapped in layout)
|
|
49
56
|
about/page.tsx → GET /about
|
|
50
57
|
blog/[slug]/
|
|
51
58
|
page.tsx → GET /blog/:slug
|
|
52
59
|
load.ts → data fetching (server-only, default export)
|
|
53
|
-
route.ts → POST /blog/:slug (API, named exports
|
|
60
|
+
route.ts → POST /blog/:slug (API, named exports POST/PUT/DELETE/...)
|
|
54
61
|
blog/layout.tsx → /blog/* layout (UI structure, receives children, hydrated)
|
|
62
|
+
api/search/
|
|
63
|
+
route.ts → GET /api/search (standalone API, no page.tsx needed)
|
|
55
64
|
```
|
|
56
65
|
|
|
57
66
|
### page.tsx — page component
|
|
@@ -155,7 +164,18 @@ export const POST: Handler = async (req, ctx) => {
|
|
|
155
164
|
}
|
|
156
165
|
```
|
|
157
166
|
|
|
158
|
-
Route.ts exports `POST`/`PUT`/`DELETE`/`PATCH` (GET is handled by page.tsx). The same `route.ts` file coexists with `page.tsx` in the same directory for handling form submissions or AJAX requests.
|
|
167
|
+
Route.ts exports `POST`/`PUT`/`DELETE`/`PATCH` (GET is handled by page.tsx). The same `route.ts` file coexists with `page.tsx` in the same directory for handling form submissions or AJAX requests. Standalone `route.ts` (without a co-located `page.tsx`) registers all methods including `GET`.
|
|
168
|
+
|
|
169
|
+
### not-found.tsx — 404 page
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
// pages/not-found.tsx
|
|
173
|
+
export default function NotFound() {
|
|
174
|
+
return <h1 class="text-4xl">404 – Not Found</h1>
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Automatically rendered for unmatched routes, wrapped in the full layout chain. Works with `use('/')` mounting and standalone usage.
|
|
159
179
|
|
|
160
180
|
### Usage within a full app
|
|
161
181
|
|
|
@@ -224,6 +244,9 @@ app.get('/protected', auth({ proxy: 'http://auth:3000/validate' }), handler)
|
|
|
224
244
|
|
|
225
245
|
// Custom header
|
|
226
246
|
app.use(auth({ header: 'X-API-Key', token: 'my-key' }))
|
|
247
|
+
|
|
248
|
+
// Token can also be passed via query string ?access_token=xxx
|
|
249
|
+
// Proxy forwards using the same method the client used (header ↔ query)
|
|
227
250
|
```
|
|
228
251
|
|
|
229
252
|
### CORS
|