elit 3.6.0 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.cjs CHANGED
@@ -56718,22 +56718,30 @@ async function resolveWorkspaceElitImportBasePath(rootDir, basePath, _mode) {
56718
56718
  }
56719
56719
  return void 0;
56720
56720
  }
56721
+ var BROWSER_SAFE_ELIT_IMPORTS = {
56722
+ "elit": "index",
56723
+ "elit/dom": "dom",
56724
+ "elit/el": "el",
56725
+ "elit/native": "native",
56726
+ "elit/universal": "universal",
56727
+ "elit/router": "router",
56728
+ "elit/state": "state",
56729
+ "elit/style": "style",
56730
+ "elit/hmr": "hmr",
56731
+ "elit/types": "types"
56732
+ };
56733
+ function createBrowserSafeElitImports(basePath, fileExt) {
56734
+ return Object.fromEntries(
56735
+ Object.entries(BROWSER_SAFE_ELIT_IMPORTS).map(([specifier, outputName]) => [
56736
+ specifier,
56737
+ `${basePath}/${outputName}${fileExt}`
56738
+ ])
56739
+ );
56740
+ }
56721
56741
  var createElitImportMap = async (rootDir, basePath = "", mode = "dev") => {
56722
56742
  const workspaceImportBasePath = await resolveWorkspaceElitImportBasePath(rootDir, basePath, mode);
56723
- const fileExt = ".js";
56724
- const elitImports = workspaceImportBasePath ? {
56725
- "elit": `${workspaceImportBasePath}/index${fileExt}`,
56726
- "elit/": `${workspaceImportBasePath}/`,
56727
- "elit/dom": `${workspaceImportBasePath}/dom${fileExt}`,
56728
- "elit/state": `${workspaceImportBasePath}/state${fileExt}`,
56729
- "elit/style": `${workspaceImportBasePath}/style${fileExt}`,
56730
- "elit/el": `${workspaceImportBasePath}/el${fileExt}`,
56731
- "elit/universal": `${workspaceImportBasePath}/universal${fileExt}`,
56732
- "elit/router": `${workspaceImportBasePath}/router${fileExt}`,
56733
- "elit/hmr": `${workspaceImportBasePath}/hmr${fileExt}`,
56734
- "elit/types": `${workspaceImportBasePath}/types${fileExt}`,
56735
- "elit/native": `${workspaceImportBasePath}/native${fileExt}`
56736
- } : {};
56743
+ const fileExt = ".mjs";
56744
+ const elitImports = workspaceImportBasePath ? createBrowserSafeElitImports(workspaceImportBasePath, fileExt) : {};
56737
56745
  const externalImports = await generateExternalImportMaps(rootDir, basePath);
56738
56746
  const allImports = { ...externalImports, ...elitImports };
56739
56747
  return `<script type="importmap">${JSON.stringify({ imports: allImports }, null, 2)}</script>`;
@@ -57004,6 +57012,29 @@ async function processPackage(nodeModulesPath, pkgName, importMap, basePath) {
57004
57012
  }
57005
57013
  }
57006
57014
  function processExportsField(pkgName, exports2, baseUrl, importMap) {
57015
+ if (pkgName === "elit") {
57016
+ if (typeof exports2 !== "object" || exports2 === null) {
57017
+ return;
57018
+ }
57019
+ const elitExports = exports2;
57020
+ const browserSafeImports = {};
57021
+ const rootResolved = "." in elitExports ? resolveExport(elitExports["."]) : "import" in elitExports ? resolveExport(elitExports) : null;
57022
+ if (rootResolved) {
57023
+ browserSafeImports.elit = `${baseUrl}/${rootResolved}`;
57024
+ }
57025
+ const allowedSubpaths = Object.keys(BROWSER_SAFE_ELIT_IMPORTS).filter((specifier) => specifier !== "elit").map((specifier) => ({
57026
+ exportKey: `./${specifier.slice("elit/".length)}`,
57027
+ importName: specifier
57028
+ }));
57029
+ for (const { exportKey, importName } of allowedSubpaths) {
57030
+ const resolved = resolveExport(elitExports[exportKey]);
57031
+ if (resolved) {
57032
+ browserSafeImports[importName] = `${baseUrl}/${resolved}`;
57033
+ }
57034
+ }
57035
+ Object.assign(importMap, browserSafeImports);
57036
+ return;
57037
+ }
57007
57038
  if (typeof exports2 === "string") {
57008
57039
  importMap[pkgName] = `${baseUrl}/${exports2}`;
57009
57040
  importMap[`${pkgName}/`] = `${baseUrl}/`;
@@ -57365,6 +57396,85 @@ function shouldUseClientFallbackRoot(primaryRoot, fallbackRoot, indexPath) {
57365
57396
  const primaryHasRuntimeSources = existsSync(join(resolvedPrimaryRoot, "src")) || existsSync(join(resolvedPrimaryRoot, "public")) || existsSync(join(resolvedPrimaryRoot, normalizedIndexPath));
57366
57397
  return !primaryHasRuntimeSources;
57367
57398
  }
57399
+ function isPathWithinRoot(filePath, rootDir) {
57400
+ return filePath === rootDir || filePath.startsWith(rootDir.endsWith(sep) ? rootDir : `${rootDir}${sep}`);
57401
+ }
57402
+ async function getAllowedClientRoots(client) {
57403
+ const allowedRoots = [];
57404
+ for (const candidateRoot of [client.root, client.fallbackRoot]) {
57405
+ if (!candidateRoot) {
57406
+ continue;
57407
+ }
57408
+ try {
57409
+ const resolvedRoot = await realpath(resolve(candidateRoot));
57410
+ if (!allowedRoots.includes(resolvedRoot)) {
57411
+ allowedRoots.push(resolvedRoot);
57412
+ }
57413
+ } catch {
57414
+ }
57415
+ }
57416
+ return allowedRoots;
57417
+ }
57418
+ async function getClientBaseDirs(client, isDistRequest, isNodeModulesRequest) {
57419
+ const baseDirs = [];
57420
+ for (const candidateRoot of [client.root, client.fallbackRoot]) {
57421
+ if (!candidateRoot) {
57422
+ continue;
57423
+ }
57424
+ try {
57425
+ const resolvedRoot = await realpath(resolve(candidateRoot));
57426
+ let baseDir = resolvedRoot;
57427
+ if (isDistRequest || isNodeModulesRequest) {
57428
+ const targetDir = isDistRequest ? "dist" : "node_modules";
57429
+ const foundDir = await findSpecialDir(candidateRoot, targetDir);
57430
+ baseDir = foundDir ? await realpath(foundDir) : resolvedRoot;
57431
+ }
57432
+ if (!baseDirs.includes(baseDir)) {
57433
+ baseDirs.push(baseDir);
57434
+ }
57435
+ } catch {
57436
+ }
57437
+ }
57438
+ return baseDirs;
57439
+ }
57440
+ async function resolveClientPathFromBaseDir(baseDir, normalizedPath) {
57441
+ const tryRealpathWithinBaseDir = async (relativePath2) => {
57442
+ const unresolvedPath = resolve(join(baseDir, relativePath2));
57443
+ if (!isPathWithinRoot(unresolvedPath, baseDir)) {
57444
+ return void 0;
57445
+ }
57446
+ try {
57447
+ return await realpath(unresolvedPath);
57448
+ } catch {
57449
+ return void 0;
57450
+ }
57451
+ };
57452
+ const exactPath = await tryRealpathWithinBaseDir(normalizedPath);
57453
+ if (exactPath) {
57454
+ return exactPath;
57455
+ }
57456
+ if (normalizedPath.endsWith(".js")) {
57457
+ const tsPath = await tryRealpathWithinBaseDir(normalizedPath.replace(/\.js$/, ".ts"));
57458
+ if (tsPath) {
57459
+ return tsPath;
57460
+ }
57461
+ }
57462
+ if (normalizedPath.includes(".")) {
57463
+ return void 0;
57464
+ }
57465
+ for (const candidatePath of [
57466
+ `${normalizedPath}.ts`,
57467
+ `${normalizedPath}.js`,
57468
+ join(normalizedPath, "index.ts"),
57469
+ join(normalizedPath, "index.js")
57470
+ ]) {
57471
+ const resolvedPath = await tryRealpathWithinBaseDir(candidatePath);
57472
+ if (resolvedPath) {
57473
+ return resolvedPath;
57474
+ }
57475
+ }
57476
+ return void 0;
57477
+ }
57368
57478
  function createDevServer(options) {
57369
57479
  const config = { ...defaultOptions, ...options };
57370
57480
  const wsClients = /* @__PURE__ */ new Set();
@@ -57394,6 +57504,7 @@ function createDevServer(options) {
57394
57504
  const activeRoot = useFallbackRoot ? client.fallbackRoot || client.root : client.root;
57395
57505
  return {
57396
57506
  root: activeRoot,
57507
+ fallbackRoot: useFallbackRoot ? void 0 : client.fallbackRoot,
57397
57508
  basePath,
57398
57509
  index: useFallbackRoot ? void 0 : indexPath,
57399
57510
  ssr: useFallbackRoot ? void 0 : client.ssr,
@@ -57495,75 +57606,26 @@ function createDevServer(options) {
57495
57606
  return send403(res, "403 Forbidden");
57496
57607
  }
57497
57608
  normalizedPath = tempPath;
57498
- const rootDir = await realpath(resolve(matchedClient.root));
57499
- let baseDir = rootDir;
57500
- if (isDistRequest || isNodeModulesRequest) {
57501
- const targetDir = isDistRequest ? "dist" : "node_modules";
57502
- const foundDir = await findSpecialDir(matchedClient.root, targetDir);
57503
- baseDir = foundDir ? await realpath(foundDir) : rootDir;
57504
- }
57505
57609
  let fullPath;
57506
- try {
57507
- const unresolvedPath = resolve(join(baseDir, normalizedPath));
57508
- if (!unresolvedPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
57509
- if (config.logging) console.log(`[403] File access outside of root (before symlink): ${unresolvedPath}`);
57510
- return send403(res, "403 Forbidden");
57511
- }
57512
- fullPath = await realpath(unresolvedPath);
57513
- if (config.logging && filePath === "/src/pages") {
57514
- console.log(`[DEBUG] Initial resolve succeeded: ${fullPath}`);
57515
- }
57516
- } catch (firstError) {
57517
- let resolvedPath;
57518
- if (config.logging && !normalizedPath.includes(".")) {
57519
- console.log(`[DEBUG] File not found: ${normalizedPath}, trying extensions...`);
57520
- }
57521
- if (normalizedPath.endsWith(".js")) {
57522
- const tsPath = normalizedPath.replace(/\.js$/, ".ts");
57523
- try {
57524
- const tsFullPath = await realpath(resolve(join(baseDir, tsPath)));
57525
- if (!tsFullPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
57526
- if (config.logging) console.log(`[403] Fallback TS path outside of root: ${tsFullPath}`);
57527
- return send403(res, "403 Forbidden");
57528
- }
57529
- resolvedPath = tsFullPath;
57530
- } catch {
57610
+ const baseDirs = await getClientBaseDirs(matchedClient, isDistRequest, isNodeModulesRequest);
57611
+ for (const baseDir of baseDirs) {
57612
+ fullPath = await resolveClientPathFromBaseDir(baseDir, normalizedPath);
57613
+ if (fullPath) {
57614
+ if (config.logging && filePath === "/src/pages") {
57615
+ console.log(`[DEBUG] Initial resolve succeeded: ${fullPath}`);
57531
57616
  }
57617
+ break;
57532
57618
  }
57533
- if (!resolvedPath && !normalizedPath.includes(".")) {
57534
- try {
57535
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".ts")));
57536
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.ts`);
57537
- } catch {
57538
- try {
57539
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".js")));
57540
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.js`);
57541
- } catch {
57542
- try {
57543
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.ts")));
57544
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.ts`);
57545
- } catch {
57546
- try {
57547
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.js")));
57548
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.js`);
57549
- } catch {
57550
- if (config.logging) console.log(`[DEBUG] Not found: all attempts failed for ${normalizedPath}`);
57551
- }
57552
- }
57553
- }
57554
- }
57555
- }
57556
- if (!resolvedPath) {
57557
- if (!res.headersSent) {
57558
- if (filePath === "/index.html" && matchedClient.ssr) {
57559
- return await serveSSR(res, matchedClient);
57560
- }
57561
- if (config.logging) console.log(`[404] ${filePath}`);
57562
- return send404(res, "404 Not Found");
57619
+ }
57620
+ if (!fullPath) {
57621
+ if (!res.headersSent) {
57622
+ if (filePath === "/index.html" && matchedClient.ssr) {
57623
+ return await serveSSR(res, matchedClient);
57563
57624
  }
57564
- return;
57625
+ if (config.logging) console.log(`[404] ${filePath}`);
57626
+ return send404(res, "404 Not Found");
57565
57627
  }
57566
- fullPath = resolvedPath;
57628
+ return;
57567
57629
  }
57568
57630
  try {
57569
57631
  const stats = await stat(fullPath);
@@ -57592,11 +57654,12 @@ function createDevServer(options) {
57592
57654
  return send404(res, "404 Not Found");
57593
57655
  }
57594
57656
  try {
57657
+ const allowedRoots = await getAllowedClientRoots(matchedClient);
57595
57658
  const stats = await stat(fullPath);
57596
57659
  if (stats.isDirectory()) {
57597
57660
  try {
57598
57661
  const indexPath = await realpath(resolve(join(fullPath, "index.html")));
57599
- if (!indexPath.startsWith(rootDir + sep) && indexPath !== rootDir) {
57662
+ if (!isPathWithinRoot(indexPath, fullPath) && !allowedRoots.some((rootDir) => isPathWithinRoot(indexPath, rootDir))) {
57600
57663
  return send403(res, "403 Forbidden");
57601
57664
  }
57602
57665
  await stat(indexPath);
@@ -57618,10 +57681,11 @@ function createDevServer(options) {
57618
57681
  return input.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
57619
57682
  }
57620
57683
  try {
57621
- const rootDir = await realpath(resolve(client.root));
57684
+ const allowedRoots = await getAllowedClientRoots(client);
57685
+ const rootDir = allowedRoots[0] || await realpath(resolve(client.root));
57622
57686
  const unresolvedPath = resolve(filePath);
57623
57687
  if (!isNodeModulesOrDist) {
57624
- if (!unresolvedPath.startsWith(rootDir + sep) && unresolvedPath !== rootDir) {
57688
+ if (!allowedRoots.some((allowedRoot) => isPathWithinRoot(unresolvedPath, allowedRoot))) {
57625
57689
  if (config.logging) console.log(`[403] Attempted to serve file outside allowed directories: ${filePath}`);
57626
57690
  return send403(res, "403 Forbidden");
57627
57691
  }
package/dist/server.js CHANGED
@@ -63445,22 +63445,30 @@ tell application "System Events" to get value of property list item "CFBundleNam
63445
63445
  }
63446
63446
  return void 0;
63447
63447
  }
63448
+ var BROWSER_SAFE_ELIT_IMPORTS = {
63449
+ "elit": "index",
63450
+ "elit/dom": "dom",
63451
+ "elit/el": "el",
63452
+ "elit/native": "native",
63453
+ "elit/universal": "universal",
63454
+ "elit/router": "router",
63455
+ "elit/state": "state",
63456
+ "elit/style": "style",
63457
+ "elit/hmr": "hmr",
63458
+ "elit/types": "types"
63459
+ };
63460
+ function createBrowserSafeElitImports(basePath, fileExt) {
63461
+ return Object.fromEntries(
63462
+ Object.entries(BROWSER_SAFE_ELIT_IMPORTS).map(([specifier, outputName]) => [
63463
+ specifier,
63464
+ `${basePath}/${outputName}${fileExt}`
63465
+ ])
63466
+ );
63467
+ }
63448
63468
  var createElitImportMap = async (rootDir, basePath = "", mode = "dev") => {
63449
63469
  const workspaceImportBasePath = await resolveWorkspaceElitImportBasePath(rootDir, basePath, mode);
63450
- const fileExt = ".js";
63451
- const elitImports = workspaceImportBasePath ? {
63452
- "elit": `${workspaceImportBasePath}/index${fileExt}`,
63453
- "elit/": `${workspaceImportBasePath}/`,
63454
- "elit/dom": `${workspaceImportBasePath}/dom${fileExt}`,
63455
- "elit/state": `${workspaceImportBasePath}/state${fileExt}`,
63456
- "elit/style": `${workspaceImportBasePath}/style${fileExt}`,
63457
- "elit/el": `${workspaceImportBasePath}/el${fileExt}`,
63458
- "elit/universal": `${workspaceImportBasePath}/universal${fileExt}`,
63459
- "elit/router": `${workspaceImportBasePath}/router${fileExt}`,
63460
- "elit/hmr": `${workspaceImportBasePath}/hmr${fileExt}`,
63461
- "elit/types": `${workspaceImportBasePath}/types${fileExt}`,
63462
- "elit/native": `${workspaceImportBasePath}/native${fileExt}`
63463
- } : {};
63470
+ const fileExt = ".mjs";
63471
+ const elitImports = workspaceImportBasePath ? createBrowserSafeElitImports(workspaceImportBasePath, fileExt) : {};
63464
63472
  const externalImports = await generateExternalImportMaps(rootDir, basePath);
63465
63473
  const allImports = { ...externalImports, ...elitImports };
63466
63474
  return `<script type="importmap">${JSON.stringify({ imports: allImports }, null, 2)}</script>`;
@@ -63731,6 +63739,29 @@ tell application "System Events" to get value of property list item "CFBundleNam
63731
63739
  }
63732
63740
  }
63733
63741
  function processExportsField(pkgName, exports2, baseUrl, importMap) {
63742
+ if (pkgName === "elit") {
63743
+ if (typeof exports2 !== "object" || exports2 === null) {
63744
+ return;
63745
+ }
63746
+ const elitExports = exports2;
63747
+ const browserSafeImports = {};
63748
+ const rootResolved = "." in elitExports ? resolveExport(elitExports["."]) : "import" in elitExports ? resolveExport(elitExports) : null;
63749
+ if (rootResolved) {
63750
+ browserSafeImports.elit = `${baseUrl}/${rootResolved}`;
63751
+ }
63752
+ const allowedSubpaths = Object.keys(BROWSER_SAFE_ELIT_IMPORTS).filter((specifier) => specifier !== "elit").map((specifier) => ({
63753
+ exportKey: `./${specifier.slice("elit/".length)}`,
63754
+ importName: specifier
63755
+ }));
63756
+ for (const { exportKey, importName } of allowedSubpaths) {
63757
+ const resolved = resolveExport(elitExports[exportKey]);
63758
+ if (resolved) {
63759
+ browserSafeImports[importName] = `${baseUrl}/${resolved}`;
63760
+ }
63761
+ }
63762
+ Object.assign(importMap, browserSafeImports);
63763
+ return;
63764
+ }
63734
63765
  if (typeof exports2 === "string") {
63735
63766
  importMap[pkgName] = `${baseUrl}/${exports2}`;
63736
63767
  importMap[`${pkgName}/`] = `${baseUrl}/`;
@@ -64092,6 +64123,85 @@ tell application "System Events" to get value of property list item "CFBundleNam
64092
64123
  const primaryHasRuntimeSources = existsSync(join(resolvedPrimaryRoot, "src")) || existsSync(join(resolvedPrimaryRoot, "public")) || existsSync(join(resolvedPrimaryRoot, normalizedIndexPath));
64093
64124
  return !primaryHasRuntimeSources;
64094
64125
  }
64126
+ function isPathWithinRoot(filePath, rootDir) {
64127
+ return filePath === rootDir || filePath.startsWith(rootDir.endsWith(sep) ? rootDir : `${rootDir}${sep}`);
64128
+ }
64129
+ async function getAllowedClientRoots(client) {
64130
+ const allowedRoots = [];
64131
+ for (const candidateRoot of [client.root, client.fallbackRoot]) {
64132
+ if (!candidateRoot) {
64133
+ continue;
64134
+ }
64135
+ try {
64136
+ const resolvedRoot = await realpath(resolve(candidateRoot));
64137
+ if (!allowedRoots.includes(resolvedRoot)) {
64138
+ allowedRoots.push(resolvedRoot);
64139
+ }
64140
+ } catch {
64141
+ }
64142
+ }
64143
+ return allowedRoots;
64144
+ }
64145
+ async function getClientBaseDirs(client, isDistRequest, isNodeModulesRequest) {
64146
+ const baseDirs = [];
64147
+ for (const candidateRoot of [client.root, client.fallbackRoot]) {
64148
+ if (!candidateRoot) {
64149
+ continue;
64150
+ }
64151
+ try {
64152
+ const resolvedRoot = await realpath(resolve(candidateRoot));
64153
+ let baseDir = resolvedRoot;
64154
+ if (isDistRequest || isNodeModulesRequest) {
64155
+ const targetDir = isDistRequest ? "dist" : "node_modules";
64156
+ const foundDir = await findSpecialDir(candidateRoot, targetDir);
64157
+ baseDir = foundDir ? await realpath(foundDir) : resolvedRoot;
64158
+ }
64159
+ if (!baseDirs.includes(baseDir)) {
64160
+ baseDirs.push(baseDir);
64161
+ }
64162
+ } catch {
64163
+ }
64164
+ }
64165
+ return baseDirs;
64166
+ }
64167
+ async function resolveClientPathFromBaseDir(baseDir, normalizedPath) {
64168
+ const tryRealpathWithinBaseDir = async (relativePath2) => {
64169
+ const unresolvedPath = resolve(join(baseDir, relativePath2));
64170
+ if (!isPathWithinRoot(unresolvedPath, baseDir)) {
64171
+ return void 0;
64172
+ }
64173
+ try {
64174
+ return await realpath(unresolvedPath);
64175
+ } catch {
64176
+ return void 0;
64177
+ }
64178
+ };
64179
+ const exactPath = await tryRealpathWithinBaseDir(normalizedPath);
64180
+ if (exactPath) {
64181
+ return exactPath;
64182
+ }
64183
+ if (normalizedPath.endsWith(".js")) {
64184
+ const tsPath = await tryRealpathWithinBaseDir(normalizedPath.replace(/\.js$/, ".ts"));
64185
+ if (tsPath) {
64186
+ return tsPath;
64187
+ }
64188
+ }
64189
+ if (normalizedPath.includes(".")) {
64190
+ return void 0;
64191
+ }
64192
+ for (const candidatePath of [
64193
+ `${normalizedPath}.ts`,
64194
+ `${normalizedPath}.js`,
64195
+ join(normalizedPath, "index.ts"),
64196
+ join(normalizedPath, "index.js")
64197
+ ]) {
64198
+ const resolvedPath = await tryRealpathWithinBaseDir(candidatePath);
64199
+ if (resolvedPath) {
64200
+ return resolvedPath;
64201
+ }
64202
+ }
64203
+ return void 0;
64204
+ }
64095
64205
  function createDevServer(options) {
64096
64206
  const config = { ...defaultOptions, ...options };
64097
64207
  const wsClients = /* @__PURE__ */ new Set();
@@ -64121,6 +64231,7 @@ tell application "System Events" to get value of property list item "CFBundleNam
64121
64231
  const activeRoot = useFallbackRoot ? client.fallbackRoot || client.root : client.root;
64122
64232
  return {
64123
64233
  root: activeRoot,
64234
+ fallbackRoot: useFallbackRoot ? void 0 : client.fallbackRoot,
64124
64235
  basePath,
64125
64236
  index: useFallbackRoot ? void 0 : indexPath,
64126
64237
  ssr: useFallbackRoot ? void 0 : client.ssr,
@@ -64222,75 +64333,26 @@ tell application "System Events" to get value of property list item "CFBundleNam
64222
64333
  return send403(res, "403 Forbidden");
64223
64334
  }
64224
64335
  normalizedPath = tempPath;
64225
- const rootDir = await realpath(resolve(matchedClient.root));
64226
- let baseDir = rootDir;
64227
- if (isDistRequest || isNodeModulesRequest) {
64228
- const targetDir = isDistRequest ? "dist" : "node_modules";
64229
- const foundDir = await findSpecialDir(matchedClient.root, targetDir);
64230
- baseDir = foundDir ? await realpath(foundDir) : rootDir;
64231
- }
64232
64336
  let fullPath;
64233
- try {
64234
- const unresolvedPath = resolve(join(baseDir, normalizedPath));
64235
- if (!unresolvedPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
64236
- if (config.logging) console.log(`[403] File access outside of root (before symlink): ${unresolvedPath}`);
64237
- return send403(res, "403 Forbidden");
64238
- }
64239
- fullPath = await realpath(unresolvedPath);
64240
- if (config.logging && filePath === "/src/pages") {
64241
- console.log(`[DEBUG] Initial resolve succeeded: ${fullPath}`);
64242
- }
64243
- } catch (firstError) {
64244
- let resolvedPath;
64245
- if (config.logging && !normalizedPath.includes(".")) {
64246
- console.log(`[DEBUG] File not found: ${normalizedPath}, trying extensions...`);
64247
- }
64248
- if (normalizedPath.endsWith(".js")) {
64249
- const tsPath = normalizedPath.replace(/\.js$/, ".ts");
64250
- try {
64251
- const tsFullPath = await realpath(resolve(join(baseDir, tsPath)));
64252
- if (!tsFullPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
64253
- if (config.logging) console.log(`[403] Fallback TS path outside of root: ${tsFullPath}`);
64254
- return send403(res, "403 Forbidden");
64255
- }
64256
- resolvedPath = tsFullPath;
64257
- } catch {
64258
- }
64259
- }
64260
- if (!resolvedPath && !normalizedPath.includes(".")) {
64261
- try {
64262
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".ts")));
64263
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.ts`);
64264
- } catch {
64265
- try {
64266
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".js")));
64267
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.js`);
64268
- } catch {
64269
- try {
64270
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.ts")));
64271
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.ts`);
64272
- } catch {
64273
- try {
64274
- resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.js")));
64275
- if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.js`);
64276
- } catch {
64277
- if (config.logging) console.log(`[DEBUG] Not found: all attempts failed for ${normalizedPath}`);
64278
- }
64279
- }
64280
- }
64337
+ const baseDirs = await getClientBaseDirs(matchedClient, isDistRequest, isNodeModulesRequest);
64338
+ for (const baseDir of baseDirs) {
64339
+ fullPath = await resolveClientPathFromBaseDir(baseDir, normalizedPath);
64340
+ if (fullPath) {
64341
+ if (config.logging && filePath === "/src/pages") {
64342
+ console.log(`[DEBUG] Initial resolve succeeded: ${fullPath}`);
64281
64343
  }
64344
+ break;
64282
64345
  }
64283
- if (!resolvedPath) {
64284
- if (!res.headersSent) {
64285
- if (filePath === "/index.html" && matchedClient.ssr) {
64286
- return await serveSSR(res, matchedClient);
64287
- }
64288
- if (config.logging) console.log(`[404] ${filePath}`);
64289
- return send404(res, "404 Not Found");
64346
+ }
64347
+ if (!fullPath) {
64348
+ if (!res.headersSent) {
64349
+ if (filePath === "/index.html" && matchedClient.ssr) {
64350
+ return await serveSSR(res, matchedClient);
64290
64351
  }
64291
- return;
64352
+ if (config.logging) console.log(`[404] ${filePath}`);
64353
+ return send404(res, "404 Not Found");
64292
64354
  }
64293
- fullPath = resolvedPath;
64355
+ return;
64294
64356
  }
64295
64357
  try {
64296
64358
  const stats = await stat(fullPath);
@@ -64319,11 +64381,12 @@ tell application "System Events" to get value of property list item "CFBundleNam
64319
64381
  return send404(res, "404 Not Found");
64320
64382
  }
64321
64383
  try {
64384
+ const allowedRoots = await getAllowedClientRoots(matchedClient);
64322
64385
  const stats = await stat(fullPath);
64323
64386
  if (stats.isDirectory()) {
64324
64387
  try {
64325
64388
  const indexPath = await realpath(resolve(join(fullPath, "index.html")));
64326
- if (!indexPath.startsWith(rootDir + sep) && indexPath !== rootDir) {
64389
+ if (!isPathWithinRoot(indexPath, fullPath) && !allowedRoots.some((rootDir) => isPathWithinRoot(indexPath, rootDir))) {
64327
64390
  return send403(res, "403 Forbidden");
64328
64391
  }
64329
64392
  await stat(indexPath);
@@ -64345,10 +64408,11 @@ tell application "System Events" to get value of property list item "CFBundleNam
64345
64408
  return input.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
64346
64409
  }
64347
64410
  try {
64348
- const rootDir = await realpath(resolve(client.root));
64411
+ const allowedRoots = await getAllowedClientRoots(client);
64412
+ const rootDir = allowedRoots[0] || await realpath(resolve(client.root));
64349
64413
  const unresolvedPath = resolve(filePath);
64350
64414
  if (!isNodeModulesOrDist) {
64351
- if (!unresolvedPath.startsWith(rootDir + sep) && unresolvedPath !== rootDir) {
64415
+ if (!allowedRoots.some((allowedRoot) => isPathWithinRoot(unresolvedPath, allowedRoot))) {
64352
64416
  if (config.logging) console.log(`[403] Attempted to serve file outside allowed directories: ${filePath}`);
64353
64417
  return send403(res, "403 Forbidden");
64354
64418
  }