@webtypen/webframez-react 0.0.2 → 0.0.4

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
@@ -1,14 +1,14 @@
1
- # webframez-react
1
+ # @webtypen/webframez-react
2
2
 
3
3
  React Server Components (RSC) extension for `@webtypen/webframez-core`.
4
4
 
5
- `webframez-react` provides:
6
-
5
+ `@webtypen/webframez-react` provides:
7
6
  - seamless `webframez-core` integration via `initWebframezReact(Route)`
8
7
  - file-based routing for `pages/**/index.tsx`
9
8
  - layout/error handling with `RouteChildren`
10
9
  - client-side navigation (`Link`, `Redirect`, `useRouter`) and cookies (`useCookie`)
11
10
  - server-rendered initial HTML plus RSC streaming
11
+ - a small CLI for the standard server/client build pipeline
12
12
 
13
13
  ## Requirements
14
14
 
@@ -26,111 +26,201 @@ npm i -D typescript webpack webpack-cli ts-loader
26
26
  ## Quick Start with webframez-core
27
27
 
28
28
  ```ts
29
- // server.ts
29
+ // src/server.ts
30
+ import path from "node:path";
30
31
  import { BaseKernelWeb, Route, WebApplication } from "@webtypen/webframez-core";
31
- import { initWebframezReact } from "@webtypen/webframez-react/webframez-core";
32
+ import { initWebframezReact } from "@webtypen/webframez-react";
32
33
 
33
34
  class Kernel extends BaseKernelWeb {
34
35
  static controller = {};
35
36
  static middleware = {};
36
37
  }
37
38
 
38
- initWebframezReact(Route);
39
+ const ReactRoute = initWebframezReact(Route);
39
40
 
40
41
  const app = new WebApplication();
41
42
  app.boot({
42
43
  kernel: Kernel,
43
44
  routesFunction: () => {
44
- Route.renderReact("/react", {
45
- distRootDir: `${process.cwd()}/dist`,
45
+ ReactRoute.renderReact("/react", {
46
+ distRootDir: path.resolve(process.cwd(), "dist"),
46
47
  });
47
48
  },
48
49
  });
49
50
  ```
50
51
 
51
52
  Notes:
52
-
53
53
  - `"/react"` is automatically registered as a catch-all route (`/react/*`).
54
- - `basePath`, `assetsPrefix`, `rscPath`, and `clientScriptUrl` are derived automatically from the mount path.
54
+ - `basePath`, `assetsPrefix`, `rscPath`, and `clientScriptUrl` are derived automatically from the mount path unless you override them.
55
+ - `initWebframezReact(Route)` returns the extended route facade, which gives you reliable editor autocompletion for `renderReact(...)` even in monorepos or symlinked development setups.
56
+ - The package also ships module augmentation for `Route.renderReact(...)`, but using the returned `ReactRoute` variable is the most robust TypeScript setup.
55
57
 
56
- ## Add to an Existing webframez-core Project
58
+ ## `Route.renderReact()`
57
59
 
58
- If you already have a running `@webtypen/webframez-core` app, this is the smallest setup to mount React and return a first JSX page.
60
+ Signature:
59
61
 
60
- 1. Install dependencies:
61
-
62
- ```bash
63
- npm i @webtypen/webframez-react react react-dom react-server-dom-webpack
64
- npm i -D typescript webpack webpack-cli ts-loader
62
+ ```ts
63
+ Route.renderReact(path, options)
65
64
  ```
66
65
 
67
- 2. Extend `Route` and mount React inside your existing `routesFunction`:
66
+ Example:
68
67
 
69
68
  ```ts
70
- // server.ts
71
- import path from "node:path";
72
- import { BaseKernelWeb, Route, WebApplication } from "@webtypen/webframez-core";
73
- import { initWebframezReact } from "@webtypen/webframez-react/webframez-core";
74
-
75
- class Kernel extends BaseKernelWeb {
76
- static controller = {};
77
- static middleware = {};
78
- }
79
-
80
- initWebframezReact(Route);
81
-
82
- const app = new WebApplication();
83
- app.boot({
84
- kernel: Kernel,
85
- port: 3000,
86
- routesFunction: () => {
87
- // Your existing core routes can stay here.
88
- Route.renderReact("/app", {
89
- distRootDir: path.resolve(process.cwd(), "dist"),
90
- });
69
+ Route.renderReact("/app", {
70
+ distRootDir: path.resolve(process.cwd(), "dist"),
71
+ method: "GET",
72
+ routeOptions: {
73
+ middleware: ["auth"],
91
74
  },
92
75
  });
93
76
  ```
94
77
 
95
- 3. Create a minimal file-router page setup:
78
+ ### Options
79
+
80
+ `distRootDir`
81
+ - Required.
82
+ - Directory containing the built client assets and generated manifests.
83
+
84
+ `pagesDir`
85
+ - Optional.
86
+ - Directory containing the compiled `pages/**` output.
87
+ - Default: `${distRootDir}/pages`
88
+
89
+ `manifestPath`
90
+ - Optional.
91
+ - Path to the React client manifest.
92
+ - Default: `${distRootDir}/react-client-manifest.json`
93
+
94
+ `assetsPrefix`
95
+ - Optional.
96
+ - Public URL prefix used to serve built client assets.
97
+ - Auto-derived from `path`.
98
+ - Example for `"/react"`: `/react/assets/`
99
+
100
+ `rscPath`
101
+ - Optional.
102
+ - Public URL for the RSC endpoint.
103
+ - Auto-derived from `path`.
104
+ - Example for `"/react"`: `/react/rsc`
105
+
106
+ `clientScriptUrl`
107
+ - Optional.
108
+ - Public URL of the browser client entry bundle.
109
+ - Auto-derived from `path`.
110
+ - Example for `"/react"`: `/react/assets/client.js`
111
+
112
+ `basePath`
113
+ - Optional.
114
+ - Basename mounted in front of all file-router paths.
115
+ - Auto-derived from `path` when `path !== "/"`.
116
+
117
+ `liveReloadPath`
118
+ - Optional.
119
+ - Enables dev live reload on a custom path or disables it explicitly with `false`.
120
+ - Automatically disabled in production mode.
121
+
122
+ `method`
123
+ - Optional.
124
+ - HTTP method or methods used to register the route.
125
+ - Supported values: `"GET" | "POST" | "PUT" | "DELETE"`
126
+ - Default: `"GET"`
127
+
128
+ `routeOptions`
129
+ - Optional.
130
+ - Additional route options forwarded to `webframez-core`.
131
+ - Typical use case: middleware.
132
+
133
+ ## Recommended Project Structure
96
134
 
97
- ```tsx
98
- // pages/layout.tsx
99
- "use server";
135
+ ```txt
136
+ pages/
137
+ layout.tsx
138
+ errors.tsx
139
+ index.tsx
140
+ about/index.tsx
141
+ src/
142
+ server.ts
143
+ client.tsx
144
+ components/
145
+ dist/
146
+ ```
100
147
 
101
- import React from "react";
102
- import { RouteChildren } from "@webtypen/webframez-react/router";
148
+ ## `tsconfig.server.json`
103
149
 
104
- export default function Layout() {
105
- return (
106
- <main>
107
- <RouteChildren />
108
- </main>
109
- );
110
- }
111
- ```
150
+ Compared to a standard `@webtypen/webframez-core` project, the server TypeScript config usually needs a few changes:
112
151
 
113
- ```tsx
114
- // pages/index.tsx
115
- "use server";
152
+ - enable JSX via `"jsx": "react-jsx"`
153
+ - include `pages/**/*.tsx`
154
+ - include `src/components/**/*.tsx`
155
+ - include your server entry (`src/server.ts` or `src/server.tsx`)
156
+ - exclude the browser client entry (`src/client.tsx` by default)
157
+ - add `paths` mappings for the `@webtypen/webframez-react` package and its subpaths
116
158
 
117
- import React from "react";
159
+ When you use the CLI (`webframez-react build:server` / `watch:server`), it generates a temporary `.webframez-react.tsconfig.server.json` that extends your project `tsconfig.server.json`. That means:
118
160
 
119
- export default function HomePage() {
120
- return <h1>Hello from webframez-react + JSX</h1>;
121
- }
122
- ```
161
+ - your own `tsconfig.server.json` stays the source of truth
162
+ - the CLI only injects the resolved server entry and the standard RSC include/exclude rules
163
+ - you only need to customize the base config when your project structure differs from the defaults
123
164
 
124
- 4. Create the client entry:
165
+ A good starting point is the shipped default config:
125
166
 
126
- ```tsx
127
- // src/client.tsx
128
- import { mountWebframezClient } from "@webtypen/webframez-react/client";
167
+ - `@webtypen/webframez-react/defaults/tsconfig.server`
168
+ - `@webtypen/webframez-react/defaults/tsconfig.server.example`
129
169
 
130
- mountWebframezClient();
170
+ Example:
171
+
172
+ ```json
173
+ {
174
+ "compilerOptions": {
175
+ "target": "ES2020",
176
+ "module": "CommonJS",
177
+ "moduleResolution": "Node",
178
+ "baseUrl": ".",
179
+ "paths": {
180
+ "@webtypen/webframez-react": [
181
+ "./node_modules/@webtypen/webframez-react/dist/index.d.ts"
182
+ ],
183
+ "@webtypen/webframez-react/types": [
184
+ "./node_modules/@webtypen/webframez-react/dist/types.d.ts"
185
+ ],
186
+ "@webtypen/webframez-react/router": [
187
+ "./node_modules/@webtypen/webframez-react/dist/router.d.ts"
188
+ ],
189
+ "@webtypen/webframez-react/client": [
190
+ "./node_modules/@webtypen/webframez-react/dist/client.d.ts"
191
+ ],
192
+ "@webtypen/webframez-react/navigation": [
193
+ "./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
194
+ ],
195
+ "@webtypen/webframez-react/webframez-core": [
196
+ "./node_modules/@webtypen/webframez-react/dist/webframez-core.d.ts"
197
+ ]
198
+ },
199
+ "jsx": "react-jsx",
200
+ "strict": true,
201
+ "esModuleInterop": true,
202
+ "skipLibCheck": true,
203
+ "outDir": "dist",
204
+ "rootDir": "."
205
+ },
206
+ "include": [
207
+ "src/server.ts",
208
+ "src/server.tsx",
209
+ "src/components/**/*.tsx",
210
+ "pages/**/*.tsx",
211
+ "src/types.d.ts"
212
+ ],
213
+ "exclude": [
214
+ "src/client.tsx",
215
+ "dist",
216
+ "node_modules"
217
+ ]
218
+ }
131
219
  ```
132
220
 
133
- 5. Add build scripts (with automatic config fallback):
221
+ ## `package.json` Scripts
222
+
223
+ Recommended scripts:
134
224
 
135
225
  ```json
136
226
  {
@@ -138,18 +228,84 @@ mountWebframezClient();
138
228
  "build:server": "webframez-react build:server",
139
229
  "build:client": "webframez-react build:client",
140
230
  "build": "npm run build:server && npm run build:client",
231
+ "start": "NODE_OPTIONS='--conditions react-server -r @webtypen/webframez-react/register' node start-server.cjs",
141
232
  "watch:server": "webframez-react watch:server",
142
233
  "watch:client": "webframez-react watch:client",
143
- "serve:watch": "node --watch --conditions react-server start-server.cjs",
234
+ "serve:watch": "NODE_OPTIONS='--conditions react-server -r @webtypen/webframez-react/register' node --watch start-server.cjs",
144
235
  "watch": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'",
145
236
  "dev": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'"
146
237
  }
147
238
  }
148
239
  ```
149
240
 
150
- After build, your first page is available at `http://localhost:3000/app`.
241
+ Notes:
242
+ - `build` compiles the server output (`pages`, `server.ts`) and the browser client bundle (`client.tsx` + RSC manifests).
243
+ - `start` runs the built app in React Server mode.
244
+ - `watch` / `dev` keep TypeScript and webpack in watch mode and restart Node automatically when server output changes.
245
+ - `@webtypen/webframez-react/register` activates the React Server module register, so `"use client"` modules are treated correctly in Node and in the package's SSR worker.
246
+
247
+ If you run an existing `webframez-core` app directly with `ts-node` or `node`, use the same preload:
248
+
249
+ ```json
250
+ {
251
+ "scripts": {
252
+ "start": "NODE_OPTIONS='--conditions react-server -r @webtypen/webframez-react/register' ts-node ./app.ts",
253
+ "watch:app": "nodemon --exec \"NODE_OPTIONS='--conditions react-server -r @webtypen/webframez-react/register' ts-node ./app.ts\""
254
+ }
255
+ }
256
+ ```
257
+
258
+ Or via the shipped wrapper command:
259
+
260
+ ```json
261
+ {
262
+ "scripts": {
263
+ "start": "TS_NODE_FILES=true webframez-react exec -- ts-node ./app.ts",
264
+ "watch:app": "nodemon --exec \"TS_NODE_FILES=true webframez-react exec -- ts-node ./app.ts\""
265
+ }
266
+ }
267
+ ```
268
+
269
+ ## CLI Config and Custom Entry Paths
270
+
271
+ The CLI first checks project override files and then falls back to the package defaults:
272
+
273
+ - `tsconfig.server.json`
274
+ - `webpack.client.cjs`
275
+ - `webpack.server.cjs`
276
+
277
+ If you do not want to create your own webpack config just to move `client.tsx` or `server.ts`, you can use a small project config file:
278
+
279
+ ```js
280
+ // webframez-react.config.mjs
281
+ export default {
282
+ clientEntryPath: "src/app/client.tsx",
283
+ serverEntryPath: "src/app/server.tsx",
284
+ };
285
+ ```
286
+
287
+ Supported file names:
288
+ - `webframez-react.config.mjs`
289
+ - `webframez-react.config.cjs`
290
+ - `webframez-react.config.js`
291
+ - `webframez-react.config.json`
292
+
293
+ You can also override the entry paths per command:
294
+
295
+ ```bash
296
+ webframez-react build:client --client-entry=src/app/client.tsx
297
+ webframez-react build:server --server-entry=src/app/server.tsx
298
+ webframez-react watch:client --client-entry=src/app/client.tsx
299
+ webframez-react watch:server --server-entry=src/app/server.tsx
300
+ ```
301
+
302
+ Notes:
303
+ - The default client entry is `src/client.tsx`.
304
+ - The default server entry is `src/server.ts`, with automatic fallback to `src/server.tsx` if present.
305
+ - `build:server:webpack` and `watch:server:webpack` also respect `serverEntryPath`.
306
+ - `build:server` and `watch:server` generate a temporary `.webframez-react.tsconfig.server.json` so custom server entry paths also work with the TypeScript compiler.
151
307
 
152
- ## Page Structure (File-Based Routing)
308
+ ## File-Based Routing
153
309
 
154
310
  Example:
155
311
 
@@ -205,9 +361,8 @@ export default function AccountPage({ params, abort }: PageProps) {
205
361
  ```
206
362
 
207
363
  Behavior:
208
-
209
364
  - default without options: `404` + `"Page not found"`
210
- - rendered through `pages/errors.tsx` (same behavior as unmatched routes)
365
+ - rendered through `pages/errors.tsx`
211
366
  - `pathname` is provided automatically by context
212
367
  - optional `payload` is forwarded to `errors.tsx`
213
368
 
@@ -255,8 +410,7 @@ export function Guard({ loggedIn }: { loggedIn: boolean }) {
255
410
  }
256
411
  ```
257
412
 
258
- Note:
259
-
413
+ Notes:
260
414
  - `Link` and `Redirect` automatically use the basename from `Route.renderReact()`.
261
415
  - You can override it per usage via `basename`.
262
416
 
@@ -288,7 +442,12 @@ export default function LoginAction() {
288
442
  ## Public Entrypoints
289
443
 
290
444
  - `@webtypen/webframez-react`
291
- - `createNodeRequestHandler`, `createFileRouter`, `createHTMLShell`, `sendRSC`, `createRSCHandler`
445
+ - `initWebframezReact`
446
+ - `createNodeRequestHandler`
447
+ - `createFileRouter`
448
+ - `createHTMLShell`
449
+ - `sendRSC`
450
+ - `createRSCHandler`
292
451
  - `@webtypen/webframez-react/webframez-core`
293
452
  - `initWebframezReact`
294
453
  - `@webtypen/webframez-react/router`
@@ -298,48 +457,17 @@ export default function LoginAction() {
298
457
  - `@webtypen/webframez-react/navigation`
299
458
  - `Link`, `Redirect`
300
459
  - `@webtypen/webframez-react/types`
301
- - all public types (`RouteContext`, `PageProps`, `ErrorPageProps`, ...)
302
-
303
- ## package.json Scripts
304
-
305
- Example scripts for a `webframez-react` app:
306
-
307
- ```json
308
- {
309
- "scripts": {
310
- "build:server": "webframez-react build:server",
311
- "build:client": "webframez-react build:client",
312
- "build": "npm run build:server && npm run build:client",
313
- "start": "node --conditions react-server start-server.cjs",
314
- "watch:server": "webframez-react watch:server",
315
- "watch:client": "webframez-react watch:client",
316
- "serve:watch": "node --watch --conditions react-server start-server.cjs",
317
- "watch": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'",
318
- "dev": "sh -c 'npm run watch:server & npm run watch:client & npm run serve:watch & wait'"
319
- }
320
- }
321
- ```
460
+ - `RouteContext`, `PageProps`, `ErrorPageProps`, `AbortRouteOptions`, ...
322
461
 
323
- Notes:
324
-
325
- - `webframez-react` CLI first checks project overrides and falls back to package defaults:
326
- - `tsconfig.server.json`
327
- - `webpack.client.cjs`
328
- - `webpack.server.cjs`
329
- - `webpack.server.cjs` is optional. Default flow compiles server with `tsc`. Use webpack-server only if you explicitly want a bundled server build:
330
- - `webframez-react build:server:webpack`
331
- - `webframez-react watch:server:webpack`
332
- - `build` compiles server output (`pages`, `server.ts`) and client output (`client.tsx` bundle + RSC manifests).
333
- - `start` runs the built app in React Server mode.
334
- - `watch` and `dev` run the same full watch pipeline and restart Node automatically on server output changes.
462
+ ## Package Build
335
463
 
336
- ## Build
464
+ Build the package itself:
337
465
 
338
466
  ```bash
339
467
  npm run build
340
468
  ```
341
469
 
342
- Watch mode:
470
+ Watch mode for package development:
343
471
 
344
472
  ```bash
345
473
  npm run build:watch