@webtypen/webframez-react 0.0.13 → 0.0.15

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 CHANGED
@@ -34,6 +34,7 @@ __export(http_exports, {
34
34
  module.exports = __toCommonJS(http_exports);
35
35
  var import_node_fs2 = __toESM(require("node:fs"), 1);
36
36
  var import_node_path3 = __toESM(require("node:path"), 1);
37
+ var import_node_url = require("node:url");
37
38
  var import_node_child_process = require("node:child_process");
38
39
 
39
40
  // src/server.ts
@@ -428,6 +429,7 @@ function createFileRouter(options) {
428
429
  const pagesDir = options.pagesDir;
429
430
  const layoutPath = import_node_path2.default.join(pagesDir, "layout.js");
430
431
  const errorPath = import_node_path2.default.join(pagesDir, "errors.js");
432
+ const middlewaresPath = import_node_path2.default.join(pagesDir, "middlewares.js");
431
433
  function buildRouteEntries() {
432
434
  const files = walkFiles(pagesDir);
433
435
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -470,6 +472,75 @@ function createFileRouter(options) {
470
472
  head: mergeHead(layoutHead, errorHead)
471
473
  };
472
474
  }
475
+ function normalizeMiddlewareNames(config) {
476
+ if (!config) {
477
+ return [];
478
+ }
479
+ return Array.isArray(config) ? config : [config];
480
+ }
481
+ function isPlainObject(value) {
482
+ if (!value || typeof value !== "object") {
483
+ return false;
484
+ }
485
+ const prototype = Object.getPrototypeOf(value);
486
+ return prototype === Object.prototype || prototype === null;
487
+ }
488
+ function mergeRouteData(currentData, nextData) {
489
+ if (typeof nextData === "undefined") {
490
+ return currentData;
491
+ }
492
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
493
+ return {
494
+ ...currentData,
495
+ ...nextData
496
+ };
497
+ }
498
+ return nextData;
499
+ }
500
+ async function resolveMiddlewares(config, context) {
501
+ const middlewareNames = normalizeMiddlewareNames(config);
502
+ const requiresNamedMiddleware = middlewareNames.length > 0;
503
+ if (!import_node_fs.default.existsSync(middlewaresPath)) {
504
+ if (!requiresNamedMiddleware) {
505
+ return context;
506
+ }
507
+ throw createAbort({
508
+ status: 500,
509
+ message: `Invalid middleware '${middlewareNames[0]}'`
510
+ });
511
+ }
512
+ const middlewareModule = resolveModule(middlewaresPath);
513
+ const registry = middlewareModule.middlewares;
514
+ if (!registry) {
515
+ if (!requiresNamedMiddleware) {
516
+ return context;
517
+ }
518
+ throw createAbort({
519
+ status: 500,
520
+ message: `Invalid middleware '${middlewareNames[0]}'`
521
+ });
522
+ }
523
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
524
+ if (orderedMiddlewareNames.length === 0) {
525
+ return context;
526
+ }
527
+ let nextContext = context;
528
+ for (const middlewareName of orderedMiddlewareNames) {
529
+ const middleware = registry[middlewareName];
530
+ if (typeof middleware !== "function") {
531
+ throw createAbort({
532
+ status: 500,
533
+ message: `Invalid middleware '${middlewareName}'`
534
+ });
535
+ }
536
+ const middlewareData = await middleware(nextContext);
537
+ nextContext = {
538
+ ...nextContext,
539
+ data: mergeRouteData(nextContext.data, middlewareData)
540
+ };
541
+ }
542
+ return nextContext;
543
+ }
473
544
  async function resolve(input) {
474
545
  const pathname = normalizePathname(input.pathname);
475
546
  const contextBase = {
@@ -495,10 +566,12 @@ function createFileRouter(options) {
495
566
  activeContext = context;
496
567
  const pageModule = resolveModule(match.entry.filePath);
497
568
  const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
498
- const pageData = await resolvePageData(pageModule, context);
569
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
570
+ activeContext = middlewareContext;
571
+ const pageData = await resolvePageData(pageModule, middlewareContext);
499
572
  const pageContext = {
500
- ...context,
501
- data: pageData
573
+ ...middlewareContext,
574
+ data: mergeRouteData(middlewareContext.data, pageData)
502
575
  };
503
576
  activeContext = pageContext;
504
577
  const pageNode = await pageModule.default(pageContext);
@@ -801,6 +874,38 @@ function parseCookies(rawCookieHeader) {
801
874
  }
802
875
  return output;
803
876
  }
877
+ function normalizeClientManifest(manifest, options) {
878
+ const normalized = { ...manifest };
879
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
880
+ import_node_path3.default.resolve(options.cwd, "node_modules"),
881
+ import_node_path3.default.resolve(options.distRootDir, "..", "..", "node_modules")
882
+ ]);
883
+ for (const [key, value] of Object.entries(manifest)) {
884
+ if (!key.startsWith("file://")) {
885
+ continue;
886
+ }
887
+ let absolutePath = "";
888
+ try {
889
+ absolutePath = (0, import_node_url.fileURLToPath)(key);
890
+ } catch {
891
+ continue;
892
+ }
893
+ const marker = `${import_node_path3.default.sep}node_modules${import_node_path3.default.sep}`;
894
+ const markerIndex = absolutePath.lastIndexOf(marker);
895
+ if (markerIndex < 0) {
896
+ continue;
897
+ }
898
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
899
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
900
+ const aliasPath = import_node_path3.default.join(nodeModulesDir, relativeModulePath);
901
+ const aliasKey = (0, import_node_url.pathToFileURL)(aliasPath).href;
902
+ if (!(aliasKey in normalized)) {
903
+ normalized[aliasKey] = value;
904
+ }
905
+ }
906
+ }
907
+ return normalized;
908
+ }
804
909
  function createNodeRequestHandler(options) {
805
910
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
806
911
  const distRootDir = import_node_path3.default.resolve(options.distRootDir);
@@ -818,7 +923,13 @@ function createNodeRequestHandler(options) {
818
923
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
819
924
  const liveReloadClients = /* @__PURE__ */ new Set();
820
925
  const router = createFileRouter({ pagesDir });
821
- const moduleMap = JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8"));
926
+ const moduleMap = normalizeClientManifest(
927
+ JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8")),
928
+ {
929
+ distRootDir,
930
+ cwd: process.cwd()
931
+ }
932
+ );
822
933
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
823
934
  const disposeInitialHtmlWorker = () => {
824
935
  initialHtmlWorker.dispose();
package/dist/http.js CHANGED
@@ -9,6 +9,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
  // src/http.ts
10
10
  import fs2 from "node:fs";
11
11
  import path3 from "node:path";
12
+ import { fileURLToPath, pathToFileURL } from "node:url";
12
13
  import { spawn } from "node:child_process";
13
14
 
14
15
  // src/server.ts
@@ -403,6 +404,7 @@ function createFileRouter(options) {
403
404
  const pagesDir = options.pagesDir;
404
405
  const layoutPath = path2.join(pagesDir, "layout.js");
405
406
  const errorPath = path2.join(pagesDir, "errors.js");
407
+ const middlewaresPath = path2.join(pagesDir, "middlewares.js");
406
408
  function buildRouteEntries() {
407
409
  const files = walkFiles(pagesDir);
408
410
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -445,6 +447,75 @@ function createFileRouter(options) {
445
447
  head: mergeHead(layoutHead, errorHead)
446
448
  };
447
449
  }
450
+ function normalizeMiddlewareNames(config) {
451
+ if (!config) {
452
+ return [];
453
+ }
454
+ return Array.isArray(config) ? config : [config];
455
+ }
456
+ function isPlainObject(value) {
457
+ if (!value || typeof value !== "object") {
458
+ return false;
459
+ }
460
+ const prototype = Object.getPrototypeOf(value);
461
+ return prototype === Object.prototype || prototype === null;
462
+ }
463
+ function mergeRouteData(currentData, nextData) {
464
+ if (typeof nextData === "undefined") {
465
+ return currentData;
466
+ }
467
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
468
+ return {
469
+ ...currentData,
470
+ ...nextData
471
+ };
472
+ }
473
+ return nextData;
474
+ }
475
+ async function resolveMiddlewares(config, context) {
476
+ const middlewareNames = normalizeMiddlewareNames(config);
477
+ const requiresNamedMiddleware = middlewareNames.length > 0;
478
+ if (!fs.existsSync(middlewaresPath)) {
479
+ if (!requiresNamedMiddleware) {
480
+ return context;
481
+ }
482
+ throw createAbort({
483
+ status: 500,
484
+ message: `Invalid middleware '${middlewareNames[0]}'`
485
+ });
486
+ }
487
+ const middlewareModule = resolveModule(middlewaresPath);
488
+ const registry = middlewareModule.middlewares;
489
+ if (!registry) {
490
+ if (!requiresNamedMiddleware) {
491
+ return context;
492
+ }
493
+ throw createAbort({
494
+ status: 500,
495
+ message: `Invalid middleware '${middlewareNames[0]}'`
496
+ });
497
+ }
498
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
499
+ if (orderedMiddlewareNames.length === 0) {
500
+ return context;
501
+ }
502
+ let nextContext = context;
503
+ for (const middlewareName of orderedMiddlewareNames) {
504
+ const middleware = registry[middlewareName];
505
+ if (typeof middleware !== "function") {
506
+ throw createAbort({
507
+ status: 500,
508
+ message: `Invalid middleware '${middlewareName}'`
509
+ });
510
+ }
511
+ const middlewareData = await middleware(nextContext);
512
+ nextContext = {
513
+ ...nextContext,
514
+ data: mergeRouteData(nextContext.data, middlewareData)
515
+ };
516
+ }
517
+ return nextContext;
518
+ }
448
519
  async function resolve(input) {
449
520
  const pathname = normalizePathname(input.pathname);
450
521
  const contextBase = {
@@ -470,10 +541,12 @@ function createFileRouter(options) {
470
541
  activeContext = context;
471
542
  const pageModule = resolveModule(match.entry.filePath);
472
543
  const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
473
- const pageData = await resolvePageData(pageModule, context);
544
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
545
+ activeContext = middlewareContext;
546
+ const pageData = await resolvePageData(pageModule, middlewareContext);
474
547
  const pageContext = {
475
- ...context,
476
- data: pageData
548
+ ...middlewareContext,
549
+ data: mergeRouteData(middlewareContext.data, pageData)
477
550
  };
478
551
  activeContext = pageContext;
479
552
  const pageNode = await pageModule.default(pageContext);
@@ -776,6 +849,38 @@ function parseCookies(rawCookieHeader) {
776
849
  }
777
850
  return output;
778
851
  }
852
+ function normalizeClientManifest(manifest, options) {
853
+ const normalized = { ...manifest };
854
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
855
+ path3.resolve(options.cwd, "node_modules"),
856
+ path3.resolve(options.distRootDir, "..", "..", "node_modules")
857
+ ]);
858
+ for (const [key, value] of Object.entries(manifest)) {
859
+ if (!key.startsWith("file://")) {
860
+ continue;
861
+ }
862
+ let absolutePath = "";
863
+ try {
864
+ absolutePath = fileURLToPath(key);
865
+ } catch {
866
+ continue;
867
+ }
868
+ const marker = `${path3.sep}node_modules${path3.sep}`;
869
+ const markerIndex = absolutePath.lastIndexOf(marker);
870
+ if (markerIndex < 0) {
871
+ continue;
872
+ }
873
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
874
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
875
+ const aliasPath = path3.join(nodeModulesDir, relativeModulePath);
876
+ const aliasKey = pathToFileURL(aliasPath).href;
877
+ if (!(aliasKey in normalized)) {
878
+ normalized[aliasKey] = value;
879
+ }
880
+ }
881
+ }
882
+ return normalized;
883
+ }
779
884
  function createNodeRequestHandler(options) {
780
885
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
781
886
  const distRootDir = path3.resolve(options.distRootDir);
@@ -793,7 +898,13 @@ function createNodeRequestHandler(options) {
793
898
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
794
899
  const liveReloadClients = /* @__PURE__ */ new Set();
795
900
  const router = createFileRouter({ pagesDir });
796
- const moduleMap = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
901
+ const moduleMap = normalizeClientManifest(
902
+ JSON.parse(fs2.readFileSync(manifestPath, "utf-8")),
903
+ {
904
+ distRootDir,
905
+ cwd: process.cwd()
906
+ }
907
+ );
797
908
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
798
909
  const disposeInitialHtmlWorker = () => {
799
910
  initialHtmlWorker.dispose();
package/dist/index.cjs CHANGED
@@ -462,6 +462,7 @@ function createFileRouter(options) {
462
462
  const pagesDir = options.pagesDir;
463
463
  const layoutPath = import_node_path2.default.join(pagesDir, "layout.js");
464
464
  const errorPath = import_node_path2.default.join(pagesDir, "errors.js");
465
+ const middlewaresPath = import_node_path2.default.join(pagesDir, "middlewares.js");
465
466
  function buildRouteEntries() {
466
467
  const files = walkFiles(pagesDir);
467
468
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -504,6 +505,75 @@ function createFileRouter(options) {
504
505
  head: mergeHead(layoutHead, errorHead)
505
506
  };
506
507
  }
508
+ function normalizeMiddlewareNames(config) {
509
+ if (!config) {
510
+ return [];
511
+ }
512
+ return Array.isArray(config) ? config : [config];
513
+ }
514
+ function isPlainObject(value) {
515
+ if (!value || typeof value !== "object") {
516
+ return false;
517
+ }
518
+ const prototype = Object.getPrototypeOf(value);
519
+ return prototype === Object.prototype || prototype === null;
520
+ }
521
+ function mergeRouteData(currentData, nextData) {
522
+ if (typeof nextData === "undefined") {
523
+ return currentData;
524
+ }
525
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
526
+ return {
527
+ ...currentData,
528
+ ...nextData
529
+ };
530
+ }
531
+ return nextData;
532
+ }
533
+ async function resolveMiddlewares(config, context) {
534
+ const middlewareNames = normalizeMiddlewareNames(config);
535
+ const requiresNamedMiddleware = middlewareNames.length > 0;
536
+ if (!import_node_fs.default.existsSync(middlewaresPath)) {
537
+ if (!requiresNamedMiddleware) {
538
+ return context;
539
+ }
540
+ throw createAbort({
541
+ status: 500,
542
+ message: `Invalid middleware '${middlewareNames[0]}'`
543
+ });
544
+ }
545
+ const middlewareModule = resolveModule(middlewaresPath);
546
+ const registry = middlewareModule.middlewares;
547
+ if (!registry) {
548
+ if (!requiresNamedMiddleware) {
549
+ return context;
550
+ }
551
+ throw createAbort({
552
+ status: 500,
553
+ message: `Invalid middleware '${middlewareNames[0]}'`
554
+ });
555
+ }
556
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
557
+ if (orderedMiddlewareNames.length === 0) {
558
+ return context;
559
+ }
560
+ let nextContext = context;
561
+ for (const middlewareName of orderedMiddlewareNames) {
562
+ const middleware = registry[middlewareName];
563
+ if (typeof middleware !== "function") {
564
+ throw createAbort({
565
+ status: 500,
566
+ message: `Invalid middleware '${middlewareName}'`
567
+ });
568
+ }
569
+ const middlewareData = await middleware(nextContext);
570
+ nextContext = {
571
+ ...nextContext,
572
+ data: mergeRouteData(nextContext.data, middlewareData)
573
+ };
574
+ }
575
+ return nextContext;
576
+ }
507
577
  async function resolve(input) {
508
578
  const pathname = normalizePathname(input.pathname);
509
579
  const contextBase = {
@@ -529,10 +599,12 @@ function createFileRouter(options) {
529
599
  activeContext = context;
530
600
  const pageModule = resolveModule(match.entry.filePath);
531
601
  const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
532
- const pageData = await resolvePageData(pageModule, context);
602
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
603
+ activeContext = middlewareContext;
604
+ const pageData = await resolvePageData(pageModule, middlewareContext);
533
605
  const pageContext = {
534
- ...context,
535
- data: pageData
606
+ ...middlewareContext,
607
+ data: mergeRouteData(middlewareContext.data, pageData)
536
608
  };
537
609
  activeContext = pageContext;
538
610
  const pageNode = await pageModule.default(pageContext);
@@ -565,6 +637,7 @@ function parseSearchParams(query) {
565
637
  // src/http.ts
566
638
  var import_node_fs2 = __toESM(require("node:fs"), 1);
567
639
  var import_node_path3 = __toESM(require("node:path"), 1);
640
+ var import_node_url = require("node:url");
568
641
  var import_node_child_process = require("node:child_process");
569
642
  function createInitialHtmlErrorMarkup(message) {
570
643
  return `<main style="font-family:system-ui,sans-serif;padding:24px"><h1 style="margin:0 0 12px">500</h1><p style="margin:0">${message}</p></main>`;
@@ -838,6 +911,38 @@ function parseCookies(rawCookieHeader) {
838
911
  }
839
912
  return output;
840
913
  }
914
+ function normalizeClientManifest(manifest, options) {
915
+ const normalized = { ...manifest };
916
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
917
+ import_node_path3.default.resolve(options.cwd, "node_modules"),
918
+ import_node_path3.default.resolve(options.distRootDir, "..", "..", "node_modules")
919
+ ]);
920
+ for (const [key, value] of Object.entries(manifest)) {
921
+ if (!key.startsWith("file://")) {
922
+ continue;
923
+ }
924
+ let absolutePath = "";
925
+ try {
926
+ absolutePath = (0, import_node_url.fileURLToPath)(key);
927
+ } catch {
928
+ continue;
929
+ }
930
+ const marker = `${import_node_path3.default.sep}node_modules${import_node_path3.default.sep}`;
931
+ const markerIndex = absolutePath.lastIndexOf(marker);
932
+ if (markerIndex < 0) {
933
+ continue;
934
+ }
935
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
936
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
937
+ const aliasPath = import_node_path3.default.join(nodeModulesDir, relativeModulePath);
938
+ const aliasKey = (0, import_node_url.pathToFileURL)(aliasPath).href;
939
+ if (!(aliasKey in normalized)) {
940
+ normalized[aliasKey] = value;
941
+ }
942
+ }
943
+ }
944
+ return normalized;
945
+ }
841
946
  function createNodeRequestHandler(options) {
842
947
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
843
948
  const distRootDir = import_node_path3.default.resolve(options.distRootDir);
@@ -855,7 +960,13 @@ function createNodeRequestHandler(options) {
855
960
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
856
961
  const liveReloadClients = /* @__PURE__ */ new Set();
857
962
  const router = createFileRouter({ pagesDir });
858
- const moduleMap = JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8"));
963
+ const moduleMap = normalizeClientManifest(
964
+ JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8")),
965
+ {
966
+ distRootDir,
967
+ cwd: process.cwd()
968
+ }
969
+ );
859
970
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
860
971
  const disposeInitialHtmlWorker = () => {
861
972
  initialHtmlWorker.dispose();
package/dist/index.js CHANGED
@@ -426,6 +426,7 @@ function createFileRouter(options) {
426
426
  const pagesDir = options.pagesDir;
427
427
  const layoutPath = path2.join(pagesDir, "layout.js");
428
428
  const errorPath = path2.join(pagesDir, "errors.js");
429
+ const middlewaresPath = path2.join(pagesDir, "middlewares.js");
429
430
  function buildRouteEntries() {
430
431
  const files = walkFiles(pagesDir);
431
432
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -468,6 +469,75 @@ function createFileRouter(options) {
468
469
  head: mergeHead(layoutHead, errorHead)
469
470
  };
470
471
  }
472
+ function normalizeMiddlewareNames(config) {
473
+ if (!config) {
474
+ return [];
475
+ }
476
+ return Array.isArray(config) ? config : [config];
477
+ }
478
+ function isPlainObject(value) {
479
+ if (!value || typeof value !== "object") {
480
+ return false;
481
+ }
482
+ const prototype = Object.getPrototypeOf(value);
483
+ return prototype === Object.prototype || prototype === null;
484
+ }
485
+ function mergeRouteData(currentData, nextData) {
486
+ if (typeof nextData === "undefined") {
487
+ return currentData;
488
+ }
489
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
490
+ return {
491
+ ...currentData,
492
+ ...nextData
493
+ };
494
+ }
495
+ return nextData;
496
+ }
497
+ async function resolveMiddlewares(config, context) {
498
+ const middlewareNames = normalizeMiddlewareNames(config);
499
+ const requiresNamedMiddleware = middlewareNames.length > 0;
500
+ if (!fs.existsSync(middlewaresPath)) {
501
+ if (!requiresNamedMiddleware) {
502
+ return context;
503
+ }
504
+ throw createAbort({
505
+ status: 500,
506
+ message: `Invalid middleware '${middlewareNames[0]}'`
507
+ });
508
+ }
509
+ const middlewareModule = resolveModule(middlewaresPath);
510
+ const registry = middlewareModule.middlewares;
511
+ if (!registry) {
512
+ if (!requiresNamedMiddleware) {
513
+ return context;
514
+ }
515
+ throw createAbort({
516
+ status: 500,
517
+ message: `Invalid middleware '${middlewareNames[0]}'`
518
+ });
519
+ }
520
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
521
+ if (orderedMiddlewareNames.length === 0) {
522
+ return context;
523
+ }
524
+ let nextContext = context;
525
+ for (const middlewareName of orderedMiddlewareNames) {
526
+ const middleware = registry[middlewareName];
527
+ if (typeof middleware !== "function") {
528
+ throw createAbort({
529
+ status: 500,
530
+ message: `Invalid middleware '${middlewareName}'`
531
+ });
532
+ }
533
+ const middlewareData = await middleware(nextContext);
534
+ nextContext = {
535
+ ...nextContext,
536
+ data: mergeRouteData(nextContext.data, middlewareData)
537
+ };
538
+ }
539
+ return nextContext;
540
+ }
471
541
  async function resolve(input) {
472
542
  const pathname = normalizePathname(input.pathname);
473
543
  const contextBase = {
@@ -493,10 +563,12 @@ function createFileRouter(options) {
493
563
  activeContext = context;
494
564
  const pageModule = resolveModule(match.entry.filePath);
495
565
  const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
496
- const pageData = await resolvePageData(pageModule, context);
566
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
567
+ activeContext = middlewareContext;
568
+ const pageData = await resolvePageData(pageModule, middlewareContext);
497
569
  const pageContext = {
498
- ...context,
499
- data: pageData
570
+ ...middlewareContext,
571
+ data: mergeRouteData(middlewareContext.data, pageData)
500
572
  };
501
573
  activeContext = pageContext;
502
574
  const pageNode = await pageModule.default(pageContext);
@@ -529,6 +601,7 @@ function parseSearchParams(query) {
529
601
  // src/http.ts
530
602
  import fs2 from "node:fs";
531
603
  import path3 from "node:path";
604
+ import { fileURLToPath, pathToFileURL } from "node:url";
532
605
  import { spawn } from "node:child_process";
533
606
  function createInitialHtmlErrorMarkup(message) {
534
607
  return `<main style="font-family:system-ui,sans-serif;padding:24px"><h1 style="margin:0 0 12px">500</h1><p style="margin:0">${message}</p></main>`;
@@ -802,6 +875,38 @@ function parseCookies(rawCookieHeader) {
802
875
  }
803
876
  return output;
804
877
  }
878
+ function normalizeClientManifest(manifest, options) {
879
+ const normalized = { ...manifest };
880
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
881
+ path3.resolve(options.cwd, "node_modules"),
882
+ path3.resolve(options.distRootDir, "..", "..", "node_modules")
883
+ ]);
884
+ for (const [key, value] of Object.entries(manifest)) {
885
+ if (!key.startsWith("file://")) {
886
+ continue;
887
+ }
888
+ let absolutePath = "";
889
+ try {
890
+ absolutePath = fileURLToPath(key);
891
+ } catch {
892
+ continue;
893
+ }
894
+ const marker = `${path3.sep}node_modules${path3.sep}`;
895
+ const markerIndex = absolutePath.lastIndexOf(marker);
896
+ if (markerIndex < 0) {
897
+ continue;
898
+ }
899
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
900
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
901
+ const aliasPath = path3.join(nodeModulesDir, relativeModulePath);
902
+ const aliasKey = pathToFileURL(aliasPath).href;
903
+ if (!(aliasKey in normalized)) {
904
+ normalized[aliasKey] = value;
905
+ }
906
+ }
907
+ }
908
+ return normalized;
909
+ }
805
910
  function createNodeRequestHandler(options) {
806
911
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
807
912
  const distRootDir = path3.resolve(options.distRootDir);
@@ -819,7 +924,13 @@ function createNodeRequestHandler(options) {
819
924
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
820
925
  const liveReloadClients = /* @__PURE__ */ new Set();
821
926
  const router = createFileRouter({ pagesDir });
822
- const moduleMap = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
927
+ const moduleMap = normalizeClientManifest(
928
+ JSON.parse(fs2.readFileSync(manifestPath, "utf-8")),
929
+ {
930
+ distRootDir,
931
+ cwd: process.cwd()
932
+ }
933
+ );
823
934
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
824
935
  const disposeInitialHtmlWorker = () => {
825
936
  initialHtmlWorker.dispose();
package/dist/router.cjs CHANGED
@@ -298,6 +298,7 @@ function createFileRouter(options) {
298
298
  const pagesDir = options.pagesDir;
299
299
  const layoutPath = import_node_path.default.join(pagesDir, "layout.js");
300
300
  const errorPath = import_node_path.default.join(pagesDir, "errors.js");
301
+ const middlewaresPath = import_node_path.default.join(pagesDir, "middlewares.js");
301
302
  function buildRouteEntries() {
302
303
  const files = walkFiles(pagesDir);
303
304
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -340,6 +341,75 @@ function createFileRouter(options) {
340
341
  head: mergeHead(layoutHead, errorHead)
341
342
  };
342
343
  }
344
+ function normalizeMiddlewareNames(config) {
345
+ if (!config) {
346
+ return [];
347
+ }
348
+ return Array.isArray(config) ? config : [config];
349
+ }
350
+ function isPlainObject(value) {
351
+ if (!value || typeof value !== "object") {
352
+ return false;
353
+ }
354
+ const prototype = Object.getPrototypeOf(value);
355
+ return prototype === Object.prototype || prototype === null;
356
+ }
357
+ function mergeRouteData(currentData, nextData) {
358
+ if (typeof nextData === "undefined") {
359
+ return currentData;
360
+ }
361
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
362
+ return {
363
+ ...currentData,
364
+ ...nextData
365
+ };
366
+ }
367
+ return nextData;
368
+ }
369
+ async function resolveMiddlewares(config, context) {
370
+ const middlewareNames = normalizeMiddlewareNames(config);
371
+ const requiresNamedMiddleware = middlewareNames.length > 0;
372
+ if (!import_node_fs.default.existsSync(middlewaresPath)) {
373
+ if (!requiresNamedMiddleware) {
374
+ return context;
375
+ }
376
+ throw createAbort({
377
+ status: 500,
378
+ message: `Invalid middleware '${middlewareNames[0]}'`
379
+ });
380
+ }
381
+ const middlewareModule = resolveModule(middlewaresPath);
382
+ const registry = middlewareModule.middlewares;
383
+ if (!registry) {
384
+ if (!requiresNamedMiddleware) {
385
+ return context;
386
+ }
387
+ throw createAbort({
388
+ status: 500,
389
+ message: `Invalid middleware '${middlewareNames[0]}'`
390
+ });
391
+ }
392
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
393
+ if (orderedMiddlewareNames.length === 0) {
394
+ return context;
395
+ }
396
+ let nextContext = context;
397
+ for (const middlewareName of orderedMiddlewareNames) {
398
+ const middleware = registry[middlewareName];
399
+ if (typeof middleware !== "function") {
400
+ throw createAbort({
401
+ status: 500,
402
+ message: `Invalid middleware '${middlewareName}'`
403
+ });
404
+ }
405
+ const middlewareData = await middleware(nextContext);
406
+ nextContext = {
407
+ ...nextContext,
408
+ data: mergeRouteData(nextContext.data, middlewareData)
409
+ };
410
+ }
411
+ return nextContext;
412
+ }
343
413
  async function resolve(input) {
344
414
  const pathname = normalizePathname(input.pathname);
345
415
  const contextBase = {
@@ -365,10 +435,12 @@ function createFileRouter(options) {
365
435
  activeContext = context;
366
436
  const pageModule = resolveModule(match.entry.filePath);
367
437
  const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
368
- const pageData = await resolvePageData(pageModule, context);
438
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
439
+ activeContext = middlewareContext;
440
+ const pageData = await resolvePageData(pageModule, middlewareContext);
369
441
  const pageContext = {
370
- ...context,
371
- data: pageData
442
+ ...middlewareContext,
443
+ data: mergeRouteData(middlewareContext.data, pageData)
372
444
  };
373
445
  activeContext = pageContext;
374
446
  const pageNode = await pageModule.default(pageContext);
package/dist/router.js CHANGED
@@ -268,6 +268,7 @@ function createFileRouter(options) {
268
268
  const pagesDir = options.pagesDir;
269
269
  const layoutPath = path.join(pagesDir, "layout.js");
270
270
  const errorPath = path.join(pagesDir, "errors.js");
271
+ const middlewaresPath = path.join(pagesDir, "middlewares.js");
271
272
  function buildRouteEntries() {
272
273
  const files = walkFiles(pagesDir);
273
274
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -310,6 +311,75 @@ function createFileRouter(options) {
310
311
  head: mergeHead(layoutHead, errorHead)
311
312
  };
312
313
  }
314
+ function normalizeMiddlewareNames(config) {
315
+ if (!config) {
316
+ return [];
317
+ }
318
+ return Array.isArray(config) ? config : [config];
319
+ }
320
+ function isPlainObject(value) {
321
+ if (!value || typeof value !== "object") {
322
+ return false;
323
+ }
324
+ const prototype = Object.getPrototypeOf(value);
325
+ return prototype === Object.prototype || prototype === null;
326
+ }
327
+ function mergeRouteData(currentData, nextData) {
328
+ if (typeof nextData === "undefined") {
329
+ return currentData;
330
+ }
331
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
332
+ return {
333
+ ...currentData,
334
+ ...nextData
335
+ };
336
+ }
337
+ return nextData;
338
+ }
339
+ async function resolveMiddlewares(config, context) {
340
+ const middlewareNames = normalizeMiddlewareNames(config);
341
+ const requiresNamedMiddleware = middlewareNames.length > 0;
342
+ if (!fs.existsSync(middlewaresPath)) {
343
+ if (!requiresNamedMiddleware) {
344
+ return context;
345
+ }
346
+ throw createAbort({
347
+ status: 500,
348
+ message: `Invalid middleware '${middlewareNames[0]}'`
349
+ });
350
+ }
351
+ const middlewareModule = resolveModule(middlewaresPath);
352
+ const registry = middlewareModule.middlewares;
353
+ if (!registry) {
354
+ if (!requiresNamedMiddleware) {
355
+ return context;
356
+ }
357
+ throw createAbort({
358
+ status: 500,
359
+ message: `Invalid middleware '${middlewareNames[0]}'`
360
+ });
361
+ }
362
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
363
+ if (orderedMiddlewareNames.length === 0) {
364
+ return context;
365
+ }
366
+ let nextContext = context;
367
+ for (const middlewareName of orderedMiddlewareNames) {
368
+ const middleware = registry[middlewareName];
369
+ if (typeof middleware !== "function") {
370
+ throw createAbort({
371
+ status: 500,
372
+ message: `Invalid middleware '${middlewareName}'`
373
+ });
374
+ }
375
+ const middlewareData = await middleware(nextContext);
376
+ nextContext = {
377
+ ...nextContext,
378
+ data: mergeRouteData(nextContext.data, middlewareData)
379
+ };
380
+ }
381
+ return nextContext;
382
+ }
313
383
  async function resolve(input) {
314
384
  const pathname = normalizePathname(input.pathname);
315
385
  const contextBase = {
@@ -335,10 +405,12 @@ function createFileRouter(options) {
335
405
  activeContext = context;
336
406
  const pageModule = resolveModule(match.entry.filePath);
337
407
  const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
338
- const pageData = await resolvePageData(pageModule, context);
408
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
409
+ activeContext = middlewareContext;
410
+ const pageData = await resolvePageData(pageModule, middlewareContext);
339
411
  const pageContext = {
340
- ...context,
341
- data: pageData
412
+ ...middlewareContext,
413
+ data: mergeRouteData(middlewareContext.data, pageData)
342
414
  };
343
415
  activeContext = pageContext;
344
416
  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;
@@ -37,6 +37,7 @@ module.exports = __toCommonJS(webframez_core_exports);
37
37
  // src/http.ts
38
38
  var import_node_fs2 = __toESM(require("node:fs"), 1);
39
39
  var import_node_path3 = __toESM(require("node:path"), 1);
40
+ var import_node_url = require("node:url");
40
41
  var import_node_child_process = require("node:child_process");
41
42
 
42
43
  // src/server.ts
@@ -431,6 +432,7 @@ function createFileRouter(options) {
431
432
  const pagesDir = options.pagesDir;
432
433
  const layoutPath = import_node_path2.default.join(pagesDir, "layout.js");
433
434
  const errorPath = import_node_path2.default.join(pagesDir, "errors.js");
435
+ const middlewaresPath = import_node_path2.default.join(pagesDir, "middlewares.js");
434
436
  function buildRouteEntries() {
435
437
  const files = walkFiles(pagesDir);
436
438
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -473,6 +475,75 @@ function createFileRouter(options) {
473
475
  head: mergeHead(layoutHead, errorHead)
474
476
  };
475
477
  }
478
+ function normalizeMiddlewareNames(config) {
479
+ if (!config) {
480
+ return [];
481
+ }
482
+ return Array.isArray(config) ? config : [config];
483
+ }
484
+ function isPlainObject(value) {
485
+ if (!value || typeof value !== "object") {
486
+ return false;
487
+ }
488
+ const prototype = Object.getPrototypeOf(value);
489
+ return prototype === Object.prototype || prototype === null;
490
+ }
491
+ function mergeRouteData(currentData, nextData) {
492
+ if (typeof nextData === "undefined") {
493
+ return currentData;
494
+ }
495
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
496
+ return {
497
+ ...currentData,
498
+ ...nextData
499
+ };
500
+ }
501
+ return nextData;
502
+ }
503
+ async function resolveMiddlewares(config, context) {
504
+ const middlewareNames = normalizeMiddlewareNames(config);
505
+ const requiresNamedMiddleware = middlewareNames.length > 0;
506
+ if (!import_node_fs.default.existsSync(middlewaresPath)) {
507
+ if (!requiresNamedMiddleware) {
508
+ return context;
509
+ }
510
+ throw createAbort({
511
+ status: 500,
512
+ message: `Invalid middleware '${middlewareNames[0]}'`
513
+ });
514
+ }
515
+ const middlewareModule = resolveModule(middlewaresPath);
516
+ const registry = middlewareModule.middlewares;
517
+ if (!registry) {
518
+ if (!requiresNamedMiddleware) {
519
+ return context;
520
+ }
521
+ throw createAbort({
522
+ status: 500,
523
+ message: `Invalid middleware '${middlewareNames[0]}'`
524
+ });
525
+ }
526
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
527
+ if (orderedMiddlewareNames.length === 0) {
528
+ return context;
529
+ }
530
+ let nextContext = context;
531
+ for (const middlewareName of orderedMiddlewareNames) {
532
+ const middleware = registry[middlewareName];
533
+ if (typeof middleware !== "function") {
534
+ throw createAbort({
535
+ status: 500,
536
+ message: `Invalid middleware '${middlewareName}'`
537
+ });
538
+ }
539
+ const middlewareData = await middleware(nextContext);
540
+ nextContext = {
541
+ ...nextContext,
542
+ data: mergeRouteData(nextContext.data, middlewareData)
543
+ };
544
+ }
545
+ return nextContext;
546
+ }
476
547
  async function resolve(input) {
477
548
  const pathname = normalizePathname(input.pathname);
478
549
  const contextBase = {
@@ -498,10 +569,12 @@ function createFileRouter(options) {
498
569
  activeContext = context;
499
570
  const pageModule = resolveModule(match.entry.filePath);
500
571
  const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
501
- const pageData = await resolvePageData(pageModule, context);
572
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
573
+ activeContext = middlewareContext;
574
+ const pageData = await resolvePageData(pageModule, middlewareContext);
502
575
  const pageContext = {
503
- ...context,
504
- data: pageData
576
+ ...middlewareContext,
577
+ data: mergeRouteData(middlewareContext.data, pageData)
505
578
  };
506
579
  activeContext = pageContext;
507
580
  const pageNode = await pageModule.default(pageContext);
@@ -804,6 +877,38 @@ function parseCookies(rawCookieHeader) {
804
877
  }
805
878
  return output;
806
879
  }
880
+ function normalizeClientManifest(manifest, options) {
881
+ const normalized = { ...manifest };
882
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
883
+ import_node_path3.default.resolve(options.cwd, "node_modules"),
884
+ import_node_path3.default.resolve(options.distRootDir, "..", "..", "node_modules")
885
+ ]);
886
+ for (const [key, value] of Object.entries(manifest)) {
887
+ if (!key.startsWith("file://")) {
888
+ continue;
889
+ }
890
+ let absolutePath = "";
891
+ try {
892
+ absolutePath = (0, import_node_url.fileURLToPath)(key);
893
+ } catch {
894
+ continue;
895
+ }
896
+ const marker = `${import_node_path3.default.sep}node_modules${import_node_path3.default.sep}`;
897
+ const markerIndex = absolutePath.lastIndexOf(marker);
898
+ if (markerIndex < 0) {
899
+ continue;
900
+ }
901
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
902
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
903
+ const aliasPath = import_node_path3.default.join(nodeModulesDir, relativeModulePath);
904
+ const aliasKey = (0, import_node_url.pathToFileURL)(aliasPath).href;
905
+ if (!(aliasKey in normalized)) {
906
+ normalized[aliasKey] = value;
907
+ }
908
+ }
909
+ }
910
+ return normalized;
911
+ }
807
912
  function createNodeRequestHandler(options) {
808
913
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
809
914
  const distRootDir = import_node_path3.default.resolve(options.distRootDir);
@@ -821,7 +926,13 @@ function createNodeRequestHandler(options) {
821
926
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
822
927
  const liveReloadClients = /* @__PURE__ */ new Set();
823
928
  const router = createFileRouter({ pagesDir });
824
- const moduleMap = JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8"));
929
+ const moduleMap = normalizeClientManifest(
930
+ JSON.parse(import_node_fs2.default.readFileSync(manifestPath, "utf-8")),
931
+ {
932
+ distRootDir,
933
+ cwd: process.cwd()
934
+ }
935
+ );
825
936
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
826
937
  const disposeInitialHtmlWorker = () => {
827
938
  initialHtmlWorker.dispose();
@@ -9,6 +9,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
9
  // src/http.ts
10
10
  import fs2 from "node:fs";
11
11
  import path3 from "node:path";
12
+ import { fileURLToPath, pathToFileURL } from "node:url";
12
13
  import { spawn } from "node:child_process";
13
14
 
14
15
  // src/server.ts
@@ -403,6 +404,7 @@ function createFileRouter(options) {
403
404
  const pagesDir = options.pagesDir;
404
405
  const layoutPath = path2.join(pagesDir, "layout.js");
405
406
  const errorPath = path2.join(pagesDir, "errors.js");
407
+ const middlewaresPath = path2.join(pagesDir, "middlewares.js");
406
408
  function buildRouteEntries() {
407
409
  const files = walkFiles(pagesDir);
408
410
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -445,6 +447,75 @@ function createFileRouter(options) {
445
447
  head: mergeHead(layoutHead, errorHead)
446
448
  };
447
449
  }
450
+ function normalizeMiddlewareNames(config) {
451
+ if (!config) {
452
+ return [];
453
+ }
454
+ return Array.isArray(config) ? config : [config];
455
+ }
456
+ function isPlainObject(value) {
457
+ if (!value || typeof value !== "object") {
458
+ return false;
459
+ }
460
+ const prototype = Object.getPrototypeOf(value);
461
+ return prototype === Object.prototype || prototype === null;
462
+ }
463
+ function mergeRouteData(currentData, nextData) {
464
+ if (typeof nextData === "undefined") {
465
+ return currentData;
466
+ }
467
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
468
+ return {
469
+ ...currentData,
470
+ ...nextData
471
+ };
472
+ }
473
+ return nextData;
474
+ }
475
+ async function resolveMiddlewares(config, context) {
476
+ const middlewareNames = normalizeMiddlewareNames(config);
477
+ const requiresNamedMiddleware = middlewareNames.length > 0;
478
+ if (!fs.existsSync(middlewaresPath)) {
479
+ if (!requiresNamedMiddleware) {
480
+ return context;
481
+ }
482
+ throw createAbort({
483
+ status: 500,
484
+ message: `Invalid middleware '${middlewareNames[0]}'`
485
+ });
486
+ }
487
+ const middlewareModule = resolveModule(middlewaresPath);
488
+ const registry = middlewareModule.middlewares;
489
+ if (!registry) {
490
+ if (!requiresNamedMiddleware) {
491
+ return context;
492
+ }
493
+ throw createAbort({
494
+ status: 500,
495
+ message: `Invalid middleware '${middlewareNames[0]}'`
496
+ });
497
+ }
498
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
499
+ if (orderedMiddlewareNames.length === 0) {
500
+ return context;
501
+ }
502
+ let nextContext = context;
503
+ for (const middlewareName of orderedMiddlewareNames) {
504
+ const middleware = registry[middlewareName];
505
+ if (typeof middleware !== "function") {
506
+ throw createAbort({
507
+ status: 500,
508
+ message: `Invalid middleware '${middlewareName}'`
509
+ });
510
+ }
511
+ const middlewareData = await middleware(nextContext);
512
+ nextContext = {
513
+ ...nextContext,
514
+ data: mergeRouteData(nextContext.data, middlewareData)
515
+ };
516
+ }
517
+ return nextContext;
518
+ }
448
519
  async function resolve(input) {
449
520
  const pathname = normalizePathname(input.pathname);
450
521
  const contextBase = {
@@ -470,10 +541,12 @@ function createFileRouter(options) {
470
541
  activeContext = context;
471
542
  const pageModule = resolveModule(match.entry.filePath);
472
543
  const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
473
- const pageData = await resolvePageData(pageModule, context);
544
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
545
+ activeContext = middlewareContext;
546
+ const pageData = await resolvePageData(pageModule, middlewareContext);
474
547
  const pageContext = {
475
- ...context,
476
- data: pageData
548
+ ...middlewareContext,
549
+ data: mergeRouteData(middlewareContext.data, pageData)
477
550
  };
478
551
  activeContext = pageContext;
479
552
  const pageNode = await pageModule.default(pageContext);
@@ -776,6 +849,38 @@ function parseCookies(rawCookieHeader) {
776
849
  }
777
850
  return output;
778
851
  }
852
+ function normalizeClientManifest(manifest, options) {
853
+ const normalized = { ...manifest };
854
+ const candidateNodeModulesDirs = /* @__PURE__ */ new Set([
855
+ path3.resolve(options.cwd, "node_modules"),
856
+ path3.resolve(options.distRootDir, "..", "..", "node_modules")
857
+ ]);
858
+ for (const [key, value] of Object.entries(manifest)) {
859
+ if (!key.startsWith("file://")) {
860
+ continue;
861
+ }
862
+ let absolutePath = "";
863
+ try {
864
+ absolutePath = fileURLToPath(key);
865
+ } catch {
866
+ continue;
867
+ }
868
+ const marker = `${path3.sep}node_modules${path3.sep}`;
869
+ const markerIndex = absolutePath.lastIndexOf(marker);
870
+ if (markerIndex < 0) {
871
+ continue;
872
+ }
873
+ const relativeModulePath = absolutePath.slice(markerIndex + marker.length);
874
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
875
+ const aliasPath = path3.join(nodeModulesDir, relativeModulePath);
876
+ const aliasKey = pathToFileURL(aliasPath).href;
877
+ if (!(aliasKey in normalized)) {
878
+ normalized[aliasKey] = value;
879
+ }
880
+ }
881
+ }
882
+ return normalized;
883
+ }
779
884
  function createNodeRequestHandler(options) {
780
885
  const devServerId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
781
886
  const distRootDir = path3.resolve(options.distRootDir);
@@ -793,7 +898,13 @@ function createNodeRequestHandler(options) {
793
898
  const liveReloadPath = !liveReloadEnabled ? "" : options.liveReloadPath ?? `${basePath || ""}/__webframez_live_reload`;
794
899
  const liveReloadClients = /* @__PURE__ */ new Set();
795
900
  const router = createFileRouter({ pagesDir });
796
- const moduleMap = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
901
+ const moduleMap = normalizeClientManifest(
902
+ JSON.parse(fs2.readFileSync(manifestPath, "utf-8")),
903
+ {
904
+ distRootDir,
905
+ cwd: process.cwd()
906
+ }
907
+ );
797
908
  const initialHtmlWorker = createInitialHtmlWorker(pagesDir);
798
909
  const disposeInitialHtmlWorker = () => {
799
910
  initialHtmlWorker.dispose();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-react",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "TypeScript React RSC addition for @webtypen/webframez-core",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "author": {