@marko/run 0.5.12 → 0.5.13

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.
@@ -14,7 +14,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
14
14
  import sade from "sade";
15
15
 
16
16
  // src/cli/commands.ts
17
- import path4 from "path";
17
+ import path5 from "path";
18
18
  import fs5 from "fs";
19
19
  import { fileURLToPath as fileURLToPath2 } from "url";
20
20
  import {
@@ -69,7 +69,7 @@ async function getAvailablePort(port) {
69
69
  }
70
70
 
71
71
  // src/vite/plugin.ts
72
- import path3 from "path";
72
+ import path4 from "path";
73
73
  import fs4 from "fs";
74
74
  import { glob } from "glob";
75
75
  import { fileURLToPath } from "url";
@@ -157,10 +157,10 @@ var _VDir = class _VDir {
157
157
  });
158
158
  return value;
159
159
  }
160
- addDir(path5, segment) {
160
+ addDir(path6, segment) {
161
161
  const map = segment.type === "_" ? __privateGet(this, _pathlessDirs) ?? __privateSet(this, _pathlessDirs, /* @__PURE__ */ new Map()) : __privateGet(this, _dirs) ?? __privateSet(this, _dirs, /* @__PURE__ */ new Map());
162
162
  if (!map.has(segment.name)) {
163
- const dir = new _VDir(this, segment, path5);
163
+ const dir = new _VDir(this, segment, path6);
164
164
  map.set(segment.name, dir);
165
165
  return dir;
166
166
  }
@@ -206,10 +206,10 @@ var _VDir = class _VDir {
206
206
  const dirs = [];
207
207
  const unique = /* @__PURE__ */ new Set();
208
208
  for (const root of roots) {
209
- for (const path5 of paths) {
209
+ for (const path6 of paths) {
210
210
  let dir = root;
211
- for (const segment of path5.segments) {
212
- dir = dir.addDir(path5, segment);
211
+ for (const segment of path6.segments) {
212
+ dir = dir.addDir(path6, segment);
213
213
  }
214
214
  if (unique.has(dir.path)) {
215
215
  const sources = /* @__PURE__ */ new Set();
@@ -221,7 +221,7 @@ var _VDir = class _VDir {
221
221
  }
222
222
  }
223
223
  throw new Error(
224
- `Ambiguous directory structure: '${sourcePath}${path5.source}' defines '${dir.path}' multiple times.`
224
+ `Ambiguous directory structure: '${sourcePath}${path6.source}' defines '${dir.path}' multiple times.`
225
225
  );
226
226
  } else {
227
227
  unique.add(dir.path);
@@ -262,9 +262,9 @@ function parseFlatRoute(pattern) {
262
262
  } else if (charCode === 44) {
263
263
  if (!current) {
264
264
  segmentEnd(
265
- basePaths.map((path5) => ({
266
- ...path5,
267
- segments: path5.segments.slice()
265
+ basePaths.map((path6) => ({
266
+ ...path6,
267
+ segments: path6.segments.slice()
268
268
  })),
269
269
  "",
270
270
  "_",
@@ -294,9 +294,9 @@ function parseFlatRoute(pattern) {
294
294
  } else if (charCode === 36) {
295
295
  type = pattern.charCodeAt(i + 1) === 36 ? "$$" : "$";
296
296
  }
297
- current ?? (current = basePaths.map((path5) => ({
298
- ...path5,
299
- segments: path5.segments.slice()
297
+ current ?? (current = basePaths.map((path6) => ({
298
+ ...path6,
299
+ segments: path6.segments.slice()
300
300
  })));
301
301
  i = len;
302
302
  for (const char of delimiters) {
@@ -316,9 +316,9 @@ function parseFlatRoute(pattern) {
316
316
  }
317
317
  if (!current) {
318
318
  segmentEnd(
319
- basePaths.map((path5) => ({
320
- ...path5,
321
- segments: path5.segments.slice()
319
+ basePaths.map((path6) => ({
320
+ ...path6,
321
+ segments: path6.segments.slice()
322
322
  })),
323
323
  "",
324
324
  "_",
@@ -342,9 +342,9 @@ function parseFlatRoute(pattern) {
342
342
  segment.param = raw.slice(type.length);
343
343
  }
344
344
  }
345
- for (const path5 of paths) {
345
+ for (const path6 of paths) {
346
346
  if (segment) {
347
- if (path5.isCatchall) {
347
+ if (path6.isCatchall) {
348
348
  throw new Error(
349
349
  `Invalid route pattern: nested segments are not allowed after a catch-all parameter. Found '.' following '${pattern.slice(
350
350
  0,
@@ -352,22 +352,22 @@ function parseFlatRoute(pattern) {
352
352
  )}' in '${pattern}'.`
353
353
  );
354
354
  }
355
- path5.segments.push(segment);
356
- path5.id += path5.id === "/" ? segment.name : `/${segment.name}`;
355
+ path6.segments.push(segment);
356
+ path6.id += path6.id === "/" ? segment.name : `/${segment.name}`;
357
357
  if (type === "$$") {
358
- path5.isCatchall = true;
358
+ path6.isCatchall = true;
359
359
  }
360
360
  }
361
361
  if (map) {
362
- if (map.has(path5.id)) {
363
- const existing = map.get(path5.id);
362
+ if (map.has(path6.id)) {
363
+ const existing = map.get(path6.id);
364
364
  const existingExpansion = existing.segments.map((s) => s.raw).join(".");
365
- const currentExpansion = path5.segments.map((s) => s.raw).join(".");
365
+ const currentExpansion = path6.segments.map((s) => s.raw).join(".");
366
366
  throw new Error(
367
- `Invalid route pattern: route '${path5.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
367
+ `Invalid route pattern: route '${path6.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
368
368
  );
369
369
  }
370
- map.set(path5.id, path5);
370
+ map.set(path6.id, path6);
371
371
  }
372
372
  }
373
373
  }
@@ -423,7 +423,7 @@ async function buildRoutes(sources) {
423
423
  dirStack.length = prevDirStackLength;
424
424
  };
425
425
  },
426
- onFile({ name, path: path5 }) {
426
+ onFile({ name, path: path6 }) {
427
427
  const match = name.match(routeableFileRegex);
428
428
  if (!match) {
429
429
  return;
@@ -431,7 +431,7 @@ async function buildRoutes(sources) {
431
431
  const type = (match[1] || match[3]).toLowerCase();
432
432
  if (dirStack.length && isSpecialType(type)) {
433
433
  console.warn(
434
- `Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path5}`
434
+ `Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path6}`
435
435
  );
436
436
  return;
437
437
  }
@@ -446,7 +446,7 @@ async function buildRoutes(sources) {
446
446
  id: String(nextFileId++),
447
447
  name,
448
448
  type,
449
- filePath: path5,
449
+ filePath: path6,
450
450
  relativePath,
451
451
  importPath: `${importPrefix}/${relativePath}`,
452
452
  verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
@@ -498,23 +498,23 @@ async function buildRoutes(sources) {
498
498
  }
499
499
  }
500
500
  if (page || handler) {
501
- const path5 = dir.pathInfo;
502
- if (uniqueRoutes.has(path5.id)) {
503
- const existing = uniqueRoutes.get(path5.id);
501
+ const path6 = dir.pathInfo;
502
+ if (uniqueRoutes.has(path6.id)) {
503
+ const existing = uniqueRoutes.get(path6.id);
504
504
  const route = routes[existing.index];
505
505
  const existingFiles = [route.handler, route.page].filter(Boolean).map((f) => f.filePath);
506
506
  const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
507
- throw new Error(`Duplicate routes for path '${path5.path}' were defined. A route established by:
507
+ throw new Error(`Duplicate routes for path '${path6.path}' were defined. A route established by:
508
508
  ${existingFiles.join(" and ")} via '${existing.dir.path}'
509
509
  collides with
510
510
  ${currentFiles.join(" and ")} via '${dir.path}'
511
511
  `);
512
512
  }
513
- uniqueRoutes.set(path5.id, { dir, index: routes.length });
513
+ uniqueRoutes.set(path6.id, { dir, index: routes.length });
514
514
  routes.push({
515
515
  index: nextRouteIndex++,
516
516
  key: dir.fullPath,
517
- paths: [path5],
517
+ paths: [path6],
518
518
  middleware: [...currentMiddleware],
519
519
  layouts: page ? [...currentLayouts] : [],
520
520
  meta: dir.files.get(RoutableFileTypes.Meta),
@@ -764,6 +764,7 @@ function hasVerb(route, verb) {
764
764
  }
765
765
 
766
766
  // src/vite/codegen/index.ts
767
+ import path2 from "path";
767
768
  function renderRouteTemplate(route, getRelativePath) {
768
769
  if (!route.page) {
769
770
  throw new Error(`Route ${route.key} has no page to render`);
@@ -858,7 +859,7 @@ function renderRouteEntry(route, entriesDir) {
858
859
  );
859
860
  }
860
861
  if (page) {
861
- const importPath = route.layouts.length ? `./${entriesDir}/${entryName}.marko` : `./${page.importPath}`;
862
+ const importPath = route.layouts.length ? `./${path2.posix.join(entriesDir, page.relativePath, "..", "route.marko")}` : `./${page.importPath}`;
862
863
  imports.writeLines(`import page from '${importPath}${serverEntryQuery}';`);
863
864
  }
864
865
  if (meta) {
@@ -965,7 +966,7 @@ function renderRouter(routes, entriesDir, options = {
965
966
  );
966
967
  }
967
968
  for (const route of Object.values(routes.special)) {
968
- const importPath = route.layouts.length ? `./${entriesDir}/${route.entryName}.marko` : `./${route.page.importPath}`;
969
+ const importPath = route.layouts.length ? `./${path2.posix.join(entriesDir, route.page.relativePath, "..", `route.${route.key}.marko`)}` : `./${route.page.importPath}`;
969
970
  imports.writeLines(
970
971
  `import page${route.key} from '${importPath}${serverEntryQuery}';`
971
972
  );
@@ -1136,7 +1137,7 @@ function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1136
1137
  if (useSwitch) {
1137
1138
  writer.writeBlockStart(`switch (${value}) {`);
1138
1139
  }
1139
- for (const { key, path: path5, route: route2 } of terminal) {
1140
+ for (const { key, path: path6, route: route2 } of terminal) {
1140
1141
  const decodedKey = decodeURIComponent(key);
1141
1142
  if (useSwitch) {
1142
1143
  writer.write(`case '${decodedKey}': `, true);
@@ -1144,7 +1145,7 @@ function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1144
1145
  writer.write(`if (${value} === '${decodedKey}') `, true);
1145
1146
  }
1146
1147
  writer.write(
1147
- `return ${renderMatch(verb, route2, path5)}; // ${path5.path}
1148
+ `return ${renderMatch(verb, route2, path6)}; // ${path6.path}
1148
1149
  `
1149
1150
  );
1150
1151
  }
@@ -1247,11 +1248,11 @@ function renderParams(params, pathIndex) {
1247
1248
  }
1248
1249
  return result ? result + " }" : "{}";
1249
1250
  }
1250
- function renderMatch(verb, route, path5, pathIndex) {
1251
+ function renderMatch(verb, route, path6, pathIndex) {
1251
1252
  const handler = `${verb}${route.index}`;
1252
- const params = path5.params ? renderParams(path5.params, pathIndex) : "{}";
1253
+ const params = path6.params ? renderParams(path6.params, pathIndex) : "{}";
1253
1254
  const meta = route.meta ? `meta${route.index}` : "{}";
1254
- const pathPattern = pathToURLPatternString(path5.path);
1255
+ const pathPattern = pathToURLPatternString(path6.path);
1255
1256
  return `{ handler: ${handler}, params: ${params}, meta: ${meta}, path: '${pathPattern}' }`;
1256
1257
  }
1257
1258
  function renderMiddleware(middleware) {
@@ -1272,15 +1273,15 @@ function renderMiddleware(middleware) {
1272
1273
  imports.join();
1273
1274
  return writer.end();
1274
1275
  }
1275
- function stripTsExtension(path5) {
1276
- const index = path5.lastIndexOf(".");
1276
+ function stripTsExtension(path6) {
1277
+ const index = path6.lastIndexOf(".");
1277
1278
  if (index !== -1) {
1278
- const ext = path5.slice(index + 1);
1279
+ const ext = path6.slice(index + 1);
1279
1280
  if (ext.toLowerCase() === "ts") {
1280
- return path5.slice(0, index);
1281
+ return path6.slice(0, index);
1281
1282
  }
1282
1283
  }
1283
- return path5;
1284
+ return path6;
1284
1285
  }
1285
1286
  async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1286
1287
  var _a, _b;
@@ -1312,8 +1313,8 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1312
1313
  const routeTypes = /* @__PURE__ */ new Map();
1313
1314
  for (const route of routes.list) {
1314
1315
  let routeType = "";
1315
- for (const path5 of route.paths) {
1316
- const pathType = `"${pathToURLPatternString(path5.path)}"`;
1316
+ for (const path6 of route.paths) {
1317
+ const pathType = `"${pathToURLPatternString(path6.path)}"`;
1317
1318
  routeType += routeType ? " | " + pathType : pathType;
1318
1319
  routesWriter.writeLines(`${pathType}: Routes["${route.key}"];`);
1319
1320
  }
@@ -1349,22 +1350,22 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1349
1350
  const pageWriter = writer.branch("page");
1350
1351
  const layoutWriter = writer.branch("layout");
1351
1352
  for (const [file, types] of routeTypes) {
1352
- const path5 = `${pathPrefix}/${file.relativePath}`;
1353
+ const path6 = `${pathPrefix}/${file.relativePath}`;
1353
1354
  const routeType = `Run.Routes[${types.join(" | ")}]`;
1354
1355
  switch (file.type) {
1355
1356
  case RoutableFileTypes.Handler:
1356
- writeModuleDeclaration(handlerWriter, path5, routeType);
1357
+ writeModuleDeclaration(handlerWriter, path6, routeType);
1357
1358
  break;
1358
1359
  case RoutableFileTypes.Middleware:
1359
- writeModuleDeclaration(middlewareWriter, path5, routeType);
1360
+ writeModuleDeclaration(middlewareWriter, path6, routeType);
1360
1361
  break;
1361
1362
  case RoutableFileTypes.Page:
1362
- writeModuleDeclaration(pageWriter, path5, routeType);
1363
+ writeModuleDeclaration(pageWriter, path6, routeType);
1363
1364
  break;
1364
1365
  case RoutableFileTypes.Layout:
1365
1366
  writeModuleDeclaration(
1366
1367
  layoutWriter,
1367
- path5,
1368
+ path6,
1368
1369
  routeType,
1369
1370
  `
1370
1371
  export interface Input {
@@ -1375,7 +1376,7 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1375
1376
  case RoutableFileTypes.Error:
1376
1377
  writeModuleDeclaration(
1377
1378
  writer,
1378
- path5,
1379
+ path6,
1379
1380
  "globalThis.MarkoRun.Route",
1380
1381
  `
1381
1382
  export interface Input {
@@ -1384,7 +1385,7 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1384
1385
  );
1385
1386
  break;
1386
1387
  case RoutableFileTypes.NotFound:
1387
- writeModuleDeclaration(writer, path5, "Run.Route");
1388
+ writeModuleDeclaration(writer, path6, "Run.Route");
1388
1389
  break;
1389
1390
  }
1390
1391
  }
@@ -1408,7 +1409,7 @@ type Routes = {`);
1408
1409
  if (meta) {
1409
1410
  const metaPath = stripTsExtension(`${pathPrefix}/${meta.relativePath}`);
1410
1411
  let metaType = `typeof import("${metaPath}")`;
1411
- if (/\.(ts|js|mjs)$/.test(meta.relativePath)) {
1412
+ if (/\.(ts|js|mjs)$/.test(meta.name)) {
1412
1413
  metaType += `["default"]`;
1413
1414
  }
1414
1415
  routeType += ` meta: ${metaType};`;
@@ -1419,13 +1420,13 @@ type Routes = {`);
1419
1420
  writer.writeBlockEnd("}");
1420
1421
  return writer.end();
1421
1422
  }
1422
- function writeModuleDeclaration(writer, path5, routeType, moduleTypes) {
1423
- writer.writeLines("").write(`declare module "${stripTsExtension(path5)}" {`);
1423
+ function writeModuleDeclaration(writer, path6, routeType, moduleTypes) {
1424
+ writer.writeLines("").write(`declare module "${stripTsExtension(path6)}" {`);
1424
1425
  if (moduleTypes) {
1425
1426
  writer.write(moduleTypes);
1426
1427
  }
1427
1428
  if (routeType) {
1428
- const isMarko = path5.endsWith(".marko");
1429
+ const isMarko = path6.endsWith(".marko");
1429
1430
  writer.write(`
1430
1431
  namespace MarkoRun {
1431
1432
  export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
@@ -1439,8 +1440,8 @@ function writeModuleDeclaration(writer, path5, routeType, moduleTypes) {
1439
1440
  writer.writeLines(`
1440
1441
  }`);
1441
1442
  }
1442
- function pathToURLPatternString(path5) {
1443
- return path5.replace(/\/\$(\$?)([^\/]*)/g, (_, catchAll, name) => {
1443
+ function pathToURLPatternString(path6) {
1444
+ return path6.replace(/\/\$(\$?)([^\/]*)/g, (_, catchAll, name) => {
1444
1445
  name = decodeURIComponent(name);
1445
1446
  return catchAll ? `/:${name || "rest"}*` : `/:${name}`;
1446
1447
  });
@@ -1449,11 +1450,11 @@ function createRouteTrie(routes) {
1449
1450
  const root = {
1450
1451
  key: ""
1451
1452
  };
1452
- function insert(path5, route) {
1453
+ function insert(path6, route) {
1453
1454
  let node = root;
1454
- for (const segment of path5.segments) {
1455
+ for (const segment of path6.segments) {
1455
1456
  if (segment === "$$") {
1456
- node.catchAll ?? (node.catchAll = { route, path: path5 });
1457
+ node.catchAll ?? (node.catchAll = { route, path: path6 });
1457
1458
  return;
1458
1459
  } else if (segment === "$") {
1459
1460
  node = node.dynamic ?? (node.dynamic = {
@@ -1471,12 +1472,12 @@ function createRouteTrie(routes) {
1471
1472
  node = next;
1472
1473
  }
1473
1474
  }
1474
- node.path ?? (node.path = path5);
1475
+ node.path ?? (node.path = path6);
1475
1476
  node.route ?? (node.route = route);
1476
1477
  }
1477
1478
  for (const route of routes) {
1478
- for (const path5 of route.paths) {
1479
- insert(path5, route);
1479
+ for (const path6 of route.paths) {
1480
+ insert(path6, route);
1480
1481
  }
1481
1482
  }
1482
1483
  return root;
@@ -1582,7 +1583,7 @@ function logRoutesTable(routes, bundle, options) {
1582
1583
  style: { compact: true }
1583
1584
  });
1584
1585
  for (const route of routes.list) {
1585
- for (const path5 of route.paths) {
1586
+ for (const path6 of route.paths) {
1586
1587
  const verbs = getVerbs(route).sort(
1587
1588
  (a, b) => HttpVerbOrder[a] - HttpVerbOrder[b]
1588
1589
  );
@@ -1601,7 +1602,7 @@ function logRoutesTable(routes, bundle, options) {
1601
1602
  kleur.bold(HttpVerbColors[verb](verb.toUpperCase()))
1602
1603
  ];
1603
1604
  if (verbs.length === 1 || firstRow) {
1604
- row.push({ rowSpan: verbs.length, content: prettyPath(path5.path) });
1605
+ row.push({ rowSpan: verbs.length, content: prettyPath(path6.path) });
1605
1606
  firstRow = false;
1606
1607
  }
1607
1608
  row.push(entryType.join(" -> "));
@@ -1662,8 +1663,8 @@ function prettySize([bytes, compBytes]) {
1662
1663
  else str += kleur.bold(kleur.red(compSize));
1663
1664
  return str;
1664
1665
  }
1665
- function prettyPath(path5) {
1666
- return path5.replace(/\/\$\$(.*)$/, (_, p) => "/" + kleur.bold(kleur.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + kleur.bold(kleur.dim(`:${p}`)));
1666
+ function prettyPath(path6) {
1667
+ return path6.replace(/\/\$\$(.*)$/, (_, p) => "/" + kleur.bold(kleur.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + kleur.bold(kleur.dim(`:${p}`)));
1667
1668
  }
1668
1669
 
1669
1670
  // src/vite/plugin.ts
@@ -1671,11 +1672,11 @@ import createDebug from "debug";
1671
1672
 
1672
1673
  // src/vite/utils/read-once-persisted-store.ts
1673
1674
  import os from "os";
1674
- import path2 from "path";
1675
+ import path3 from "path";
1675
1676
  import { promises as fs3 } from "fs";
1676
1677
  var noop = () => {
1677
1678
  };
1678
- var tmpFile = path2.join(os.tmpdir(), "marko-run-storage.json");
1679
+ var tmpFile = path3.join(os.tmpdir(), "marko-run-storage.json");
1679
1680
  var values = /* @__PURE__ */ new Map();
1680
1681
  var loadedFromDisk;
1681
1682
  var ReadOncePersistedStore = class {
@@ -1743,7 +1744,7 @@ function prepareError(err) {
1743
1744
  // src/vite/plugin.ts
1744
1745
  import { createHash } from "crypto";
1745
1746
  var debug = createDebug("@marko/run");
1746
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
1747
+ var __dirname = path4.dirname(fileURLToPath(import.meta.url));
1747
1748
  var PLUGIN_NAME_PREFIX = "marko-run-vite";
1748
1749
  var POSIX_SEP = "/";
1749
1750
  var WINDOWS_SEP = "\\";
@@ -1751,7 +1752,7 @@ var CLIENT_OUT_DIR = "public";
1751
1752
  var MIDDLEWARE_FILENAME = `${markoRunFilePrefix}middleware.js`;
1752
1753
  var ROUTER_FILENAME = `${markoRunFilePrefix}router.js`;
1753
1754
  var defaultPort = Number(process.env.PORT || 3e3);
1754
- var normalizePath = path3.sep === WINDOWS_SEP ? (id) => id.replace(/\\/g, POSIX_SEP) : (id) => id;
1755
+ var normalizePath = path4.sep === WINDOWS_SEP ? (id) => id.replace(/\\/g, POSIX_SEP) : (id) => id;
1755
1756
  function markoRun(opts = {}) {
1756
1757
  let { routesDir, adapter, ...markoVitePluginOptions } = opts;
1757
1758
  let store;
@@ -1779,18 +1780,15 @@ function markoRun(opts = {}) {
1779
1780
  routesBuild: 0,
1780
1781
  routesRender: 0
1781
1782
  };
1782
- function getEntryFileRelativePath(to) {
1783
- return normalizePath(path3.relative(entryFilesDir, to));
1784
- }
1785
1783
  async function writeTypesFile(routes2) {
1786
1784
  if (routes2 && (tsConfigExists ?? (tsConfigExists = await globFileExists(
1787
1785
  root,
1788
1786
  "{.tsconfig*,tsconfig*.json}"
1789
1787
  )))) {
1790
- const filepath = path3.join(typesDir, "routes.d.ts");
1788
+ const filepath = path4.join(typesDir, "routes.d.ts");
1791
1789
  const data = await renderRouteTypeInfo(
1792
1790
  routes2,
1793
- normalizePath(path3.relative(typesDir, resolvedRoutesDir)),
1791
+ normalizePath(path4.relative(typesDir, resolvedRoutesDir)),
1794
1792
  adapter
1795
1793
  );
1796
1794
  if (data !== typesFile || !fs4.existsSync(filepath)) {
@@ -1812,12 +1810,12 @@ function markoRun(opts = {}) {
1812
1810
  throw new Error("No routes generated");
1813
1811
  }
1814
1812
  for (const route of routes.list) {
1815
- virtualFiles.set(path3.posix.join(root, `${route.entryName}.js`), "");
1813
+ virtualFiles.set(path4.posix.join(root, `${route.entryName}.js`), "");
1816
1814
  }
1817
1815
  if (routes.middleware.length) {
1818
- virtualFiles.set(path3.posix.join(root, MIDDLEWARE_FILENAME), "");
1816
+ virtualFiles.set(path4.posix.join(root, MIDDLEWARE_FILENAME), "");
1819
1817
  }
1820
- virtualFiles.set(path3.posix.join(root, ROUTER_FILENAME), "");
1818
+ virtualFiles.set(path4.posix.join(root, ROUTER_FILENAME), "");
1821
1819
  resolve(routes);
1822
1820
  } catch (err) {
1823
1821
  reject(err);
@@ -1830,7 +1828,6 @@ function markoRun(opts = {}) {
1830
1828
  var _a;
1831
1829
  try {
1832
1830
  const routes2 = await buildVirtualFiles();
1833
- let entryFilesDirExists = false;
1834
1831
  if (fs4.existsSync(entryFilesDir)) {
1835
1832
  fs4.rmSync(entryFilesDir, { recursive: true });
1836
1833
  }
@@ -1849,32 +1846,34 @@ function markoRun(opts = {}) {
1849
1846
  }
1850
1847
  if (!route.handler.verbs.length) {
1851
1848
  context.warn(
1852
- `Did not find any http verb exports in handler '${path3.relative(root, route.handler.filePath)}' - expected ${httpVerbs.map((v) => v.toUpperCase()).join(", ")}`
1849
+ `Did not find any http verb exports in handler '${path4.relative(root, route.handler.filePath)}' - expected ${httpVerbs.map((v) => v.toUpperCase()).join(", ")}`
1853
1850
  );
1854
1851
  }
1855
1852
  }
1856
1853
  if (route.page && route.layouts.length) {
1857
- entryFilesDirExists || (entryFilesDirExists = !!fs4.mkdirSync(entryFilesDir, {
1858
- recursive: true
1859
- }));
1854
+ const relativePath = path4.relative(resolvedRoutesDir, route.page.filePath);
1855
+ const routeFileDir = path4.join(entryFilesDir, relativePath, "..");
1856
+ const routeFileRelativePathPosix = normalizePath(path4.relative(routeFileDir, root));
1857
+ fs4.mkdirSync(routeFileDir, { recursive: true });
1860
1858
  fs4.writeFileSync(
1861
- path3.join(entryFilesDir, `${route.entryName}.marko`),
1862
- renderRouteTemplate(route, getEntryFileRelativePath)
1859
+ path4.join(routeFileDir, "route.marko"),
1860
+ renderRouteTemplate(route, (to) => path4.posix.join(routeFileRelativePathPosix, to))
1863
1861
  );
1864
1862
  }
1865
1863
  virtualFiles.set(
1866
- path3.posix.join(root, `${route.entryName}.js`),
1864
+ path4.posix.join(root, `${route.entryName}.js`),
1867
1865
  renderRouteEntry(route, relativeEntryFilesDirPosix)
1868
1866
  );
1869
1867
  }
1870
1868
  for (const route of Object.values(routes2.special)) {
1871
- if (route.layouts.length) {
1872
- entryFilesDirExists || (entryFilesDirExists = !!fs4.mkdirSync(entryFilesDir, {
1873
- recursive: true
1874
- }));
1869
+ if (route.page && route.layouts.length) {
1870
+ const relativePath = path4.relative(resolvedRoutesDir, route.page.filePath);
1871
+ const routeFileDir = path4.join(entryFilesDir, relativePath, "..");
1872
+ const routeFileRelativePathPosix = normalizePath(path4.relative(routeFileDir, root));
1873
+ fs4.mkdirSync(routeFileDir, { recursive: true });
1875
1874
  fs4.writeFileSync(
1876
- path3.join(entryFilesDir, `${route.entryName}.marko`),
1877
- renderRouteTemplate(route, getEntryFileRelativePath)
1875
+ path4.join(routeFileDir, `route.${route.key}.marko`),
1876
+ renderRouteTemplate(route, (to) => path4.posix.join(routeFileRelativePathPosix, to))
1878
1877
  );
1879
1878
  }
1880
1879
  }
@@ -1882,17 +1881,17 @@ function markoRun(opts = {}) {
1882
1881
  for (const middleware of routes2.middleware) {
1883
1882
  if (!(await getExportsFromFile(context, middleware.filePath)).includes("default")) {
1884
1883
  context.warn(
1885
- `Did not find a default export in middleware '${path3.relative(root, middleware.filePath)}'`
1884
+ `Did not find a default export in middleware '${path4.relative(root, middleware.filePath)}'`
1886
1885
  );
1887
1886
  }
1888
1887
  }
1889
1888
  virtualFiles.set(
1890
- path3.posix.join(root, MIDDLEWARE_FILENAME),
1889
+ path4.posix.join(root, MIDDLEWARE_FILENAME),
1891
1890
  renderMiddleware(routes2.middleware)
1892
1891
  );
1893
1892
  }
1894
1893
  virtualFiles.set(
1895
- path3.posix.join(root, ROUTER_FILENAME),
1894
+ path4.posix.join(root, ROUTER_FILENAME),
1896
1895
  renderRouter(routes2, relativeEntryFilesDirPosix, {
1897
1896
  trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1898
1897
  })
@@ -1916,7 +1915,7 @@ function markoRun(opts = {}) {
1916
1915
  throw err;
1917
1916
  }
1918
1917
  virtualFiles.set(
1919
- path3.posix.join(root, ROUTER_FILENAME),
1918
+ path4.posix.join(root, ROUTER_FILENAME),
1920
1919
  `throw ${JSON.stringify(prepareError(err))}`
1921
1920
  );
1922
1921
  }
@@ -1959,23 +1958,23 @@ function markoRun(opts = {}) {
1959
1958
  );
1960
1959
  markoVitePluginOptions.runtimeId = opts.runtimeId;
1961
1960
  markoVitePluginOptions.basePathVar = opts.basePathVar;
1962
- resolvedRoutesDir = path3.resolve(root, routesDir);
1963
- entryFilesDir = path3.join(
1961
+ resolvedRoutesDir = path4.resolve(root, routesDir);
1962
+ entryFilesDir = path4.join(
1964
1963
  getModulesDir(root),
1965
1964
  ".marko",
1966
1965
  createHash("shake256", { outputLength: 4 }).update(root).digest("hex")
1967
1966
  );
1968
1967
  entryFilesDirPosix = normalizePath(entryFilesDir);
1969
- relativeEntryFilesDirPosix = normalizePath(path3.relative(root, entryFilesDir));
1970
- typesDir = path3.join(root, ".marko-run");
1971
- devEntryFile = path3.join(root, "index.html");
1968
+ relativeEntryFilesDirPosix = normalizePath(path4.relative(root, entryFilesDir));
1969
+ typesDir = path4.join(root, ".marko-run");
1970
+ devEntryFile = path4.join(root, "index.html");
1972
1971
  devEntryFilePosix = normalizePath(devEntryFile);
1973
1972
  let outDir = ((_d = config2.build) == null ? void 0 : _d.outDir) || "dist";
1974
1973
  const assetsDir = ((_e = config2.build) == null ? void 0 : _e.assetsDir) || "assets";
1975
1974
  let rollupOutputOptions = (_g = (_f = config2.build) == null ? void 0 : _f.rollupOptions) == null ? void 0 : _g.output;
1976
1975
  if (isBuild) {
1977
1976
  if (!isSSRBuild) {
1978
- outDir = path3.join(outDir, CLIENT_OUT_DIR);
1977
+ outDir = path4.join(outDir, CLIENT_OUT_DIR);
1979
1978
  }
1980
1979
  const defaultRollupOutputOptions = {
1981
1980
  assetFileNames({ name }) {
@@ -2107,7 +2106,7 @@ function markoRun(opts = {}) {
2107
2106
  devServer.watcher.on("all", async (type, filename) => {
2108
2107
  seenErrors.clear();
2109
2108
  const routableFileType = matchRoutableFile(
2110
- path3.parse(filename).base
2109
+ path4.parse(filename).base
2111
2110
  );
2112
2111
  if (filename.startsWith(resolvedRoutesDir) && routableFileType) {
2113
2112
  if (type === "add" || type === "unlink" || type === "change" && (routableFileType === RoutableFileTypes.Handler || routableFileType === RoutableFileTypes.Middleware)) {
@@ -2152,19 +2151,19 @@ function markoRun(opts = {}) {
2152
2151
  },
2153
2152
  async resolveId(importee, importer) {
2154
2153
  if (importee === "@marko/run/router") {
2155
- return path3.resolve(root, ROUTER_FILENAME);
2154
+ return path4.resolve(root, ROUTER_FILENAME);
2156
2155
  } else if (importee.endsWith(".marko") && importee.includes(relativeEntryFilesDirPosix)) {
2157
2156
  if (!importee.startsWith(root)) {
2158
- importee = path3.resolve(root, "." + importee);
2157
+ importee = path4.resolve(root, "." + importee);
2159
2158
  }
2160
2159
  return normalizePath(importee);
2161
2160
  }
2162
2161
  let virtualFilePath;
2163
2162
  if (importee.startsWith(virtualFilePrefix)) {
2164
2163
  virtualFilePath = importee.slice(virtualFilePrefix.length + 1);
2165
- importee = path3.resolve(root, virtualFilePath);
2164
+ importee = path4.resolve(root, virtualFilePath);
2166
2165
  } else if (!isBuild && importer && (importer === devEntryFile || normalizePath(importer) === devEntryFilePosix) && importee.startsWith(`/${markoRunFilePrefix}`)) {
2167
- importee = path3.resolve(root, "." + importee);
2166
+ importee = path4.resolve(root, "." + importee);
2168
2167
  }
2169
2168
  importee = normalizePath(importee);
2170
2169
  if (!buildVirtualFilesResult) {
@@ -2173,7 +2172,7 @@ function markoRun(opts = {}) {
2173
2172
  if (virtualFiles.has(importee)) {
2174
2173
  return importee;
2175
2174
  } else if (virtualFilePath) {
2176
- const filePath = path3.resolve(__dirname, "..", virtualFilePath);
2175
+ const filePath = path4.resolve(__dirname, "..", virtualFilePath);
2177
2176
  return await this.resolve(filePath, importer, {
2178
2177
  skipSelf: true
2179
2178
  });
@@ -2212,7 +2211,7 @@ function markoRun(opts = {}) {
2212
2211
  const builtEntries = Object.values(bundle).reduce(
2213
2212
  (acc, item) => {
2214
2213
  if (item.type === "chunk" && item.isEntry) {
2215
- acc.push(path3.join(options.dir, item.fileName));
2214
+ acc.push(path4.join(options.dir, item.fileName));
2216
2215
  }
2217
2216
  return acc;
2218
2217
  },
@@ -2272,11 +2271,11 @@ async function ensureDir(dir) {
2272
2271
  }
2273
2272
  async function getPackageData(dir) {
2274
2273
  do {
2275
- const pkgPath = path3.join(dir, "package.json");
2274
+ const pkgPath = path4.join(dir, "package.json");
2276
2275
  if (fs4.existsSync(pkgPath)) {
2277
2276
  return JSON.parse(await fs4.promises.readFile(pkgPath, "utf-8"));
2278
2277
  }
2279
- } while (dir !== (dir = path3.dirname(dir)));
2278
+ } while (dir !== (dir = path4.dirname(dir)));
2280
2279
  return null;
2281
2280
  }
2282
2281
  async function resolveAdapter(root, options, log) {
@@ -2334,7 +2333,7 @@ function getModulesDir(root, dir = __dirname) {
2334
2333
  return dir.slice(0, index + 12);
2335
2334
  }
2336
2335
  }
2337
- return path3.join(root, "node_modules");
2336
+ return path4.join(root, "node_modules");
2338
2337
  }
2339
2338
  var defaultConfigPlugin = {
2340
2339
  name: `${PLUGIN_NAME_PREFIX}:defaults`,
@@ -2353,7 +2352,7 @@ var defaultConfigPlugin = {
2353
2352
  };
2354
2353
 
2355
2354
  // src/cli/commands.ts
2356
- var __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
2355
+ var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
2357
2356
  var defaultConfigFileBases = ["serve.config", "vite.config"];
2358
2357
  var defaultConfigFileExts = [".js", ".cjs", ".mjs", ".ts", ".mts"];
2359
2358
  async function preview(entry, distEntry, cwd, configFile, port, outDir, envFile, args = []) {
@@ -2382,10 +2381,10 @@ async function preview(entry, distEntry, cwd, configFile, port, outDir, envFile,
2382
2381
  if (!entry) {
2383
2382
  entry = await ((_a = adapter.getEntryFile) == null ? void 0 : _a.call(adapter));
2384
2383
  }
2385
- const dir = path4.resolve(cwd, resolvedConfig.build.outDir);
2386
- const entryFile = distEntry ? path4.join(dir, distEntry) : await findFileWithExt(dir, "index", [".mjs", ".js"]);
2384
+ const dir = path5.resolve(cwd, resolvedConfig.build.outDir);
2385
+ const entryFile = distEntry ? path5.join(dir, distEntry) : await findFileWithExt(dir, "index", [".mjs", ".js"]);
2387
2386
  if (envFile) {
2388
- envFile = path4.resolve(cwd, envFile);
2387
+ envFile = path5.resolve(cwd, envFile);
2389
2388
  }
2390
2389
  const options = {
2391
2390
  cwd,
@@ -2409,7 +2408,7 @@ async function dev(entry, cwd, configFile, port, envFile, args = []) {
2409
2408
  "serve"
2410
2409
  );
2411
2410
  if (envFile) {
2412
- envFile = path4.resolve(cwd, envFile);
2411
+ envFile = path5.resolve(cwd, envFile);
2413
2412
  }
2414
2413
  const [availablePort, adapter] = await Promise.all([
2415
2414
  getAvailablePort(
@@ -2463,7 +2462,7 @@ async function build(entry, cwd, configFile, outDir, envFile) {
2463
2462
  }
2464
2463
  }
2465
2464
  if (envFile) {
2466
- envFile = path4.resolve(cwd, envFile);
2465
+ envFile = path5.resolve(cwd, envFile);
2467
2466
  }
2468
2467
  const buildConfig = setExternalAdapterOptions(
2469
2468
  {
@@ -2501,7 +2500,7 @@ async function build(entry, cwd, configFile, outDir, envFile) {
2501
2500
  }
2502
2501
  function findFileWithExt(dir, base, extensions = defaultConfigFileExts) {
2503
2502
  for (const ext of extensions) {
2504
- const filePath = path4.join(dir, base + ext);
2503
+ const filePath = path5.join(dir, base + ext);
2505
2504
  if (fs5.existsSync(filePath)) {
2506
2505
  return filePath;
2507
2506
  }
@@ -2510,7 +2509,7 @@ function findFileWithExt(dir, base, extensions = defaultConfigFileExts) {
2510
2509
  }
2511
2510
  async function getViteConfig(dir, configFile, bases = defaultConfigFileBases) {
2512
2511
  if (configFile) {
2513
- const configFilePath = path4.join(dir, configFile);
2512
+ const configFilePath = path5.join(dir, configFile);
2514
2513
  if (!fs5.existsSync(configFilePath)) {
2515
2514
  throw new Error(`No config file found at '${configFilePath}'`);
2516
2515
  }
@@ -2522,7 +2521,7 @@ async function getViteConfig(dir, configFile, bases = defaultConfigFileBases) {
2522
2521
  return configFile;
2523
2522
  }
2524
2523
  }
2525
- return path4.join(__dirname2, "default.config.mjs");
2524
+ return path5.join(__dirname2, "default.config.mjs");
2526
2525
  }
2527
2526
  async function resolveAdapter2(config2) {
2528
2527
  const options = getExternalPluginOptions(config2);