@lolyjs/core 0.2.0-alpha.27 → 0.2.0-alpha.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -0
- package/dist/cli.cjs +904 -315
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +898 -309
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +916 -316
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +910 -310
- package/dist/index.js.map +1 -1
- package/dist/{index.types-DMOO-uvF.d.mts → index.types-B9j4OQft.d.mts} +1 -0
- package/dist/{index.types-DMOO-uvF.d.ts → index.types-B9j4OQft.d.ts} +1 -0
- package/dist/react/cache.cjs.map +1 -1
- package/dist/react/cache.d.mts +3 -1
- package/dist/react/cache.d.ts +3 -1
- package/dist/react/cache.js.map +1 -1
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/components.js.map +1 -1
- package/dist/runtime.cjs +16 -5
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +16 -5
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9871,8 +9871,8 @@ var require_built3 = __commonJS({
|
|
|
9871
9871
|
});
|
|
9872
9872
|
|
|
9873
9873
|
// src/server.ts
|
|
9874
|
-
import
|
|
9875
|
-
import
|
|
9874
|
+
import fs19 from "fs";
|
|
9875
|
+
import path25 from "path";
|
|
9876
9876
|
|
|
9877
9877
|
// modules/server/utils/server-dir.ts
|
|
9878
9878
|
init_globals();
|
|
@@ -9912,8 +9912,8 @@ async function runInitIfExists(projectRoot, serverData) {
|
|
|
9912
9912
|
|
|
9913
9913
|
// modules/server/setup.ts
|
|
9914
9914
|
import express from "express";
|
|
9915
|
-
import
|
|
9916
|
-
import
|
|
9915
|
+
import path19 from "path";
|
|
9916
|
+
import fs17 from "fs";
|
|
9917
9917
|
|
|
9918
9918
|
// modules/router/loader-pages.ts
|
|
9919
9919
|
import fs4 from "fs";
|
|
@@ -9924,10 +9924,17 @@ var PAGE_FILE_REGEX = /^page\.(tsx|ts|jsx|js)$/;
|
|
|
9924
9924
|
var LAYOUT_FILE_BASENAME = "layout";
|
|
9925
9925
|
|
|
9926
9926
|
// modules/router/path.ts
|
|
9927
|
+
function isRouteGroup(dirName) {
|
|
9928
|
+
return dirName.startsWith("(") && dirName.endsWith(")");
|
|
9929
|
+
}
|
|
9927
9930
|
function buildRoutePathFromDir(relDir) {
|
|
9928
9931
|
if (!relDir || relDir === ".") return "/";
|
|
9929
9932
|
const clean = relDir.replace(/\\/g, "/");
|
|
9930
|
-
|
|
9933
|
+
const segments = clean.split("/").filter((seg) => {
|
|
9934
|
+
return !isRouteGroup(seg);
|
|
9935
|
+
});
|
|
9936
|
+
if (segments.length === 0) return "/";
|
|
9937
|
+
return "/" + segments.join("/");
|
|
9931
9938
|
}
|
|
9932
9939
|
function buildRegexFromRoutePath(routePath) {
|
|
9933
9940
|
const segments = routePath.split("/").filter(Boolean);
|
|
@@ -10143,13 +10150,17 @@ function validateRoutes(routes, appDir) {
|
|
|
10143
10150
|
}
|
|
10144
10151
|
for (const [pattern, duplicateRoutes] of routePatterns.entries()) {
|
|
10145
10152
|
if (duplicateRoutes.length > 1) {
|
|
10146
|
-
const files = duplicateRoutes.map(
|
|
10147
|
-
|
|
10148
|
-
|
|
10153
|
+
const files = duplicateRoutes.map((r) => {
|
|
10154
|
+
const relPath = r.pageFile ? path4.relative(appDir, r.pageFile) : "unknown";
|
|
10155
|
+
const segments = relPath.split(path4.sep);
|
|
10156
|
+
const hasRouteGroup = segments.some((seg) => isRouteGroup(seg));
|
|
10157
|
+
return hasRouteGroup ? `${relPath} (inside route group)` : relPath;
|
|
10158
|
+
}).join(", ");
|
|
10149
10159
|
errors.push(
|
|
10150
10160
|
`Duplicate route pattern "${pattern}" found in multiple files:
|
|
10151
10161
|
${files}
|
|
10152
|
-
\u{1F4A1} Suggestion:
|
|
10162
|
+
\u{1F4A1} Suggestion: Route groups (directories in parentheses) don't appear in URLs.
|
|
10163
|
+
Ensure each route has a unique path pattern after route groups are ignored.`
|
|
10153
10164
|
);
|
|
10154
10165
|
}
|
|
10155
10166
|
}
|
|
@@ -10426,12 +10437,13 @@ function loadApiRoutes(appDir) {
|
|
|
10426
10437
|
|
|
10427
10438
|
// modules/router/matcher.ts
|
|
10428
10439
|
function matchRoute(routes, urlPath) {
|
|
10440
|
+
const normalizedPath = urlPath.replace(/\/$/, "") || "/";
|
|
10429
10441
|
for (const route of routes) {
|
|
10430
|
-
const match = route.regex.exec(
|
|
10442
|
+
const match = route.regex.exec(normalizedPath);
|
|
10431
10443
|
if (!match) continue;
|
|
10432
10444
|
const params = {};
|
|
10433
10445
|
route.paramNames.forEach((name, idx) => {
|
|
10434
|
-
params[name] = match[idx + 1];
|
|
10446
|
+
params[name] = decodeURIComponent(match[idx + 1] || "");
|
|
10435
10447
|
});
|
|
10436
10448
|
return { route, params };
|
|
10437
10449
|
}
|
|
@@ -11441,34 +11453,504 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
11441
11453
|
};
|
|
11442
11454
|
}
|
|
11443
11455
|
|
|
11456
|
+
// modules/router/rewrites.ts
|
|
11457
|
+
function parseRewritePattern(pattern) {
|
|
11458
|
+
const cleanPattern = pattern.replace(/^\/+|\/+$/g, "") || "";
|
|
11459
|
+
if (!cleanPattern) {
|
|
11460
|
+
return {
|
|
11461
|
+
regex: /^\/?$/,
|
|
11462
|
+
paramNames: []
|
|
11463
|
+
};
|
|
11464
|
+
}
|
|
11465
|
+
const segments = cleanPattern.split("/").filter(Boolean);
|
|
11466
|
+
const paramNames = [];
|
|
11467
|
+
const regexParts = [];
|
|
11468
|
+
for (let i = 0; i < segments.length; i++) {
|
|
11469
|
+
const seg = segments[i];
|
|
11470
|
+
if (seg === "*") {
|
|
11471
|
+
if (i !== segments.length - 1) {
|
|
11472
|
+
throw new Error(
|
|
11473
|
+
`Catch-all "*" in "${pattern}" must be the last segment.`
|
|
11474
|
+
);
|
|
11475
|
+
}
|
|
11476
|
+
regexParts.push("(.+)");
|
|
11477
|
+
continue;
|
|
11478
|
+
}
|
|
11479
|
+
if (seg.endsWith("*") && seg.startsWith(":")) {
|
|
11480
|
+
const paramName = seg.slice(1, -1);
|
|
11481
|
+
if (i !== segments.length - 1) {
|
|
11482
|
+
throw new Error(
|
|
11483
|
+
`Catch-all segment "${seg}" in "${pattern}" must be the last segment.`
|
|
11484
|
+
);
|
|
11485
|
+
}
|
|
11486
|
+
paramNames.push(paramName);
|
|
11487
|
+
regexParts.push("(.+)");
|
|
11488
|
+
continue;
|
|
11489
|
+
}
|
|
11490
|
+
if (seg.startsWith(":") && seg.length > 1) {
|
|
11491
|
+
const paramName = seg.slice(1);
|
|
11492
|
+
paramNames.push(paramName);
|
|
11493
|
+
regexParts.push("([^/]+)");
|
|
11494
|
+
continue;
|
|
11495
|
+
}
|
|
11496
|
+
const escaped = seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11497
|
+
regexParts.push(escaped);
|
|
11498
|
+
}
|
|
11499
|
+
const regexSource = "^/?" + regexParts.join("/") + "/?$";
|
|
11500
|
+
const regex = new RegExp(regexSource);
|
|
11501
|
+
return { regex, paramNames };
|
|
11502
|
+
}
|
|
11503
|
+
function extractHostParams(hostPattern, actualHost) {
|
|
11504
|
+
const regexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
11505
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
11506
|
+
const match = regex.exec(actualHost);
|
|
11507
|
+
if (!match) return null;
|
|
11508
|
+
const paramNames = [];
|
|
11509
|
+
const paramPattern = /:([^.]+)/g;
|
|
11510
|
+
let paramMatch;
|
|
11511
|
+
while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
|
|
11512
|
+
paramNames.push(paramMatch[1]);
|
|
11513
|
+
}
|
|
11514
|
+
const params = {};
|
|
11515
|
+
paramNames.forEach((name, idx) => {
|
|
11516
|
+
params[name] = match[idx + 1] || "";
|
|
11517
|
+
});
|
|
11518
|
+
return params;
|
|
11519
|
+
}
|
|
11520
|
+
function evaluateRewriteConditions(conditions, req) {
|
|
11521
|
+
const extractedParams = {};
|
|
11522
|
+
for (const condition of conditions) {
|
|
11523
|
+
switch (condition.type) {
|
|
11524
|
+
case "host": {
|
|
11525
|
+
const hostWithPort = req.get("host") || req.hostname || req.get("x-forwarded-host")?.split(",")[0] || "";
|
|
11526
|
+
const host = hostWithPort.split(":")[0];
|
|
11527
|
+
if (process.env.NODE_ENV === "development") {
|
|
11528
|
+
console.log("[rewrites] Host matching:", {
|
|
11529
|
+
pattern: condition.value,
|
|
11530
|
+
actualHost: host,
|
|
11531
|
+
hostWithPort,
|
|
11532
|
+
reqHost: req.get("host"),
|
|
11533
|
+
reqHostname: req.hostname
|
|
11534
|
+
});
|
|
11535
|
+
}
|
|
11536
|
+
const hostParams = extractHostParams(condition.value, host);
|
|
11537
|
+
if (!hostParams) {
|
|
11538
|
+
if (process.env.NODE_ENV === "development") {
|
|
11539
|
+
console.log("[rewrites] Host params extraction failed:", {
|
|
11540
|
+
pattern: condition.value,
|
|
11541
|
+
actualHost: host
|
|
11542
|
+
});
|
|
11543
|
+
}
|
|
11544
|
+
return { matches: false, params: {} };
|
|
11545
|
+
}
|
|
11546
|
+
Object.assign(extractedParams, hostParams);
|
|
11547
|
+
break;
|
|
11548
|
+
}
|
|
11549
|
+
case "header": {
|
|
11550
|
+
if (!condition.key) {
|
|
11551
|
+
return { matches: false, params: {} };
|
|
11552
|
+
}
|
|
11553
|
+
const headerValue = req.get(condition.key.toLowerCase());
|
|
11554
|
+
if (!headerValue || headerValue !== condition.value) {
|
|
11555
|
+
return { matches: false, params: {} };
|
|
11556
|
+
}
|
|
11557
|
+
break;
|
|
11558
|
+
}
|
|
11559
|
+
case "cookie": {
|
|
11560
|
+
if (!condition.key) {
|
|
11561
|
+
return { matches: false, params: {} };
|
|
11562
|
+
}
|
|
11563
|
+
const cookieValue = req.cookies?.[condition.key];
|
|
11564
|
+
if (!cookieValue || cookieValue !== condition.value) {
|
|
11565
|
+
return { matches: false, params: {} };
|
|
11566
|
+
}
|
|
11567
|
+
break;
|
|
11568
|
+
}
|
|
11569
|
+
case "query": {
|
|
11570
|
+
if (!condition.key) {
|
|
11571
|
+
return { matches: false, params: {} };
|
|
11572
|
+
}
|
|
11573
|
+
const queryValue = req.query[condition.key];
|
|
11574
|
+
if (!queryValue || String(queryValue) !== condition.value) {
|
|
11575
|
+
return { matches: false, params: {} };
|
|
11576
|
+
}
|
|
11577
|
+
break;
|
|
11578
|
+
}
|
|
11579
|
+
default:
|
|
11580
|
+
return { matches: false, params: {} };
|
|
11581
|
+
}
|
|
11582
|
+
}
|
|
11583
|
+
return { matches: true, params: extractedParams };
|
|
11584
|
+
}
|
|
11585
|
+
function replaceDestinationParams(destination, params) {
|
|
11586
|
+
let result = destination;
|
|
11587
|
+
for (const [key, value] of Object.entries(params)) {
|
|
11588
|
+
const pattern = new RegExp(`:${key}(?:\\*)?`, "g");
|
|
11589
|
+
result = result.replace(pattern, value);
|
|
11590
|
+
}
|
|
11591
|
+
return result;
|
|
11592
|
+
}
|
|
11593
|
+
async function processRewrites(urlPath, compiledRewrites, req) {
|
|
11594
|
+
const normalizedPath = urlPath.replace(/\/$/, "") || "/";
|
|
11595
|
+
if (normalizedPath.startsWith("/static/") || // Static assets (client.js, client.css, etc.)
|
|
11596
|
+
normalizedPath.startsWith("/__fw/") || // Framework internal routes (hot reload, etc.)
|
|
11597
|
+
normalizedPath === "/favicon.ico" || // Favicon
|
|
11598
|
+
normalizedPath.startsWith("/wss/")) {
|
|
11599
|
+
if (process.env.NODE_ENV === "development") {
|
|
11600
|
+
console.log("[rewrites] Skipping rewrite for system route:", normalizedPath);
|
|
11601
|
+
}
|
|
11602
|
+
return null;
|
|
11603
|
+
}
|
|
11604
|
+
if (process.env.NODE_ENV === "development") {
|
|
11605
|
+
console.log("[rewrites] Processing rewrites:", {
|
|
11606
|
+
urlPath,
|
|
11607
|
+
normalizedPath,
|
|
11608
|
+
host: req.get("host"),
|
|
11609
|
+
hostname: req.hostname,
|
|
11610
|
+
compiledRewritesCount: compiledRewrites.length
|
|
11611
|
+
});
|
|
11612
|
+
}
|
|
11613
|
+
for (const rewrite of compiledRewrites) {
|
|
11614
|
+
let conditionParams = {};
|
|
11615
|
+
if (rewrite.has && rewrite.has.length > 0) {
|
|
11616
|
+
const conditionResult = evaluateRewriteConditions(rewrite.has, req);
|
|
11617
|
+
if (!conditionResult.matches) {
|
|
11618
|
+
if (process.env.NODE_ENV === "development") {
|
|
11619
|
+
console.log("[rewrites] Condition not matched:", {
|
|
11620
|
+
source: rewrite.source,
|
|
11621
|
+
conditions: rewrite.has
|
|
11622
|
+
});
|
|
11623
|
+
}
|
|
11624
|
+
continue;
|
|
11625
|
+
}
|
|
11626
|
+
conditionParams = conditionResult.params;
|
|
11627
|
+
if (process.env.NODE_ENV === "development") {
|
|
11628
|
+
console.log("[rewrites] Condition matched:", {
|
|
11629
|
+
source: rewrite.source,
|
|
11630
|
+
conditionParams
|
|
11631
|
+
});
|
|
11632
|
+
}
|
|
11633
|
+
}
|
|
11634
|
+
const sourceMatch = rewrite.sourceRegex.exec(normalizedPath);
|
|
11635
|
+
if (!sourceMatch) {
|
|
11636
|
+
if (process.env.NODE_ENV === "development") {
|
|
11637
|
+
console.log("[rewrites] Source pattern not matched:", {
|
|
11638
|
+
source: rewrite.source,
|
|
11639
|
+
normalizedPath,
|
|
11640
|
+
sourceRegex: rewrite.sourceRegex.toString()
|
|
11641
|
+
});
|
|
11642
|
+
}
|
|
11643
|
+
continue;
|
|
11644
|
+
}
|
|
11645
|
+
if (process.env.NODE_ENV === "development") {
|
|
11646
|
+
console.log("[rewrites] Source pattern matched:", {
|
|
11647
|
+
source: rewrite.source,
|
|
11648
|
+
normalizedPath,
|
|
11649
|
+
match: sourceMatch[0]
|
|
11650
|
+
});
|
|
11651
|
+
}
|
|
11652
|
+
const sourceParams = {};
|
|
11653
|
+
rewrite.sourceParamNames.forEach((name, idx) => {
|
|
11654
|
+
sourceParams[name] = decodeURIComponent(sourceMatch[idx + 1] || "");
|
|
11655
|
+
});
|
|
11656
|
+
const allParams = { ...sourceParams, ...conditionParams };
|
|
11657
|
+
let destination;
|
|
11658
|
+
if (typeof rewrite.destination === "function") {
|
|
11659
|
+
destination = await rewrite.destination(allParams, req);
|
|
11660
|
+
} else {
|
|
11661
|
+
destination = replaceDestinationParams(rewrite.destination, allParams);
|
|
11662
|
+
}
|
|
11663
|
+
const normalizedDestination = destination.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
|
|
11664
|
+
if (process.env.NODE_ENV === "development") {
|
|
11665
|
+
console.log("[rewrites] Rewrite successful:", {
|
|
11666
|
+
originalPath: urlPath,
|
|
11667
|
+
rewrittenPath: normalizedDestination,
|
|
11668
|
+
allParams
|
|
11669
|
+
});
|
|
11670
|
+
}
|
|
11671
|
+
return {
|
|
11672
|
+
rewrittenPath: normalizedDestination,
|
|
11673
|
+
extractedParams: allParams
|
|
11674
|
+
};
|
|
11675
|
+
}
|
|
11676
|
+
return null;
|
|
11677
|
+
}
|
|
11678
|
+
function validateRewrites(rules) {
|
|
11679
|
+
for (const rule of rules) {
|
|
11680
|
+
if (typeof rule.destination === "string") {
|
|
11681
|
+
if (rule.source === rule.destination) {
|
|
11682
|
+
console.warn(
|
|
11683
|
+
`[framework][rewrites] Rewrite rule has identical source and destination: "${rule.source}". This may cause issues.`
|
|
11684
|
+
);
|
|
11685
|
+
}
|
|
11686
|
+
}
|
|
11687
|
+
}
|
|
11688
|
+
const sources = /* @__PURE__ */ new Set();
|
|
11689
|
+
for (const rule of rules) {
|
|
11690
|
+
if (sources.has(rule.source)) {
|
|
11691
|
+
console.warn(
|
|
11692
|
+
`[framework][rewrites] Duplicate rewrite source pattern: "${rule.source}". Only the first match will be used.`
|
|
11693
|
+
);
|
|
11694
|
+
}
|
|
11695
|
+
sources.add(rule.source);
|
|
11696
|
+
}
|
|
11697
|
+
}
|
|
11698
|
+
function compileRewriteRules(rules) {
|
|
11699
|
+
validateRewrites(rules);
|
|
11700
|
+
return rules.map((rule) => {
|
|
11701
|
+
const { regex, paramNames } = parseRewritePattern(rule.source);
|
|
11702
|
+
let hostRegex;
|
|
11703
|
+
let hostParamNames;
|
|
11704
|
+
if (rule.has) {
|
|
11705
|
+
const hostCondition = rule.has.find((c) => c.type === "host");
|
|
11706
|
+
if (hostCondition) {
|
|
11707
|
+
const hostPattern = hostCondition.value;
|
|
11708
|
+
const hostRegexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
11709
|
+
hostRegex = new RegExp(`^${hostRegexPattern}$`);
|
|
11710
|
+
hostParamNames = [];
|
|
11711
|
+
const paramPattern = /:([^.]+)/g;
|
|
11712
|
+
let paramMatch;
|
|
11713
|
+
while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
|
|
11714
|
+
hostParamNames.push(paramMatch[1]);
|
|
11715
|
+
}
|
|
11716
|
+
}
|
|
11717
|
+
}
|
|
11718
|
+
return {
|
|
11719
|
+
source: rule.source,
|
|
11720
|
+
sourceRegex: regex,
|
|
11721
|
+
sourceParamNames: paramNames,
|
|
11722
|
+
destination: rule.destination,
|
|
11723
|
+
has: rule.has,
|
|
11724
|
+
hostRegex,
|
|
11725
|
+
hostParamNames
|
|
11726
|
+
};
|
|
11727
|
+
});
|
|
11728
|
+
}
|
|
11729
|
+
|
|
11730
|
+
// modules/router/rewrites-loader.ts
|
|
11731
|
+
import fs11 from "fs";
|
|
11732
|
+
import path11 from "path";
|
|
11733
|
+
var FilesystemRewriteLoader = class {
|
|
11734
|
+
// Maximum cache age in ms (1 second fallback)
|
|
11735
|
+
constructor(projectRoot) {
|
|
11736
|
+
this.projectRoot = projectRoot;
|
|
11737
|
+
this.cache = null;
|
|
11738
|
+
this.cacheMaxAge = 1e3;
|
|
11739
|
+
}
|
|
11740
|
+
/**
|
|
11741
|
+
* Invalidates the cache, forcing a reload on next access.
|
|
11742
|
+
*/
|
|
11743
|
+
invalidateCache() {
|
|
11744
|
+
this.cache = null;
|
|
11745
|
+
}
|
|
11746
|
+
/**
|
|
11747
|
+
* Finds the rewrites config file.
|
|
11748
|
+
* Looks for rewrites.config.ts, rewrites.config.js, or rewrites.config.json
|
|
11749
|
+
*/
|
|
11750
|
+
findRewritesConfig() {
|
|
11751
|
+
const candidates = [
|
|
11752
|
+
path11.join(this.projectRoot, "rewrites.config.ts"),
|
|
11753
|
+
path11.join(this.projectRoot, "rewrites.config.js"),
|
|
11754
|
+
path11.join(this.projectRoot, "rewrites.config.json")
|
|
11755
|
+
];
|
|
11756
|
+
for (const candidate of candidates) {
|
|
11757
|
+
if (fs11.existsSync(candidate)) {
|
|
11758
|
+
return candidate;
|
|
11759
|
+
}
|
|
11760
|
+
}
|
|
11761
|
+
return null;
|
|
11762
|
+
}
|
|
11763
|
+
/**
|
|
11764
|
+
* Checks if the rewrites config file has changed.
|
|
11765
|
+
*/
|
|
11766
|
+
hasConfigChanged(configPath) {
|
|
11767
|
+
if (!this.cache || !this.cache.fileStats) {
|
|
11768
|
+
return true;
|
|
11769
|
+
}
|
|
11770
|
+
if (!fs11.existsSync(configPath)) {
|
|
11771
|
+
return this.cache.rewrites.length > 0;
|
|
11772
|
+
}
|
|
11773
|
+
const stats = fs11.statSync(configPath);
|
|
11774
|
+
const cachedStats = this.cache.fileStats;
|
|
11775
|
+
return stats.mtimeMs !== cachedStats.mtime || stats.size !== cachedStats.size;
|
|
11776
|
+
}
|
|
11777
|
+
/**
|
|
11778
|
+
* Loads rewrites from a config file.
|
|
11779
|
+
*/
|
|
11780
|
+
async loadRewritesFromFile(configPath) {
|
|
11781
|
+
const ext = path11.extname(configPath);
|
|
11782
|
+
if (ext === ".json") {
|
|
11783
|
+
const content = fs11.readFileSync(configPath, "utf-8");
|
|
11784
|
+
const config2 = JSON.parse(content);
|
|
11785
|
+
return Array.isArray(config2) ? config2 : [];
|
|
11786
|
+
}
|
|
11787
|
+
delete __require.cache[__require.resolve(configPath)];
|
|
11788
|
+
const mod = __require(configPath);
|
|
11789
|
+
const config = mod.default || mod;
|
|
11790
|
+
if (typeof config === "function") {
|
|
11791
|
+
return await config();
|
|
11792
|
+
}
|
|
11793
|
+
if (Array.isArray(config)) {
|
|
11794
|
+
return config;
|
|
11795
|
+
}
|
|
11796
|
+
throw new Error(
|
|
11797
|
+
`Invalid rewrites config in ${configPath}. Expected array or function returning array.`
|
|
11798
|
+
);
|
|
11799
|
+
}
|
|
11800
|
+
/**
|
|
11801
|
+
* Checks if cache is still valid, invalidates if config changed.
|
|
11802
|
+
*/
|
|
11803
|
+
ensureCacheValid() {
|
|
11804
|
+
if (!this.cache) {
|
|
11805
|
+
return;
|
|
11806
|
+
}
|
|
11807
|
+
const now = Date.now();
|
|
11808
|
+
if (now - this.cache.timestamp > this.cacheMaxAge) {
|
|
11809
|
+
const configPath = this.findRewritesConfig();
|
|
11810
|
+
if (configPath && this.hasConfigChanged(configPath)) {
|
|
11811
|
+
this.cache = null;
|
|
11812
|
+
} else {
|
|
11813
|
+
this.cache.timestamp = now;
|
|
11814
|
+
}
|
|
11815
|
+
}
|
|
11816
|
+
}
|
|
11817
|
+
async loadRewrites() {
|
|
11818
|
+
this.ensureCacheValid();
|
|
11819
|
+
const configPath = this.findRewritesConfig();
|
|
11820
|
+
if (!configPath) {
|
|
11821
|
+
if (this.cache && this.cache.rewrites.length === 0) {
|
|
11822
|
+
return this.cache.rewrites;
|
|
11823
|
+
}
|
|
11824
|
+
this.cache = {
|
|
11825
|
+
rewrites: [],
|
|
11826
|
+
fileStats: null,
|
|
11827
|
+
timestamp: Date.now()
|
|
11828
|
+
};
|
|
11829
|
+
return [];
|
|
11830
|
+
}
|
|
11831
|
+
if (!this.cache || this.hasConfigChanged(configPath)) {
|
|
11832
|
+
const rules = await this.loadRewritesFromFile(configPath);
|
|
11833
|
+
const compiled = compileRewriteRules(rules);
|
|
11834
|
+
const stats = fs11.statSync(configPath);
|
|
11835
|
+
const fileStats = {
|
|
11836
|
+
mtime: stats.mtimeMs,
|
|
11837
|
+
size: stats.size
|
|
11838
|
+
};
|
|
11839
|
+
this.cache = {
|
|
11840
|
+
rewrites: compiled,
|
|
11841
|
+
fileStats,
|
|
11842
|
+
timestamp: Date.now()
|
|
11843
|
+
};
|
|
11844
|
+
}
|
|
11845
|
+
return this.cache.rewrites;
|
|
11846
|
+
}
|
|
11847
|
+
};
|
|
11848
|
+
var ManifestRewriteLoader = class {
|
|
11849
|
+
constructor(projectRoot) {
|
|
11850
|
+
this.cache = null;
|
|
11851
|
+
this.manifestPath = path11.join(projectRoot, ".loly", "rewrites-manifest.json");
|
|
11852
|
+
}
|
|
11853
|
+
/**
|
|
11854
|
+
* Reads the rewrites manifest from disk.
|
|
11855
|
+
*/
|
|
11856
|
+
readManifest() {
|
|
11857
|
+
if (!fs11.existsSync(this.manifestPath)) {
|
|
11858
|
+
return null;
|
|
11859
|
+
}
|
|
11860
|
+
try {
|
|
11861
|
+
const content = fs11.readFileSync(this.manifestPath, "utf-8");
|
|
11862
|
+
return JSON.parse(content);
|
|
11863
|
+
} catch (error) {
|
|
11864
|
+
console.warn(
|
|
11865
|
+
`Failed to read rewrites manifest from ${this.manifestPath}:`,
|
|
11866
|
+
error
|
|
11867
|
+
);
|
|
11868
|
+
return null;
|
|
11869
|
+
}
|
|
11870
|
+
}
|
|
11871
|
+
async loadRewrites() {
|
|
11872
|
+
if (this.cache) {
|
|
11873
|
+
return this.cache;
|
|
11874
|
+
}
|
|
11875
|
+
const manifest = this.readManifest();
|
|
11876
|
+
if (!manifest || !manifest.rewrites) {
|
|
11877
|
+
this.cache = [];
|
|
11878
|
+
return [];
|
|
11879
|
+
}
|
|
11880
|
+
const compiled = compileRewriteRules(manifest.rewrites);
|
|
11881
|
+
this.cache = compiled;
|
|
11882
|
+
return compiled;
|
|
11883
|
+
}
|
|
11884
|
+
};
|
|
11885
|
+
function createRewriteLoader(projectRoot, isDev) {
|
|
11886
|
+
if (isDev) {
|
|
11887
|
+
return new FilesystemRewriteLoader(projectRoot);
|
|
11888
|
+
} else {
|
|
11889
|
+
return new ManifestRewriteLoader(projectRoot);
|
|
11890
|
+
}
|
|
11891
|
+
}
|
|
11892
|
+
|
|
11893
|
+
// modules/router/rewrites-manifest.ts
|
|
11894
|
+
import fs12 from "fs";
|
|
11895
|
+
import path12 from "path";
|
|
11896
|
+
init_globals();
|
|
11897
|
+
async function writeRewritesManifest(projectRoot) {
|
|
11898
|
+
const buildDir = path12.join(projectRoot, BUILD_FOLDER_NAME);
|
|
11899
|
+
if (!fs12.existsSync(buildDir)) {
|
|
11900
|
+
fs12.mkdirSync(buildDir, { recursive: true });
|
|
11901
|
+
}
|
|
11902
|
+
const manifestPath = path12.join(buildDir, "rewrites-manifest.json");
|
|
11903
|
+
const loader = createRewriteLoader(projectRoot, true);
|
|
11904
|
+
const compiledRewrites = await loader.loadRewrites();
|
|
11905
|
+
const serializableRules = [];
|
|
11906
|
+
for (const compiled of compiledRewrites) {
|
|
11907
|
+
if (typeof compiled.destination === "string") {
|
|
11908
|
+
serializableRules.push({
|
|
11909
|
+
source: compiled.source,
|
|
11910
|
+
destination: compiled.destination,
|
|
11911
|
+
has: compiled.has
|
|
11912
|
+
});
|
|
11913
|
+
} else {
|
|
11914
|
+
console.warn(
|
|
11915
|
+
`[framework][build] Rewrite with source "${compiled.source}" has a function destination and will not be included in the manifest. Only static rewrites are supported in production builds.`
|
|
11916
|
+
);
|
|
11917
|
+
}
|
|
11918
|
+
}
|
|
11919
|
+
const manifest = {
|
|
11920
|
+
version: 1,
|
|
11921
|
+
rewrites: serializableRules
|
|
11922
|
+
};
|
|
11923
|
+
fs12.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
11924
|
+
}
|
|
11925
|
+
|
|
11444
11926
|
// modules/build/bundler/client.ts
|
|
11445
11927
|
import { rspack as rspack2 } from "@rspack/core";
|
|
11446
11928
|
|
|
11447
11929
|
// modules/build/config/client.ts
|
|
11448
|
-
import
|
|
11449
|
-
import
|
|
11930
|
+
import path14 from "path";
|
|
11931
|
+
import fs14 from "fs";
|
|
11450
11932
|
import { rspack } from "@rspack/core";
|
|
11451
11933
|
|
|
11452
11934
|
// modules/build/utils/index.ts
|
|
11453
|
-
import
|
|
11454
|
-
import
|
|
11935
|
+
import fs13 from "fs";
|
|
11936
|
+
import path13 from "path";
|
|
11455
11937
|
function ensureDir(dir) {
|
|
11456
|
-
|
|
11938
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
11457
11939
|
}
|
|
11458
11940
|
function loadAliasesFromTsconfig(projectRoot) {
|
|
11459
|
-
const tsconfigPath =
|
|
11941
|
+
const tsconfigPath = path13.join(projectRoot, "tsconfig.json");
|
|
11460
11942
|
const aliases = {};
|
|
11461
|
-
if (!
|
|
11462
|
-
aliases["@app"] =
|
|
11943
|
+
if (!fs13.existsSync(tsconfigPath)) {
|
|
11944
|
+
aliases["@app"] = path13.resolve(projectRoot, "app");
|
|
11463
11945
|
return aliases;
|
|
11464
11946
|
}
|
|
11465
11947
|
let tsconfig;
|
|
11466
11948
|
try {
|
|
11467
|
-
tsconfig = JSON.parse(
|
|
11949
|
+
tsconfig = JSON.parse(fs13.readFileSync(tsconfigPath, "utf-8"));
|
|
11468
11950
|
} catch (err) {
|
|
11469
11951
|
console.warn("\u26A0\uFE0F [framework] Could not read tsconfig.json:", err instanceof Error ? err.message : String(err));
|
|
11470
11952
|
console.warn("\u{1F4A1} Using default path aliases. For custom aliases, ensure tsconfig.json is valid.");
|
|
11471
|
-
aliases["@app"] =
|
|
11953
|
+
aliases["@app"] = path13.resolve(projectRoot, "app");
|
|
11472
11954
|
return aliases;
|
|
11473
11955
|
}
|
|
11474
11956
|
const compilerOptions = tsconfig.compilerOptions ?? {};
|
|
@@ -11479,40 +11961,40 @@ function loadAliasesFromTsconfig(projectRoot) {
|
|
|
11479
11961
|
const aliasKey = aliasPattern.replace(/\/\*$/, "");
|
|
11480
11962
|
const firstTarget = targets[0];
|
|
11481
11963
|
const targetPath = firstTarget.replace(/\/\*$/, "");
|
|
11482
|
-
const resolved =
|
|
11964
|
+
const resolved = path13.resolve(projectRoot, baseUrl, targetPath);
|
|
11483
11965
|
aliases[aliasKey] = resolved;
|
|
11484
11966
|
}
|
|
11485
11967
|
if (!aliases["@app"]) {
|
|
11486
|
-
aliases["@app"] =
|
|
11968
|
+
aliases["@app"] = path13.resolve(projectRoot, "app");
|
|
11487
11969
|
}
|
|
11488
11970
|
return aliases;
|
|
11489
11971
|
}
|
|
11490
11972
|
function copyDirRecursive(srcDir, destDir) {
|
|
11491
|
-
if (!
|
|
11973
|
+
if (!fs13.existsSync(srcDir)) return;
|
|
11492
11974
|
ensureDir(destDir);
|
|
11493
|
-
const entries =
|
|
11975
|
+
const entries = fs13.readdirSync(srcDir, { withFileTypes: true });
|
|
11494
11976
|
for (const entry of entries) {
|
|
11495
|
-
const srcPath =
|
|
11496
|
-
const destPath =
|
|
11977
|
+
const srcPath = path13.join(srcDir, entry.name);
|
|
11978
|
+
const destPath = path13.join(destDir, entry.name);
|
|
11497
11979
|
if (entry.isDirectory()) {
|
|
11498
11980
|
copyDirRecursive(srcPath, destPath);
|
|
11499
11981
|
} else if (entry.isFile()) {
|
|
11500
|
-
|
|
11982
|
+
fs13.copyFileSync(srcPath, destPath);
|
|
11501
11983
|
}
|
|
11502
11984
|
}
|
|
11503
11985
|
}
|
|
11504
11986
|
function copyStaticAssets(projectRoot, outDir) {
|
|
11505
|
-
const assetsSrc =
|
|
11506
|
-
const assetsDest =
|
|
11987
|
+
const assetsSrc = path13.join(projectRoot, "assets");
|
|
11988
|
+
const assetsDest = path13.join(outDir, "assets");
|
|
11507
11989
|
copyDirRecursive(assetsSrc, assetsDest);
|
|
11508
|
-
const publicDir =
|
|
11990
|
+
const publicDir = path13.join(projectRoot, "public");
|
|
11509
11991
|
const candidates = ["favicon.ico", "favicon.png"];
|
|
11510
11992
|
for (const name of candidates) {
|
|
11511
|
-
const fromPublic =
|
|
11512
|
-
if (
|
|
11513
|
-
const dest =
|
|
11514
|
-
ensureDir(
|
|
11515
|
-
|
|
11993
|
+
const fromPublic = path13.join(publicDir, name);
|
|
11994
|
+
if (fs13.existsSync(fromPublic)) {
|
|
11995
|
+
const dest = path13.join(outDir, name);
|
|
11996
|
+
ensureDir(path13.dirname(dest));
|
|
11997
|
+
fs13.copyFileSync(fromPublic, dest);
|
|
11516
11998
|
break;
|
|
11517
11999
|
}
|
|
11518
12000
|
}
|
|
@@ -11522,10 +12004,10 @@ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
|
|
|
11522
12004
|
{ name: "favicon.ico", type: "image/x-icon" },
|
|
11523
12005
|
{ name: "favicon.png", type: "image/png" }
|
|
11524
12006
|
];
|
|
11525
|
-
const publicDir =
|
|
12007
|
+
const publicDir = path13.join(projectRoot, staticDir);
|
|
11526
12008
|
for (const candidate of candidates) {
|
|
11527
|
-
const publicPath =
|
|
11528
|
-
if (
|
|
12009
|
+
const publicPath = path13.join(publicDir, candidate.name);
|
|
12010
|
+
if (fs13.existsSync(publicPath)) {
|
|
11529
12011
|
return {
|
|
11530
12012
|
path: `/${candidate.name}`,
|
|
11531
12013
|
// Served at root from public/
|
|
@@ -11543,10 +12025,10 @@ function generateAssetManifest(outDir, stats) {
|
|
|
11543
12025
|
},
|
|
11544
12026
|
chunks: {}
|
|
11545
12027
|
};
|
|
11546
|
-
if (!
|
|
12028
|
+
if (!fs13.existsSync(outDir)) {
|
|
11547
12029
|
return manifest;
|
|
11548
12030
|
}
|
|
11549
|
-
const files =
|
|
12031
|
+
const files = fs13.readdirSync(outDir);
|
|
11550
12032
|
if (stats) {
|
|
11551
12033
|
try {
|
|
11552
12034
|
const statsJson = stats.toJson({
|
|
@@ -11675,12 +12157,12 @@ function generateAssetManifest(outDir, stats) {
|
|
|
11675
12157
|
}
|
|
11676
12158
|
function loadAssetManifest(projectRoot) {
|
|
11677
12159
|
const { BUILD_FOLDER_NAME: BUILD_FOLDER_NAME2 } = (init_globals(), __toCommonJS(globals_exports));
|
|
11678
|
-
const manifestPath =
|
|
11679
|
-
if (!
|
|
12160
|
+
const manifestPath = path13.join(projectRoot, BUILD_FOLDER_NAME2, "asset-manifest.json");
|
|
12161
|
+
if (!fs13.existsSync(manifestPath)) {
|
|
11680
12162
|
return null;
|
|
11681
12163
|
}
|
|
11682
12164
|
try {
|
|
11683
|
-
const manifest = JSON.parse(
|
|
12165
|
+
const manifest = JSON.parse(fs13.readFileSync(manifestPath, "utf-8"));
|
|
11684
12166
|
return manifest;
|
|
11685
12167
|
} catch (err) {
|
|
11686
12168
|
return null;
|
|
@@ -11703,11 +12185,11 @@ function getClientCssPath(projectRoot) {
|
|
|
11703
12185
|
init_globals();
|
|
11704
12186
|
import dotenv from "dotenv";
|
|
11705
12187
|
function createClientConfig(projectRoot, mode) {
|
|
11706
|
-
const buildDir =
|
|
11707
|
-
const clientEntry =
|
|
11708
|
-
const outDir =
|
|
11709
|
-
const envPath2 =
|
|
11710
|
-
if (
|
|
12188
|
+
const buildDir = path14.join(projectRoot, BUILD_FOLDER_NAME);
|
|
12189
|
+
const clientEntry = path14.join(buildDir, "boostrap.ts");
|
|
12190
|
+
const outDir = path14.join(buildDir, "client");
|
|
12191
|
+
const envPath2 = path14.join(projectRoot, ".env");
|
|
12192
|
+
if (fs14.existsSync(envPath2)) {
|
|
11711
12193
|
dotenv.config({ path: envPath2 });
|
|
11712
12194
|
}
|
|
11713
12195
|
const publicEnv = {};
|
|
@@ -11828,8 +12310,8 @@ function createClientConfig(projectRoot, mode) {
|
|
|
11828
12310
|
|
|
11829
12311
|
// modules/build/bundler/client.ts
|
|
11830
12312
|
init_globals();
|
|
11831
|
-
import
|
|
11832
|
-
import
|
|
12313
|
+
import path15 from "path";
|
|
12314
|
+
import fs15 from "fs";
|
|
11833
12315
|
function startClientBundler(projectRoot, mode = "development") {
|
|
11834
12316
|
const { config, outDir } = createClientConfig(projectRoot, mode);
|
|
11835
12317
|
copyStaticAssets(projectRoot, outDir);
|
|
@@ -11938,8 +12420,8 @@ function buildClientBundle(projectRoot) {
|
|
|
11938
12420
|
}
|
|
11939
12421
|
copyStaticAssets(projectRoot, outDir);
|
|
11940
12422
|
const assetManifest = generateAssetManifest(outDir, stats);
|
|
11941
|
-
const manifestPath =
|
|
11942
|
-
|
|
12423
|
+
const manifestPath = path15.join(projectRoot, BUILD_FOLDER_NAME, "asset-manifest.json");
|
|
12424
|
+
fs15.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), "utf-8");
|
|
11943
12425
|
resolve3({ outDir });
|
|
11944
12426
|
});
|
|
11945
12427
|
});
|
|
@@ -12021,7 +12503,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
12021
12503
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
12022
12504
|
const statMethod = opts.lstat ? lstat : stat;
|
|
12023
12505
|
if (wantBigintFsStats) {
|
|
12024
|
-
this._stat = (
|
|
12506
|
+
this._stat = (path30) => statMethod(path30, { bigint: true });
|
|
12025
12507
|
} else {
|
|
12026
12508
|
this._stat = statMethod;
|
|
12027
12509
|
}
|
|
@@ -12046,8 +12528,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
12046
12528
|
const par = this.parent;
|
|
12047
12529
|
const fil = par && par.files;
|
|
12048
12530
|
if (fil && fil.length > 0) {
|
|
12049
|
-
const { path:
|
|
12050
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
12531
|
+
const { path: path30, depth } = par;
|
|
12532
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path30));
|
|
12051
12533
|
const awaited = await Promise.all(slice);
|
|
12052
12534
|
for (const entry of awaited) {
|
|
12053
12535
|
if (!entry)
|
|
@@ -12087,20 +12569,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
12087
12569
|
this.reading = false;
|
|
12088
12570
|
}
|
|
12089
12571
|
}
|
|
12090
|
-
async _exploreDir(
|
|
12572
|
+
async _exploreDir(path30, depth) {
|
|
12091
12573
|
let files;
|
|
12092
12574
|
try {
|
|
12093
|
-
files = await readdir(
|
|
12575
|
+
files = await readdir(path30, this._rdOptions);
|
|
12094
12576
|
} catch (error) {
|
|
12095
12577
|
this._onError(error);
|
|
12096
12578
|
}
|
|
12097
|
-
return { files, depth, path:
|
|
12579
|
+
return { files, depth, path: path30 };
|
|
12098
12580
|
}
|
|
12099
|
-
async _formatEntry(dirent,
|
|
12581
|
+
async _formatEntry(dirent, path30) {
|
|
12100
12582
|
let entry;
|
|
12101
12583
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
12102
12584
|
try {
|
|
12103
|
-
const fullPath = presolve(pjoin(
|
|
12585
|
+
const fullPath = presolve(pjoin(path30, basename3));
|
|
12104
12586
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
12105
12587
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
12106
12588
|
} catch (err) {
|
|
@@ -12500,16 +12982,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
12500
12982
|
};
|
|
12501
12983
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
12502
12984
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
12503
|
-
function createFsWatchInstance(
|
|
12985
|
+
function createFsWatchInstance(path30, options, listener, errHandler, emitRaw) {
|
|
12504
12986
|
const handleEvent = (rawEvent, evPath) => {
|
|
12505
|
-
listener(
|
|
12506
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
12507
|
-
if (evPath &&
|
|
12508
|
-
fsWatchBroadcast(sysPath.resolve(
|
|
12987
|
+
listener(path30);
|
|
12988
|
+
emitRaw(rawEvent, evPath, { watchedPath: path30 });
|
|
12989
|
+
if (evPath && path30 !== evPath) {
|
|
12990
|
+
fsWatchBroadcast(sysPath.resolve(path30, evPath), KEY_LISTENERS, sysPath.join(path30, evPath));
|
|
12509
12991
|
}
|
|
12510
12992
|
};
|
|
12511
12993
|
try {
|
|
12512
|
-
return fs_watch(
|
|
12994
|
+
return fs_watch(path30, {
|
|
12513
12995
|
persistent: options.persistent
|
|
12514
12996
|
}, handleEvent);
|
|
12515
12997
|
} catch (error) {
|
|
@@ -12525,12 +13007,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
12525
13007
|
listener(val1, val2, val3);
|
|
12526
13008
|
});
|
|
12527
13009
|
};
|
|
12528
|
-
var setFsWatchListener = (
|
|
13010
|
+
var setFsWatchListener = (path30, fullPath, options, handlers) => {
|
|
12529
13011
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
12530
13012
|
let cont = FsWatchInstances.get(fullPath);
|
|
12531
13013
|
let watcher;
|
|
12532
13014
|
if (!options.persistent) {
|
|
12533
|
-
watcher = createFsWatchInstance(
|
|
13015
|
+
watcher = createFsWatchInstance(path30, options, listener, errHandler, rawEmitter);
|
|
12534
13016
|
if (!watcher)
|
|
12535
13017
|
return;
|
|
12536
13018
|
return watcher.close.bind(watcher);
|
|
@@ -12541,7 +13023,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
12541
13023
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
12542
13024
|
} else {
|
|
12543
13025
|
watcher = createFsWatchInstance(
|
|
12544
|
-
|
|
13026
|
+
path30,
|
|
12545
13027
|
options,
|
|
12546
13028
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
12547
13029
|
errHandler,
|
|
@@ -12556,7 +13038,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
12556
13038
|
cont.watcherUnusable = true;
|
|
12557
13039
|
if (isWindows && error.code === "EPERM") {
|
|
12558
13040
|
try {
|
|
12559
|
-
const fd = await open(
|
|
13041
|
+
const fd = await open(path30, "r");
|
|
12560
13042
|
await fd.close();
|
|
12561
13043
|
broadcastErr(error);
|
|
12562
13044
|
} catch (err) {
|
|
@@ -12587,7 +13069,7 @@ var setFsWatchListener = (path28, fullPath, options, handlers) => {
|
|
|
12587
13069
|
};
|
|
12588
13070
|
};
|
|
12589
13071
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
12590
|
-
var setFsWatchFileListener = (
|
|
13072
|
+
var setFsWatchFileListener = (path30, fullPath, options, handlers) => {
|
|
12591
13073
|
const { listener, rawEmitter } = handlers;
|
|
12592
13074
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
12593
13075
|
const copts = cont && cont.options;
|
|
@@ -12609,7 +13091,7 @@ var setFsWatchFileListener = (path28, fullPath, options, handlers) => {
|
|
|
12609
13091
|
});
|
|
12610
13092
|
const currmtime = curr.mtimeMs;
|
|
12611
13093
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
12612
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
13094
|
+
foreach(cont.listeners, (listener2) => listener2(path30, curr));
|
|
12613
13095
|
}
|
|
12614
13096
|
})
|
|
12615
13097
|
};
|
|
@@ -12637,13 +13119,13 @@ var NodeFsHandler = class {
|
|
|
12637
13119
|
* @param listener on fs change
|
|
12638
13120
|
* @returns closer for the watcher instance
|
|
12639
13121
|
*/
|
|
12640
|
-
_watchWithNodeFs(
|
|
13122
|
+
_watchWithNodeFs(path30, listener) {
|
|
12641
13123
|
const opts = this.fsw.options;
|
|
12642
|
-
const directory = sysPath.dirname(
|
|
12643
|
-
const basename3 = sysPath.basename(
|
|
13124
|
+
const directory = sysPath.dirname(path30);
|
|
13125
|
+
const basename3 = sysPath.basename(path30);
|
|
12644
13126
|
const parent = this.fsw._getWatchedDir(directory);
|
|
12645
13127
|
parent.add(basename3);
|
|
12646
|
-
const absolutePath = sysPath.resolve(
|
|
13128
|
+
const absolutePath = sysPath.resolve(path30);
|
|
12647
13129
|
const options = {
|
|
12648
13130
|
persistent: opts.persistent
|
|
12649
13131
|
};
|
|
@@ -12653,12 +13135,12 @@ var NodeFsHandler = class {
|
|
|
12653
13135
|
if (opts.usePolling) {
|
|
12654
13136
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
12655
13137
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
12656
|
-
closer = setFsWatchFileListener(
|
|
13138
|
+
closer = setFsWatchFileListener(path30, absolutePath, options, {
|
|
12657
13139
|
listener,
|
|
12658
13140
|
rawEmitter: this.fsw._emitRaw
|
|
12659
13141
|
});
|
|
12660
13142
|
} else {
|
|
12661
|
-
closer = setFsWatchListener(
|
|
13143
|
+
closer = setFsWatchListener(path30, absolutePath, options, {
|
|
12662
13144
|
listener,
|
|
12663
13145
|
errHandler: this._boundHandleError,
|
|
12664
13146
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -12680,7 +13162,7 @@ var NodeFsHandler = class {
|
|
|
12680
13162
|
let prevStats = stats;
|
|
12681
13163
|
if (parent.has(basename3))
|
|
12682
13164
|
return;
|
|
12683
|
-
const listener = async (
|
|
13165
|
+
const listener = async (path30, newStats) => {
|
|
12684
13166
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
12685
13167
|
return;
|
|
12686
13168
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -12694,11 +13176,11 @@ var NodeFsHandler = class {
|
|
|
12694
13176
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
12695
13177
|
}
|
|
12696
13178
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
12697
|
-
this.fsw._closeFile(
|
|
13179
|
+
this.fsw._closeFile(path30);
|
|
12698
13180
|
prevStats = newStats2;
|
|
12699
13181
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
12700
13182
|
if (closer2)
|
|
12701
|
-
this.fsw._addPathCloser(
|
|
13183
|
+
this.fsw._addPathCloser(path30, closer2);
|
|
12702
13184
|
} else {
|
|
12703
13185
|
prevStats = newStats2;
|
|
12704
13186
|
}
|
|
@@ -12730,7 +13212,7 @@ var NodeFsHandler = class {
|
|
|
12730
13212
|
* @param item basename of this item
|
|
12731
13213
|
* @returns true if no more processing is needed for this entry.
|
|
12732
13214
|
*/
|
|
12733
|
-
async _handleSymlink(entry, directory,
|
|
13215
|
+
async _handleSymlink(entry, directory, path30, item) {
|
|
12734
13216
|
if (this.fsw.closed) {
|
|
12735
13217
|
return;
|
|
12736
13218
|
}
|
|
@@ -12740,7 +13222,7 @@ var NodeFsHandler = class {
|
|
|
12740
13222
|
this.fsw._incrReadyCount();
|
|
12741
13223
|
let linkPath;
|
|
12742
13224
|
try {
|
|
12743
|
-
linkPath = await fsrealpath(
|
|
13225
|
+
linkPath = await fsrealpath(path30);
|
|
12744
13226
|
} catch (e) {
|
|
12745
13227
|
this.fsw._emitReady();
|
|
12746
13228
|
return true;
|
|
@@ -12750,12 +13232,12 @@ var NodeFsHandler = class {
|
|
|
12750
13232
|
if (dir.has(item)) {
|
|
12751
13233
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
12752
13234
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
12753
|
-
this.fsw._emit(EV.CHANGE,
|
|
13235
|
+
this.fsw._emit(EV.CHANGE, path30, entry.stats);
|
|
12754
13236
|
}
|
|
12755
13237
|
} else {
|
|
12756
13238
|
dir.add(item);
|
|
12757
13239
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
12758
|
-
this.fsw._emit(EV.ADD,
|
|
13240
|
+
this.fsw._emit(EV.ADD, path30, entry.stats);
|
|
12759
13241
|
}
|
|
12760
13242
|
this.fsw._emitReady();
|
|
12761
13243
|
return true;
|
|
@@ -12784,9 +13266,9 @@ var NodeFsHandler = class {
|
|
|
12784
13266
|
return;
|
|
12785
13267
|
}
|
|
12786
13268
|
const item = entry.path;
|
|
12787
|
-
let
|
|
13269
|
+
let path30 = sysPath.join(directory, item);
|
|
12788
13270
|
current.add(item);
|
|
12789
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
13271
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path30, item)) {
|
|
12790
13272
|
return;
|
|
12791
13273
|
}
|
|
12792
13274
|
if (this.fsw.closed) {
|
|
@@ -12795,8 +13277,8 @@ var NodeFsHandler = class {
|
|
|
12795
13277
|
}
|
|
12796
13278
|
if (item === target || !target && !previous.has(item)) {
|
|
12797
13279
|
this.fsw._incrReadyCount();
|
|
12798
|
-
|
|
12799
|
-
this._addToNodeFs(
|
|
13280
|
+
path30 = sysPath.join(dir, sysPath.relative(dir, path30));
|
|
13281
|
+
this._addToNodeFs(path30, initialAdd, wh, depth + 1);
|
|
12800
13282
|
}
|
|
12801
13283
|
}).on(EV.ERROR, this._boundHandleError);
|
|
12802
13284
|
return new Promise((resolve3, reject) => {
|
|
@@ -12865,13 +13347,13 @@ var NodeFsHandler = class {
|
|
|
12865
13347
|
* @param depth Child path actually targeted for watch
|
|
12866
13348
|
* @param target Child path actually targeted for watch
|
|
12867
13349
|
*/
|
|
12868
|
-
async _addToNodeFs(
|
|
13350
|
+
async _addToNodeFs(path30, initialAdd, priorWh, depth, target) {
|
|
12869
13351
|
const ready = this.fsw._emitReady;
|
|
12870
|
-
if (this.fsw._isIgnored(
|
|
13352
|
+
if (this.fsw._isIgnored(path30) || this.fsw.closed) {
|
|
12871
13353
|
ready();
|
|
12872
13354
|
return false;
|
|
12873
13355
|
}
|
|
12874
|
-
const wh = this.fsw._getWatchHelpers(
|
|
13356
|
+
const wh = this.fsw._getWatchHelpers(path30);
|
|
12875
13357
|
if (priorWh) {
|
|
12876
13358
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
12877
13359
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -12887,8 +13369,8 @@ var NodeFsHandler = class {
|
|
|
12887
13369
|
const follow = this.fsw.options.followSymlinks;
|
|
12888
13370
|
let closer;
|
|
12889
13371
|
if (stats.isDirectory()) {
|
|
12890
|
-
const absPath = sysPath.resolve(
|
|
12891
|
-
const targetPath = follow ? await fsrealpath(
|
|
13372
|
+
const absPath = sysPath.resolve(path30);
|
|
13373
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
12892
13374
|
if (this.fsw.closed)
|
|
12893
13375
|
return;
|
|
12894
13376
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -12898,29 +13380,29 @@ var NodeFsHandler = class {
|
|
|
12898
13380
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
12899
13381
|
}
|
|
12900
13382
|
} else if (stats.isSymbolicLink()) {
|
|
12901
|
-
const targetPath = follow ? await fsrealpath(
|
|
13383
|
+
const targetPath = follow ? await fsrealpath(path30) : path30;
|
|
12902
13384
|
if (this.fsw.closed)
|
|
12903
13385
|
return;
|
|
12904
13386
|
const parent = sysPath.dirname(wh.watchPath);
|
|
12905
13387
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
12906
13388
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
12907
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
13389
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path30, wh, targetPath);
|
|
12908
13390
|
if (this.fsw.closed)
|
|
12909
13391
|
return;
|
|
12910
13392
|
if (targetPath !== void 0) {
|
|
12911
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(
|
|
13393
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path30), targetPath);
|
|
12912
13394
|
}
|
|
12913
13395
|
} else {
|
|
12914
13396
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
12915
13397
|
}
|
|
12916
13398
|
ready();
|
|
12917
13399
|
if (closer)
|
|
12918
|
-
this.fsw._addPathCloser(
|
|
13400
|
+
this.fsw._addPathCloser(path30, closer);
|
|
12919
13401
|
return false;
|
|
12920
13402
|
} catch (error) {
|
|
12921
13403
|
if (this.fsw._handleError(error)) {
|
|
12922
13404
|
ready();
|
|
12923
|
-
return
|
|
13405
|
+
return path30;
|
|
12924
13406
|
}
|
|
12925
13407
|
}
|
|
12926
13408
|
}
|
|
@@ -12963,26 +13445,26 @@ function createPattern(matcher) {
|
|
|
12963
13445
|
}
|
|
12964
13446
|
return () => false;
|
|
12965
13447
|
}
|
|
12966
|
-
function normalizePath(
|
|
12967
|
-
if (typeof
|
|
13448
|
+
function normalizePath(path30) {
|
|
13449
|
+
if (typeof path30 !== "string")
|
|
12968
13450
|
throw new Error("string expected");
|
|
12969
|
-
|
|
12970
|
-
|
|
13451
|
+
path30 = sysPath2.normalize(path30);
|
|
13452
|
+
path30 = path30.replace(/\\/g, "/");
|
|
12971
13453
|
let prepend = false;
|
|
12972
|
-
if (
|
|
13454
|
+
if (path30.startsWith("//"))
|
|
12973
13455
|
prepend = true;
|
|
12974
13456
|
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
12975
|
-
while (
|
|
12976
|
-
|
|
13457
|
+
while (path30.match(DOUBLE_SLASH_RE2))
|
|
13458
|
+
path30 = path30.replace(DOUBLE_SLASH_RE2, "/");
|
|
12977
13459
|
if (prepend)
|
|
12978
|
-
|
|
12979
|
-
return
|
|
13460
|
+
path30 = "/" + path30;
|
|
13461
|
+
return path30;
|
|
12980
13462
|
}
|
|
12981
13463
|
function matchPatterns(patterns, testString, stats) {
|
|
12982
|
-
const
|
|
13464
|
+
const path30 = normalizePath(testString);
|
|
12983
13465
|
for (let index = 0; index < patterns.length; index++) {
|
|
12984
13466
|
const pattern = patterns[index];
|
|
12985
|
-
if (pattern(
|
|
13467
|
+
if (pattern(path30, stats)) {
|
|
12986
13468
|
return true;
|
|
12987
13469
|
}
|
|
12988
13470
|
}
|
|
@@ -13022,19 +13504,19 @@ var toUnix = (string) => {
|
|
|
13022
13504
|
}
|
|
13023
13505
|
return str;
|
|
13024
13506
|
};
|
|
13025
|
-
var normalizePathToUnix = (
|
|
13026
|
-
var normalizeIgnored = (cwd = "") => (
|
|
13027
|
-
if (typeof
|
|
13028
|
-
return normalizePathToUnix(sysPath2.isAbsolute(
|
|
13507
|
+
var normalizePathToUnix = (path30) => toUnix(sysPath2.normalize(toUnix(path30)));
|
|
13508
|
+
var normalizeIgnored = (cwd = "") => (path30) => {
|
|
13509
|
+
if (typeof path30 === "string") {
|
|
13510
|
+
return normalizePathToUnix(sysPath2.isAbsolute(path30) ? path30 : sysPath2.join(cwd, path30));
|
|
13029
13511
|
} else {
|
|
13030
|
-
return
|
|
13512
|
+
return path30;
|
|
13031
13513
|
}
|
|
13032
13514
|
};
|
|
13033
|
-
var getAbsolutePath = (
|
|
13034
|
-
if (sysPath2.isAbsolute(
|
|
13035
|
-
return
|
|
13515
|
+
var getAbsolutePath = (path30, cwd) => {
|
|
13516
|
+
if (sysPath2.isAbsolute(path30)) {
|
|
13517
|
+
return path30;
|
|
13036
13518
|
}
|
|
13037
|
-
return sysPath2.join(cwd,
|
|
13519
|
+
return sysPath2.join(cwd, path30);
|
|
13038
13520
|
};
|
|
13039
13521
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
13040
13522
|
var DirEntry = class {
|
|
@@ -13089,10 +13571,10 @@ var DirEntry = class {
|
|
|
13089
13571
|
var STAT_METHOD_F = "stat";
|
|
13090
13572
|
var STAT_METHOD_L = "lstat";
|
|
13091
13573
|
var WatchHelper = class {
|
|
13092
|
-
constructor(
|
|
13574
|
+
constructor(path30, follow, fsw) {
|
|
13093
13575
|
this.fsw = fsw;
|
|
13094
|
-
const watchPath =
|
|
13095
|
-
this.path =
|
|
13576
|
+
const watchPath = path30;
|
|
13577
|
+
this.path = path30 = path30.replace(REPLACER_RE, "");
|
|
13096
13578
|
this.watchPath = watchPath;
|
|
13097
13579
|
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
13098
13580
|
this.dirParts = [];
|
|
@@ -13214,20 +13696,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13214
13696
|
this._closePromise = void 0;
|
|
13215
13697
|
let paths = unifyPaths(paths_);
|
|
13216
13698
|
if (cwd) {
|
|
13217
|
-
paths = paths.map((
|
|
13218
|
-
const absPath = getAbsolutePath(
|
|
13699
|
+
paths = paths.map((path30) => {
|
|
13700
|
+
const absPath = getAbsolutePath(path30, cwd);
|
|
13219
13701
|
return absPath;
|
|
13220
13702
|
});
|
|
13221
13703
|
}
|
|
13222
|
-
paths.forEach((
|
|
13223
|
-
this._removeIgnoredPath(
|
|
13704
|
+
paths.forEach((path30) => {
|
|
13705
|
+
this._removeIgnoredPath(path30);
|
|
13224
13706
|
});
|
|
13225
13707
|
this._userIgnored = void 0;
|
|
13226
13708
|
if (!this._readyCount)
|
|
13227
13709
|
this._readyCount = 0;
|
|
13228
13710
|
this._readyCount += paths.length;
|
|
13229
|
-
Promise.all(paths.map(async (
|
|
13230
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
13711
|
+
Promise.all(paths.map(async (path30) => {
|
|
13712
|
+
const res = await this._nodeFsHandler._addToNodeFs(path30, !_internal, void 0, 0, _origAdd);
|
|
13231
13713
|
if (res)
|
|
13232
13714
|
this._emitReady();
|
|
13233
13715
|
return res;
|
|
@@ -13249,17 +13731,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13249
13731
|
return this;
|
|
13250
13732
|
const paths = unifyPaths(paths_);
|
|
13251
13733
|
const { cwd } = this.options;
|
|
13252
|
-
paths.forEach((
|
|
13253
|
-
if (!sysPath2.isAbsolute(
|
|
13734
|
+
paths.forEach((path30) => {
|
|
13735
|
+
if (!sysPath2.isAbsolute(path30) && !this._closers.has(path30)) {
|
|
13254
13736
|
if (cwd)
|
|
13255
|
-
|
|
13256
|
-
|
|
13737
|
+
path30 = sysPath2.join(cwd, path30);
|
|
13738
|
+
path30 = sysPath2.resolve(path30);
|
|
13257
13739
|
}
|
|
13258
|
-
this._closePath(
|
|
13259
|
-
this._addIgnoredPath(
|
|
13260
|
-
if (this._watched.has(
|
|
13740
|
+
this._closePath(path30);
|
|
13741
|
+
this._addIgnoredPath(path30);
|
|
13742
|
+
if (this._watched.has(path30)) {
|
|
13261
13743
|
this._addIgnoredPath({
|
|
13262
|
-
path:
|
|
13744
|
+
path: path30,
|
|
13263
13745
|
recursive: true
|
|
13264
13746
|
});
|
|
13265
13747
|
}
|
|
@@ -13323,38 +13805,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13323
13805
|
* @param stats arguments to be passed with event
|
|
13324
13806
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
13325
13807
|
*/
|
|
13326
|
-
async _emit(event,
|
|
13808
|
+
async _emit(event, path30, stats) {
|
|
13327
13809
|
if (this.closed)
|
|
13328
13810
|
return;
|
|
13329
13811
|
const opts = this.options;
|
|
13330
13812
|
if (isWindows)
|
|
13331
|
-
|
|
13813
|
+
path30 = sysPath2.normalize(path30);
|
|
13332
13814
|
if (opts.cwd)
|
|
13333
|
-
|
|
13334
|
-
const args = [
|
|
13815
|
+
path30 = sysPath2.relative(opts.cwd, path30);
|
|
13816
|
+
const args = [path30];
|
|
13335
13817
|
if (stats != null)
|
|
13336
13818
|
args.push(stats);
|
|
13337
13819
|
const awf = opts.awaitWriteFinish;
|
|
13338
13820
|
let pw;
|
|
13339
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
13821
|
+
if (awf && (pw = this._pendingWrites.get(path30))) {
|
|
13340
13822
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
13341
13823
|
return this;
|
|
13342
13824
|
}
|
|
13343
13825
|
if (opts.atomic) {
|
|
13344
13826
|
if (event === EVENTS.UNLINK) {
|
|
13345
|
-
this._pendingUnlinks.set(
|
|
13827
|
+
this._pendingUnlinks.set(path30, [event, ...args]);
|
|
13346
13828
|
setTimeout(() => {
|
|
13347
|
-
this._pendingUnlinks.forEach((entry,
|
|
13829
|
+
this._pendingUnlinks.forEach((entry, path31) => {
|
|
13348
13830
|
this.emit(...entry);
|
|
13349
13831
|
this.emit(EVENTS.ALL, ...entry);
|
|
13350
|
-
this._pendingUnlinks.delete(
|
|
13832
|
+
this._pendingUnlinks.delete(path31);
|
|
13351
13833
|
});
|
|
13352
13834
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
13353
13835
|
return this;
|
|
13354
13836
|
}
|
|
13355
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
13837
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path30)) {
|
|
13356
13838
|
event = EVENTS.CHANGE;
|
|
13357
|
-
this._pendingUnlinks.delete(
|
|
13839
|
+
this._pendingUnlinks.delete(path30);
|
|
13358
13840
|
}
|
|
13359
13841
|
}
|
|
13360
13842
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -13372,16 +13854,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13372
13854
|
this.emitWithAll(event, args);
|
|
13373
13855
|
}
|
|
13374
13856
|
};
|
|
13375
|
-
this._awaitWriteFinish(
|
|
13857
|
+
this._awaitWriteFinish(path30, awf.stabilityThreshold, event, awfEmit);
|
|
13376
13858
|
return this;
|
|
13377
13859
|
}
|
|
13378
13860
|
if (event === EVENTS.CHANGE) {
|
|
13379
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
13861
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path30, 50);
|
|
13380
13862
|
if (isThrottled)
|
|
13381
13863
|
return this;
|
|
13382
13864
|
}
|
|
13383
13865
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
13384
|
-
const fullPath = opts.cwd ? sysPath2.join(opts.cwd,
|
|
13866
|
+
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path30) : path30;
|
|
13385
13867
|
let stats2;
|
|
13386
13868
|
try {
|
|
13387
13869
|
stats2 = await stat3(fullPath);
|
|
@@ -13412,23 +13894,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13412
13894
|
* @param timeout duration of time to suppress duplicate actions
|
|
13413
13895
|
* @returns tracking object or false if action should be suppressed
|
|
13414
13896
|
*/
|
|
13415
|
-
_throttle(actionType,
|
|
13897
|
+
_throttle(actionType, path30, timeout) {
|
|
13416
13898
|
if (!this._throttled.has(actionType)) {
|
|
13417
13899
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
13418
13900
|
}
|
|
13419
13901
|
const action = this._throttled.get(actionType);
|
|
13420
13902
|
if (!action)
|
|
13421
13903
|
throw new Error("invalid throttle");
|
|
13422
|
-
const actionPath = action.get(
|
|
13904
|
+
const actionPath = action.get(path30);
|
|
13423
13905
|
if (actionPath) {
|
|
13424
13906
|
actionPath.count++;
|
|
13425
13907
|
return false;
|
|
13426
13908
|
}
|
|
13427
13909
|
let timeoutObject;
|
|
13428
13910
|
const clear = () => {
|
|
13429
|
-
const item = action.get(
|
|
13911
|
+
const item = action.get(path30);
|
|
13430
13912
|
const count = item ? item.count : 0;
|
|
13431
|
-
action.delete(
|
|
13913
|
+
action.delete(path30);
|
|
13432
13914
|
clearTimeout(timeoutObject);
|
|
13433
13915
|
if (item)
|
|
13434
13916
|
clearTimeout(item.timeoutObject);
|
|
@@ -13436,7 +13918,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13436
13918
|
};
|
|
13437
13919
|
timeoutObject = setTimeout(clear, timeout);
|
|
13438
13920
|
const thr = { timeoutObject, clear, count: 0 };
|
|
13439
|
-
action.set(
|
|
13921
|
+
action.set(path30, thr);
|
|
13440
13922
|
return thr;
|
|
13441
13923
|
}
|
|
13442
13924
|
_incrReadyCount() {
|
|
@@ -13450,44 +13932,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13450
13932
|
* @param event
|
|
13451
13933
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
13452
13934
|
*/
|
|
13453
|
-
_awaitWriteFinish(
|
|
13935
|
+
_awaitWriteFinish(path30, threshold, event, awfEmit) {
|
|
13454
13936
|
const awf = this.options.awaitWriteFinish;
|
|
13455
13937
|
if (typeof awf !== "object")
|
|
13456
13938
|
return;
|
|
13457
13939
|
const pollInterval = awf.pollInterval;
|
|
13458
13940
|
let timeoutHandler;
|
|
13459
|
-
let fullPath =
|
|
13460
|
-
if (this.options.cwd && !sysPath2.isAbsolute(
|
|
13461
|
-
fullPath = sysPath2.join(this.options.cwd,
|
|
13941
|
+
let fullPath = path30;
|
|
13942
|
+
if (this.options.cwd && !sysPath2.isAbsolute(path30)) {
|
|
13943
|
+
fullPath = sysPath2.join(this.options.cwd, path30);
|
|
13462
13944
|
}
|
|
13463
13945
|
const now = /* @__PURE__ */ new Date();
|
|
13464
13946
|
const writes = this._pendingWrites;
|
|
13465
13947
|
function awaitWriteFinishFn(prevStat) {
|
|
13466
13948
|
statcb(fullPath, (err, curStat) => {
|
|
13467
|
-
if (err || !writes.has(
|
|
13949
|
+
if (err || !writes.has(path30)) {
|
|
13468
13950
|
if (err && err.code !== "ENOENT")
|
|
13469
13951
|
awfEmit(err);
|
|
13470
13952
|
return;
|
|
13471
13953
|
}
|
|
13472
13954
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
13473
13955
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
13474
|
-
writes.get(
|
|
13956
|
+
writes.get(path30).lastChange = now2;
|
|
13475
13957
|
}
|
|
13476
|
-
const pw = writes.get(
|
|
13958
|
+
const pw = writes.get(path30);
|
|
13477
13959
|
const df = now2 - pw.lastChange;
|
|
13478
13960
|
if (df >= threshold) {
|
|
13479
|
-
writes.delete(
|
|
13961
|
+
writes.delete(path30);
|
|
13480
13962
|
awfEmit(void 0, curStat);
|
|
13481
13963
|
} else {
|
|
13482
13964
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
13483
13965
|
}
|
|
13484
13966
|
});
|
|
13485
13967
|
}
|
|
13486
|
-
if (!writes.has(
|
|
13487
|
-
writes.set(
|
|
13968
|
+
if (!writes.has(path30)) {
|
|
13969
|
+
writes.set(path30, {
|
|
13488
13970
|
lastChange: now,
|
|
13489
13971
|
cancelWait: () => {
|
|
13490
|
-
writes.delete(
|
|
13972
|
+
writes.delete(path30);
|
|
13491
13973
|
clearTimeout(timeoutHandler);
|
|
13492
13974
|
return event;
|
|
13493
13975
|
}
|
|
@@ -13498,8 +13980,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13498
13980
|
/**
|
|
13499
13981
|
* Determines whether user has asked to ignore this path.
|
|
13500
13982
|
*/
|
|
13501
|
-
_isIgnored(
|
|
13502
|
-
if (this.options.atomic && DOT_RE.test(
|
|
13983
|
+
_isIgnored(path30, stats) {
|
|
13984
|
+
if (this.options.atomic && DOT_RE.test(path30))
|
|
13503
13985
|
return true;
|
|
13504
13986
|
if (!this._userIgnored) {
|
|
13505
13987
|
const { cwd } = this.options;
|
|
@@ -13509,17 +13991,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13509
13991
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
13510
13992
|
this._userIgnored = anymatch(list, void 0);
|
|
13511
13993
|
}
|
|
13512
|
-
return this._userIgnored(
|
|
13994
|
+
return this._userIgnored(path30, stats);
|
|
13513
13995
|
}
|
|
13514
|
-
_isntIgnored(
|
|
13515
|
-
return !this._isIgnored(
|
|
13996
|
+
_isntIgnored(path30, stat4) {
|
|
13997
|
+
return !this._isIgnored(path30, stat4);
|
|
13516
13998
|
}
|
|
13517
13999
|
/**
|
|
13518
14000
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
13519
14001
|
* @param path file or directory pattern being watched
|
|
13520
14002
|
*/
|
|
13521
|
-
_getWatchHelpers(
|
|
13522
|
-
return new WatchHelper(
|
|
14003
|
+
_getWatchHelpers(path30) {
|
|
14004
|
+
return new WatchHelper(path30, this.options.followSymlinks, this);
|
|
13523
14005
|
}
|
|
13524
14006
|
// Directory helpers
|
|
13525
14007
|
// -----------------
|
|
@@ -13551,63 +14033,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
13551
14033
|
* @param item base path of item/directory
|
|
13552
14034
|
*/
|
|
13553
14035
|
_remove(directory, item, isDirectory) {
|
|
13554
|
-
const
|
|
13555
|
-
const fullPath = sysPath2.resolve(
|
|
13556
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
13557
|
-
if (!this._throttle("remove",
|
|
14036
|
+
const path30 = sysPath2.join(directory, item);
|
|
14037
|
+
const fullPath = sysPath2.resolve(path30);
|
|
14038
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path30) || this._watched.has(fullPath);
|
|
14039
|
+
if (!this._throttle("remove", path30, 100))
|
|
13558
14040
|
return;
|
|
13559
14041
|
if (!isDirectory && this._watched.size === 1) {
|
|
13560
14042
|
this.add(directory, item, true);
|
|
13561
14043
|
}
|
|
13562
|
-
const wp = this._getWatchedDir(
|
|
14044
|
+
const wp = this._getWatchedDir(path30);
|
|
13563
14045
|
const nestedDirectoryChildren = wp.getChildren();
|
|
13564
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
14046
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path30, nested));
|
|
13565
14047
|
const parent = this._getWatchedDir(directory);
|
|
13566
14048
|
const wasTracked = parent.has(item);
|
|
13567
14049
|
parent.remove(item);
|
|
13568
14050
|
if (this._symlinkPaths.has(fullPath)) {
|
|
13569
14051
|
this._symlinkPaths.delete(fullPath);
|
|
13570
14052
|
}
|
|
13571
|
-
let relPath =
|
|
14053
|
+
let relPath = path30;
|
|
13572
14054
|
if (this.options.cwd)
|
|
13573
|
-
relPath = sysPath2.relative(this.options.cwd,
|
|
14055
|
+
relPath = sysPath2.relative(this.options.cwd, path30);
|
|
13574
14056
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
13575
14057
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
13576
14058
|
if (event === EVENTS.ADD)
|
|
13577
14059
|
return;
|
|
13578
14060
|
}
|
|
13579
|
-
this._watched.delete(
|
|
14061
|
+
this._watched.delete(path30);
|
|
13580
14062
|
this._watched.delete(fullPath);
|
|
13581
14063
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
13582
|
-
if (wasTracked && !this._isIgnored(
|
|
13583
|
-
this._emit(eventName,
|
|
13584
|
-
this._closePath(
|
|
14064
|
+
if (wasTracked && !this._isIgnored(path30))
|
|
14065
|
+
this._emit(eventName, path30);
|
|
14066
|
+
this._closePath(path30);
|
|
13585
14067
|
}
|
|
13586
14068
|
/**
|
|
13587
14069
|
* Closes all watchers for a path
|
|
13588
14070
|
*/
|
|
13589
|
-
_closePath(
|
|
13590
|
-
this._closeFile(
|
|
13591
|
-
const dir = sysPath2.dirname(
|
|
13592
|
-
this._getWatchedDir(dir).remove(sysPath2.basename(
|
|
14071
|
+
_closePath(path30) {
|
|
14072
|
+
this._closeFile(path30);
|
|
14073
|
+
const dir = sysPath2.dirname(path30);
|
|
14074
|
+
this._getWatchedDir(dir).remove(sysPath2.basename(path30));
|
|
13593
14075
|
}
|
|
13594
14076
|
/**
|
|
13595
14077
|
* Closes only file-specific watchers
|
|
13596
14078
|
*/
|
|
13597
|
-
_closeFile(
|
|
13598
|
-
const closers = this._closers.get(
|
|
14079
|
+
_closeFile(path30) {
|
|
14080
|
+
const closers = this._closers.get(path30);
|
|
13599
14081
|
if (!closers)
|
|
13600
14082
|
return;
|
|
13601
14083
|
closers.forEach((closer) => closer());
|
|
13602
|
-
this._closers.delete(
|
|
14084
|
+
this._closers.delete(path30);
|
|
13603
14085
|
}
|
|
13604
|
-
_addPathCloser(
|
|
14086
|
+
_addPathCloser(path30, closer) {
|
|
13605
14087
|
if (!closer)
|
|
13606
14088
|
return;
|
|
13607
|
-
let list = this._closers.get(
|
|
14089
|
+
let list = this._closers.get(path30);
|
|
13608
14090
|
if (!list) {
|
|
13609
14091
|
list = [];
|
|
13610
|
-
this._closers.set(
|
|
14092
|
+
this._closers.set(path30, list);
|
|
13611
14093
|
}
|
|
13612
14094
|
list.push(closer);
|
|
13613
14095
|
}
|
|
@@ -13638,7 +14120,7 @@ var esm_default = { watch, FSWatcher };
|
|
|
13638
14120
|
|
|
13639
14121
|
// modules/dev/hot-reload-client/index.ts
|
|
13640
14122
|
init_globals();
|
|
13641
|
-
import
|
|
14123
|
+
import path16 from "path";
|
|
13642
14124
|
function setupHotReload({
|
|
13643
14125
|
app,
|
|
13644
14126
|
appDir,
|
|
@@ -13679,7 +14161,7 @@ function setupHotReload({
|
|
|
13679
14161
|
});
|
|
13680
14162
|
});
|
|
13681
14163
|
console.log(`[hot-reload-server] \u2705 SSE endpoint registered at ${route}`);
|
|
13682
|
-
const resolvedProjectRoot = projectRoot ?
|
|
14164
|
+
const resolvedProjectRoot = projectRoot ? path16.resolve(projectRoot) : path16.dirname(path16.resolve(appDir));
|
|
13683
14165
|
const watcher = esm_default.watch(resolvedProjectRoot, {
|
|
13684
14166
|
ignoreInitial: true,
|
|
13685
14167
|
ignored: [
|
|
@@ -13719,11 +14201,11 @@ function setupHotReload({
|
|
|
13719
14201
|
let broadcastTimeout = null;
|
|
13720
14202
|
const BROADCAST_DEBOUNCE_MS = 300;
|
|
13721
14203
|
async function broadcastReload(reason, filePath) {
|
|
13722
|
-
const normalizedPath =
|
|
14204
|
+
const normalizedPath = path16.normalize(filePath);
|
|
13723
14205
|
if (normalizedPath.includes(BUILD_FOLDER_NAME) || normalizedPath.includes(".loly") || normalizedPath.endsWith(".map") || normalizedPath.endsWith(".log") || normalizedPath.includes("route-chunks.json") || normalizedPath.includes("routes-client.ts") || normalizedPath.includes("/client/route-")) {
|
|
13724
14206
|
return;
|
|
13725
14207
|
}
|
|
13726
|
-
const rel =
|
|
14208
|
+
const rel = path16.relative(appDir, filePath);
|
|
13727
14209
|
console.log(`[hot-reload] ${reason}: ${rel}`);
|
|
13728
14210
|
if (broadcastTimeout) {
|
|
13729
14211
|
clearTimeout(broadcastTimeout);
|
|
@@ -13773,9 +14255,9 @@ data: reload:${rel}
|
|
|
13773
14255
|
}
|
|
13774
14256
|
|
|
13775
14257
|
// modules/dev/hot-reload-server/index.ts
|
|
13776
|
-
import
|
|
14258
|
+
import path17 from "path";
|
|
13777
14259
|
function clearAppRequireCache(appDir) {
|
|
13778
|
-
const appDirNormalized =
|
|
14260
|
+
const appDirNormalized = path17.resolve(appDir);
|
|
13779
14261
|
for (const id of Object.keys(__require.cache)) {
|
|
13780
14262
|
if (id.startsWith(appDirNormalized)) {
|
|
13781
14263
|
delete __require.cache[id];
|
|
@@ -13788,8 +14270,8 @@ init_globals();
|
|
|
13788
14270
|
|
|
13789
14271
|
// src/config.ts
|
|
13790
14272
|
init_globals();
|
|
13791
|
-
import
|
|
13792
|
-
import
|
|
14273
|
+
import path18 from "path";
|
|
14274
|
+
import fs16 from "fs";
|
|
13793
14275
|
var DEFAULT_CONFIG = {
|
|
13794
14276
|
directories: {
|
|
13795
14277
|
app: "app",
|
|
@@ -13855,8 +14337,8 @@ function validateConfig(config, projectRoot) {
|
|
|
13855
14337
|
if (!config.directories.app || typeof config.directories.app !== "string") {
|
|
13856
14338
|
errors.push("config.directories.app must be a non-empty string");
|
|
13857
14339
|
} else {
|
|
13858
|
-
const appDir =
|
|
13859
|
-
if (!
|
|
14340
|
+
const appDir = path18.join(projectRoot, config.directories.app);
|
|
14341
|
+
if (!fs16.existsSync(appDir) && process.env.NODE_ENV !== "test") {
|
|
13860
14342
|
errors.push(
|
|
13861
14343
|
`App directory not found: ${config.directories.app}
|
|
13862
14344
|
Expected at: ${appDir}
|
|
@@ -13960,17 +14442,17 @@ function validateConfig(config, projectRoot) {
|
|
|
13960
14442
|
}
|
|
13961
14443
|
function loadConfig(projectRoot) {
|
|
13962
14444
|
const configFiles = [
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
14445
|
+
path18.join(projectRoot, "loly.config.ts"),
|
|
14446
|
+
path18.join(projectRoot, "loly.config.js"),
|
|
14447
|
+
path18.join(projectRoot, "loly.config.json")
|
|
13966
14448
|
];
|
|
13967
14449
|
let userConfig = {};
|
|
13968
14450
|
let loadedConfigFile = null;
|
|
13969
14451
|
for (const configFile of configFiles) {
|
|
13970
|
-
if (
|
|
14452
|
+
if (fs16.existsSync(configFile)) {
|
|
13971
14453
|
try {
|
|
13972
14454
|
if (configFile.endsWith(".json")) {
|
|
13973
|
-
const content =
|
|
14455
|
+
const content = fs16.readFileSync(configFile, "utf-8");
|
|
13974
14456
|
userConfig = JSON.parse(content);
|
|
13975
14457
|
} else {
|
|
13976
14458
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -13979,12 +14461,12 @@ function loadConfig(projectRoot) {
|
|
|
13979
14461
|
const mod = __require(configFile);
|
|
13980
14462
|
userConfig = typeof mod.default === "function" ? mod.default(process.env.NODE_ENV) : mod.default || mod.config || mod;
|
|
13981
14463
|
}
|
|
13982
|
-
loadedConfigFile =
|
|
14464
|
+
loadedConfigFile = path18.relative(projectRoot, configFile);
|
|
13983
14465
|
break;
|
|
13984
14466
|
} catch (error) {
|
|
13985
14467
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
13986
14468
|
throw new ConfigValidationError(
|
|
13987
|
-
`Failed to load configuration from ${
|
|
14469
|
+
`Failed to load configuration from ${path18.relative(projectRoot, configFile)}:
|
|
13988
14470
|
${errorMessage}
|
|
13989
14471
|
\u{1F4A1} Suggestion: Check that your config file exports a valid configuration object`
|
|
13990
14472
|
);
|
|
@@ -14008,20 +14490,20 @@ ${error.message}`;
|
|
|
14008
14490
|
return config;
|
|
14009
14491
|
}
|
|
14010
14492
|
function getAppDir(projectRoot, config) {
|
|
14011
|
-
return
|
|
14493
|
+
return path18.resolve(projectRoot, config.directories.app);
|
|
14012
14494
|
}
|
|
14013
14495
|
function getBuildDir(projectRoot, config) {
|
|
14014
|
-
return
|
|
14496
|
+
return path18.join(projectRoot, config.directories.build);
|
|
14015
14497
|
}
|
|
14016
14498
|
function getStaticDir(projectRoot, config) {
|
|
14017
|
-
return
|
|
14499
|
+
return path18.resolve(projectRoot, config.directories.static);
|
|
14018
14500
|
}
|
|
14019
14501
|
|
|
14020
14502
|
// modules/server/setup.ts
|
|
14021
14503
|
function setupStaticFiles(app, projectRoot, config) {
|
|
14022
14504
|
if (!config) return;
|
|
14023
14505
|
const staticDir = getStaticDir(projectRoot, config);
|
|
14024
|
-
if (
|
|
14506
|
+
if (fs17.existsSync(staticDir)) {
|
|
14025
14507
|
app.use(
|
|
14026
14508
|
express.static(staticDir, {
|
|
14027
14509
|
// In production, add caching headers for better performance
|
|
@@ -14047,7 +14529,7 @@ function setupServer(app, options) {
|
|
|
14047
14529
|
var getRoutes = getRoutes2;
|
|
14048
14530
|
const { outDir, waitForBuild } = startClientBundler(projectRoot, "development");
|
|
14049
14531
|
const onFileChange = async (filePath) => {
|
|
14050
|
-
const rel =
|
|
14532
|
+
const rel = path19.relative(appDir, filePath);
|
|
14051
14533
|
const isPageFile = filePath.includes("page.tsx") || filePath.includes("page.ts") || filePath.includes("layout.tsx") || filePath.includes("layout.ts") || filePath.includes("_not-found") || filePath.includes("_error");
|
|
14052
14534
|
const isTsFile = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
|
|
14053
14535
|
if (isTsFile) {
|
|
@@ -14083,8 +14565,8 @@ function setupServer(app, options) {
|
|
|
14083
14565
|
const wssRoutes = routeLoader.loadWssRoutes();
|
|
14084
14566
|
const notFoundPage = routeLoader.loadNotFoundRoute();
|
|
14085
14567
|
const errorPage = routeLoader.loadErrorRoute();
|
|
14086
|
-
const buildDir = config ? getBuildDir(projectRoot, config) :
|
|
14087
|
-
const clientOutDir =
|
|
14568
|
+
const buildDir = config ? getBuildDir(projectRoot, config) : path19.join(projectRoot, BUILD_FOLDER_NAME);
|
|
14569
|
+
const clientOutDir = path19.join(buildDir, "client");
|
|
14088
14570
|
app.use(
|
|
14089
14571
|
"/static",
|
|
14090
14572
|
express.static(clientOutDir, {
|
|
@@ -14293,12 +14775,12 @@ var DEFAULT_IGNORED_PATHS = [
|
|
|
14293
14775
|
/^\/sockjs-node/
|
|
14294
14776
|
// Hot reload websocket
|
|
14295
14777
|
];
|
|
14296
|
-
function shouldIgnorePath(
|
|
14778
|
+
function shouldIgnorePath(path30, ignoredPaths) {
|
|
14297
14779
|
return ignoredPaths.some((pattern) => {
|
|
14298
14780
|
if (typeof pattern === "string") {
|
|
14299
|
-
return
|
|
14781
|
+
return path30 === pattern || path30.startsWith(pattern);
|
|
14300
14782
|
}
|
|
14301
|
-
return pattern.test(
|
|
14783
|
+
return pattern.test(path30);
|
|
14302
14784
|
});
|
|
14303
14785
|
}
|
|
14304
14786
|
function requestLoggerMiddleware(options = {}) {
|
|
@@ -14457,11 +14939,11 @@ function createStrictRateLimiterFromConfig(config) {
|
|
|
14457
14939
|
}
|
|
14458
14940
|
|
|
14459
14941
|
// modules/server/middleware/auto-rate-limit.ts
|
|
14460
|
-
function matchesStrictPattern(
|
|
14942
|
+
function matchesStrictPattern(path30, patterns) {
|
|
14461
14943
|
for (const pattern of patterns) {
|
|
14462
14944
|
const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
|
|
14463
14945
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
14464
|
-
if (regex.test(
|
|
14946
|
+
if (regex.test(path30)) {
|
|
14465
14947
|
return true;
|
|
14466
14948
|
}
|
|
14467
14949
|
}
|
|
@@ -14496,8 +14978,31 @@ function getAutoRateLimiter(route, strictPatterns = [], rateLimitConfig) {
|
|
|
14496
14978
|
|
|
14497
14979
|
// modules/server/handlers/api.ts
|
|
14498
14980
|
async function handleApiRequest(options) {
|
|
14499
|
-
const { apiRoutes, urlPath, req, res, env = "dev" } = options;
|
|
14500
|
-
|
|
14981
|
+
const { apiRoutes, urlPath, req, res, env = "dev", rewriteLoader } = options;
|
|
14982
|
+
let finalUrlPath = urlPath;
|
|
14983
|
+
let extractedParams = {};
|
|
14984
|
+
if (rewriteLoader) {
|
|
14985
|
+
try {
|
|
14986
|
+
const compiledRewrites = await rewriteLoader.loadRewrites();
|
|
14987
|
+
const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
|
|
14988
|
+
if (rewriteResult) {
|
|
14989
|
+
finalUrlPath = rewriteResult.rewrittenPath;
|
|
14990
|
+
extractedParams = rewriteResult.extractedParams;
|
|
14991
|
+
Object.assign(req.query, extractedParams);
|
|
14992
|
+
if (!req.locals) {
|
|
14993
|
+
req.locals = {};
|
|
14994
|
+
}
|
|
14995
|
+
Object.assign(req.locals, extractedParams);
|
|
14996
|
+
}
|
|
14997
|
+
} catch (error) {
|
|
14998
|
+
const reqLogger = getRequestLogger(req);
|
|
14999
|
+
reqLogger.error("Error processing rewrites", error, {
|
|
15000
|
+
urlPath
|
|
15001
|
+
});
|
|
15002
|
+
}
|
|
15003
|
+
}
|
|
15004
|
+
finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
|
|
15005
|
+
const matched = matchApiRoute(apiRoutes, finalUrlPath);
|
|
14501
15006
|
if (!matched) {
|
|
14502
15007
|
res.status(404).json({ error: "Not Found" });
|
|
14503
15008
|
return;
|
|
@@ -14518,9 +15023,13 @@ async function handleApiRequest(options) {
|
|
|
14518
15023
|
Response: (body = {}, status = 200) => res.status(status).json(body),
|
|
14519
15024
|
NotFound: (body = {}) => res.status(404).json(body),
|
|
14520
15025
|
params: sanitizedParams,
|
|
14521
|
-
pathname:
|
|
15026
|
+
pathname: finalUrlPath,
|
|
15027
|
+
// Use rewritten path
|
|
14522
15028
|
locals: {}
|
|
14523
15029
|
};
|
|
15030
|
+
if (extractedParams && Object.keys(extractedParams).length > 0) {
|
|
15031
|
+
Object.assign(ctx.locals, extractedParams);
|
|
15032
|
+
}
|
|
14524
15033
|
req.query = sanitizedQuery;
|
|
14525
15034
|
try {
|
|
14526
15035
|
const autoRateLimiter = getAutoRateLimiter(
|
|
@@ -15014,7 +15523,7 @@ var buildRouterData = (req) => {
|
|
|
15014
15523
|
};
|
|
15015
15524
|
|
|
15016
15525
|
// modules/server/handlers/middleware.ts
|
|
15017
|
-
import
|
|
15526
|
+
import path20 from "path";
|
|
15018
15527
|
async function runRouteMiddlewares(route, ctx) {
|
|
15019
15528
|
for (let i = 0; i < route.middlewares.length; i++) {
|
|
15020
15529
|
const mw = route.middlewares[i];
|
|
@@ -15025,7 +15534,7 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
15025
15534
|
);
|
|
15026
15535
|
} catch (error) {
|
|
15027
15536
|
const reqLogger = getRequestLogger(ctx.req);
|
|
15028
|
-
const relativePath = route.pageFile ?
|
|
15537
|
+
const relativePath = route.pageFile ? path20.relative(process.cwd(), route.pageFile) : route.pattern;
|
|
15029
15538
|
reqLogger.error("Route middleware failed", error instanceof Error ? error : new Error(String(error)), {
|
|
15030
15539
|
route: route.pattern,
|
|
15031
15540
|
middlewareIndex: i,
|
|
@@ -15040,7 +15549,7 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
15040
15549
|
}
|
|
15041
15550
|
|
|
15042
15551
|
// modules/server/handlers/server-hook.ts
|
|
15043
|
-
import
|
|
15552
|
+
import path21 from "path";
|
|
15044
15553
|
function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
|
|
15045
15554
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15046
15555
|
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
@@ -15049,7 +15558,7 @@ function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
|
|
|
15049
15558
|
message += `Route: ${routePattern}
|
|
15050
15559
|
`;
|
|
15051
15560
|
if (filePath) {
|
|
15052
|
-
const relativePath =
|
|
15561
|
+
const relativePath = path21.relative(process.cwd(), filePath);
|
|
15053
15562
|
message += `File: ${relativePath}
|
|
15054
15563
|
`;
|
|
15055
15564
|
}
|
|
@@ -15110,7 +15619,9 @@ function handleDataResponse(res, loaderResult, theme, layoutProps, pageProps, er
|
|
|
15110
15619
|
// Combined props for backward compatibility
|
|
15111
15620
|
props: loaderResult.props ?? {},
|
|
15112
15621
|
metadata: loaderResult.metadata ?? null,
|
|
15113
|
-
theme: loaderResult.theme ?? theme ?? null
|
|
15622
|
+
theme: loaderResult.theme ?? theme ?? null,
|
|
15623
|
+
// Include pathname if provided (for rewrites - client needs to know the rewritten path)
|
|
15624
|
+
...loaderResult.pathname ? { pathname: loaderResult.pathname } : {}
|
|
15114
15625
|
};
|
|
15115
15626
|
if (layoutProps !== void 0 && layoutProps !== null) {
|
|
15116
15627
|
response.layoutProps = layoutProps;
|
|
@@ -15142,24 +15653,24 @@ function handleNotFound(res, urlPath) {
|
|
|
15142
15653
|
}
|
|
15143
15654
|
|
|
15144
15655
|
// modules/server/handlers/ssg.ts
|
|
15145
|
-
import
|
|
15146
|
-
import
|
|
15656
|
+
import fs18 from "fs";
|
|
15657
|
+
import path22 from "path";
|
|
15147
15658
|
var logger3 = createModuleLogger("ssg");
|
|
15148
15659
|
function getSsgDirForPath(baseDir, urlPath) {
|
|
15149
15660
|
const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
|
|
15150
|
-
return
|
|
15661
|
+
return path22.join(baseDir, clean);
|
|
15151
15662
|
}
|
|
15152
15663
|
function getSsgHtmlPath(baseDir, urlPath) {
|
|
15153
15664
|
const dir = getSsgDirForPath(baseDir, urlPath);
|
|
15154
|
-
return
|
|
15665
|
+
return path22.join(dir, "index.html");
|
|
15155
15666
|
}
|
|
15156
15667
|
function getSsgDataPath(baseDir, urlPath) {
|
|
15157
15668
|
const dir = getSsgDirForPath(baseDir, urlPath);
|
|
15158
|
-
return
|
|
15669
|
+
return path22.join(dir, "data.json");
|
|
15159
15670
|
}
|
|
15160
15671
|
function tryServeSsgHtml(res, ssgOutDir, urlPath) {
|
|
15161
15672
|
const ssgHtmlPath = getSsgHtmlPath(ssgOutDir, urlPath);
|
|
15162
|
-
if (!
|
|
15673
|
+
if (!fs18.existsSync(ssgHtmlPath)) {
|
|
15163
15674
|
return false;
|
|
15164
15675
|
}
|
|
15165
15676
|
logger3.info("Serving SSG HTML", { urlPath, ssgHtmlPath });
|
|
@@ -15169,17 +15680,17 @@ function tryServeSsgHtml(res, ssgOutDir, urlPath) {
|
|
|
15169
15680
|
);
|
|
15170
15681
|
res.statusCode = 200;
|
|
15171
15682
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
15172
|
-
const stream =
|
|
15683
|
+
const stream = fs18.createReadStream(ssgHtmlPath, { encoding: "utf-8" });
|
|
15173
15684
|
stream.pipe(res);
|
|
15174
15685
|
return true;
|
|
15175
15686
|
}
|
|
15176
15687
|
function tryServeSsgData(res, ssgOutDir, urlPath) {
|
|
15177
15688
|
const ssgDataPath = getSsgDataPath(ssgOutDir, urlPath);
|
|
15178
|
-
if (!
|
|
15689
|
+
if (!fs18.existsSync(ssgDataPath)) {
|
|
15179
15690
|
return false;
|
|
15180
15691
|
}
|
|
15181
15692
|
try {
|
|
15182
|
-
const raw =
|
|
15693
|
+
const raw = fs18.readFileSync(ssgDataPath, "utf-8");
|
|
15183
15694
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
15184
15695
|
res.status(200).end(raw);
|
|
15185
15696
|
return true;
|
|
@@ -15191,7 +15702,7 @@ function tryServeSsgData(res, ssgOutDir, urlPath) {
|
|
|
15191
15702
|
|
|
15192
15703
|
// modules/server/handlers/pages.ts
|
|
15193
15704
|
init_globals();
|
|
15194
|
-
import
|
|
15705
|
+
import path23 from "path";
|
|
15195
15706
|
function mergeMetadata(base, override) {
|
|
15196
15707
|
if (!base && !override) return null;
|
|
15197
15708
|
if (!base) return override;
|
|
@@ -15258,8 +15769,43 @@ async function handlePageRequestInternal(options) {
|
|
|
15258
15769
|
ssgOutDir,
|
|
15259
15770
|
theme,
|
|
15260
15771
|
projectRoot,
|
|
15261
|
-
config
|
|
15772
|
+
config,
|
|
15773
|
+
rewriteLoader
|
|
15262
15774
|
} = options;
|
|
15775
|
+
let finalUrlPath = urlPath;
|
|
15776
|
+
let extractedParams = {};
|
|
15777
|
+
if (rewriteLoader) {
|
|
15778
|
+
try {
|
|
15779
|
+
const compiledRewrites = await rewriteLoader.loadRewrites();
|
|
15780
|
+
const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
|
|
15781
|
+
if (rewriteResult) {
|
|
15782
|
+
finalUrlPath = rewriteResult.rewrittenPath;
|
|
15783
|
+
extractedParams = rewriteResult.extractedParams;
|
|
15784
|
+
finalUrlPath = finalUrlPath.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
|
|
15785
|
+
if (env === "dev") {
|
|
15786
|
+
const reqLogger2 = getRequestLogger(req);
|
|
15787
|
+
reqLogger2.debug("Rewrite applied", {
|
|
15788
|
+
originalPath: urlPath,
|
|
15789
|
+
rewrittenPath: finalUrlPath,
|
|
15790
|
+
extractedParams,
|
|
15791
|
+
host: req.get("host")
|
|
15792
|
+
});
|
|
15793
|
+
}
|
|
15794
|
+
Object.assign(req.query, extractedParams);
|
|
15795
|
+
if (!req.locals) {
|
|
15796
|
+
req.locals = {};
|
|
15797
|
+
}
|
|
15798
|
+
Object.assign(req.locals, extractedParams);
|
|
15799
|
+
}
|
|
15800
|
+
} catch (error) {
|
|
15801
|
+
const reqLogger2 = getRequestLogger(req);
|
|
15802
|
+
reqLogger2.error("Error processing rewrites", error, {
|
|
15803
|
+
urlPath,
|
|
15804
|
+
host: req.get("host")
|
|
15805
|
+
});
|
|
15806
|
+
}
|
|
15807
|
+
}
|
|
15808
|
+
finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
|
|
15263
15809
|
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
15264
15810
|
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
15265
15811
|
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
@@ -15268,18 +15814,43 @@ async function handlePageRequestInternal(options) {
|
|
|
15268
15814
|
const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
|
|
15269
15815
|
if (env === "prod" && ssgOutDir) {
|
|
15270
15816
|
if (isDataReq) {
|
|
15271
|
-
if (tryServeSsgData(res, ssgOutDir,
|
|
15817
|
+
if (tryServeSsgData(res, ssgOutDir, finalUrlPath)) {
|
|
15272
15818
|
return;
|
|
15273
15819
|
}
|
|
15274
15820
|
} else {
|
|
15275
|
-
if (tryServeSsgHtml(res, ssgOutDir,
|
|
15821
|
+
if (tryServeSsgHtml(res, ssgOutDir, finalUrlPath)) {
|
|
15276
15822
|
return;
|
|
15277
15823
|
}
|
|
15278
15824
|
}
|
|
15279
15825
|
}
|
|
15280
|
-
const matched = matchRoute(routes,
|
|
15826
|
+
const matched = matchRoute(routes, finalUrlPath);
|
|
15827
|
+
if (env === "dev") {
|
|
15828
|
+
const reqLogger2 = getRequestLogger(req);
|
|
15829
|
+
if (finalUrlPath !== urlPath) {
|
|
15830
|
+
reqLogger2.debug("Route matching after rewrite", {
|
|
15831
|
+
originalPath: urlPath,
|
|
15832
|
+
rewrittenPath: finalUrlPath,
|
|
15833
|
+
matched: !!matched,
|
|
15834
|
+
matchedRoute: matched?.route.pattern,
|
|
15835
|
+
matchedParams: matched?.params,
|
|
15836
|
+
availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
|
|
15837
|
+
// Show first 10 routes
|
|
15838
|
+
});
|
|
15839
|
+
} else if (!matched) {
|
|
15840
|
+
reqLogger2.debug("No route match found", {
|
|
15841
|
+
path: finalUrlPath,
|
|
15842
|
+
availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
|
|
15843
|
+
});
|
|
15844
|
+
}
|
|
15845
|
+
}
|
|
15281
15846
|
const routerData = buildRouterData(req);
|
|
15282
15847
|
if (!matched) {
|
|
15848
|
+
if (isDataReq) {
|
|
15849
|
+
res.statusCode = 404;
|
|
15850
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
15851
|
+
res.end(JSON.stringify({ notFound: true, pathname: finalUrlPath }));
|
|
15852
|
+
return;
|
|
15853
|
+
}
|
|
15283
15854
|
if (notFoundPage) {
|
|
15284
15855
|
const ctx2 = {
|
|
15285
15856
|
req,
|
|
@@ -15303,7 +15874,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15303
15874
|
} catch (error) {
|
|
15304
15875
|
const reqLogger2 = getRequestLogger(req);
|
|
15305
15876
|
const layoutFile = notFoundPage.layoutFiles[i];
|
|
15306
|
-
const relativeLayoutPath = layoutFile ?
|
|
15877
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15307
15878
|
reqLogger2.error("Layout middleware failed for not-found page", error instanceof Error ? error : new Error(String(error)), {
|
|
15308
15879
|
layoutIndex: i,
|
|
15309
15880
|
layoutFile: relativeLayoutPath
|
|
@@ -15324,7 +15895,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15324
15895
|
} catch (error) {
|
|
15325
15896
|
const reqLogger2 = getRequestLogger(req);
|
|
15326
15897
|
const layoutFile = notFoundPage.layoutFiles[i];
|
|
15327
|
-
const relativeLayoutPath = layoutFile ?
|
|
15898
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15328
15899
|
reqLogger2.warn("Layout server hook failed for not-found page", {
|
|
15329
15900
|
error: error instanceof Error ? error.message : String(error),
|
|
15330
15901
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -15358,7 +15929,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15358
15929
|
);
|
|
15359
15930
|
return;
|
|
15360
15931
|
}
|
|
15361
|
-
const initialData2 = buildInitialData(
|
|
15932
|
+
const initialData2 = buildInitialData(finalUrlPath, {}, combinedLoaderResult2);
|
|
15362
15933
|
const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
|
|
15363
15934
|
initialData2.notFound = true;
|
|
15364
15935
|
const nonce2 = res.locals.nonce || void 0;
|
|
@@ -15444,7 +16015,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15444
16015
|
);
|
|
15445
16016
|
} catch (error) {
|
|
15446
16017
|
const layoutFile = route.layoutFiles[i];
|
|
15447
|
-
const relativeLayoutPath = layoutFile ?
|
|
16018
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15448
16019
|
reqLogger.error("Layout middleware failed", error instanceof Error ? error : new Error(String(error)), {
|
|
15449
16020
|
route: route.pattern,
|
|
15450
16021
|
layoutIndex: i,
|
|
@@ -15468,7 +16039,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15468
16039
|
}
|
|
15469
16040
|
} catch (error) {
|
|
15470
16041
|
const layoutFile = route.layoutFiles[i];
|
|
15471
|
-
const relativeLayoutPath = layoutFile ?
|
|
16042
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15472
16043
|
reqLogger.warn("Layout server hook failed", {
|
|
15473
16044
|
error: error instanceof Error ? error.message : String(error),
|
|
15474
16045
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -15488,7 +16059,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15488
16059
|
loaderResult.theme = theme;
|
|
15489
16060
|
}
|
|
15490
16061
|
} catch (error) {
|
|
15491
|
-
const relativePagePath = route.pageFile ?
|
|
16062
|
+
const relativePagePath = route.pageFile ? path23.relative(projectRoot || process.cwd(), route.pageFile) : "unknown";
|
|
15492
16063
|
reqLogger.error("Page server hook failed", {
|
|
15493
16064
|
error: error instanceof Error ? error.message : String(error),
|
|
15494
16065
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -15535,7 +16106,9 @@ async function handlePageRequestInternal(options) {
|
|
|
15535
16106
|
const combinedLoaderResult = {
|
|
15536
16107
|
...loaderResult,
|
|
15537
16108
|
props: combinedProps,
|
|
15538
|
-
metadata: combinedMetadata
|
|
16109
|
+
metadata: combinedMetadata,
|
|
16110
|
+
pathname: finalUrlPath
|
|
16111
|
+
// Include rewritten pathname for client-side matching
|
|
15539
16112
|
};
|
|
15540
16113
|
if (isDataReq) {
|
|
15541
16114
|
const pagePropsOnly = loaderResult.props || {};
|
|
@@ -15560,7 +16133,7 @@ async function handlePageRequestInternal(options) {
|
|
|
15560
16133
|
}
|
|
15561
16134
|
return;
|
|
15562
16135
|
}
|
|
15563
|
-
const initialData = buildInitialData(
|
|
16136
|
+
const initialData = buildInitialData(finalUrlPath, params, combinedLoaderResult);
|
|
15564
16137
|
const appTree = buildAppTree(route, params, initialData.props);
|
|
15565
16138
|
const chunkName = routeChunks[route.pattern];
|
|
15566
16139
|
let chunkHref = null;
|
|
@@ -15665,7 +16238,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
15665
16238
|
);
|
|
15666
16239
|
} catch (error2) {
|
|
15667
16240
|
const layoutFile = errorPage.layoutFiles[i];
|
|
15668
|
-
const relativeLayoutPath = layoutFile ?
|
|
16241
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15669
16242
|
reqLogger.error("Layout middleware failed for error page", error2 instanceof Error ? error2 : new Error(String(error2)), {
|
|
15670
16243
|
layoutIndex: i,
|
|
15671
16244
|
layoutFile: relativeLayoutPath
|
|
@@ -15685,7 +16258,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
15685
16258
|
}
|
|
15686
16259
|
} catch (err) {
|
|
15687
16260
|
const layoutFile = errorPage.layoutFiles[i];
|
|
15688
|
-
const relativeLayoutPath = layoutFile ?
|
|
16261
|
+
const relativeLayoutPath = layoutFile ? path23.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
15689
16262
|
reqLogger.warn("Layout server hook failed for error page", {
|
|
15690
16263
|
error: err instanceof Error ? err.message : String(err),
|
|
15691
16264
|
stack: err instanceof Error ? err.stack : void 0,
|
|
@@ -15961,7 +16534,19 @@ function validateRealtimeConfig(config) {
|
|
|
15961
16534
|
}
|
|
15962
16535
|
|
|
15963
16536
|
// modules/server/routes.ts
|
|
15964
|
-
import
|
|
16537
|
+
import path24 from "path";
|
|
16538
|
+
var cachedRewriteLoader = null;
|
|
16539
|
+
var cachedProjectRoot = null;
|
|
16540
|
+
var cachedIsDev = null;
|
|
16541
|
+
function getRewriteLoader(projectRoot, isDev) {
|
|
16542
|
+
if (cachedRewriteLoader && cachedProjectRoot === projectRoot && cachedIsDev === isDev) {
|
|
16543
|
+
return cachedRewriteLoader;
|
|
16544
|
+
}
|
|
16545
|
+
cachedRewriteLoader = createRewriteLoader(projectRoot, isDev);
|
|
16546
|
+
cachedProjectRoot = projectRoot;
|
|
16547
|
+
cachedIsDev = isDev;
|
|
16548
|
+
return cachedRewriteLoader;
|
|
16549
|
+
}
|
|
15965
16550
|
function setupRoutes(options) {
|
|
15966
16551
|
const {
|
|
15967
16552
|
app,
|
|
@@ -15976,8 +16561,9 @@ function setupRoutes(options) {
|
|
|
15976
16561
|
config
|
|
15977
16562
|
} = options;
|
|
15978
16563
|
const routeChunks = routeLoader.loadRouteChunks();
|
|
15979
|
-
const
|
|
15980
|
-
|
|
16564
|
+
const rewriteLoader = getRewriteLoader(projectRoot, isDev);
|
|
16565
|
+
const ssgOutDir = path24.join(
|
|
16566
|
+
config ? getBuildDir(projectRoot, config) : path24.join(projectRoot, BUILD_FOLDER_NAME),
|
|
15981
16567
|
"ssg"
|
|
15982
16568
|
);
|
|
15983
16569
|
app.all("/api/*", async (req, res) => {
|
|
@@ -15992,7 +16578,8 @@ function setupRoutes(options) {
|
|
|
15992
16578
|
res,
|
|
15993
16579
|
env: isDev ? "dev" : "prod",
|
|
15994
16580
|
strictRateLimitPatterns: strictPatterns,
|
|
15995
|
-
rateLimitConfig
|
|
16581
|
+
rateLimitConfig,
|
|
16582
|
+
rewriteLoader
|
|
15996
16583
|
});
|
|
15997
16584
|
});
|
|
15998
16585
|
app.get("*", async (req, res) => {
|
|
@@ -16015,7 +16602,8 @@ function setupRoutes(options) {
|
|
|
16015
16602
|
ssgOutDir,
|
|
16016
16603
|
theme: req.cookies?.theme || "light",
|
|
16017
16604
|
projectRoot,
|
|
16018
|
-
config
|
|
16605
|
+
config,
|
|
16606
|
+
rewriteLoader
|
|
16019
16607
|
});
|
|
16020
16608
|
});
|
|
16021
16609
|
}
|
|
@@ -17204,8 +17792,8 @@ var setupApplication = async ({
|
|
|
17204
17792
|
|
|
17205
17793
|
// src/server.ts
|
|
17206
17794
|
import dotenv2 from "dotenv";
|
|
17207
|
-
var envPath =
|
|
17208
|
-
if (
|
|
17795
|
+
var envPath = path25.join(process.cwd(), ".env");
|
|
17796
|
+
if (fs19.existsSync(envPath)) {
|
|
17209
17797
|
dotenv2.config({ path: envPath });
|
|
17210
17798
|
} else {
|
|
17211
17799
|
dotenv2.config();
|
|
@@ -17226,8 +17814,8 @@ async function startServer(options = {}) {
|
|
|
17226
17814
|
}
|
|
17227
17815
|
const port = options.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : void 0) ?? config.server.port;
|
|
17228
17816
|
const host = process.env.HOST ?? (!isDev ? "0.0.0.0" : void 0) ?? config.server.host;
|
|
17229
|
-
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) :
|
|
17230
|
-
if (!isDev && !
|
|
17817
|
+
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : path25.join(getBuildDir(projectRoot, config), "server"));
|
|
17818
|
+
if (!isDev && !fs19.existsSync(appDir)) {
|
|
17231
17819
|
logger4.error("Compiled directory not found", void 0, {
|
|
17232
17820
|
buildDir: config.directories.build,
|
|
17233
17821
|
appDir,
|
|
@@ -17298,10 +17886,10 @@ async function startProdServer(options = {}) {
|
|
|
17298
17886
|
}
|
|
17299
17887
|
|
|
17300
17888
|
// modules/build/ssg/builder.ts
|
|
17301
|
-
import
|
|
17889
|
+
import path28 from "path";
|
|
17302
17890
|
|
|
17303
17891
|
// modules/build/ssg/path.ts
|
|
17304
|
-
import
|
|
17892
|
+
import path26 from "path";
|
|
17305
17893
|
function buildPathFromPattern(pattern, params) {
|
|
17306
17894
|
const segments = pattern.split("/").filter(Boolean);
|
|
17307
17895
|
const parts = [];
|
|
@@ -17330,12 +17918,12 @@ function buildPathFromPattern(pattern, params) {
|
|
|
17330
17918
|
}
|
|
17331
17919
|
function pathToOutDir(baseDir, urlPath) {
|
|
17332
17920
|
const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
|
|
17333
|
-
return
|
|
17921
|
+
return path26.join(baseDir, clean);
|
|
17334
17922
|
}
|
|
17335
17923
|
|
|
17336
17924
|
// modules/build/ssg/renderer.ts
|
|
17337
|
-
import
|
|
17338
|
-
import
|
|
17925
|
+
import fs20 from "fs";
|
|
17926
|
+
import path27 from "path";
|
|
17339
17927
|
import { renderToString } from "react-dom/server";
|
|
17340
17928
|
init_globals();
|
|
17341
17929
|
async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
|
|
@@ -17459,16 +18047,16 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params,
|
|
|
17459
18047
|
const html = "<!DOCTYPE html>" + renderToString(documentTree);
|
|
17460
18048
|
const dir = pathToOutDir(ssgOutDir, urlPath);
|
|
17461
18049
|
ensureDir(dir);
|
|
17462
|
-
const htmlFile =
|
|
17463
|
-
const dataFile =
|
|
17464
|
-
|
|
17465
|
-
|
|
18050
|
+
const htmlFile = path27.join(dir, "index.html");
|
|
18051
|
+
const dataFile = path27.join(dir, "data.json");
|
|
18052
|
+
fs20.writeFileSync(htmlFile, html, "utf-8");
|
|
18053
|
+
fs20.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
|
|
17466
18054
|
}
|
|
17467
18055
|
|
|
17468
18056
|
// modules/build/ssg/builder.ts
|
|
17469
18057
|
init_globals();
|
|
17470
18058
|
async function buildStaticPages(projectRoot, routes, config) {
|
|
17471
|
-
const ssgOutDir =
|
|
18059
|
+
const ssgOutDir = path28.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
|
|
17472
18060
|
ensureDir(ssgOutDir);
|
|
17473
18061
|
for (const route of routes) {
|
|
17474
18062
|
if (route.dynamic !== "force-static") continue;
|
|
@@ -17523,36 +18111,36 @@ async function buildStaticPages(projectRoot, routes, config) {
|
|
|
17523
18111
|
}
|
|
17524
18112
|
|
|
17525
18113
|
// modules/build/bundler/server.ts
|
|
17526
|
-
import
|
|
17527
|
-
import
|
|
18114
|
+
import path29 from "path";
|
|
18115
|
+
import fs21 from "fs";
|
|
17528
18116
|
import esbuild from "esbuild";
|
|
17529
18117
|
init_globals();
|
|
17530
18118
|
var SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];
|
|
17531
18119
|
function createPathAliasPlugin(projectRoot, outDir) {
|
|
17532
18120
|
const aliases = loadAliasesFromTsconfig(projectRoot);
|
|
17533
|
-
const tsconfigPath =
|
|
18121
|
+
const tsconfigPath = path29.join(projectRoot, "tsconfig.json");
|
|
17534
18122
|
let baseUrl = ".";
|
|
17535
|
-
if (
|
|
18123
|
+
if (fs21.existsSync(tsconfigPath)) {
|
|
17536
18124
|
try {
|
|
17537
|
-
const tsconfig = JSON.parse(
|
|
18125
|
+
const tsconfig = JSON.parse(fs21.readFileSync(tsconfigPath, "utf-8"));
|
|
17538
18126
|
baseUrl = tsconfig.compilerOptions?.baseUrl ?? ".";
|
|
17539
18127
|
} catch {
|
|
17540
18128
|
}
|
|
17541
18129
|
}
|
|
17542
18130
|
function resolveAliasToRelative(importPath, sourceFile) {
|
|
17543
|
-
if (importPath.startsWith(".") || importPath.startsWith("/") ||
|
|
18131
|
+
if (importPath.startsWith(".") || importPath.startsWith("/") || path29.isAbsolute(importPath) || importPath.includes("node_modules")) {
|
|
17544
18132
|
return null;
|
|
17545
18133
|
}
|
|
17546
18134
|
for (const [aliasKey, aliasPath] of Object.entries(aliases)) {
|
|
17547
18135
|
if (importPath.startsWith(aliasKey + "/") || importPath === aliasKey) {
|
|
17548
18136
|
const restPath = importPath.startsWith(aliasKey + "/") ? importPath.slice(aliasKey.length + 1) : "";
|
|
17549
|
-
const resolvedPath = restPath ?
|
|
18137
|
+
const resolvedPath = restPath ? path29.join(aliasPath, restPath) : aliasPath;
|
|
17550
18138
|
let actualPath = null;
|
|
17551
18139
|
const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
|
|
17552
|
-
if (
|
|
18140
|
+
if (fs21.existsSync(resolvedPath) && fs21.statSync(resolvedPath).isDirectory()) {
|
|
17553
18141
|
for (const ext of extensions) {
|
|
17554
|
-
const indexPath =
|
|
17555
|
-
if (
|
|
18142
|
+
const indexPath = path29.join(resolvedPath, `index${ext}`);
|
|
18143
|
+
if (fs21.existsSync(indexPath)) {
|
|
17556
18144
|
actualPath = indexPath;
|
|
17557
18145
|
break;
|
|
17558
18146
|
}
|
|
@@ -17560,20 +18148,20 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
17560
18148
|
} else {
|
|
17561
18149
|
for (const ext of extensions) {
|
|
17562
18150
|
const filePath = resolvedPath + ext;
|
|
17563
|
-
if (
|
|
18151
|
+
if (fs21.existsSync(filePath)) {
|
|
17564
18152
|
actualPath = filePath;
|
|
17565
18153
|
break;
|
|
17566
18154
|
}
|
|
17567
18155
|
}
|
|
17568
|
-
if (!actualPath &&
|
|
18156
|
+
if (!actualPath && fs21.existsSync(resolvedPath)) {
|
|
17569
18157
|
actualPath = resolvedPath;
|
|
17570
18158
|
}
|
|
17571
18159
|
}
|
|
17572
18160
|
if (actualPath) {
|
|
17573
|
-
const relativePath =
|
|
18161
|
+
const relativePath = path29.relative(outDir, actualPath);
|
|
17574
18162
|
const normalizedPath = relativePath.replace(/\\/g, "/");
|
|
17575
18163
|
const finalPath = normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
|
|
17576
|
-
const ext =
|
|
18164
|
+
const ext = path29.extname(finalPath);
|
|
17577
18165
|
const pathWithoutExt = ext === ".json" ? finalPath : finalPath.slice(0, -ext.length);
|
|
17578
18166
|
return pathWithoutExt;
|
|
17579
18167
|
}
|
|
@@ -17585,13 +18173,13 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
17585
18173
|
name: "path-alias-resolver",
|
|
17586
18174
|
setup(build) {
|
|
17587
18175
|
build.onLoad({ filter: /\.(ts|tsx|js|jsx)$/ }, (args) => {
|
|
17588
|
-
const fileName =
|
|
18176
|
+
const fileName = path29.basename(args.path);
|
|
17589
18177
|
const isServerFile = SERVER_FILES.some((f) => fileName === `${f}.ts` || fileName === `${f}.tsx` || fileName === `${f}.js` || fileName === `${f}.jsx`);
|
|
17590
|
-
const isInProjectRoot =
|
|
18178
|
+
const isInProjectRoot = path29.dirname(args.path) === projectRoot;
|
|
17591
18179
|
if (!isServerFile || !isInProjectRoot) {
|
|
17592
18180
|
return null;
|
|
17593
18181
|
}
|
|
17594
|
-
const contents =
|
|
18182
|
+
const contents = fs21.readFileSync(args.path, "utf-8");
|
|
17595
18183
|
let transformed = contents;
|
|
17596
18184
|
const aliasPatterns = Object.keys(aliases).sort((a, b) => b.length - a.length);
|
|
17597
18185
|
for (const aliasKey of aliasPatterns) {
|
|
@@ -17611,7 +18199,7 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
17611
18199
|
}
|
|
17612
18200
|
return {
|
|
17613
18201
|
contents: transformed,
|
|
17614
|
-
loader:
|
|
18202
|
+
loader: path29.extname(args.path).slice(1)
|
|
17615
18203
|
};
|
|
17616
18204
|
});
|
|
17617
18205
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
@@ -17630,9 +18218,9 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
17630
18218
|
function collectAppSources(appDir) {
|
|
17631
18219
|
const entries = [];
|
|
17632
18220
|
function walk(dir) {
|
|
17633
|
-
const items =
|
|
18221
|
+
const items = fs21.readdirSync(dir, { withFileTypes: true });
|
|
17634
18222
|
for (const item of items) {
|
|
17635
|
-
const full =
|
|
18223
|
+
const full = path29.join(dir, item.name);
|
|
17636
18224
|
if (item.isDirectory()) {
|
|
17637
18225
|
walk(full);
|
|
17638
18226
|
continue;
|
|
@@ -17649,7 +18237,7 @@ function collectAppSources(appDir) {
|
|
|
17649
18237
|
return entries;
|
|
17650
18238
|
}
|
|
17651
18239
|
async function buildServerApp(projectRoot, appDir) {
|
|
17652
|
-
const outDir =
|
|
18240
|
+
const outDir = path29.join(projectRoot, BUILD_FOLDER_NAME, "server");
|
|
17653
18241
|
const entryPoints = collectAppSources(appDir);
|
|
17654
18242
|
ensureDir(outDir);
|
|
17655
18243
|
if (entryPoints.length === 0) {
|
|
@@ -17667,14 +18255,14 @@ async function buildServerApp(projectRoot, appDir) {
|
|
|
17667
18255
|
bundle: true,
|
|
17668
18256
|
splitting: false,
|
|
17669
18257
|
logLevel: "info",
|
|
17670
|
-
tsconfig:
|
|
18258
|
+
tsconfig: path29.join(projectRoot, "tsconfig.json"),
|
|
17671
18259
|
packages: "external"
|
|
17672
18260
|
});
|
|
17673
18261
|
const pathAliasPlugin = createPathAliasPlugin(projectRoot, outDir);
|
|
17674
18262
|
for (const fileName of SERVER_FILES) {
|
|
17675
|
-
const initTS =
|
|
17676
|
-
const initJS =
|
|
17677
|
-
if (
|
|
18263
|
+
const initTS = path29.join(projectRoot, `${fileName}.ts`);
|
|
18264
|
+
const initJS = path29.join(outDir, `${fileName}.js`);
|
|
18265
|
+
if (fs21.existsSync(initTS)) {
|
|
17678
18266
|
await esbuild.build({
|
|
17679
18267
|
entryPoints: [initTS],
|
|
17680
18268
|
outfile: initJS,
|
|
@@ -17685,7 +18273,7 @@ async function buildServerApp(projectRoot, appDir) {
|
|
|
17685
18273
|
sourcemap: true,
|
|
17686
18274
|
bundle: false,
|
|
17687
18275
|
logLevel: "info",
|
|
17688
|
-
tsconfig:
|
|
18276
|
+
tsconfig: path29.join(projectRoot, "tsconfig.json"),
|
|
17689
18277
|
plugins: [pathAliasPlugin]
|
|
17690
18278
|
});
|
|
17691
18279
|
}
|
|
@@ -17736,6 +18324,7 @@ async function buildApp(options = {}) {
|
|
|
17736
18324
|
});
|
|
17737
18325
|
writeClientBoostrapManifest(projectRoot);
|
|
17738
18326
|
writeClientRoutesManifest(routes, projectRoot);
|
|
18327
|
+
await writeRewritesManifest(projectRoot);
|
|
17739
18328
|
await buildClientBundle(projectRoot);
|
|
17740
18329
|
await buildStaticPages(projectRoot, routes, config);
|
|
17741
18330
|
delete process.env.LOLY_BUILD;
|
|
@@ -18444,13 +19033,22 @@ async function handleNormalRoute(nextUrl, json, routes, setState) {
|
|
|
18444
19033
|
theme
|
|
18445
19034
|
// Always include theme
|
|
18446
19035
|
};
|
|
18447
|
-
const
|
|
19036
|
+
const pathnameForMatch = json.pathname || nextUrl;
|
|
19037
|
+
let matched = matchRouteClient(pathnameForMatch, routes);
|
|
19038
|
+
if (!matched) {
|
|
19039
|
+
matched = matchRouteClient(nextUrl, routes);
|
|
19040
|
+
}
|
|
18448
19041
|
if (!matched) {
|
|
19042
|
+
console.warn(
|
|
19043
|
+
`[client] Server returned data for ${nextUrl} but no route match found. Available routes:`,
|
|
19044
|
+
routes.map((r) => r.pattern)
|
|
19045
|
+
);
|
|
18449
19046
|
window.location.href = nextUrl;
|
|
18450
19047
|
return false;
|
|
18451
19048
|
}
|
|
19049
|
+
const finalPathname = json.pathname || nextUrl;
|
|
18452
19050
|
const windowData = {
|
|
18453
|
-
pathname:
|
|
19051
|
+
pathname: finalPathname,
|
|
18454
19052
|
params: matched.params,
|
|
18455
19053
|
props: combinedProps,
|
|
18456
19054
|
metadata: json.metadata ?? null,
|
|
@@ -18849,8 +19447,9 @@ function initializeRouterData(initialUrl, initialData) {
|
|
|
18849
19447
|
let routerData = getRouterData();
|
|
18850
19448
|
if (!routerData) {
|
|
18851
19449
|
const url = new URL(initialUrl, window.location.origin);
|
|
19450
|
+
const pathname = initialData?.pathname || url.pathname;
|
|
18852
19451
|
routerData = {
|
|
18853
|
-
pathname
|
|
19452
|
+
pathname,
|
|
18854
19453
|
params: initialData?.params || {},
|
|
18855
19454
|
searchParams: Object.fromEntries(url.searchParams.entries())
|
|
18856
19455
|
};
|
|
@@ -18909,11 +19508,12 @@ function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
|
|
|
18909
19508
|
return;
|
|
18910
19509
|
}
|
|
18911
19510
|
const initialData = getWindowData();
|
|
18912
|
-
const initialUrl = window.location.pathname + window.location.search;
|
|
19511
|
+
const initialUrl = (initialData?.pathname || window.location.pathname) + window.location.search;
|
|
18913
19512
|
if (initialData?.props) {
|
|
18914
19513
|
setPreservedLayoutProps(initialData.props);
|
|
18915
19514
|
}
|
|
18916
|
-
|
|
19515
|
+
const routerPathname = initialData?.pathname || window.location.pathname;
|
|
19516
|
+
initializeRouterData(routerPathname + window.location.search, initialData);
|
|
18917
19517
|
await hydrateInitialRoute(
|
|
18918
19518
|
container,
|
|
18919
19519
|
initialUrl,
|
|
@@ -18960,11 +19560,11 @@ var ValidationError = class extends Error {
|
|
|
18960
19560
|
format() {
|
|
18961
19561
|
const formatted = {};
|
|
18962
19562
|
for (const error of this.errors) {
|
|
18963
|
-
const
|
|
18964
|
-
if (!formatted[
|
|
18965
|
-
formatted[
|
|
19563
|
+
const path30 = error.path.join(".");
|
|
19564
|
+
if (!formatted[path30]) {
|
|
19565
|
+
formatted[path30] = [];
|
|
18966
19566
|
}
|
|
18967
|
-
formatted[
|
|
19567
|
+
formatted[path30].push(error.message);
|
|
18968
19568
|
}
|
|
18969
19569
|
return formatted;
|
|
18970
19570
|
}
|