@webtypen/webframez-react 0.0.14 → 0.0.16
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/dist/http.cjs +139 -8
- package/dist/http.js +139 -8
- package/dist/index.cjs +139 -8
- package/dist/index.js +139 -8
- package/dist/router.cjs +119 -3
- package/dist/router.js +119 -3
- package/dist/types.d.ts +10 -0
- package/dist/webframez-core.cjs +139 -8
- package/dist/webframez-core.js +139 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -166,6 +166,7 @@ function createRSCHandler(options) {
|
|
|
166
166
|
|
|
167
167
|
// src/file-router.tsx
|
|
168
168
|
import fs from "node:fs";
|
|
169
|
+
import Module from "node:module";
|
|
169
170
|
import path2 from "node:path";
|
|
170
171
|
|
|
171
172
|
// src/router-runtime.tsx
|
|
@@ -228,6 +229,26 @@ function injectRouteChildren(node, routeChildren) {
|
|
|
228
229
|
|
|
229
230
|
// src/file-router.tsx
|
|
230
231
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
232
|
+
var ROOT_RUNTIME_REQUIRE = Module.createRequire(
|
|
233
|
+
path2.join(process.cwd(), "__webframez_react_runtime__.js")
|
|
234
|
+
);
|
|
235
|
+
var FORCED_PACKAGE_REQUESTS = [
|
|
236
|
+
"@webtypen/webframez-core",
|
|
237
|
+
"@webtypen/webframez-react",
|
|
238
|
+
"react",
|
|
239
|
+
"react/jsx-runtime",
|
|
240
|
+
"react/jsx-dev-runtime",
|
|
241
|
+
"react-dom",
|
|
242
|
+
"react-dom/client",
|
|
243
|
+
"react-dom/server",
|
|
244
|
+
"react-dom/server.node",
|
|
245
|
+
"react-server-dom-webpack",
|
|
246
|
+
"react-server-dom-webpack/server",
|
|
247
|
+
"react-server-dom-webpack/client",
|
|
248
|
+
"react-server-dom-webpack/client.node",
|
|
249
|
+
"scheduler"
|
|
250
|
+
];
|
|
251
|
+
var forcedPackageResolutionInstalled = false;
|
|
231
252
|
function normalizePathname(pathname) {
|
|
232
253
|
const trimmed = pathname.replace(/\/+$/, "") || "/";
|
|
233
254
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
@@ -276,6 +297,28 @@ var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
|
276
297
|
function createManagedAttributes() {
|
|
277
298
|
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
278
299
|
}
|
|
300
|
+
function shouldForcePackageResolution(request) {
|
|
301
|
+
return FORCED_PACKAGE_REQUESTS.some(
|
|
302
|
+
(candidate) => request === candidate || request.startsWith(`${candidate}/`)
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
function installForcedPackageResolution() {
|
|
306
|
+
if (forcedPackageResolutionInstalled) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const moduleWithPrivateResolver = Module;
|
|
310
|
+
const originalResolveFilename = moduleWithPrivateResolver._resolveFilename;
|
|
311
|
+
moduleWithPrivateResolver._resolveFilename = function patchedResolveFilename(request, parent, isMain, options) {
|
|
312
|
+
if (typeof request === "string" && shouldForcePackageResolution(request)) {
|
|
313
|
+
try {
|
|
314
|
+
return ROOT_RUNTIME_REQUIRE.resolve(request);
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
319
|
+
};
|
|
320
|
+
forcedPackageResolutionInstalled = true;
|
|
321
|
+
}
|
|
279
322
|
function toRouteEntry(pagesDir, filePath) {
|
|
280
323
|
const normalized = filePath.replace(/\\/g, "/");
|
|
281
324
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -423,9 +466,11 @@ function isRouteAbort(value) {
|
|
|
423
466
|
}
|
|
424
467
|
}
|
|
425
468
|
function createFileRouter(options) {
|
|
469
|
+
installForcedPackageResolution();
|
|
426
470
|
const pagesDir = options.pagesDir;
|
|
427
471
|
const layoutPath = path2.join(pagesDir, "layout.js");
|
|
428
472
|
const errorPath = path2.join(pagesDir, "errors.js");
|
|
473
|
+
const middlewaresPath = path2.join(pagesDir, "middlewares.js");
|
|
429
474
|
function buildRouteEntries() {
|
|
430
475
|
const files = walkFiles(pagesDir);
|
|
431
476
|
return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
|
|
@@ -468,6 +513,75 @@ function createFileRouter(options) {
|
|
|
468
513
|
head: mergeHead(layoutHead, errorHead)
|
|
469
514
|
};
|
|
470
515
|
}
|
|
516
|
+
function normalizeMiddlewareNames(config) {
|
|
517
|
+
if (!config) {
|
|
518
|
+
return [];
|
|
519
|
+
}
|
|
520
|
+
return Array.isArray(config) ? config : [config];
|
|
521
|
+
}
|
|
522
|
+
function isPlainObject(value) {
|
|
523
|
+
if (!value || typeof value !== "object") {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
const prototype = Object.getPrototypeOf(value);
|
|
527
|
+
return prototype === Object.prototype || prototype === null;
|
|
528
|
+
}
|
|
529
|
+
function mergeRouteData(currentData, nextData) {
|
|
530
|
+
if (typeof nextData === "undefined") {
|
|
531
|
+
return currentData;
|
|
532
|
+
}
|
|
533
|
+
if (isPlainObject(currentData) && isPlainObject(nextData)) {
|
|
534
|
+
return {
|
|
535
|
+
...currentData,
|
|
536
|
+
...nextData
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
return nextData;
|
|
540
|
+
}
|
|
541
|
+
async function resolveMiddlewares(config, context) {
|
|
542
|
+
const middlewareNames = normalizeMiddlewareNames(config);
|
|
543
|
+
const requiresNamedMiddleware = middlewareNames.length > 0;
|
|
544
|
+
if (!fs.existsSync(middlewaresPath)) {
|
|
545
|
+
if (!requiresNamedMiddleware) {
|
|
546
|
+
return context;
|
|
547
|
+
}
|
|
548
|
+
throw createAbort({
|
|
549
|
+
status: 500,
|
|
550
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
const middlewareModule = resolveModule(middlewaresPath);
|
|
554
|
+
const registry = middlewareModule.middlewares;
|
|
555
|
+
if (!registry) {
|
|
556
|
+
if (!requiresNamedMiddleware) {
|
|
557
|
+
return context;
|
|
558
|
+
}
|
|
559
|
+
throw createAbort({
|
|
560
|
+
status: 500,
|
|
561
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
|
|
565
|
+
if (orderedMiddlewareNames.length === 0) {
|
|
566
|
+
return context;
|
|
567
|
+
}
|
|
568
|
+
let nextContext = context;
|
|
569
|
+
for (const middlewareName of orderedMiddlewareNames) {
|
|
570
|
+
const middleware = registry[middlewareName];
|
|
571
|
+
if (typeof middleware !== "function") {
|
|
572
|
+
throw createAbort({
|
|
573
|
+
status: 500,
|
|
574
|
+
message: `Invalid middleware '${middlewareName}'`
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
const middlewareData = await middleware(nextContext);
|
|
578
|
+
nextContext = {
|
|
579
|
+
...nextContext,
|
|
580
|
+
data: mergeRouteData(nextContext.data, middlewareData)
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
return nextContext;
|
|
584
|
+
}
|
|
471
585
|
async function resolve(input) {
|
|
472
586
|
const pathname = normalizePathname(input.pathname);
|
|
473
587
|
const contextBase = {
|
|
@@ -493,10 +607,12 @@ function createFileRouter(options) {
|
|
|
493
607
|
activeContext = context;
|
|
494
608
|
const pageModule = resolveModule(match.entry.filePath);
|
|
495
609
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
496
|
-
const
|
|
610
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
611
|
+
activeContext = middlewareContext;
|
|
612
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
497
613
|
const pageContext = {
|
|
498
|
-
...
|
|
499
|
-
data: pageData
|
|
614
|
+
...middlewareContext,
|
|
615
|
+
data: mergeRouteData(middlewareContext.data, pageData)
|
|
500
616
|
};
|
|
501
617
|
activeContext = pageContext;
|
|
502
618
|
const pageNode = await pageModule.default(pageContext);
|
|
@@ -544,19 +660,34 @@ if (!pagesDir) {
|
|
|
544
660
|
throw new Error("Missing WEBFRAMEZ_REACT_PAGES_DIR");
|
|
545
661
|
}
|
|
546
662
|
|
|
547
|
-
const
|
|
663
|
+
const rootRequire = Module.createRequire(path.join(process.cwd(), "__webframez_react_worker__.js"));
|
|
548
664
|
const originalResolveFilename = Module._resolveFilename;
|
|
549
665
|
const forcedResolutions = new Map([
|
|
550
|
-
["
|
|
551
|
-
["
|
|
552
|
-
["react
|
|
553
|
-
["react-
|
|
666
|
+
["@webtypen/webframez-core", rootRequire.resolve("@webtypen/webframez-core")],
|
|
667
|
+
["@webtypen/webframez-react", rootRequire.resolve("@webtypen/webframez-react")],
|
|
668
|
+
["react", rootRequire.resolve("react")],
|
|
669
|
+
["react/jsx-runtime", rootRequire.resolve("react/jsx-runtime")],
|
|
670
|
+
["react/jsx-dev-runtime", rootRequire.resolve("react/jsx-dev-runtime")],
|
|
671
|
+
["react-dom", rootRequire.resolve("react-dom")],
|
|
672
|
+
["react-dom/client", rootRequire.resolve("react-dom/client")],
|
|
673
|
+
["react-dom/server", rootRequire.resolve("react-dom/server")],
|
|
674
|
+
["react-dom/server.node", rootRequire.resolve("react-dom/server.node")],
|
|
675
|
+
["react-server-dom-webpack", rootRequire.resolve("react-server-dom-webpack")],
|
|
676
|
+
["react-server-dom-webpack/server", rootRequire.resolve("react-server-dom-webpack/server")],
|
|
677
|
+
["react-server-dom-webpack/client", rootRequire.resolve("react-server-dom-webpack/client")],
|
|
678
|
+
["react-server-dom-webpack/client.node", rootRequire.resolve("react-server-dom-webpack/client.node")],
|
|
679
|
+
["scheduler", rootRequire.resolve("scheduler")]
|
|
554
680
|
]);
|
|
555
681
|
|
|
556
682
|
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
557
683
|
if (forcedResolutions.has(request)) {
|
|
558
684
|
return forcedResolutions.get(request);
|
|
559
685
|
}
|
|
686
|
+
for (const forcedRequest of forcedResolutions.keys()) {
|
|
687
|
+
if (request.startsWith(forcedRequest + "/")) {
|
|
688
|
+
return rootRequire.resolve(request);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
560
691
|
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
561
692
|
};
|
|
562
693
|
|
package/dist/router.cjs
CHANGED
|
@@ -38,6 +38,7 @@ module.exports = __toCommonJS(router_exports);
|
|
|
38
38
|
|
|
39
39
|
// src/file-router.tsx
|
|
40
40
|
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
41
|
+
var import_node_module = __toESM(require("node:module"), 1);
|
|
41
42
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
42
43
|
|
|
43
44
|
// src/router-runtime.tsx
|
|
@@ -100,6 +101,26 @@ function injectRouteChildren(node, routeChildren) {
|
|
|
100
101
|
|
|
101
102
|
// src/file-router.tsx
|
|
102
103
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
104
|
+
var ROOT_RUNTIME_REQUIRE = import_node_module.default.createRequire(
|
|
105
|
+
import_node_path.default.join(process.cwd(), "__webframez_react_runtime__.js")
|
|
106
|
+
);
|
|
107
|
+
var FORCED_PACKAGE_REQUESTS = [
|
|
108
|
+
"@webtypen/webframez-core",
|
|
109
|
+
"@webtypen/webframez-react",
|
|
110
|
+
"react",
|
|
111
|
+
"react/jsx-runtime",
|
|
112
|
+
"react/jsx-dev-runtime",
|
|
113
|
+
"react-dom",
|
|
114
|
+
"react-dom/client",
|
|
115
|
+
"react-dom/server",
|
|
116
|
+
"react-dom/server.node",
|
|
117
|
+
"react-server-dom-webpack",
|
|
118
|
+
"react-server-dom-webpack/server",
|
|
119
|
+
"react-server-dom-webpack/client",
|
|
120
|
+
"react-server-dom-webpack/client.node",
|
|
121
|
+
"scheduler"
|
|
122
|
+
];
|
|
123
|
+
var forcedPackageResolutionInstalled = false;
|
|
103
124
|
function normalizePathname(pathname) {
|
|
104
125
|
const trimmed = pathname.replace(/\/+$/, "") || "/";
|
|
105
126
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
@@ -148,6 +169,28 @@ var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
|
148
169
|
function createManagedAttributes() {
|
|
149
170
|
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
150
171
|
}
|
|
172
|
+
function shouldForcePackageResolution(request) {
|
|
173
|
+
return FORCED_PACKAGE_REQUESTS.some(
|
|
174
|
+
(candidate) => request === candidate || request.startsWith(`${candidate}/`)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
function installForcedPackageResolution() {
|
|
178
|
+
if (forcedPackageResolutionInstalled) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const moduleWithPrivateResolver = import_node_module.default;
|
|
182
|
+
const originalResolveFilename = moduleWithPrivateResolver._resolveFilename;
|
|
183
|
+
moduleWithPrivateResolver._resolveFilename = function patchedResolveFilename(request, parent, isMain, options) {
|
|
184
|
+
if (typeof request === "string" && shouldForcePackageResolution(request)) {
|
|
185
|
+
try {
|
|
186
|
+
return ROOT_RUNTIME_REQUIRE.resolve(request);
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
191
|
+
};
|
|
192
|
+
forcedPackageResolutionInstalled = true;
|
|
193
|
+
}
|
|
151
194
|
function toRouteEntry(pagesDir, filePath) {
|
|
152
195
|
const normalized = filePath.replace(/\\/g, "/");
|
|
153
196
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -295,9 +338,11 @@ function isRouteAbort(value) {
|
|
|
295
338
|
}
|
|
296
339
|
}
|
|
297
340
|
function createFileRouter(options) {
|
|
341
|
+
installForcedPackageResolution();
|
|
298
342
|
const pagesDir = options.pagesDir;
|
|
299
343
|
const layoutPath = import_node_path.default.join(pagesDir, "layout.js");
|
|
300
344
|
const errorPath = import_node_path.default.join(pagesDir, "errors.js");
|
|
345
|
+
const middlewaresPath = import_node_path.default.join(pagesDir, "middlewares.js");
|
|
301
346
|
function buildRouteEntries() {
|
|
302
347
|
const files = walkFiles(pagesDir);
|
|
303
348
|
return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
|
|
@@ -340,6 +385,75 @@ function createFileRouter(options) {
|
|
|
340
385
|
head: mergeHead(layoutHead, errorHead)
|
|
341
386
|
};
|
|
342
387
|
}
|
|
388
|
+
function normalizeMiddlewareNames(config) {
|
|
389
|
+
if (!config) {
|
|
390
|
+
return [];
|
|
391
|
+
}
|
|
392
|
+
return Array.isArray(config) ? config : [config];
|
|
393
|
+
}
|
|
394
|
+
function isPlainObject(value) {
|
|
395
|
+
if (!value || typeof value !== "object") {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
const prototype = Object.getPrototypeOf(value);
|
|
399
|
+
return prototype === Object.prototype || prototype === null;
|
|
400
|
+
}
|
|
401
|
+
function mergeRouteData(currentData, nextData) {
|
|
402
|
+
if (typeof nextData === "undefined") {
|
|
403
|
+
return currentData;
|
|
404
|
+
}
|
|
405
|
+
if (isPlainObject(currentData) && isPlainObject(nextData)) {
|
|
406
|
+
return {
|
|
407
|
+
...currentData,
|
|
408
|
+
...nextData
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
return nextData;
|
|
412
|
+
}
|
|
413
|
+
async function resolveMiddlewares(config, context) {
|
|
414
|
+
const middlewareNames = normalizeMiddlewareNames(config);
|
|
415
|
+
const requiresNamedMiddleware = middlewareNames.length > 0;
|
|
416
|
+
if (!import_node_fs.default.existsSync(middlewaresPath)) {
|
|
417
|
+
if (!requiresNamedMiddleware) {
|
|
418
|
+
return context;
|
|
419
|
+
}
|
|
420
|
+
throw createAbort({
|
|
421
|
+
status: 500,
|
|
422
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const middlewareModule = resolveModule(middlewaresPath);
|
|
426
|
+
const registry = middlewareModule.middlewares;
|
|
427
|
+
if (!registry) {
|
|
428
|
+
if (!requiresNamedMiddleware) {
|
|
429
|
+
return context;
|
|
430
|
+
}
|
|
431
|
+
throw createAbort({
|
|
432
|
+
status: 500,
|
|
433
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
|
|
437
|
+
if (orderedMiddlewareNames.length === 0) {
|
|
438
|
+
return context;
|
|
439
|
+
}
|
|
440
|
+
let nextContext = context;
|
|
441
|
+
for (const middlewareName of orderedMiddlewareNames) {
|
|
442
|
+
const middleware = registry[middlewareName];
|
|
443
|
+
if (typeof middleware !== "function") {
|
|
444
|
+
throw createAbort({
|
|
445
|
+
status: 500,
|
|
446
|
+
message: `Invalid middleware '${middlewareName}'`
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
const middlewareData = await middleware(nextContext);
|
|
450
|
+
nextContext = {
|
|
451
|
+
...nextContext,
|
|
452
|
+
data: mergeRouteData(nextContext.data, middlewareData)
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
return nextContext;
|
|
456
|
+
}
|
|
343
457
|
async function resolve(input) {
|
|
344
458
|
const pathname = normalizePathname(input.pathname);
|
|
345
459
|
const contextBase = {
|
|
@@ -365,10 +479,12 @@ function createFileRouter(options) {
|
|
|
365
479
|
activeContext = context;
|
|
366
480
|
const pageModule = resolveModule(match.entry.filePath);
|
|
367
481
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
368
|
-
const
|
|
482
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
483
|
+
activeContext = middlewareContext;
|
|
484
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
369
485
|
const pageContext = {
|
|
370
|
-
...
|
|
371
|
-
data: pageData
|
|
486
|
+
...middlewareContext,
|
|
487
|
+
data: mergeRouteData(middlewareContext.data, pageData)
|
|
372
488
|
};
|
|
373
489
|
activeContext = pageContext;
|
|
374
490
|
const pageNode = await pageModule.default(pageContext);
|
package/dist/router.js
CHANGED
|
@@ -8,6 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
|
|
9
9
|
// src/file-router.tsx
|
|
10
10
|
import fs from "node:fs";
|
|
11
|
+
import Module from "node:module";
|
|
11
12
|
import path from "node:path";
|
|
12
13
|
|
|
13
14
|
// src/router-runtime.tsx
|
|
@@ -70,6 +71,26 @@ function injectRouteChildren(node, routeChildren) {
|
|
|
70
71
|
|
|
71
72
|
// src/file-router.tsx
|
|
72
73
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
74
|
+
var ROOT_RUNTIME_REQUIRE = Module.createRequire(
|
|
75
|
+
path.join(process.cwd(), "__webframez_react_runtime__.js")
|
|
76
|
+
);
|
|
77
|
+
var FORCED_PACKAGE_REQUESTS = [
|
|
78
|
+
"@webtypen/webframez-core",
|
|
79
|
+
"@webtypen/webframez-react",
|
|
80
|
+
"react",
|
|
81
|
+
"react/jsx-runtime",
|
|
82
|
+
"react/jsx-dev-runtime",
|
|
83
|
+
"react-dom",
|
|
84
|
+
"react-dom/client",
|
|
85
|
+
"react-dom/server",
|
|
86
|
+
"react-dom/server.node",
|
|
87
|
+
"react-server-dom-webpack",
|
|
88
|
+
"react-server-dom-webpack/server",
|
|
89
|
+
"react-server-dom-webpack/client",
|
|
90
|
+
"react-server-dom-webpack/client.node",
|
|
91
|
+
"scheduler"
|
|
92
|
+
];
|
|
93
|
+
var forcedPackageResolutionInstalled = false;
|
|
73
94
|
function normalizePathname(pathname) {
|
|
74
95
|
const trimmed = pathname.replace(/\/+$/, "") || "/";
|
|
75
96
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
@@ -118,6 +139,28 @@ var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
|
118
139
|
function createManagedAttributes() {
|
|
119
140
|
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
120
141
|
}
|
|
142
|
+
function shouldForcePackageResolution(request) {
|
|
143
|
+
return FORCED_PACKAGE_REQUESTS.some(
|
|
144
|
+
(candidate) => request === candidate || request.startsWith(`${candidate}/`)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function installForcedPackageResolution() {
|
|
148
|
+
if (forcedPackageResolutionInstalled) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const moduleWithPrivateResolver = Module;
|
|
152
|
+
const originalResolveFilename = moduleWithPrivateResolver._resolveFilename;
|
|
153
|
+
moduleWithPrivateResolver._resolveFilename = function patchedResolveFilename(request, parent, isMain, options) {
|
|
154
|
+
if (typeof request === "string" && shouldForcePackageResolution(request)) {
|
|
155
|
+
try {
|
|
156
|
+
return ROOT_RUNTIME_REQUIRE.resolve(request);
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return originalResolveFilename.call(this, request, parent, isMain, options);
|
|
161
|
+
};
|
|
162
|
+
forcedPackageResolutionInstalled = true;
|
|
163
|
+
}
|
|
121
164
|
function toRouteEntry(pagesDir, filePath) {
|
|
122
165
|
const normalized = filePath.replace(/\\/g, "/");
|
|
123
166
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -265,9 +308,11 @@ function isRouteAbort(value) {
|
|
|
265
308
|
}
|
|
266
309
|
}
|
|
267
310
|
function createFileRouter(options) {
|
|
311
|
+
installForcedPackageResolution();
|
|
268
312
|
const pagesDir = options.pagesDir;
|
|
269
313
|
const layoutPath = path.join(pagesDir, "layout.js");
|
|
270
314
|
const errorPath = path.join(pagesDir, "errors.js");
|
|
315
|
+
const middlewaresPath = path.join(pagesDir, "middlewares.js");
|
|
271
316
|
function buildRouteEntries() {
|
|
272
317
|
const files = walkFiles(pagesDir);
|
|
273
318
|
return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
|
|
@@ -310,6 +355,75 @@ function createFileRouter(options) {
|
|
|
310
355
|
head: mergeHead(layoutHead, errorHead)
|
|
311
356
|
};
|
|
312
357
|
}
|
|
358
|
+
function normalizeMiddlewareNames(config) {
|
|
359
|
+
if (!config) {
|
|
360
|
+
return [];
|
|
361
|
+
}
|
|
362
|
+
return Array.isArray(config) ? config : [config];
|
|
363
|
+
}
|
|
364
|
+
function isPlainObject(value) {
|
|
365
|
+
if (!value || typeof value !== "object") {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
const prototype = Object.getPrototypeOf(value);
|
|
369
|
+
return prototype === Object.prototype || prototype === null;
|
|
370
|
+
}
|
|
371
|
+
function mergeRouteData(currentData, nextData) {
|
|
372
|
+
if (typeof nextData === "undefined") {
|
|
373
|
+
return currentData;
|
|
374
|
+
}
|
|
375
|
+
if (isPlainObject(currentData) && isPlainObject(nextData)) {
|
|
376
|
+
return {
|
|
377
|
+
...currentData,
|
|
378
|
+
...nextData
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return nextData;
|
|
382
|
+
}
|
|
383
|
+
async function resolveMiddlewares(config, context) {
|
|
384
|
+
const middlewareNames = normalizeMiddlewareNames(config);
|
|
385
|
+
const requiresNamedMiddleware = middlewareNames.length > 0;
|
|
386
|
+
if (!fs.existsSync(middlewaresPath)) {
|
|
387
|
+
if (!requiresNamedMiddleware) {
|
|
388
|
+
return context;
|
|
389
|
+
}
|
|
390
|
+
throw createAbort({
|
|
391
|
+
status: 500,
|
|
392
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
const middlewareModule = resolveModule(middlewaresPath);
|
|
396
|
+
const registry = middlewareModule.middlewares;
|
|
397
|
+
if (!registry) {
|
|
398
|
+
if (!requiresNamedMiddleware) {
|
|
399
|
+
return context;
|
|
400
|
+
}
|
|
401
|
+
throw createAbort({
|
|
402
|
+
status: 500,
|
|
403
|
+
message: `Invalid middleware '${middlewareNames[0]}'`
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
|
|
407
|
+
if (orderedMiddlewareNames.length === 0) {
|
|
408
|
+
return context;
|
|
409
|
+
}
|
|
410
|
+
let nextContext = context;
|
|
411
|
+
for (const middlewareName of orderedMiddlewareNames) {
|
|
412
|
+
const middleware = registry[middlewareName];
|
|
413
|
+
if (typeof middleware !== "function") {
|
|
414
|
+
throw createAbort({
|
|
415
|
+
status: 500,
|
|
416
|
+
message: `Invalid middleware '${middlewareName}'`
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
const middlewareData = await middleware(nextContext);
|
|
420
|
+
nextContext = {
|
|
421
|
+
...nextContext,
|
|
422
|
+
data: mergeRouteData(nextContext.data, middlewareData)
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
return nextContext;
|
|
426
|
+
}
|
|
313
427
|
async function resolve(input) {
|
|
314
428
|
const pathname = normalizePathname(input.pathname);
|
|
315
429
|
const contextBase = {
|
|
@@ -335,10 +449,12 @@ function createFileRouter(options) {
|
|
|
335
449
|
activeContext = context;
|
|
336
450
|
const pageModule = resolveModule(match.entry.filePath);
|
|
337
451
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
338
|
-
const
|
|
452
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
453
|
+
activeContext = middlewareContext;
|
|
454
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
339
455
|
const pageContext = {
|
|
340
|
-
...
|
|
341
|
-
data: pageData
|
|
456
|
+
...middlewareContext,
|
|
457
|
+
data: mergeRouteData(middlewareContext.data, pageData)
|
|
342
458
|
};
|
|
343
459
|
activeContext = pageContext;
|
|
344
460
|
const pageNode = await pageModule.default(pageContext);
|
package/dist/types.d.ts
CHANGED
|
@@ -69,10 +69,18 @@ export type PageDataResolver<TData = unknown> = (
|
|
|
69
69
|
context: RouteContext
|
|
70
70
|
) => TData | Promise<TData>;
|
|
71
71
|
|
|
72
|
+
export type RouteMiddlewareResult = Record<string, unknown> | undefined | void;
|
|
73
|
+
export type RouteMiddlewareResolver<TData = unknown> = (
|
|
74
|
+
context: RouteContext<TData>
|
|
75
|
+
) => RouteMiddlewareResult | Promise<RouteMiddlewareResult>;
|
|
76
|
+
export type RouteMiddlewareRegistry = Record<string, RouteMiddlewareResolver<any>>;
|
|
77
|
+
export type RouteMiddlewareConfig = string | string[];
|
|
78
|
+
|
|
72
79
|
export type PageModule<TData = unknown> = {
|
|
73
80
|
default: (props: PageProps<TData>) => ReactNode | Promise<ReactNode>;
|
|
74
81
|
Head?: HeadResolver<PageProps<TData>>;
|
|
75
82
|
Data?: PageDataResolver<TData>;
|
|
83
|
+
middlewares?: RouteMiddlewareConfig;
|
|
76
84
|
};
|
|
77
85
|
|
|
78
86
|
export type LayoutModule = {
|
|
@@ -91,6 +99,8 @@ export type CreateHtmlShellOptions = {
|
|
|
91
99
|
clientScriptUrl?: string;
|
|
92
100
|
headTags?: string;
|
|
93
101
|
rootHtml?: string;
|
|
102
|
+
initialFlightData?: string;
|
|
103
|
+
clientRenderMode?: "hydrate" | "mount";
|
|
94
104
|
basename?: string;
|
|
95
105
|
liveReloadPath?: string;
|
|
96
106
|
liveReloadServerId?: string;
|