@webtypen/webframez-react 0.0.1 → 0.0.3
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 +276 -52
- package/bin/webframez-react.mjs +309 -0
- package/defaults/tsconfig.server.example.json +46 -0
- package/defaults/tsconfig.server.json +64 -0
- package/defaults/webpack.client.cjs +64 -0
- package/defaults/webpack.server.cjs +40 -0
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +50 -11
- package/dist/http.d.ts +18 -7
- package/dist/http.js +50 -11
- package/dist/index.cjs +50 -11
- package/dist/index.d.ts +2 -5
- package/dist/index.js +50 -11
- package/dist/router.cjs +30 -10
- package/dist/router.js +30 -10
- package/dist/types.d.ts +25 -8
- package/dist/webframez-core.cjs +50 -11
- package/dist/webframez-core.d.ts +32 -8
- package/dist/webframez-core.js +50 -11
- package/package.json +13 -3
package/dist/router.js
CHANGED
|
@@ -114,6 +114,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
114
114
|
function escapeHtml(value) {
|
|
115
115
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
116
116
|
}
|
|
117
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
118
|
+
function createManagedAttributes() {
|
|
119
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
120
|
+
}
|
|
117
121
|
function toRouteEntry(pagesDir, filePath) {
|
|
118
122
|
const normalized = filePath.replace(/\\/g, "/");
|
|
119
123
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -182,19 +186,21 @@ function renderHeadToString(head) {
|
|
|
182
186
|
const tags = [];
|
|
183
187
|
if (head.description) {
|
|
184
188
|
tags.push(
|
|
185
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
189
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
186
190
|
);
|
|
187
191
|
}
|
|
188
192
|
if (head.favicon) {
|
|
189
|
-
tags.push(
|
|
193
|
+
tags.push(
|
|
194
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
195
|
+
);
|
|
190
196
|
}
|
|
191
197
|
for (const meta of head.meta ?? []) {
|
|
192
198
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
193
|
-
tags.push(`<meta ${attrs} />`);
|
|
199
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
194
200
|
}
|
|
195
201
|
for (const link of head.links ?? []) {
|
|
196
202
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
197
|
-
tags.push(`<link ${attrs} />`);
|
|
203
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
198
204
|
}
|
|
199
205
|
return tags.join("\n");
|
|
200
206
|
}
|
|
@@ -208,6 +214,12 @@ async function resolveHead(candidate, context) {
|
|
|
208
214
|
}
|
|
209
215
|
return candidate.Head(context);
|
|
210
216
|
}
|
|
217
|
+
async function resolvePageData(candidate, context) {
|
|
218
|
+
if (!candidate.Data) {
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
return candidate.Data(context);
|
|
222
|
+
}
|
|
211
223
|
function findBestMatch(entries, pathname) {
|
|
212
224
|
const matches = [];
|
|
213
225
|
for (const entry of entries) {
|
|
@@ -287,10 +299,11 @@ function createFileRouter(options) {
|
|
|
287
299
|
};
|
|
288
300
|
}
|
|
289
301
|
const errorModule = resolveModule(errorPath);
|
|
290
|
-
const errorNode = errorModule.default(errorProps);
|
|
302
|
+
const errorNode = await errorModule.default(errorProps);
|
|
291
303
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
292
304
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
293
|
-
const
|
|
305
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
306
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
294
307
|
return {
|
|
295
308
|
statusCode,
|
|
296
309
|
model,
|
|
@@ -322,10 +335,17 @@ function createFileRouter(options) {
|
|
|
322
335
|
activeContext = context;
|
|
323
336
|
const pageModule = resolveModule(match.entry.filePath);
|
|
324
337
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
325
|
-
const
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
338
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
339
|
+
const pageContext = {
|
|
340
|
+
...context,
|
|
341
|
+
data: pageData
|
|
342
|
+
};
|
|
343
|
+
activeContext = pageContext;
|
|
344
|
+
const pageNode = await pageModule.default(pageContext);
|
|
345
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
346
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
347
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
348
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
329
349
|
return {
|
|
330
350
|
statusCode: 200,
|
|
331
351
|
model,
|
package/dist/types.d.ts
CHANGED
|
@@ -9,17 +9,24 @@ export type AbortRouteOptions = {
|
|
|
9
9
|
payload?: unknown;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type RouteContext = {
|
|
12
|
+
export type RouteContext<TData = unknown> = {
|
|
13
13
|
pathname: string;
|
|
14
14
|
params: RouteParams;
|
|
15
15
|
searchParams: RouteSearchParams;
|
|
16
16
|
cookies: Record<string, string>;
|
|
17
|
+
data?: TData;
|
|
17
18
|
abort: (options?: AbortRouteOptions) => never;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
|
-
export type
|
|
21
|
+
export type InferPageData<TDataResolver> =
|
|
22
|
+
TDataResolver extends (...args: any[]) => any
|
|
23
|
+
? Awaited<ReturnType<TDataResolver>>
|
|
24
|
+
: TDataResolver;
|
|
25
|
+
export type PageProps<TData = unknown> = RouteContext<InferPageData<TData>>;
|
|
26
|
+
export type PagePropsFromData<TDataResolver extends (...args: any[]) => any> =
|
|
27
|
+
PageProps<InferPageData<TDataResolver>>;
|
|
21
28
|
|
|
22
|
-
export type ErrorPageProps = RouteContext & {
|
|
29
|
+
export type ErrorPageProps<TData = unknown> = RouteContext<TData> & {
|
|
23
30
|
statusCode: number;
|
|
24
31
|
message: string;
|
|
25
32
|
payload?: unknown;
|
|
@@ -49,22 +56,32 @@ export type HeadConfig = {
|
|
|
49
56
|
links?: HeadLinkTag[];
|
|
50
57
|
};
|
|
51
58
|
|
|
59
|
+
export type ClientNavigationPayload = {
|
|
60
|
+
model: ReactNode;
|
|
61
|
+
head: HeadConfig;
|
|
62
|
+
};
|
|
63
|
+
|
|
52
64
|
export type HeadResolver<TContext = RouteContext> = (
|
|
53
65
|
context: TContext
|
|
54
66
|
) => HeadConfig | Promise<HeadConfig>;
|
|
55
67
|
|
|
56
|
-
export type
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
export type PageDataResolver<TData = unknown> = (
|
|
69
|
+
context: RouteContext
|
|
70
|
+
) => TData | Promise<TData>;
|
|
71
|
+
|
|
72
|
+
export type PageModule<TData = unknown> = {
|
|
73
|
+
default: (props: PageProps<TData>) => ReactNode | Promise<ReactNode>;
|
|
74
|
+
Head?: HeadResolver<PageProps<TData>>;
|
|
75
|
+
Data?: PageDataResolver<TData>;
|
|
59
76
|
};
|
|
60
77
|
|
|
61
78
|
export type LayoutModule = {
|
|
62
|
-
default: (props: RouteContext) => ReactNode
|
|
79
|
+
default: (props: RouteContext) => ReactNode | Promise<ReactNode>;
|
|
63
80
|
Head?: HeadResolver<RouteContext>;
|
|
64
81
|
};
|
|
65
82
|
|
|
66
83
|
export type ErrorModule = {
|
|
67
|
-
default: (props: ErrorPageProps) => ReactNode
|
|
84
|
+
default: (props: ErrorPageProps) => ReactNode | Promise<ReactNode>;
|
|
68
85
|
Head?: HeadResolver<ErrorPageProps>;
|
|
69
86
|
};
|
|
70
87
|
|
package/dist/webframez-core.cjs
CHANGED
|
@@ -226,6 +226,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
226
226
|
function escapeHtml(value) {
|
|
227
227
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
228
228
|
}
|
|
229
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
230
|
+
function createManagedAttributes() {
|
|
231
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
232
|
+
}
|
|
229
233
|
function toRouteEntry(pagesDir, filePath) {
|
|
230
234
|
const normalized = filePath.replace(/\\/g, "/");
|
|
231
235
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -294,19 +298,21 @@ function renderHeadToString(head) {
|
|
|
294
298
|
const tags = [];
|
|
295
299
|
if (head.description) {
|
|
296
300
|
tags.push(
|
|
297
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
301
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
298
302
|
);
|
|
299
303
|
}
|
|
300
304
|
if (head.favicon) {
|
|
301
|
-
tags.push(
|
|
305
|
+
tags.push(
|
|
306
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
307
|
+
);
|
|
302
308
|
}
|
|
303
309
|
for (const meta of head.meta ?? []) {
|
|
304
310
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
305
|
-
tags.push(`<meta ${attrs} />`);
|
|
311
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
306
312
|
}
|
|
307
313
|
for (const link of head.links ?? []) {
|
|
308
314
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
309
|
-
tags.push(`<link ${attrs} />`);
|
|
315
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
310
316
|
}
|
|
311
317
|
return tags.join("\n");
|
|
312
318
|
}
|
|
@@ -320,6 +326,12 @@ async function resolveHead(candidate, context) {
|
|
|
320
326
|
}
|
|
321
327
|
return candidate.Head(context);
|
|
322
328
|
}
|
|
329
|
+
async function resolvePageData(candidate, context) {
|
|
330
|
+
if (!candidate.Data) {
|
|
331
|
+
return void 0;
|
|
332
|
+
}
|
|
333
|
+
return candidate.Data(context);
|
|
334
|
+
}
|
|
323
335
|
function findBestMatch(entries, pathname) {
|
|
324
336
|
const matches = [];
|
|
325
337
|
for (const entry of entries) {
|
|
@@ -399,10 +411,11 @@ function createFileRouter(options) {
|
|
|
399
411
|
};
|
|
400
412
|
}
|
|
401
413
|
const errorModule = resolveModule(errorPath);
|
|
402
|
-
const errorNode = errorModule.default(errorProps);
|
|
414
|
+
const errorNode = await errorModule.default(errorProps);
|
|
403
415
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
404
416
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
405
|
-
const
|
|
417
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
418
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
406
419
|
return {
|
|
407
420
|
statusCode,
|
|
408
421
|
model,
|
|
@@ -434,10 +447,17 @@ function createFileRouter(options) {
|
|
|
434
447
|
activeContext = context;
|
|
435
448
|
const pageModule = resolveModule(match.entry.filePath);
|
|
436
449
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
450
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
451
|
+
const pageContext = {
|
|
452
|
+
...context,
|
|
453
|
+
data: pageData
|
|
454
|
+
};
|
|
455
|
+
activeContext = pageContext;
|
|
456
|
+
const pageNode = await pageModule.default(pageContext);
|
|
457
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
458
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
459
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
460
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
441
461
|
return {
|
|
442
462
|
statusCode: 200,
|
|
443
463
|
model,
|
|
@@ -496,8 +516,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
496
516
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
497
517
|
const script = `
|
|
498
518
|
const path = require("node:path");
|
|
519
|
+
const Module = require("node:module");
|
|
499
520
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
500
521
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
522
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
523
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
524
|
+
const forcedResolutions = new Map([
|
|
525
|
+
["react", appRequire.resolve("react")],
|
|
526
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
527
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
528
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
529
|
+
]);
|
|
530
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
531
|
+
if (forcedResolutions.has(request)) {
|
|
532
|
+
return forcedResolutions.get(request);
|
|
533
|
+
}
|
|
534
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
535
|
+
};
|
|
501
536
|
const { createFileRouter } = require("webframez-react/router");
|
|
502
537
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
503
538
|
paths: [process.cwd(), input.pagesDir]
|
|
@@ -637,7 +672,11 @@ function createNodeRequestHandler(options) {
|
|
|
637
672
|
cookies: requestCookies
|
|
638
673
|
})
|
|
639
674
|
);
|
|
640
|
-
|
|
675
|
+
const payload = {
|
|
676
|
+
model: resolved2.model,
|
|
677
|
+
head: resolved2.head
|
|
678
|
+
};
|
|
679
|
+
sendRSC(res, payload, {
|
|
641
680
|
moduleMap,
|
|
642
681
|
statusCode: resolved2.statusCode
|
|
643
682
|
});
|
package/dist/webframez-core.d.ts
CHANGED
|
@@ -2,18 +2,42 @@ import type { RouteFacade } from "@webtypen/webframez-core";
|
|
|
2
2
|
import type { CreateNodeHandlerOptions } from "./http";
|
|
3
3
|
|
|
4
4
|
export type WebframezCoreRouteMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
5
|
+
export type WebframezCoreRouteMiddleware = string | string[];
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
+
export interface WebframezCoreRouteRegistrationOptions {
|
|
8
|
+
middleware?: WebframezCoreRouteMiddleware;
|
|
9
|
+
domains?: string | string[];
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface WebframezCoreReactRenderRouteOptions
|
|
14
|
+
extends CreateNodeHandlerOptions {
|
|
7
15
|
method?: WebframezCoreRouteMethod | WebframezCoreRouteMethod[];
|
|
8
|
-
routeOptions?:
|
|
9
|
-
}
|
|
16
|
+
routeOptions?: WebframezCoreRouteRegistrationOptions;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface WebframezCoreRouteFacadeExtensions {
|
|
20
|
+
renderReact(path: string, options: WebframezCoreReactRenderRouteOptions): void;
|
|
21
|
+
reactRender(path: string, options: WebframezCoreReactRenderRouteOptions): void;
|
|
22
|
+
}
|
|
10
23
|
|
|
11
24
|
declare module "@webtypen/webframez-core" {
|
|
12
|
-
interface RouteFacade {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
interface RouteFacade extends WebframezCoreRouteFacadeExtensions {}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare module "webframez-core" {
|
|
29
|
+
interface RouteFacade extends WebframezCoreRouteFacadeExtensions {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare module "@webtypen/webframez-core/dist/Router/Route" {
|
|
33
|
+
interface RouteFacade extends WebframezCoreRouteFacadeExtensions {}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare module "webframez-core/dist/Router/Route" {
|
|
37
|
+
interface RouteFacade extends WebframezCoreRouteFacadeExtensions {}
|
|
16
38
|
}
|
|
17
39
|
|
|
18
|
-
export function initWebframezReact
|
|
40
|
+
export function initWebframezReact<T extends RouteFacade>(
|
|
41
|
+
route: T,
|
|
42
|
+
): T & WebframezCoreRouteFacadeExtensions;
|
|
19
43
|
export const setupWebframezCoreReactRoute: typeof initWebframezReact;
|
package/dist/webframez-core.js
CHANGED
|
@@ -198,6 +198,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
198
198
|
function escapeHtml(value) {
|
|
199
199
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
200
200
|
}
|
|
201
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
202
|
+
function createManagedAttributes() {
|
|
203
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
204
|
+
}
|
|
201
205
|
function toRouteEntry(pagesDir, filePath) {
|
|
202
206
|
const normalized = filePath.replace(/\\/g, "/");
|
|
203
207
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -266,19 +270,21 @@ function renderHeadToString(head) {
|
|
|
266
270
|
const tags = [];
|
|
267
271
|
if (head.description) {
|
|
268
272
|
tags.push(
|
|
269
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
273
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
270
274
|
);
|
|
271
275
|
}
|
|
272
276
|
if (head.favicon) {
|
|
273
|
-
tags.push(
|
|
277
|
+
tags.push(
|
|
278
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
279
|
+
);
|
|
274
280
|
}
|
|
275
281
|
for (const meta of head.meta ?? []) {
|
|
276
282
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
277
|
-
tags.push(`<meta ${attrs} />`);
|
|
283
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
278
284
|
}
|
|
279
285
|
for (const link of head.links ?? []) {
|
|
280
286
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
281
|
-
tags.push(`<link ${attrs} />`);
|
|
287
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
282
288
|
}
|
|
283
289
|
return tags.join("\n");
|
|
284
290
|
}
|
|
@@ -292,6 +298,12 @@ async function resolveHead(candidate, context) {
|
|
|
292
298
|
}
|
|
293
299
|
return candidate.Head(context);
|
|
294
300
|
}
|
|
301
|
+
async function resolvePageData(candidate, context) {
|
|
302
|
+
if (!candidate.Data) {
|
|
303
|
+
return void 0;
|
|
304
|
+
}
|
|
305
|
+
return candidate.Data(context);
|
|
306
|
+
}
|
|
295
307
|
function findBestMatch(entries, pathname) {
|
|
296
308
|
const matches = [];
|
|
297
309
|
for (const entry of entries) {
|
|
@@ -371,10 +383,11 @@ function createFileRouter(options) {
|
|
|
371
383
|
};
|
|
372
384
|
}
|
|
373
385
|
const errorModule = resolveModule(errorPath);
|
|
374
|
-
const errorNode = errorModule.default(errorProps);
|
|
386
|
+
const errorNode = await errorModule.default(errorProps);
|
|
375
387
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
376
388
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
377
|
-
const
|
|
389
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
390
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
378
391
|
return {
|
|
379
392
|
statusCode,
|
|
380
393
|
model,
|
|
@@ -406,10 +419,17 @@ function createFileRouter(options) {
|
|
|
406
419
|
activeContext = context;
|
|
407
420
|
const pageModule = resolveModule(match.entry.filePath);
|
|
408
421
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
422
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
423
|
+
const pageContext = {
|
|
424
|
+
...context,
|
|
425
|
+
data: pageData
|
|
426
|
+
};
|
|
427
|
+
activeContext = pageContext;
|
|
428
|
+
const pageNode = await pageModule.default(pageContext);
|
|
429
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
430
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
431
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
432
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
413
433
|
return {
|
|
414
434
|
statusCode: 200,
|
|
415
435
|
model,
|
|
@@ -468,8 +488,23 @@ async function renderInitialHtmlInWorker(options) {
|
|
|
468
488
|
const payload = Buffer.from(JSON.stringify(options), "utf8").toString("base64url");
|
|
469
489
|
const script = `
|
|
470
490
|
const path = require("node:path");
|
|
491
|
+
const Module = require("node:module");
|
|
471
492
|
const input = JSON.parse(Buffer.from(process.argv[1], "base64url").toString("utf8"));
|
|
472
493
|
globalThis.__RSC_BASENAME = input.basename || "";
|
|
494
|
+
const appRequire = Module.createRequire(path.join(input.pagesDir, "__webframez_react_worker__.js"));
|
|
495
|
+
const originalResolveFilename = Module._resolveFilename;
|
|
496
|
+
const forcedResolutions = new Map([
|
|
497
|
+
["react", appRequire.resolve("react")],
|
|
498
|
+
["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
|
|
499
|
+
["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
|
|
500
|
+
["react-dom/client", appRequire.resolve("react-dom/client")]
|
|
501
|
+
]);
|
|
502
|
+
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
503
|
+
if (forcedResolutions.has(request)) {
|
|
504
|
+
return forcedResolutions.get(request);
|
|
505
|
+
}
|
|
506
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
507
|
+
};
|
|
473
508
|
const { createFileRouter } = require("webframez-react/router");
|
|
474
509
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
475
510
|
paths: [process.cwd(), input.pagesDir]
|
|
@@ -609,7 +644,11 @@ function createNodeRequestHandler(options) {
|
|
|
609
644
|
cookies: requestCookies
|
|
610
645
|
})
|
|
611
646
|
);
|
|
612
|
-
|
|
647
|
+
const payload = {
|
|
648
|
+
model: resolved2.model,
|
|
649
|
+
head: resolved2.head
|
|
650
|
+
};
|
|
651
|
+
sendRSC(res, payload, {
|
|
613
652
|
moduleMap,
|
|
614
653
|
statusCode: resolved2.statusCode
|
|
615
654
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webtypen/webframez-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "TypeScript React RSC addition for @webtypen/webframez-core",
|
|
5
5
|
"homepage": "https://webtypen.de/",
|
|
6
6
|
"author": {
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"main": "./dist/index.cjs",
|
|
20
20
|
"module": "./dist/index.js",
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
|
+
"bin": {
|
|
23
|
+
"webframez-react": "./bin/webframez-react.mjs"
|
|
24
|
+
},
|
|
22
25
|
"exports": {
|
|
23
26
|
".": {
|
|
24
27
|
"types": "./dist/index.d.ts",
|
|
@@ -54,10 +57,17 @@
|
|
|
54
57
|
"types": "./dist/webframez-core.d.ts",
|
|
55
58
|
"import": "./dist/webframez-core.js",
|
|
56
59
|
"require": "./dist/webframez-core.cjs"
|
|
57
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"./defaults/webpack.client": "./defaults/webpack.client.cjs",
|
|
62
|
+
"./defaults/webpack.server": "./defaults/webpack.server.cjs",
|
|
63
|
+
"./defaults/tsconfig.server": "./defaults/tsconfig.server.json",
|
|
64
|
+
"./defaults/tsconfig.server.example": "./defaults/tsconfig.server.example.json",
|
|
65
|
+
"./cli": "./bin/webframez-react.mjs"
|
|
58
66
|
},
|
|
59
67
|
"files": [
|
|
60
|
-
"dist"
|
|
68
|
+
"dist",
|
|
69
|
+
"defaults",
|
|
70
|
+
"bin"
|
|
61
71
|
],
|
|
62
72
|
"scripts": {
|
|
63
73
|
"clean": "rm -rf dist",
|