@marko/run 0.5.11 → 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.
@@ -55,7 +55,7 @@ var import_url = require("url");
55
55
  var __importMetaURL = (0, import_url.pathToFileURL)(__filename);
56
56
 
57
57
  // src/vite/plugin.ts
58
- var import_path3 = __toESM(require("path"), 1);
58
+ var import_path4 = __toESM(require("path"), 1);
59
59
  var import_fs3 = __toESM(require("fs"), 1);
60
60
  var import_glob = require("glob");
61
61
  var import_url2 = require("url");
@@ -143,10 +143,10 @@ var _VDir = class _VDir {
143
143
  });
144
144
  return value;
145
145
  }
146
- addDir(path4, segment) {
146
+ addDir(path5, segment) {
147
147
  const map = segment.type === "_" ? __privateGet(this, _pathlessDirs) ?? __privateSet(this, _pathlessDirs, /* @__PURE__ */ new Map()) : __privateGet(this, _dirs) ?? __privateSet(this, _dirs, /* @__PURE__ */ new Map());
148
148
  if (!map.has(segment.name)) {
149
- const dir = new _VDir(this, segment, path4);
149
+ const dir = new _VDir(this, segment, path5);
150
150
  map.set(segment.name, dir);
151
151
  return dir;
152
152
  }
@@ -192,10 +192,10 @@ var _VDir = class _VDir {
192
192
  const dirs = [];
193
193
  const unique = /* @__PURE__ */ new Set();
194
194
  for (const root of roots) {
195
- for (const path4 of paths) {
195
+ for (const path5 of paths) {
196
196
  let dir = root;
197
- for (const segment of path4.segments) {
198
- dir = dir.addDir(path4, segment);
197
+ for (const segment of path5.segments) {
198
+ dir = dir.addDir(path5, segment);
199
199
  }
200
200
  if (unique.has(dir.path)) {
201
201
  const sources = /* @__PURE__ */ new Set();
@@ -207,7 +207,7 @@ var _VDir = class _VDir {
207
207
  }
208
208
  }
209
209
  throw new Error(
210
- `Ambiguous directory structure: '${sourcePath}${path4.source}' defines '${dir.path}' multiple times.`
210
+ `Ambiguous directory structure: '${sourcePath}${path5.source}' defines '${dir.path}' multiple times.`
211
211
  );
212
212
  } else {
213
213
  unique.add(dir.path);
@@ -248,9 +248,9 @@ function parseFlatRoute(pattern) {
248
248
  } else if (charCode === 44) {
249
249
  if (!current) {
250
250
  segmentEnd(
251
- basePaths.map((path4) => ({
252
- ...path4,
253
- segments: path4.segments.slice()
251
+ basePaths.map((path5) => ({
252
+ ...path5,
253
+ segments: path5.segments.slice()
254
254
  })),
255
255
  "",
256
256
  "_",
@@ -280,9 +280,9 @@ function parseFlatRoute(pattern) {
280
280
  } else if (charCode === 36) {
281
281
  type = pattern.charCodeAt(i + 1) === 36 ? "$$" : "$";
282
282
  }
283
- current ?? (current = basePaths.map((path4) => ({
284
- ...path4,
285
- segments: path4.segments.slice()
283
+ current ?? (current = basePaths.map((path5) => ({
284
+ ...path5,
285
+ segments: path5.segments.slice()
286
286
  })));
287
287
  i = len;
288
288
  for (const char of delimiters) {
@@ -302,9 +302,9 @@ function parseFlatRoute(pattern) {
302
302
  }
303
303
  if (!current) {
304
304
  segmentEnd(
305
- basePaths.map((path4) => ({
306
- ...path4,
307
- segments: path4.segments.slice()
305
+ basePaths.map((path5) => ({
306
+ ...path5,
307
+ segments: path5.segments.slice()
308
308
  })),
309
309
  "",
310
310
  "_",
@@ -328,9 +328,9 @@ function parseFlatRoute(pattern) {
328
328
  segment.param = raw.slice(type.length);
329
329
  }
330
330
  }
331
- for (const path4 of paths) {
331
+ for (const path5 of paths) {
332
332
  if (segment) {
333
- if (path4.isCatchall) {
333
+ if (path5.isCatchall) {
334
334
  throw new Error(
335
335
  `Invalid route pattern: nested segments are not allowed after a catch-all parameter. Found '.' following '${pattern.slice(
336
336
  0,
@@ -338,22 +338,22 @@ function parseFlatRoute(pattern) {
338
338
  )}' in '${pattern}'.`
339
339
  );
340
340
  }
341
- path4.segments.push(segment);
342
- path4.id += path4.id === "/" ? segment.name : `/${segment.name}`;
341
+ path5.segments.push(segment);
342
+ path5.id += path5.id === "/" ? segment.name : `/${segment.name}`;
343
343
  if (type === "$$") {
344
- path4.isCatchall = true;
344
+ path5.isCatchall = true;
345
345
  }
346
346
  }
347
347
  if (map) {
348
- if (map.has(path4.id)) {
349
- const existing = map.get(path4.id);
348
+ if (map.has(path5.id)) {
349
+ const existing = map.get(path5.id);
350
350
  const existingExpansion = existing.segments.map((s) => s.raw).join(".");
351
- const currentExpansion = path4.segments.map((s) => s.raw).join(".");
351
+ const currentExpansion = path5.segments.map((s) => s.raw).join(".");
352
352
  throw new Error(
353
- `Invalid route pattern: route '${path4.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
353
+ `Invalid route pattern: route '${path5.id}' is ambiguous. Expansion '${currentExpansion}' collides with '${existingExpansion}' in '${pattern}'.`
354
354
  );
355
355
  }
356
- map.set(path4.id, path4);
356
+ map.set(path5.id, path5);
357
357
  }
358
358
  }
359
359
  }
@@ -409,7 +409,7 @@ async function buildRoutes(sources) {
409
409
  dirStack.length = prevDirStackLength;
410
410
  };
411
411
  },
412
- onFile({ name, path: path4 }) {
412
+ onFile({ name, path: path5 }) {
413
413
  const match = name.match(routeableFileRegex);
414
414
  if (!match) {
415
415
  return;
@@ -417,7 +417,7 @@ async function buildRoutes(sources) {
417
417
  const type = (match[1] || match[3]).toLowerCase();
418
418
  if (dirStack.length && isSpecialType(type)) {
419
419
  console.warn(
420
- `Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path4}`
420
+ `Special pages '${RoutableFileTypes.NotFound}' and '${RoutableFileTypes.Error}' are only considered in the root directory - ignoring ${path5}`
421
421
  );
422
422
  return;
423
423
  }
@@ -432,7 +432,7 @@ async function buildRoutes(sources) {
432
432
  id: String(nextFileId++),
433
433
  name,
434
434
  type,
435
- filePath: path4,
435
+ filePath: path5,
436
436
  relativePath,
437
437
  importPath: `${importPrefix}/${relativePath}`,
438
438
  verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
@@ -484,23 +484,23 @@ async function buildRoutes(sources) {
484
484
  }
485
485
  }
486
486
  if (page || handler) {
487
- const path4 = dir.pathInfo;
488
- if (uniqueRoutes.has(path4.id)) {
489
- const existing = uniqueRoutes.get(path4.id);
487
+ const path5 = dir.pathInfo;
488
+ if (uniqueRoutes.has(path5.id)) {
489
+ const existing = uniqueRoutes.get(path5.id);
490
490
  const route = routes[existing.index];
491
491
  const existingFiles = [route.handler, route.page].filter(Boolean).map((f) => f.filePath);
492
492
  const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
493
- throw new Error(`Duplicate routes for path '${path4.path}' were defined. A route established by:
493
+ throw new Error(`Duplicate routes for path '${path5.path}' were defined. A route established by:
494
494
  ${existingFiles.join(" and ")} via '${existing.dir.path}'
495
495
  collides with
496
496
  ${currentFiles.join(" and ")} via '${dir.path}'
497
497
  `);
498
498
  }
499
- uniqueRoutes.set(path4.id, { dir, index: routes.length });
499
+ uniqueRoutes.set(path5.id, { dir, index: routes.length });
500
500
  routes.push({
501
501
  index: nextRouteIndex++,
502
502
  key: dir.fullPath,
503
- paths: [path4],
503
+ paths: [path5],
504
504
  middleware: [...currentMiddleware],
505
505
  layouts: page ? [...currentLayouts] : [],
506
506
  meta: dir.files.get(RoutableFileTypes.Meta),
@@ -750,6 +750,7 @@ function hasVerb(route, verb) {
750
750
  }
751
751
 
752
752
  // src/vite/codegen/index.ts
753
+ var import_path2 = __toESM(require("path"), 1);
753
754
  function renderRouteTemplate(route, getRelativePath) {
754
755
  if (!route.page) {
755
756
  throw new Error(`Route ${route.key} has no page to render`);
@@ -844,7 +845,7 @@ function renderRouteEntry(route, entriesDir) {
844
845
  );
845
846
  }
846
847
  if (page) {
847
- const importPath = route.layouts.length ? `./${entriesDir}/${entryName}.marko` : `./${page.importPath}`;
848
+ const importPath = route.layouts.length ? `./${import_path2.default.posix.join(entriesDir, page.relativePath, "..", "route.marko")}` : `./${page.importPath}`;
848
849
  imports.writeLines(`import page from '${importPath}${serverEntryQuery}';`);
849
850
  }
850
851
  if (meta) {
@@ -951,7 +952,7 @@ function renderRouter(routes, entriesDir, options = {
951
952
  );
952
953
  }
953
954
  for (const route of Object.values(routes.special)) {
954
- const importPath = route.layouts.length ? `./${entriesDir}/${route.entryName}.marko` : `./${route.page.importPath}`;
955
+ const importPath = route.layouts.length ? `./${import_path2.default.posix.join(entriesDir, route.page.relativePath, "..", `route.${route.key}.marko`)}` : `./${route.page.importPath}`;
955
956
  imports.writeLines(
956
957
  `import page${route.key} from '${importPath}${serverEntryQuery}';`
957
958
  );
@@ -1122,7 +1123,7 @@ function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1122
1123
  if (useSwitch) {
1123
1124
  writer.writeBlockStart(`switch (${value}) {`);
1124
1125
  }
1125
- for (const { key, path: path4, route: route2 } of terminal) {
1126
+ for (const { key, path: path5, route: route2 } of terminal) {
1126
1127
  const decodedKey = decodeURIComponent(key);
1127
1128
  if (useSwitch) {
1128
1129
  writer.write(`case '${decodedKey}': `, true);
@@ -1130,7 +1131,7 @@ function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1130
1131
  writer.write(`if (${value} === '${decodedKey}') `, true);
1131
1132
  }
1132
1133
  writer.write(
1133
- `return ${renderMatch(verb, route2, path4)}; // ${path4.path}
1134
+ `return ${renderMatch(verb, route2, path5)}; // ${path5.path}
1134
1135
  `
1135
1136
  );
1136
1137
  }
@@ -1233,11 +1234,11 @@ function renderParams(params, pathIndex) {
1233
1234
  }
1234
1235
  return result ? result + " }" : "{}";
1235
1236
  }
1236
- function renderMatch(verb, route, path4, pathIndex) {
1237
+ function renderMatch(verb, route, path5, pathIndex) {
1237
1238
  const handler = `${verb}${route.index}`;
1238
- const params = path4.params ? renderParams(path4.params, pathIndex) : "{}";
1239
+ const params = path5.params ? renderParams(path5.params, pathIndex) : "{}";
1239
1240
  const meta = route.meta ? `meta${route.index}` : "{}";
1240
- const pathPattern = pathToURLPatternString(path4.path);
1241
+ const pathPattern = pathToURLPatternString(path5.path);
1241
1242
  return `{ handler: ${handler}, params: ${params}, meta: ${meta}, path: '${pathPattern}' }`;
1242
1243
  }
1243
1244
  function renderMiddleware(middleware) {
@@ -1258,15 +1259,15 @@ function renderMiddleware(middleware) {
1258
1259
  imports.join();
1259
1260
  return writer.end();
1260
1261
  }
1261
- function stripTsExtension(path4) {
1262
- const index = path4.lastIndexOf(".");
1262
+ function stripTsExtension(path5) {
1263
+ const index = path5.lastIndexOf(".");
1263
1264
  if (index !== -1) {
1264
- const ext = path4.slice(index + 1);
1265
+ const ext = path5.slice(index + 1);
1265
1266
  if (ext.toLowerCase() === "ts") {
1266
- return path4.slice(0, index);
1267
+ return path5.slice(0, index);
1267
1268
  }
1268
1269
  }
1269
- return path4;
1270
+ return path5;
1270
1271
  }
1271
1272
  async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1272
1273
  var _a, _b;
@@ -1298,8 +1299,8 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1298
1299
  const routeTypes = /* @__PURE__ */ new Map();
1299
1300
  for (const route of routes.list) {
1300
1301
  let routeType = "";
1301
- for (const path4 of route.paths) {
1302
- const pathType = `"${pathToURLPatternString(path4.path)}"`;
1302
+ for (const path5 of route.paths) {
1303
+ const pathType = `"${pathToURLPatternString(path5.path)}"`;
1303
1304
  routeType += routeType ? " | " + pathType : pathType;
1304
1305
  routesWriter.writeLines(`${pathType}: Routes["${route.key}"];`);
1305
1306
  }
@@ -1335,22 +1336,22 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1335
1336
  const pageWriter = writer.branch("page");
1336
1337
  const layoutWriter = writer.branch("layout");
1337
1338
  for (const [file, types] of routeTypes) {
1338
- const path4 = `${pathPrefix}/${file.relativePath}`;
1339
+ const path5 = `${pathPrefix}/${file.relativePath}`;
1339
1340
  const routeType = `Run.Routes[${types.join(" | ")}]`;
1340
1341
  switch (file.type) {
1341
1342
  case RoutableFileTypes.Handler:
1342
- writeModuleDeclaration(handlerWriter, path4, routeType);
1343
+ writeModuleDeclaration(handlerWriter, path5, routeType);
1343
1344
  break;
1344
1345
  case RoutableFileTypes.Middleware:
1345
- writeModuleDeclaration(middlewareWriter, path4, routeType);
1346
+ writeModuleDeclaration(middlewareWriter, path5, routeType);
1346
1347
  break;
1347
1348
  case RoutableFileTypes.Page:
1348
- writeModuleDeclaration(pageWriter, path4, routeType);
1349
+ writeModuleDeclaration(pageWriter, path5, routeType);
1349
1350
  break;
1350
1351
  case RoutableFileTypes.Layout:
1351
1352
  writeModuleDeclaration(
1352
1353
  layoutWriter,
1353
- path4,
1354
+ path5,
1354
1355
  routeType,
1355
1356
  `
1356
1357
  export interface Input {
@@ -1361,7 +1362,7 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1361
1362
  case RoutableFileTypes.Error:
1362
1363
  writeModuleDeclaration(
1363
1364
  writer,
1364
- path4,
1365
+ path5,
1365
1366
  "globalThis.MarkoRun.Route",
1366
1367
  `
1367
1368
  export interface Input {
@@ -1370,7 +1371,7 @@ async function renderRouteTypeInfo(routes, pathPrefix = ".", adapter) {
1370
1371
  );
1371
1372
  break;
1372
1373
  case RoutableFileTypes.NotFound:
1373
- writeModuleDeclaration(writer, path4, "Run.Route");
1374
+ writeModuleDeclaration(writer, path5, "Run.Route");
1374
1375
  break;
1375
1376
  }
1376
1377
  }
@@ -1394,7 +1395,7 @@ type Routes = {`);
1394
1395
  if (meta) {
1395
1396
  const metaPath = stripTsExtension(`${pathPrefix}/${meta.relativePath}`);
1396
1397
  let metaType = `typeof import("${metaPath}")`;
1397
- if (/\.(ts|js|mjs)$/.test(meta.relativePath)) {
1398
+ if (/\.(ts|js|mjs)$/.test(meta.name)) {
1398
1399
  metaType += `["default"]`;
1399
1400
  }
1400
1401
  routeType += ` meta: ${metaType};`;
@@ -1405,13 +1406,13 @@ type Routes = {`);
1405
1406
  writer.writeBlockEnd("}");
1406
1407
  return writer.end();
1407
1408
  }
1408
- function writeModuleDeclaration(writer, path4, routeType, moduleTypes) {
1409
- writer.writeLines("").write(`declare module "${stripTsExtension(path4)}" {`);
1409
+ function writeModuleDeclaration(writer, path5, routeType, moduleTypes) {
1410
+ writer.writeLines("").write(`declare module "${stripTsExtension(path5)}" {`);
1410
1411
  if (moduleTypes) {
1411
1412
  writer.write(moduleTypes);
1412
1413
  }
1413
1414
  if (routeType) {
1414
- const isMarko = path4.endsWith(".marko");
1415
+ const isMarko = path5.endsWith(".marko");
1415
1416
  writer.write(`
1416
1417
  namespace MarkoRun {
1417
1418
  export { NotHandled, NotMatched, GetPaths, PostPaths, GetablePath, GetableHref, PostablePath, PostableHref, Platform };
@@ -1425,8 +1426,8 @@ function writeModuleDeclaration(writer, path4, routeType, moduleTypes) {
1425
1426
  writer.writeLines(`
1426
1427
  }`);
1427
1428
  }
1428
- function pathToURLPatternString(path4) {
1429
- return path4.replace(/\/\$(\$?)([^\/]*)/g, (_, catchAll, name) => {
1429
+ function pathToURLPatternString(path5) {
1430
+ return path5.replace(/\/\$(\$?)([^\/]*)/g, (_, catchAll, name) => {
1430
1431
  name = decodeURIComponent(name);
1431
1432
  return catchAll ? `/:${name || "rest"}*` : `/:${name}`;
1432
1433
  });
@@ -1435,11 +1436,11 @@ function createRouteTrie(routes) {
1435
1436
  const root = {
1436
1437
  key: ""
1437
1438
  };
1438
- function insert(path4, route) {
1439
+ function insert(path5, route) {
1439
1440
  let node = root;
1440
- for (const segment of path4.segments) {
1441
+ for (const segment of path5.segments) {
1441
1442
  if (segment === "$$") {
1442
- node.catchAll ?? (node.catchAll = { route, path: path4 });
1443
+ node.catchAll ?? (node.catchAll = { route, path: path5 });
1443
1444
  return;
1444
1445
  } else if (segment === "$") {
1445
1446
  node = node.dynamic ?? (node.dynamic = {
@@ -1457,12 +1458,12 @@ function createRouteTrie(routes) {
1457
1458
  node = next;
1458
1459
  }
1459
1460
  }
1460
- node.path ?? (node.path = path4);
1461
+ node.path ?? (node.path = path5);
1461
1462
  node.route ?? (node.route = route);
1462
1463
  }
1463
1464
  for (const route of routes) {
1464
- for (const path4 of route.paths) {
1465
- insert(path4, route);
1465
+ for (const path5 of route.paths) {
1466
+ insert(path5, route);
1466
1467
  }
1467
1468
  }
1468
1469
  return root;
@@ -1568,7 +1569,7 @@ function logRoutesTable(routes, bundle, options) {
1568
1569
  style: { compact: true }
1569
1570
  });
1570
1571
  for (const route of routes.list) {
1571
- for (const path4 of route.paths) {
1572
+ for (const path5 of route.paths) {
1572
1573
  const verbs = getVerbs(route).sort(
1573
1574
  (a, b) => HttpVerbOrder[a] - HttpVerbOrder[b]
1574
1575
  );
@@ -1587,7 +1588,7 @@ function logRoutesTable(routes, bundle, options) {
1587
1588
  import_kleur.default.bold(HttpVerbColors[verb](verb.toUpperCase()))
1588
1589
  ];
1589
1590
  if (verbs.length === 1 || firstRow) {
1590
- row.push({ rowSpan: verbs.length, content: prettyPath(path4.path) });
1591
+ row.push({ rowSpan: verbs.length, content: prettyPath(path5.path) });
1591
1592
  firstRow = false;
1592
1593
  }
1593
1594
  row.push(entryType.join(" -> "));
@@ -1648,8 +1649,8 @@ function prettySize([bytes, compBytes]) {
1648
1649
  else str += import_kleur.default.bold(import_kleur.default.red(compSize));
1649
1650
  return str;
1650
1651
  }
1651
- function prettyPath(path4) {
1652
- return path4.replace(/\/\$\$(.*)$/, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`:${p}`)));
1652
+ function prettyPath(path5) {
1653
+ return path5.replace(/\/\$\$(.*)$/, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`:${p}`)));
1653
1654
  }
1654
1655
 
1655
1656
  // src/vite/utils/config.ts
@@ -1671,11 +1672,11 @@ var import_debug = __toESM(require("debug"), 1);
1671
1672
 
1672
1673
  // src/vite/utils/read-once-persisted-store.ts
1673
1674
  var import_os = __toESM(require("os"), 1);
1674
- var import_path2 = __toESM(require("path"), 1);
1675
+ var import_path3 = __toESM(require("path"), 1);
1675
1676
  var import_fs2 = require("fs");
1676
1677
  var noop = () => {
1677
1678
  };
1678
- var tmpFile = import_path2.default.join(import_os.default.tmpdir(), "marko-run-storage.json");
1679
+ var tmpFile = import_path3.default.join(import_os.default.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
  var import_crypto = require("crypto");
1745
1746
  var debug = (0, import_debug.default)("@marko/run");
1746
- var __dirname = import_path3.default.dirname((0, import_url2.fileURLToPath)(__importMetaURL));
1747
+ var __dirname = import_path4.default.dirname((0, import_url2.fileURLToPath)(__importMetaURL));
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 = import_path3.default.sep === WINDOWS_SEP ? (id) => id.replace(/\\/g, POSIX_SEP) : (id) => id;
1755
+ var normalizePath = import_path4.default.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(import_path3.default.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 = import_path3.default.join(typesDir, "routes.d.ts");
1788
+ const filepath = import_path4.default.join(typesDir, "routes.d.ts");
1791
1789
  const data = await renderRouteTypeInfo(
1792
1790
  routes2,
1793
- normalizePath(import_path3.default.relative(typesDir, resolvedRoutesDir)),
1791
+ normalizePath(import_path4.default.relative(typesDir, resolvedRoutesDir)),
1794
1792
  adapter
1795
1793
  );
1796
1794
  if (data !== typesFile || !import_fs3.default.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(import_path3.default.posix.join(root, `${route.entryName}.js`), "");
1813
+ virtualFiles.set(import_path4.default.posix.join(root, `${route.entryName}.js`), "");
1816
1814
  }
1817
1815
  if (routes.middleware.length) {
1818
- virtualFiles.set(import_path3.default.posix.join(root, MIDDLEWARE_FILENAME), "");
1816
+ virtualFiles.set(import_path4.default.posix.join(root, MIDDLEWARE_FILENAME), "");
1819
1817
  }
1820
- virtualFiles.set(import_path3.default.posix.join(root, ROUTER_FILENAME), "");
1818
+ virtualFiles.set(import_path4.default.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 (import_fs3.default.existsSync(entryFilesDir)) {
1835
1832
  import_fs3.default.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 '${import_path3.default.relative(root, route.handler.filePath)}' - expected ${httpVerbs.map((v) => v.toUpperCase()).join(", ")}`
1849
+ `Did not find any http verb exports in handler '${import_path4.default.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 = !!import_fs3.default.mkdirSync(entryFilesDir, {
1858
- recursive: true
1859
- }));
1854
+ const relativePath = import_path4.default.relative(resolvedRoutesDir, route.page.filePath);
1855
+ const routeFileDir = import_path4.default.join(entryFilesDir, relativePath, "..");
1856
+ const routeFileRelativePathPosix = normalizePath(import_path4.default.relative(routeFileDir, root));
1857
+ import_fs3.default.mkdirSync(routeFileDir, { recursive: true });
1860
1858
  import_fs3.default.writeFileSync(
1861
- import_path3.default.join(entryFilesDir, `${route.entryName}.marko`),
1862
- renderRouteTemplate(route, getEntryFileRelativePath)
1859
+ import_path4.default.join(routeFileDir, "route.marko"),
1860
+ renderRouteTemplate(route, (to) => import_path4.default.posix.join(routeFileRelativePathPosix, to))
1863
1861
  );
1864
1862
  }
1865
1863
  virtualFiles.set(
1866
- import_path3.default.posix.join(root, `${route.entryName}.js`),
1864
+ import_path4.default.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 = !!import_fs3.default.mkdirSync(entryFilesDir, {
1873
- recursive: true
1874
- }));
1869
+ if (route.page && route.layouts.length) {
1870
+ const relativePath = import_path4.default.relative(resolvedRoutesDir, route.page.filePath);
1871
+ const routeFileDir = import_path4.default.join(entryFilesDir, relativePath, "..");
1872
+ const routeFileRelativePathPosix = normalizePath(import_path4.default.relative(routeFileDir, root));
1873
+ import_fs3.default.mkdirSync(routeFileDir, { recursive: true });
1875
1874
  import_fs3.default.writeFileSync(
1876
- import_path3.default.join(entryFilesDir, `${route.entryName}.marko`),
1877
- renderRouteTemplate(route, getEntryFileRelativePath)
1875
+ import_path4.default.join(routeFileDir, `route.${route.key}.marko`),
1876
+ renderRouteTemplate(route, (to) => import_path4.default.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 '${import_path3.default.relative(root, middleware.filePath)}'`
1884
+ `Did not find a default export in middleware '${import_path4.default.relative(root, middleware.filePath)}'`
1886
1885
  );
1887
1886
  }
1888
1887
  }
1889
1888
  virtualFiles.set(
1890
- import_path3.default.posix.join(root, MIDDLEWARE_FILENAME),
1889
+ import_path4.default.posix.join(root, MIDDLEWARE_FILENAME),
1891
1890
  renderMiddleware(routes2.middleware)
1892
1891
  );
1893
1892
  }
1894
1893
  virtualFiles.set(
1895
- import_path3.default.posix.join(root, ROUTER_FILENAME),
1894
+ import_path4.default.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
- import_path3.default.posix.join(root, ROUTER_FILENAME),
1918
+ import_path4.default.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 = import_path3.default.resolve(root, routesDir);
1963
- entryFilesDir = import_path3.default.join(
1961
+ resolvedRoutesDir = import_path4.default.resolve(root, routesDir);
1962
+ entryFilesDir = import_path4.default.join(
1964
1963
  getModulesDir(root),
1965
1964
  ".marko",
1966
1965
  (0, import_crypto.createHash)("shake256", { outputLength: 4 }).update(root).digest("hex")
1967
1966
  );
1968
1967
  entryFilesDirPosix = normalizePath(entryFilesDir);
1969
- relativeEntryFilesDirPosix = normalizePath(import_path3.default.relative(root, entryFilesDir));
1970
- typesDir = import_path3.default.join(root, ".marko-run");
1971
- devEntryFile = import_path3.default.join(root, "index.html");
1968
+ relativeEntryFilesDirPosix = normalizePath(import_path4.default.relative(root, entryFilesDir));
1969
+ typesDir = import_path4.default.join(root, ".marko-run");
1970
+ devEntryFile = import_path4.default.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 = import_path3.default.join(outDir, CLIENT_OUT_DIR);
1977
+ outDir = import_path4.default.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
- import_path3.default.parse(filename).base
2109
+ import_path4.default.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 import_path3.default.resolve(root, ROUTER_FILENAME);
2154
+ return import_path4.default.resolve(root, ROUTER_FILENAME);
2156
2155
  } else if (importee.endsWith(".marko") && importee.includes(relativeEntryFilesDirPosix)) {
2157
2156
  if (!importee.startsWith(root)) {
2158
- importee = import_path3.default.resolve(root, "." + importee);
2157
+ importee = import_path4.default.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 = import_path3.default.resolve(root, virtualFilePath);
2164
+ importee = import_path4.default.resolve(root, virtualFilePath);
2166
2165
  } else if (!isBuild && importer && (importer === devEntryFile || normalizePath(importer) === devEntryFilePosix) && importee.startsWith(`/${markoRunFilePrefix}`)) {
2167
- importee = import_path3.default.resolve(root, "." + importee);
2166
+ importee = import_path4.default.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 = import_path3.default.resolve(__dirname, "..", virtualFilePath);
2175
+ const filePath = import_path4.default.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(import_path3.default.join(options.dir, item.fileName));
2214
+ acc.push(import_path4.default.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 = import_path3.default.join(dir, "package.json");
2274
+ const pkgPath = import_path4.default.join(dir, "package.json");
2276
2275
  if (import_fs3.default.existsSync(pkgPath)) {
2277
2276
  return JSON.parse(await import_fs3.default.promises.readFile(pkgPath, "utf-8"));
2278
2277
  }
2279
- } while (dir !== (dir = import_path3.default.dirname(dir)));
2278
+ } while (dir !== (dir = import_path4.default.dirname(dir)));
2280
2279
  return null;
2281
2280
  }
2282
2281
  async function resolveAdapter(root, options, log) {
@@ -2329,7 +2328,7 @@ function getModulesDir(root, dir = __dirname) {
2329
2328
  return dir.slice(0, index + 12);
2330
2329
  }
2331
2330
  }
2332
- return import_path3.default.join(root, "node_modules");
2331
+ return import_path4.default.join(root, "node_modules");
2333
2332
  }
2334
2333
  var defaultConfigPlugin = {
2335
2334
  name: `${PLUGIN_NAME_PREFIX}:defaults`,