@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 +115 -4
- package/dist/http.js +115 -4
- package/dist/index.cjs +115 -4
- package/dist/index.js +115 -4
- package/dist/router.cjs +75 -3
- package/dist/router.js +75 -3
- package/dist/types.d.ts +10 -0
- package/dist/webframez-core.cjs +115 -4
- package/dist/webframez-core.js +115 -4
- package/package.json +1 -1
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
|
|
569
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
570
|
+
activeContext = middlewareContext;
|
|
571
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
499
572
|
const pageContext = {
|
|
500
|
-
...
|
|
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 =
|
|
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
|
|
544
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
545
|
+
activeContext = middlewareContext;
|
|
546
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
474
547
|
const pageContext = {
|
|
475
|
-
...
|
|
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 =
|
|
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
|
|
602
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
603
|
+
activeContext = middlewareContext;
|
|
604
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
533
605
|
const pageContext = {
|
|
534
|
-
...
|
|
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 =
|
|
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
|
|
566
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
567
|
+
activeContext = middlewareContext;
|
|
568
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
497
569
|
const pageContext = {
|
|
498
|
-
...
|
|
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 =
|
|
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
|
|
438
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
439
|
+
activeContext = middlewareContext;
|
|
440
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
369
441
|
const pageContext = {
|
|
370
|
-
...
|
|
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
|
|
408
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
409
|
+
activeContext = middlewareContext;
|
|
410
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
339
411
|
const pageContext = {
|
|
340
|
-
...
|
|
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;
|
package/dist/webframez-core.cjs
CHANGED
|
@@ -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
|
|
572
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
573
|
+
activeContext = middlewareContext;
|
|
574
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
502
575
|
const pageContext = {
|
|
503
|
-
...
|
|
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 =
|
|
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();
|
package/dist/webframez-core.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
|
|
544
|
+
const middlewareContext = await resolveMiddlewares(pageModule.middlewares, context);
|
|
545
|
+
activeContext = middlewareContext;
|
|
546
|
+
const pageData = await resolvePageData(pageModule, middlewareContext);
|
|
474
547
|
const pageContext = {
|
|
475
|
-
...
|
|
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 =
|
|
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();
|