@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 +238 -110
- package/bin/webframez-react.mjs +179 -7
- package/defaults/tsconfig.server.example.json +46 -0
- package/defaults/tsconfig.server.json +13 -0
- package/defaults/webpack.client.cjs +4 -1
- package/defaults/webpack.server.cjs +8 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +55 -19
- package/dist/http.d.ts +18 -7
- package/dist/http.js +55 -19
- package/dist/index.cjs +55 -19
- package/dist/index.d.ts +2 -5
- package/dist/index.js +55 -19
- package/dist/router.cjs +30 -10
- package/dist/router.js +30 -10
- package/dist/types.d.ts +25 -8
- package/dist/webframez-core.cjs +55 -19
- package/dist/webframez-core.d.ts +32 -8
- package/dist/webframez-core.js +55 -19
- package/package.json +5 -2
- package/register.cjs +1 -0
package/dist/http.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,
|
|
@@ -454,14 +474,26 @@ function stripBasePath(pathname, basePath) {
|
|
|
454
474
|
}
|
|
455
475
|
function runNodeCommand(args) {
|
|
456
476
|
return new Promise((resolve, reject) => {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
477
|
+
const execArgs = [
|
|
478
|
+
"--conditions",
|
|
479
|
+
"react-server",
|
|
480
|
+
"-r",
|
|
481
|
+
"@webtypen/webframez-react/register",
|
|
482
|
+
...args
|
|
483
|
+
];
|
|
484
|
+
execFile(
|
|
485
|
+
process.execPath,
|
|
486
|
+
execArgs,
|
|
487
|
+
{ timeout: 1e4, maxBuffer: 1024 * 1024 * 5 },
|
|
488
|
+
(error, stdout, stderr) => {
|
|
489
|
+
if (error) {
|
|
490
|
+
const out = stderr && stderr.trim() !== "" ? stderr : stdout;
|
|
491
|
+
reject(new Error(out || error.message));
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
resolve({ stdout, stderr });
|
|
462
495
|
}
|
|
463
|
-
|
|
464
|
-
});
|
|
496
|
+
);
|
|
465
497
|
});
|
|
466
498
|
}
|
|
467
499
|
async function renderInitialHtmlInWorker(options) {
|
|
@@ -485,7 +517,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
|
|
485
517
|
}
|
|
486
518
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
487
519
|
};
|
|
488
|
-
const { createFileRouter } = require("webframez-react/router");
|
|
520
|
+
const { createFileRouter } = require("@webtypen/webframez-react/router");
|
|
489
521
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
490
522
|
paths: [process.cwd(), input.pagesDir]
|
|
491
523
|
});
|
|
@@ -624,7 +656,11 @@ function createNodeRequestHandler(options) {
|
|
|
624
656
|
cookies: requestCookies
|
|
625
657
|
})
|
|
626
658
|
);
|
|
627
|
-
|
|
659
|
+
const payload = {
|
|
660
|
+
model: resolved2.model,
|
|
661
|
+
head: resolved2.head
|
|
662
|
+
};
|
|
663
|
+
sendRSC(res, payload, {
|
|
628
664
|
moduleMap,
|
|
629
665
|
statusCode: resolved2.statusCode
|
|
630
666
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -257,6 +257,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
257
257
|
function escapeHtml(value) {
|
|
258
258
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
259
259
|
}
|
|
260
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
261
|
+
function createManagedAttributes() {
|
|
262
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
263
|
+
}
|
|
260
264
|
function toRouteEntry(pagesDir, filePath) {
|
|
261
265
|
const normalized = filePath.replace(/\\/g, "/");
|
|
262
266
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -325,19 +329,21 @@ function renderHeadToString(head) {
|
|
|
325
329
|
const tags = [];
|
|
326
330
|
if (head.description) {
|
|
327
331
|
tags.push(
|
|
328
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
332
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
329
333
|
);
|
|
330
334
|
}
|
|
331
335
|
if (head.favicon) {
|
|
332
|
-
tags.push(
|
|
336
|
+
tags.push(
|
|
337
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
338
|
+
);
|
|
333
339
|
}
|
|
334
340
|
for (const meta of head.meta ?? []) {
|
|
335
341
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
336
|
-
tags.push(`<meta ${attrs} />`);
|
|
342
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
337
343
|
}
|
|
338
344
|
for (const link of head.links ?? []) {
|
|
339
345
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
340
|
-
tags.push(`<link ${attrs} />`);
|
|
346
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
341
347
|
}
|
|
342
348
|
return tags.join("\n");
|
|
343
349
|
}
|
|
@@ -351,6 +357,12 @@ async function resolveHead(candidate, context) {
|
|
|
351
357
|
}
|
|
352
358
|
return candidate.Head(context);
|
|
353
359
|
}
|
|
360
|
+
async function resolvePageData(candidate, context) {
|
|
361
|
+
if (!candidate.Data) {
|
|
362
|
+
return void 0;
|
|
363
|
+
}
|
|
364
|
+
return candidate.Data(context);
|
|
365
|
+
}
|
|
354
366
|
function findBestMatch(entries, pathname) {
|
|
355
367
|
const matches = [];
|
|
356
368
|
for (const entry of entries) {
|
|
@@ -430,10 +442,11 @@ function createFileRouter(options) {
|
|
|
430
442
|
};
|
|
431
443
|
}
|
|
432
444
|
const errorModule = resolveModule(errorPath);
|
|
433
|
-
const errorNode = errorModule.default(errorProps);
|
|
445
|
+
const errorNode = await errorModule.default(errorProps);
|
|
434
446
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
435
447
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
436
|
-
const
|
|
448
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
449
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
437
450
|
return {
|
|
438
451
|
statusCode,
|
|
439
452
|
model,
|
|
@@ -465,10 +478,17 @@ function createFileRouter(options) {
|
|
|
465
478
|
activeContext = context;
|
|
466
479
|
const pageModule = resolveModule(match.entry.filePath);
|
|
467
480
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
481
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
482
|
+
const pageContext = {
|
|
483
|
+
...context,
|
|
484
|
+
data: pageData
|
|
485
|
+
};
|
|
486
|
+
activeContext = pageContext;
|
|
487
|
+
const pageNode = await pageModule.default(pageContext);
|
|
488
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
489
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
490
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
491
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
472
492
|
return {
|
|
473
493
|
statusCode: 200,
|
|
474
494
|
model,
|
|
@@ -516,14 +536,26 @@ function stripBasePath(pathname, basePath) {
|
|
|
516
536
|
}
|
|
517
537
|
function runNodeCommand(args) {
|
|
518
538
|
return new Promise((resolve, reject) => {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
539
|
+
const execArgs = [
|
|
540
|
+
"--conditions",
|
|
541
|
+
"react-server",
|
|
542
|
+
"-r",
|
|
543
|
+
"@webtypen/webframez-react/register",
|
|
544
|
+
...args
|
|
545
|
+
];
|
|
546
|
+
(0, import_node_child_process.execFile)(
|
|
547
|
+
process.execPath,
|
|
548
|
+
execArgs,
|
|
549
|
+
{ timeout: 1e4, maxBuffer: 1024 * 1024 * 5 },
|
|
550
|
+
(error, stdout, stderr) => {
|
|
551
|
+
if (error) {
|
|
552
|
+
const out = stderr && stderr.trim() !== "" ? stderr : stdout;
|
|
553
|
+
reject(new Error(out || error.message));
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
resolve({ stdout, stderr });
|
|
524
557
|
}
|
|
525
|
-
|
|
526
|
-
});
|
|
558
|
+
);
|
|
527
559
|
});
|
|
528
560
|
}
|
|
529
561
|
async function renderInitialHtmlInWorker(options) {
|
|
@@ -547,7 +579,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
|
|
547
579
|
}
|
|
548
580
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
549
581
|
};
|
|
550
|
-
const { createFileRouter } = require("webframez-react/router");
|
|
582
|
+
const { createFileRouter } = require("@webtypen/webframez-react/router");
|
|
551
583
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
552
584
|
paths: [process.cwd(), input.pagesDir]
|
|
553
585
|
});
|
|
@@ -686,7 +718,11 @@ function createNodeRequestHandler(options) {
|
|
|
686
718
|
cookies: requestCookies
|
|
687
719
|
})
|
|
688
720
|
);
|
|
689
|
-
|
|
721
|
+
const payload = {
|
|
722
|
+
model: resolved2.model,
|
|
723
|
+
head: resolved2.head
|
|
724
|
+
};
|
|
725
|
+
sendRSC(res, payload, {
|
|
690
726
|
moduleMap,
|
|
691
727
|
statusCode: resolved2.statusCode
|
|
692
728
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { CreateHtmlShellOptions, SendRSCOptions } from "./types";
|
|
3
3
|
import type { CreateNodeHandlerOptions } from "./http";
|
|
4
|
+
import "./webframez-core";
|
|
4
5
|
|
|
5
6
|
export * from "./types";
|
|
6
7
|
export { createFileRouter, parseSearchParams, renderHeadToString, RouteChildren } from "./router";
|
|
7
8
|
export type { ResolvedRoute } from "./router";
|
|
8
|
-
export
|
|
9
|
-
export type {
|
|
10
|
-
WebframezCoreRouteMethod,
|
|
11
|
-
WebframezCoreReactRenderRouteOptions,
|
|
12
|
-
} from "./webframez-core";
|
|
9
|
+
export * from "./webframez-core";
|
|
13
10
|
|
|
14
11
|
export function createHTMLShell(options?: CreateHtmlShellOptions): string;
|
|
15
12
|
export function sendRSC(
|
package/dist/index.js
CHANGED
|
@@ -221,6 +221,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
221
221
|
function escapeHtml(value) {
|
|
222
222
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
223
223
|
}
|
|
224
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
225
|
+
function createManagedAttributes() {
|
|
226
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
227
|
+
}
|
|
224
228
|
function toRouteEntry(pagesDir, filePath) {
|
|
225
229
|
const normalized = filePath.replace(/\\/g, "/");
|
|
226
230
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -289,19 +293,21 @@ function renderHeadToString(head) {
|
|
|
289
293
|
const tags = [];
|
|
290
294
|
if (head.description) {
|
|
291
295
|
tags.push(
|
|
292
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
296
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
293
297
|
);
|
|
294
298
|
}
|
|
295
299
|
if (head.favicon) {
|
|
296
|
-
tags.push(
|
|
300
|
+
tags.push(
|
|
301
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
302
|
+
);
|
|
297
303
|
}
|
|
298
304
|
for (const meta of head.meta ?? []) {
|
|
299
305
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
300
|
-
tags.push(`<meta ${attrs} />`);
|
|
306
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
301
307
|
}
|
|
302
308
|
for (const link of head.links ?? []) {
|
|
303
309
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
304
|
-
tags.push(`<link ${attrs} />`);
|
|
310
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
305
311
|
}
|
|
306
312
|
return tags.join("\n");
|
|
307
313
|
}
|
|
@@ -315,6 +321,12 @@ async function resolveHead(candidate, context) {
|
|
|
315
321
|
}
|
|
316
322
|
return candidate.Head(context);
|
|
317
323
|
}
|
|
324
|
+
async function resolvePageData(candidate, context) {
|
|
325
|
+
if (!candidate.Data) {
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
return candidate.Data(context);
|
|
329
|
+
}
|
|
318
330
|
function findBestMatch(entries, pathname) {
|
|
319
331
|
const matches = [];
|
|
320
332
|
for (const entry of entries) {
|
|
@@ -394,10 +406,11 @@ function createFileRouter(options) {
|
|
|
394
406
|
};
|
|
395
407
|
}
|
|
396
408
|
const errorModule = resolveModule(errorPath);
|
|
397
|
-
const errorNode = errorModule.default(errorProps);
|
|
409
|
+
const errorNode = await errorModule.default(errorProps);
|
|
398
410
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
399
411
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
400
|
-
const
|
|
412
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
413
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
401
414
|
return {
|
|
402
415
|
statusCode,
|
|
403
416
|
model,
|
|
@@ -429,10 +442,17 @@ function createFileRouter(options) {
|
|
|
429
442
|
activeContext = context;
|
|
430
443
|
const pageModule = resolveModule(match.entry.filePath);
|
|
431
444
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
432
|
-
const
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
445
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
446
|
+
const pageContext = {
|
|
447
|
+
...context,
|
|
448
|
+
data: pageData
|
|
449
|
+
};
|
|
450
|
+
activeContext = pageContext;
|
|
451
|
+
const pageNode = await pageModule.default(pageContext);
|
|
452
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
453
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
454
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
455
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
436
456
|
return {
|
|
437
457
|
statusCode: 200,
|
|
438
458
|
model,
|
|
@@ -480,14 +500,26 @@ function stripBasePath(pathname, basePath) {
|
|
|
480
500
|
}
|
|
481
501
|
function runNodeCommand(args) {
|
|
482
502
|
return new Promise((resolve, reject) => {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
503
|
+
const execArgs = [
|
|
504
|
+
"--conditions",
|
|
505
|
+
"react-server",
|
|
506
|
+
"-r",
|
|
507
|
+
"@webtypen/webframez-react/register",
|
|
508
|
+
...args
|
|
509
|
+
];
|
|
510
|
+
execFile(
|
|
511
|
+
process.execPath,
|
|
512
|
+
execArgs,
|
|
513
|
+
{ timeout: 1e4, maxBuffer: 1024 * 1024 * 5 },
|
|
514
|
+
(error, stdout, stderr) => {
|
|
515
|
+
if (error) {
|
|
516
|
+
const out = stderr && stderr.trim() !== "" ? stderr : stdout;
|
|
517
|
+
reject(new Error(out || error.message));
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
resolve({ stdout, stderr });
|
|
488
521
|
}
|
|
489
|
-
|
|
490
|
-
});
|
|
522
|
+
);
|
|
491
523
|
});
|
|
492
524
|
}
|
|
493
525
|
async function renderInitialHtmlInWorker(options) {
|
|
@@ -511,7 +543,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
|
|
511
543
|
}
|
|
512
544
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
513
545
|
};
|
|
514
|
-
const { createFileRouter } = require("webframez-react/router");
|
|
546
|
+
const { createFileRouter } = require("@webtypen/webframez-react/router");
|
|
515
547
|
const reactDomPkg = require.resolve("react-dom/package.json", {
|
|
516
548
|
paths: [process.cwd(), input.pagesDir]
|
|
517
549
|
});
|
|
@@ -650,7 +682,11 @@ function createNodeRequestHandler(options) {
|
|
|
650
682
|
cookies: requestCookies
|
|
651
683
|
})
|
|
652
684
|
);
|
|
653
|
-
|
|
685
|
+
const payload = {
|
|
686
|
+
model: resolved2.model,
|
|
687
|
+
head: resolved2.head
|
|
688
|
+
};
|
|
689
|
+
sendRSC(res, payload, {
|
|
654
690
|
moduleMap,
|
|
655
691
|
statusCode: resolved2.statusCode
|
|
656
692
|
});
|
package/dist/router.cjs
CHANGED
|
@@ -144,6 +144,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
144
144
|
function escapeHtml(value) {
|
|
145
145
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
146
146
|
}
|
|
147
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
148
|
+
function createManagedAttributes() {
|
|
149
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
150
|
+
}
|
|
147
151
|
function toRouteEntry(pagesDir, filePath) {
|
|
148
152
|
const normalized = filePath.replace(/\\/g, "/");
|
|
149
153
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -212,19 +216,21 @@ function renderHeadToString(head) {
|
|
|
212
216
|
const tags = [];
|
|
213
217
|
if (head.description) {
|
|
214
218
|
tags.push(
|
|
215
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
219
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
216
220
|
);
|
|
217
221
|
}
|
|
218
222
|
if (head.favicon) {
|
|
219
|
-
tags.push(
|
|
223
|
+
tags.push(
|
|
224
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
225
|
+
);
|
|
220
226
|
}
|
|
221
227
|
for (const meta of head.meta ?? []) {
|
|
222
228
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
223
|
-
tags.push(`<meta ${attrs} />`);
|
|
229
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
224
230
|
}
|
|
225
231
|
for (const link of head.links ?? []) {
|
|
226
232
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
227
|
-
tags.push(`<link ${attrs} />`);
|
|
233
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
228
234
|
}
|
|
229
235
|
return tags.join("\n");
|
|
230
236
|
}
|
|
@@ -238,6 +244,12 @@ async function resolveHead(candidate, context) {
|
|
|
238
244
|
}
|
|
239
245
|
return candidate.Head(context);
|
|
240
246
|
}
|
|
247
|
+
async function resolvePageData(candidate, context) {
|
|
248
|
+
if (!candidate.Data) {
|
|
249
|
+
return void 0;
|
|
250
|
+
}
|
|
251
|
+
return candidate.Data(context);
|
|
252
|
+
}
|
|
241
253
|
function findBestMatch(entries, pathname) {
|
|
242
254
|
const matches = [];
|
|
243
255
|
for (const entry of entries) {
|
|
@@ -317,10 +329,11 @@ function createFileRouter(options) {
|
|
|
317
329
|
};
|
|
318
330
|
}
|
|
319
331
|
const errorModule = resolveModule(errorPath);
|
|
320
|
-
const errorNode = errorModule.default(errorProps);
|
|
332
|
+
const errorNode = await errorModule.default(errorProps);
|
|
321
333
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
322
334
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
323
|
-
const
|
|
335
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
336
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
324
337
|
return {
|
|
325
338
|
statusCode,
|
|
326
339
|
model,
|
|
@@ -352,10 +365,17 @@ function createFileRouter(options) {
|
|
|
352
365
|
activeContext = context;
|
|
353
366
|
const pageModule = resolveModule(match.entry.filePath);
|
|
354
367
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
368
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
369
|
+
const pageContext = {
|
|
370
|
+
...context,
|
|
371
|
+
data: pageData
|
|
372
|
+
};
|
|
373
|
+
activeContext = pageContext;
|
|
374
|
+
const pageNode = await pageModule.default(pageContext);
|
|
375
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
376
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
377
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
378
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
359
379
|
return {
|
|
360
380
|
statusCode: 200,
|
|
361
381
|
model,
|
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,
|