@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.
@@ -172,6 +172,7 @@ function sendRSC(res, model, options = {}) {
172
172
 
173
173
  // src/file-router.tsx
174
174
  var import_node_fs = __toESM(require("node:fs"), 1);
175
+ var import_node_module2 = __toESM(require("node:module"), 1);
175
176
  var import_node_path2 = __toESM(require("node:path"), 1);
176
177
 
177
178
  // src/router-runtime.tsx
@@ -234,6 +235,26 @@ function injectRouteChildren(node, routeChildren) {
234
235
 
235
236
  // src/file-router.tsx
236
237
  var import_jsx_runtime = require("react/jsx-runtime");
238
+ var ROOT_RUNTIME_REQUIRE = import_node_module2.default.createRequire(
239
+ import_node_path2.default.join(process.cwd(), "__webframez_react_runtime__.js")
240
+ );
241
+ var FORCED_PACKAGE_REQUESTS = [
242
+ "@webtypen/webframez-core",
243
+ "@webtypen/webframez-react",
244
+ "react",
245
+ "react/jsx-runtime",
246
+ "react/jsx-dev-runtime",
247
+ "react-dom",
248
+ "react-dom/client",
249
+ "react-dom/server",
250
+ "react-dom/server.node",
251
+ "react-server-dom-webpack",
252
+ "react-server-dom-webpack/server",
253
+ "react-server-dom-webpack/client",
254
+ "react-server-dom-webpack/client.node",
255
+ "scheduler"
256
+ ];
257
+ var forcedPackageResolutionInstalled = false;
237
258
  function normalizePathname(pathname) {
238
259
  const trimmed = pathname.replace(/\/+$/, "") || "/";
239
260
  return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
@@ -282,6 +303,28 @@ var MANAGED_HEAD_ATTR = "data-webframez-head";
282
303
  function createManagedAttributes() {
283
304
  return `${MANAGED_HEAD_ATTR}="true"`;
284
305
  }
306
+ function shouldForcePackageResolution(request) {
307
+ return FORCED_PACKAGE_REQUESTS.some(
308
+ (candidate) => request === candidate || request.startsWith(`${candidate}/`)
309
+ );
310
+ }
311
+ function installForcedPackageResolution() {
312
+ if (forcedPackageResolutionInstalled) {
313
+ return;
314
+ }
315
+ const moduleWithPrivateResolver = import_node_module2.default;
316
+ const originalResolveFilename = moduleWithPrivateResolver._resolveFilename;
317
+ moduleWithPrivateResolver._resolveFilename = function patchedResolveFilename(request, parent, isMain, options) {
318
+ if (typeof request === "string" && shouldForcePackageResolution(request)) {
319
+ try {
320
+ return ROOT_RUNTIME_REQUIRE.resolve(request);
321
+ } catch {
322
+ }
323
+ }
324
+ return originalResolveFilename.call(this, request, parent, isMain, options);
325
+ };
326
+ forcedPackageResolutionInstalled = true;
327
+ }
285
328
  function toRouteEntry(pagesDir, filePath) {
286
329
  const normalized = filePath.replace(/\\/g, "/");
287
330
  if (!normalized.endsWith("/index.js")) {
@@ -429,9 +472,11 @@ function isRouteAbort(value) {
429
472
  }
430
473
  }
431
474
  function createFileRouter(options) {
475
+ installForcedPackageResolution();
432
476
  const pagesDir = options.pagesDir;
433
477
  const layoutPath = import_node_path2.default.join(pagesDir, "layout.js");
434
478
  const errorPath = import_node_path2.default.join(pagesDir, "errors.js");
479
+ const middlewaresPath = import_node_path2.default.join(pagesDir, "middlewares.js");
435
480
  function buildRouteEntries() {
436
481
  const files = walkFiles(pagesDir);
437
482
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -474,6 +519,75 @@ function createFileRouter(options) {
474
519
  head: mergeHead(layoutHead, errorHead)
475
520
  };
476
521
  }
522
+ function normalizeMiddlewareNames(config) {
523
+ if (!config) {
524
+ return [];
525
+ }
526
+ return Array.isArray(config) ? config : [config];
527
+ }
528
+ function isPlainObject(value) {
529
+ if (!value || typeof value !== "object") {
530
+ return false;
531
+ }
532
+ const prototype = Object.getPrototypeOf(value);
533
+ return prototype === Object.prototype || prototype === null;
534
+ }
535
+ function mergeRouteData(currentData, nextData) {
536
+ if (typeof nextData === "undefined") {
537
+ return currentData;
538
+ }
539
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
540
+ return {
541
+ ...currentData,
542
+ ...nextData
543
+ };
544
+ }
545
+ return nextData;
546
+ }
547
+ async function resolveMiddlewares(config, context) {
548
+ const middlewareNames = normalizeMiddlewareNames(config);
549
+ const requiresNamedMiddleware = middlewareNames.length > 0;
550
+ if (!import_node_fs.default.existsSync(middlewaresPath)) {
551
+ if (!requiresNamedMiddleware) {
552
+ return context;
553
+ }
554
+ throw createAbort({
555
+ status: 500,
556
+ message: `Invalid middleware '${middlewareNames[0]}'`
557
+ });
558
+ }
559
+ const middlewareModule = resolveModule(middlewaresPath);
560
+ const registry = middlewareModule.middlewares;
561
+ if (!registry) {
562
+ if (!requiresNamedMiddleware) {
563
+ return context;
564
+ }
565
+ throw createAbort({
566
+ status: 500,
567
+ message: `Invalid middleware '${middlewareNames[0]}'`
568
+ });
569
+ }
570
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
571
+ if (orderedMiddlewareNames.length === 0) {
572
+ return context;
573
+ }
574
+ let nextContext = context;
575
+ for (const middlewareName of orderedMiddlewareNames) {
576
+ const middleware = registry[middlewareName];
577
+ if (typeof middleware !== "function") {
578
+ throw createAbort({
579
+ status: 500,
580
+ message: `Invalid middleware '${middlewareName}'`
581
+ });
582
+ }
583
+ const middlewareData = await middleware(nextContext);
584
+ nextContext = {
585
+ ...nextContext,
586
+ data: mergeRouteData(nextContext.data, middlewareData)
587
+ };
588
+ }
589
+ return nextContext;
590
+ }
477
591
  async function resolve(input) {
478
592
  const pathname = normalizePathname(input.pathname);
479
593
  const contextBase = {
@@ -499,10 +613,12 @@ function createFileRouter(options) {
499
613
  activeContext = context;
500
614
  const pageModule = resolveModule(match.entry.filePath);
501
615
  const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
502
- const pageData = await resolvePageData(pageModule, context);
616
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
617
+ activeContext = middlewareContext;
618
+ const pageData = await resolvePageData(pageModule, middlewareContext);
503
619
  const pageContext = {
504
- ...context,
505
- data: pageData
620
+ ...middlewareContext,
621
+ data: mergeRouteData(middlewareContext.data, pageData)
506
622
  };
507
623
  activeContext = pageContext;
508
624
  const pageNode = await pageModule.default(pageContext);
@@ -546,19 +662,34 @@ if (!pagesDir) {
546
662
  throw new Error("Missing WEBFRAMEZ_REACT_PAGES_DIR");
547
663
  }
548
664
 
549
- const appRequire = Module.createRequire(path.join(pagesDir, "__webframez_react_worker__.js"));
665
+ const rootRequire = Module.createRequire(path.join(process.cwd(), "__webframez_react_worker__.js"));
550
666
  const originalResolveFilename = Module._resolveFilename;
551
667
  const forcedResolutions = new Map([
552
- ["react", appRequire.resolve("react")],
553
- ["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
554
- ["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
555
- ["react-dom/client", appRequire.resolve("react-dom/client")]
668
+ ["@webtypen/webframez-core", rootRequire.resolve("@webtypen/webframez-core")],
669
+ ["@webtypen/webframez-react", rootRequire.resolve("@webtypen/webframez-react")],
670
+ ["react", rootRequire.resolve("react")],
671
+ ["react/jsx-runtime", rootRequire.resolve("react/jsx-runtime")],
672
+ ["react/jsx-dev-runtime", rootRequire.resolve("react/jsx-dev-runtime")],
673
+ ["react-dom", rootRequire.resolve("react-dom")],
674
+ ["react-dom/client", rootRequire.resolve("react-dom/client")],
675
+ ["react-dom/server", rootRequire.resolve("react-dom/server")],
676
+ ["react-dom/server.node", rootRequire.resolve("react-dom/server.node")],
677
+ ["react-server-dom-webpack", rootRequire.resolve("react-server-dom-webpack")],
678
+ ["react-server-dom-webpack/server", rootRequire.resolve("react-server-dom-webpack/server")],
679
+ ["react-server-dom-webpack/client", rootRequire.resolve("react-server-dom-webpack/client")],
680
+ ["react-server-dom-webpack/client.node", rootRequire.resolve("react-server-dom-webpack/client.node")],
681
+ ["scheduler", rootRequire.resolve("scheduler")]
556
682
  ]);
557
683
 
558
684
  Module._resolveFilename = function(request, parent, isMain, options) {
559
685
  if (forcedResolutions.has(request)) {
560
686
  return forcedResolutions.get(request);
561
687
  }
688
+ for (const forcedRequest of forcedResolutions.keys()) {
689
+ if (request.startsWith(forcedRequest + "/")) {
690
+ return rootRequire.resolve(request);
691
+ }
692
+ }
562
693
  return originalResolveFilename.call(this, request, parent, isMain, options);
563
694
  };
564
695
 
@@ -144,6 +144,7 @@ function sendRSC(res, model, options = {}) {
144
144
 
145
145
  // src/file-router.tsx
146
146
  import fs from "node:fs";
147
+ import Module from "node:module";
147
148
  import path2 from "node:path";
148
149
 
149
150
  // src/router-runtime.tsx
@@ -206,6 +207,26 @@ function injectRouteChildren(node, routeChildren) {
206
207
 
207
208
  // src/file-router.tsx
208
209
  import { jsx, jsxs } from "react/jsx-runtime";
210
+ var ROOT_RUNTIME_REQUIRE = Module.createRequire(
211
+ path2.join(process.cwd(), "__webframez_react_runtime__.js")
212
+ );
213
+ var FORCED_PACKAGE_REQUESTS = [
214
+ "@webtypen/webframez-core",
215
+ "@webtypen/webframez-react",
216
+ "react",
217
+ "react/jsx-runtime",
218
+ "react/jsx-dev-runtime",
219
+ "react-dom",
220
+ "react-dom/client",
221
+ "react-dom/server",
222
+ "react-dom/server.node",
223
+ "react-server-dom-webpack",
224
+ "react-server-dom-webpack/server",
225
+ "react-server-dom-webpack/client",
226
+ "react-server-dom-webpack/client.node",
227
+ "scheduler"
228
+ ];
229
+ var forcedPackageResolutionInstalled = false;
209
230
  function normalizePathname(pathname) {
210
231
  const trimmed = pathname.replace(/\/+$/, "") || "/";
211
232
  return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
@@ -254,6 +275,28 @@ var MANAGED_HEAD_ATTR = "data-webframez-head";
254
275
  function createManagedAttributes() {
255
276
  return `${MANAGED_HEAD_ATTR}="true"`;
256
277
  }
278
+ function shouldForcePackageResolution(request) {
279
+ return FORCED_PACKAGE_REQUESTS.some(
280
+ (candidate) => request === candidate || request.startsWith(`${candidate}/`)
281
+ );
282
+ }
283
+ function installForcedPackageResolution() {
284
+ if (forcedPackageResolutionInstalled) {
285
+ return;
286
+ }
287
+ const moduleWithPrivateResolver = Module;
288
+ const originalResolveFilename = moduleWithPrivateResolver._resolveFilename;
289
+ moduleWithPrivateResolver._resolveFilename = function patchedResolveFilename(request, parent, isMain, options) {
290
+ if (typeof request === "string" && shouldForcePackageResolution(request)) {
291
+ try {
292
+ return ROOT_RUNTIME_REQUIRE.resolve(request);
293
+ } catch {
294
+ }
295
+ }
296
+ return originalResolveFilename.call(this, request, parent, isMain, options);
297
+ };
298
+ forcedPackageResolutionInstalled = true;
299
+ }
257
300
  function toRouteEntry(pagesDir, filePath) {
258
301
  const normalized = filePath.replace(/\\/g, "/");
259
302
  if (!normalized.endsWith("/index.js")) {
@@ -401,9 +444,11 @@ function isRouteAbort(value) {
401
444
  }
402
445
  }
403
446
  function createFileRouter(options) {
447
+ installForcedPackageResolution();
404
448
  const pagesDir = options.pagesDir;
405
449
  const layoutPath = path2.join(pagesDir, "layout.js");
406
450
  const errorPath = path2.join(pagesDir, "errors.js");
451
+ const middlewaresPath = path2.join(pagesDir, "middlewares.js");
407
452
  function buildRouteEntries() {
408
453
  const files = walkFiles(pagesDir);
409
454
  return files.map((filePath) => toRouteEntry(pagesDir, filePath)).filter((entry) => entry !== null).sort((a, b) => {
@@ -446,6 +491,75 @@ function createFileRouter(options) {
446
491
  head: mergeHead(layoutHead, errorHead)
447
492
  };
448
493
  }
494
+ function normalizeMiddlewareNames(config) {
495
+ if (!config) {
496
+ return [];
497
+ }
498
+ return Array.isArray(config) ? config : [config];
499
+ }
500
+ function isPlainObject(value) {
501
+ if (!value || typeof value !== "object") {
502
+ return false;
503
+ }
504
+ const prototype = Object.getPrototypeOf(value);
505
+ return prototype === Object.prototype || prototype === null;
506
+ }
507
+ function mergeRouteData(currentData, nextData) {
508
+ if (typeof nextData === "undefined") {
509
+ return currentData;
510
+ }
511
+ if (isPlainObject(currentData) && isPlainObject(nextData)) {
512
+ return {
513
+ ...currentData,
514
+ ...nextData
515
+ };
516
+ }
517
+ return nextData;
518
+ }
519
+ async function resolveMiddlewares(config, context) {
520
+ const middlewareNames = normalizeMiddlewareNames(config);
521
+ const requiresNamedMiddleware = middlewareNames.length > 0;
522
+ if (!fs.existsSync(middlewaresPath)) {
523
+ if (!requiresNamedMiddleware) {
524
+ return context;
525
+ }
526
+ throw createAbort({
527
+ status: 500,
528
+ message: `Invalid middleware '${middlewareNames[0]}'`
529
+ });
530
+ }
531
+ const middlewareModule = resolveModule(middlewaresPath);
532
+ const registry = middlewareModule.middlewares;
533
+ if (!registry) {
534
+ if (!requiresNamedMiddleware) {
535
+ return context;
536
+ }
537
+ throw createAbort({
538
+ status: 500,
539
+ message: `Invalid middleware '${middlewareNames[0]}'`
540
+ });
541
+ }
542
+ const orderedMiddlewareNames = typeof registry["*"] === "function" ? ["*", ...middlewareNames] : middlewareNames;
543
+ if (orderedMiddlewareNames.length === 0) {
544
+ return context;
545
+ }
546
+ let nextContext = context;
547
+ for (const middlewareName of orderedMiddlewareNames) {
548
+ const middleware = registry[middlewareName];
549
+ if (typeof middleware !== "function") {
550
+ throw createAbort({
551
+ status: 500,
552
+ message: `Invalid middleware '${middlewareName}'`
553
+ });
554
+ }
555
+ const middlewareData = await middleware(nextContext);
556
+ nextContext = {
557
+ ...nextContext,
558
+ data: mergeRouteData(nextContext.data, middlewareData)
559
+ };
560
+ }
561
+ return nextContext;
562
+ }
449
563
  async function resolve(input) {
450
564
  const pathname = normalizePathname(input.pathname);
451
565
  const contextBase = {
@@ -471,10 +585,12 @@ function createFileRouter(options) {
471
585
  activeContext = context;
472
586
  const pageModule = resolveModule(match.entry.filePath);
473
587
  const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
474
- const pageData = await resolvePageData(pageModule, context);
588
+ const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
589
+ activeContext = middlewareContext;
590
+ const pageData = await resolvePageData(pageModule, middlewareContext);
475
591
  const pageContext = {
476
- ...context,
477
- data: pageData
592
+ ...middlewareContext,
593
+ data: mergeRouteData(middlewareContext.data, pageData)
478
594
  };
479
595
  activeContext = pageContext;
480
596
  const pageNode = await pageModule.default(pageContext);
@@ -518,19 +634,34 @@ if (!pagesDir) {
518
634
  throw new Error("Missing WEBFRAMEZ_REACT_PAGES_DIR");
519
635
  }
520
636
 
521
- const appRequire = Module.createRequire(path.join(pagesDir, "__webframez_react_worker__.js"));
637
+ const rootRequire = Module.createRequire(path.join(process.cwd(), "__webframez_react_worker__.js"));
522
638
  const originalResolveFilename = Module._resolveFilename;
523
639
  const forcedResolutions = new Map([
524
- ["react", appRequire.resolve("react")],
525
- ["react/jsx-runtime", appRequire.resolve("react/jsx-runtime")],
526
- ["react/jsx-dev-runtime", appRequire.resolve("react/jsx-dev-runtime")],
527
- ["react-dom/client", appRequire.resolve("react-dom/client")]
640
+ ["@webtypen/webframez-core", rootRequire.resolve("@webtypen/webframez-core")],
641
+ ["@webtypen/webframez-react", rootRequire.resolve("@webtypen/webframez-react")],
642
+ ["react", rootRequire.resolve("react")],
643
+ ["react/jsx-runtime", rootRequire.resolve("react/jsx-runtime")],
644
+ ["react/jsx-dev-runtime", rootRequire.resolve("react/jsx-dev-runtime")],
645
+ ["react-dom", rootRequire.resolve("react-dom")],
646
+ ["react-dom/client", rootRequire.resolve("react-dom/client")],
647
+ ["react-dom/server", rootRequire.resolve("react-dom/server")],
648
+ ["react-dom/server.node", rootRequire.resolve("react-dom/server.node")],
649
+ ["react-server-dom-webpack", rootRequire.resolve("react-server-dom-webpack")],
650
+ ["react-server-dom-webpack/server", rootRequire.resolve("react-server-dom-webpack/server")],
651
+ ["react-server-dom-webpack/client", rootRequire.resolve("react-server-dom-webpack/client")],
652
+ ["react-server-dom-webpack/client.node", rootRequire.resolve("react-server-dom-webpack/client.node")],
653
+ ["scheduler", rootRequire.resolve("scheduler")]
528
654
  ]);
529
655
 
530
656
  Module._resolveFilename = function(request, parent, isMain, options) {
531
657
  if (forcedResolutions.has(request)) {
532
658
  return forcedResolutions.get(request);
533
659
  }
660
+ for (const forcedRequest of forcedResolutions.keys()) {
661
+ if (request.startsWith(forcedRequest + "/")) {
662
+ return rootRequire.resolve(request);
663
+ }
664
+ }
534
665
  return originalResolveFilename.call(this, request, parent, isMain, options);
535
666
  };
536
667
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-react",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "TypeScript React RSC addition for @webtypen/webframez-core",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "author": {