@marko/run 0.5.0 → 0.5.1

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.
@@ -764,16 +764,19 @@ function hasVerb(route, verb) {
764
764
  }
765
765
 
766
766
  // src/vite/codegen/index.ts
767
- function renderRouteTemplate(route) {
767
+ function renderRouteTemplate(route, getRelativePath) {
768
768
  if (!route.page) {
769
769
  throw new Error(`Route ${route.key} has no page to render`);
770
770
  }
771
771
  return renderEntryTemplate(
772
772
  route.entryName,
773
- [...route.layouts, route.page].map((file) => `./${file.importPath}`)
773
+ [...route.layouts, route.page].map(
774
+ (file) => getRelativePath(file.importPath)
775
+ ),
776
+ route.key === RoutableFileTypes.Error ? ["error"] : []
774
777
  );
775
778
  }
776
- function renderEntryTemplate(name, files) {
779
+ function renderEntryTemplate(name, files, pageInputs = []) {
777
780
  if (!name) {
778
781
  throw new Error(`Invalid argument - 'name' cannot be empty`);
779
782
  }
@@ -781,27 +784,28 @@ function renderEntryTemplate(name, files) {
781
784
  throw new Error(`Invalid argument - 'files' cannot be empty`);
782
785
  }
783
786
  const writer = createStringWriter();
784
- writer.writeLines(`// ${virtualFilePrefix}/${name}.marko`);
787
+ writer.writeLines(`// ${name}.marko`);
785
788
  writer.branch("imports");
786
789
  writer.writeLines("");
787
- writeEntryTemplateTag(writer, files);
790
+ writeEntryTemplateTag(writer, files, pageInputs);
788
791
  return writer.end();
789
792
  }
790
- function writeEntryTemplateTag(writer, [file, ...rest], index = 1) {
793
+ function writeEntryTemplateTag(writer, [file, ...rest], pageInputs, index = 1) {
791
794
  if (file) {
792
795
  const isLast = !rest.length;
793
796
  const tag = isLast ? "Page" : `Layout${index}`;
794
797
  writer.branch("imports").writeLines(`import ${tag} from '${file}';`);
795
798
  if (isLast) {
796
- writer.writeLines(`<${tag} ...input/>`);
799
+ const attributes = pageInputs.length ? " " + pageInputs.map((name) => `${name}=input.${name}`).join(" ") : "";
800
+ writer.writeLines(`<${tag}${attributes}/>`);
797
801
  } else {
798
- writer.writeBlockStart(`<${tag} ...input>`);
799
- writeEntryTemplateTag(writer, rest, index + 1);
802
+ writer.writeBlockStart(`<${tag}>`);
803
+ writeEntryTemplateTag(writer, rest, pageInputs, index + 1);
800
804
  writer.writeBlockEnd(`</>`);
801
805
  }
802
806
  }
803
807
  }
804
- function renderRouteEntry(route) {
808
+ function renderRouteEntry(route, entriesDir) {
805
809
  var _a;
806
810
  const { key, index, handler, page, middleware, meta, entryName } = route;
807
811
  const verbs = getVerbs(route);
@@ -854,9 +858,8 @@ function renderRouteEntry(route) {
854
858
  );
855
859
  }
856
860
  if (page) {
857
- imports.writeLines(
858
- `import page from '${virtualFilePrefix}/${entryName}.marko${serverEntryQuery}';`
859
- );
861
+ const importPath = route.layouts.length ? `./${entriesDir}/${entryName}.marko` : `./${page.importPath}`;
862
+ imports.writeLines(`import page from '${importPath}${serverEntryQuery}';`);
860
863
  }
861
864
  if (meta) {
862
865
  imports.writeLines(
@@ -944,7 +947,7 @@ function writeRouteEntryHandler(writer, route, verb) {
944
947
  continuations.join();
945
948
  writer.writeBlockEnd("}");
946
949
  }
947
- function renderRouter(routes, options = {
950
+ function renderRouter(routes, entriesDir, options = {
948
951
  trailingSlashes: "RedirectWithout"
949
952
  }) {
950
953
  const writer = createStringWriter();
@@ -961,9 +964,10 @@ function renderRouter(routes, options = {
961
964
  `import { ${names.join(", ")} } from '${virtualFilePrefix}/${route.entryName}.js';`
962
965
  );
963
966
  }
964
- for (const { key, entryName } of Object.values(routes.special)) {
967
+ for (const page of Object.values(routes.special)) {
968
+ const importPath = page.layouts.length ? `./${entriesDir}/${page.entryName}.marko` : `./${page.importPath}`;
965
969
  imports.writeLines(
966
- `import page${key} from '${virtualFilePrefix}/${entryName}.marko${serverEntryQuery}';`
970
+ `import page${page.key} from '${importPath}${serverEntryQuery}';`
967
971
  );
968
972
  }
969
973
  writer.writeLines(
@@ -1737,18 +1741,23 @@ function prepareError(err) {
1737
1741
  }
1738
1742
 
1739
1743
  // src/vite/plugin.ts
1744
+ import { createHash } from "crypto";
1740
1745
  var debug = createDebug("@marko/run");
1741
1746
  var __dirname = path3.dirname(fileURLToPath(import.meta.url));
1742
1747
  var PLUGIN_NAME_PREFIX = "marko-run-vite";
1743
1748
  var POSIX_SEP = "/";
1744
1749
  var WINDOWS_SEP = "\\";
1745
1750
  var CLIENT_OUT_DIR = "public";
1751
+ var MIDDLEWARE_FILENAME = `${markoRunFilePrefix}middleware.js`;
1752
+ var ROUTER_FILENAME = `${markoRunFilePrefix}router.js`;
1746
1753
  var normalizePath = path3.sep === WINDOWS_SEP ? (id) => id.replace(/\\/g, POSIX_SEP) : (id) => id;
1747
1754
  function markoRun(opts = {}) {
1748
1755
  let { routesDir, adapter, ...markoVitePluginOptions } = opts;
1749
1756
  let store;
1750
1757
  let root;
1751
1758
  let resolvedRoutesDir;
1759
+ let entryFilesDir;
1760
+ let relativeEntryFilesDir;
1752
1761
  let typesDir;
1753
1762
  let isBuild = false;
1754
1763
  let isSSRBuild = false;
@@ -1768,6 +1777,9 @@ function markoRun(opts = {}) {
1768
1777
  routesBuild: 0,
1769
1778
  routesRender: 0
1770
1779
  };
1780
+ function getEntryFileRelativePath(to) {
1781
+ return path3.relative(entryFilesDir, to);
1782
+ }
1771
1783
  async function writeTypesFile(routes2) {
1772
1784
  if (routes2 && (tsConfigExists ?? (tsConfigExists = await globFileExists(
1773
1785
  root,
@@ -1798,27 +1810,12 @@ function markoRun(opts = {}) {
1798
1810
  throw new Error("No routes generated");
1799
1811
  }
1800
1812
  for (const route of routes.list) {
1801
- if (route.page) {
1802
- virtualFiles.set(
1803
- path3.posix.join(root, `${route.entryName}.marko`),
1804
- ""
1805
- );
1806
- }
1807
1813
  virtualFiles.set(path3.posix.join(root, `${route.entryName}.js`), "");
1808
1814
  }
1809
- for (const route of Object.values(routes.special)) {
1810
- virtualFiles.set(
1811
- path3.posix.join(root, `${route.entryName}.marko`),
1812
- ""
1813
- );
1814
- }
1815
1815
  if (routes.middleware.length) {
1816
- virtualFiles.set(
1817
- path3.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1818
- ""
1819
- );
1816
+ virtualFiles.set(path3.posix.join(root, MIDDLEWARE_FILENAME), "");
1820
1817
  }
1821
- virtualFiles.set("@marko/run/router", "");
1818
+ virtualFiles.set(path3.posix.join(root, ROUTER_FILENAME), "");
1822
1819
  resolve(routes);
1823
1820
  } catch (err) {
1824
1821
  reject(err);
@@ -1829,11 +1826,12 @@ function markoRun(opts = {}) {
1829
1826
  function renderVirtualFiles(context) {
1830
1827
  return renderVirtualFilesResult ?? (renderVirtualFilesResult = new Promise(async (resolve) => {
1831
1828
  var _a;
1832
- const routerOptions = {
1833
- trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1834
- };
1835
1829
  try {
1836
1830
  const routes2 = await buildVirtualFiles();
1831
+ let entryFilesDirExists = false;
1832
+ if (fs4.existsSync(entryFilesDir)) {
1833
+ fs4.rmSync(entryFilesDir, { recursive: true });
1834
+ }
1837
1835
  for (const route of routes2.list) {
1838
1836
  if (route.handler) {
1839
1837
  const exports = await getExportsFromFile(
@@ -1853,22 +1851,30 @@ function markoRun(opts = {}) {
1853
1851
  );
1854
1852
  }
1855
1853
  }
1856
- if (route.page) {
1857
- virtualFiles.set(
1858
- path3.posix.join(root, `${route.entryName}.marko`),
1859
- renderRouteTemplate(route)
1854
+ if (route.page && route.layouts.length) {
1855
+ entryFilesDirExists || (entryFilesDirExists = !!fs4.mkdirSync(entryFilesDir, {
1856
+ recursive: true
1857
+ }));
1858
+ fs4.writeFileSync(
1859
+ path3.posix.join(entryFilesDir, `${route.entryName}.marko`),
1860
+ renderRouteTemplate(route, getEntryFileRelativePath)
1860
1861
  );
1861
1862
  }
1862
1863
  virtualFiles.set(
1863
1864
  path3.posix.join(root, `${route.entryName}.js`),
1864
- renderRouteEntry(route)
1865
+ renderRouteEntry(route, relativeEntryFilesDir)
1865
1866
  );
1866
1867
  }
1867
1868
  for (const route of Object.values(routes2.special)) {
1868
- virtualFiles.set(
1869
- path3.posix.join(root, `${route.entryName}.marko`),
1870
- renderRouteTemplate(route)
1871
- );
1869
+ if (route.layouts.length) {
1870
+ entryFilesDirExists || (entryFilesDirExists = !!fs4.mkdirSync(entryFilesDir, {
1871
+ recursive: true
1872
+ }));
1873
+ fs4.writeFileSync(
1874
+ path3.posix.join(entryFilesDir, `${route.entryName}.marko`),
1875
+ renderRouteTemplate(route, getEntryFileRelativePath)
1876
+ );
1877
+ }
1872
1878
  }
1873
1879
  if (routes2.middleware.length) {
1874
1880
  for (const middleware of routes2.middleware) {
@@ -1879,13 +1885,15 @@ function markoRun(opts = {}) {
1879
1885
  }
1880
1886
  }
1881
1887
  virtualFiles.set(
1882
- path3.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1888
+ path3.posix.join(root, MIDDLEWARE_FILENAME),
1883
1889
  renderMiddleware(routes2.middleware)
1884
1890
  );
1885
1891
  }
1886
1892
  virtualFiles.set(
1887
- "@marko/run/router",
1888
- renderRouter(routes2, routerOptions)
1893
+ path3.posix.join(root, ROUTER_FILENAME),
1894
+ renderRouter(routes2, relativeEntryFilesDir, {
1895
+ trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1896
+ })
1889
1897
  );
1890
1898
  await writeTypesFile(routes2);
1891
1899
  if (adapter == null ? void 0 : adapter.routesGenerated) {
@@ -1906,7 +1914,7 @@ function markoRun(opts = {}) {
1906
1914
  throw err;
1907
1915
  }
1908
1916
  virtualFiles.set(
1909
- "@marko/run/router",
1917
+ path3.posix.join(root, ROUTER_FILENAME),
1910
1918
  `throw ${JSON.stringify(prepareError(err))}`
1911
1919
  );
1912
1920
  }
@@ -1949,6 +1957,13 @@ function markoRun(opts = {}) {
1949
1957
  markoVitePluginOptions.runtimeId = opts.runtimeId;
1950
1958
  markoVitePluginOptions.basePathVar = opts.basePathVar;
1951
1959
  resolvedRoutesDir = path3.resolve(root, routesDir);
1960
+ const modulesDir = getModulesDir() || path3.join(root, "node_modules");
1961
+ entryFilesDir = path3.join(
1962
+ modulesDir,
1963
+ ".marko",
1964
+ createHash("shake256", { outputLength: 4 }).update(root).digest("hex")
1965
+ );
1966
+ relativeEntryFilesDir = path3.relative(root, entryFilesDir);
1952
1967
  typesDir = path3.join(root, ".marko-run");
1953
1968
  devEntryFile = path3.join(root, "index.html");
1954
1969
  devEntryFilePosix = normalizePath(devEntryFile);
@@ -2134,7 +2149,9 @@ function markoRun(opts = {}) {
2134
2149
  async resolveId(importee, importer) {
2135
2150
  let resolved;
2136
2151
  let virtualFilePath;
2137
- if (importee.startsWith(virtualFilePrefix)) {
2152
+ if (importee === "@marko/run/router") {
2153
+ importee = path3.resolve(root, ROUTER_FILENAME);
2154
+ } else if (importee.startsWith(virtualFilePrefix)) {
2138
2155
  virtualFilePath = importee.slice(virtualFilePrefix.length + 1);
2139
2156
  importee = path3.resolve(root, virtualFilePath);
2140
2157
  } else if (!isBuild && importer && (importer === devEntryFile || normalizePath(importer) === devEntryFilePosix) && importee.startsWith(`/${markoRunFilePrefix}`)) {
@@ -2164,7 +2181,7 @@ function markoRun(opts = {}) {
2164
2181
  }
2165
2182
  if (virtualFiles.has(id)) {
2166
2183
  return virtualFiles.get(id);
2167
- } else if (/[/\\]__marko-run__[^?/\\]+\.(js|marko)$/.exec(id)) {
2184
+ } else if (!id.startsWith(entryFilesDir) && /[/\\]__marko-run__[^?/\\]+\.(js|marko)$/.exec(id)) {
2168
2185
  return "";
2169
2186
  }
2170
2187
  }
@@ -2303,6 +2320,12 @@ function getImporters(module, fileName, seen = /* @__PURE__ */ new Set()) {
2303
2320
  }
2304
2321
  return seen;
2305
2322
  }
2323
+ function getModulesDir(dir = __dirname) {
2324
+ const index = dir.indexOf("node_modules");
2325
+ if (index >= 0) {
2326
+ return dir.slice(0, index + 12);
2327
+ }
2328
+ }
2306
2329
 
2307
2330
  // src/cli/commands.ts
2308
2331
  var __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
@@ -1,7 +1,7 @@
1
1
  import type { Adapter, Route, BuiltRoutes, RoutableFile, RouterOptions } from "../types";
2
- export declare function renderRouteTemplate(route: Route): string;
3
- export declare function renderEntryTemplate(name: string, files: string[]): string;
4
- export declare function renderRouteEntry(route: Route): string;
5
- export declare function renderRouter(routes: BuiltRoutes, options?: RouterOptions): string;
2
+ export declare function renderRouteTemplate(route: Route, getRelativePath: (path: string) => string): string;
3
+ export declare function renderEntryTemplate(name: string, files: string[], pageInputs?: string[]): string;
4
+ export declare function renderRouteEntry(route: Route, entriesDir: string): string;
5
+ export declare function renderRouter(routes: BuiltRoutes, entriesDir: string, options?: RouterOptions): string;
6
6
  export declare function renderMiddleware(middleware: RoutableFile[]): string;
7
7
  export declare function renderRouteTypeInfo(routes: BuiltRoutes, pathPrefix?: string, adapter?: Adapter | null): Promise<string>;
@@ -750,16 +750,19 @@ function hasVerb(route, verb) {
750
750
  }
751
751
 
752
752
  // src/vite/codegen/index.ts
753
- function renderRouteTemplate(route) {
753
+ function renderRouteTemplate(route, getRelativePath) {
754
754
  if (!route.page) {
755
755
  throw new Error(`Route ${route.key} has no page to render`);
756
756
  }
757
757
  return renderEntryTemplate(
758
758
  route.entryName,
759
- [...route.layouts, route.page].map((file) => `./${file.importPath}`)
759
+ [...route.layouts, route.page].map(
760
+ (file) => getRelativePath(file.importPath)
761
+ ),
762
+ route.key === RoutableFileTypes.Error ? ["error"] : []
760
763
  );
761
764
  }
762
- function renderEntryTemplate(name, files) {
765
+ function renderEntryTemplate(name, files, pageInputs = []) {
763
766
  if (!name) {
764
767
  throw new Error(`Invalid argument - 'name' cannot be empty`);
765
768
  }
@@ -767,27 +770,28 @@ function renderEntryTemplate(name, files) {
767
770
  throw new Error(`Invalid argument - 'files' cannot be empty`);
768
771
  }
769
772
  const writer = createStringWriter();
770
- writer.writeLines(`// ${virtualFilePrefix}/${name}.marko`);
773
+ writer.writeLines(`// ${name}.marko`);
771
774
  writer.branch("imports");
772
775
  writer.writeLines("");
773
- writeEntryTemplateTag(writer, files);
776
+ writeEntryTemplateTag(writer, files, pageInputs);
774
777
  return writer.end();
775
778
  }
776
- function writeEntryTemplateTag(writer, [file, ...rest], index = 1) {
779
+ function writeEntryTemplateTag(writer, [file, ...rest], pageInputs, index = 1) {
777
780
  if (file) {
778
781
  const isLast = !rest.length;
779
782
  const tag = isLast ? "Page" : `Layout${index}`;
780
783
  writer.branch("imports").writeLines(`import ${tag} from '${file}';`);
781
784
  if (isLast) {
782
- writer.writeLines(`<${tag} ...input/>`);
785
+ const attributes = pageInputs.length ? " " + pageInputs.map((name) => `${name}=input.${name}`).join(" ") : "";
786
+ writer.writeLines(`<${tag}${attributes}/>`);
783
787
  } else {
784
- writer.writeBlockStart(`<${tag} ...input>`);
785
- writeEntryTemplateTag(writer, rest, index + 1);
788
+ writer.writeBlockStart(`<${tag}>`);
789
+ writeEntryTemplateTag(writer, rest, pageInputs, index + 1);
786
790
  writer.writeBlockEnd(`</>`);
787
791
  }
788
792
  }
789
793
  }
790
- function renderRouteEntry(route) {
794
+ function renderRouteEntry(route, entriesDir) {
791
795
  var _a;
792
796
  const { key, index, handler, page, middleware, meta, entryName } = route;
793
797
  const verbs = getVerbs(route);
@@ -840,9 +844,8 @@ function renderRouteEntry(route) {
840
844
  );
841
845
  }
842
846
  if (page) {
843
- imports.writeLines(
844
- `import page from '${virtualFilePrefix}/${entryName}.marko${serverEntryQuery}';`
845
- );
847
+ const importPath = route.layouts.length ? `./${entriesDir}/${entryName}.marko` : `./${page.importPath}`;
848
+ imports.writeLines(`import page from '${importPath}${serverEntryQuery}';`);
846
849
  }
847
850
  if (meta) {
848
851
  imports.writeLines(
@@ -930,7 +933,7 @@ function writeRouteEntryHandler(writer, route, verb) {
930
933
  continuations.join();
931
934
  writer.writeBlockEnd("}");
932
935
  }
933
- function renderRouter(routes, options = {
936
+ function renderRouter(routes, entriesDir, options = {
934
937
  trailingSlashes: "RedirectWithout"
935
938
  }) {
936
939
  const writer = createStringWriter();
@@ -947,9 +950,10 @@ function renderRouter(routes, options = {
947
950
  `import { ${names.join(", ")} } from '${virtualFilePrefix}/${route.entryName}.js';`
948
951
  );
949
952
  }
950
- for (const { key, entryName } of Object.values(routes.special)) {
953
+ for (const page of Object.values(routes.special)) {
954
+ const importPath = page.layouts.length ? `./${entriesDir}/${page.entryName}.marko` : `./${page.importPath}`;
951
955
  imports.writeLines(
952
- `import page${key} from '${virtualFilePrefix}/${entryName}.marko${serverEntryQuery}';`
956
+ `import page${page.key} from '${importPath}${serverEntryQuery}';`
953
957
  );
954
958
  }
955
959
  writer.writeLines(
@@ -1737,18 +1741,23 @@ function prepareError(err) {
1737
1741
  }
1738
1742
 
1739
1743
  // src/vite/plugin.ts
1744
+ var import_crypto = require("crypto");
1740
1745
  var debug = (0, import_debug.default)("@marko/run");
1741
1746
  var __dirname = import_path3.default.dirname((0, import_url2.fileURLToPath)(__importMetaURL));
1742
1747
  var PLUGIN_NAME_PREFIX = "marko-run-vite";
1743
1748
  var POSIX_SEP = "/";
1744
1749
  var WINDOWS_SEP = "\\";
1745
1750
  var CLIENT_OUT_DIR = "public";
1751
+ var MIDDLEWARE_FILENAME = `${markoRunFilePrefix}middleware.js`;
1752
+ var ROUTER_FILENAME = `${markoRunFilePrefix}router.js`;
1746
1753
  var normalizePath = import_path3.default.sep === WINDOWS_SEP ? (id) => id.replace(/\\/g, POSIX_SEP) : (id) => id;
1747
1754
  function markoRun(opts = {}) {
1748
1755
  let { routesDir, adapter, ...markoVitePluginOptions } = opts;
1749
1756
  let store;
1750
1757
  let root;
1751
1758
  let resolvedRoutesDir;
1759
+ let entryFilesDir;
1760
+ let relativeEntryFilesDir;
1752
1761
  let typesDir;
1753
1762
  let isBuild = false;
1754
1763
  let isSSRBuild = false;
@@ -1768,6 +1777,9 @@ function markoRun(opts = {}) {
1768
1777
  routesBuild: 0,
1769
1778
  routesRender: 0
1770
1779
  };
1780
+ function getEntryFileRelativePath(to) {
1781
+ return import_path3.default.relative(entryFilesDir, to);
1782
+ }
1771
1783
  async function writeTypesFile(routes2) {
1772
1784
  if (routes2 && (tsConfigExists ?? (tsConfigExists = await globFileExists(
1773
1785
  root,
@@ -1798,27 +1810,12 @@ function markoRun(opts = {}) {
1798
1810
  throw new Error("No routes generated");
1799
1811
  }
1800
1812
  for (const route of routes.list) {
1801
- if (route.page) {
1802
- virtualFiles.set(
1803
- import_path3.default.posix.join(root, `${route.entryName}.marko`),
1804
- ""
1805
- );
1806
- }
1807
1813
  virtualFiles.set(import_path3.default.posix.join(root, `${route.entryName}.js`), "");
1808
1814
  }
1809
- for (const route of Object.values(routes.special)) {
1810
- virtualFiles.set(
1811
- import_path3.default.posix.join(root, `${route.entryName}.marko`),
1812
- ""
1813
- );
1814
- }
1815
1815
  if (routes.middleware.length) {
1816
- virtualFiles.set(
1817
- import_path3.default.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1818
- ""
1819
- );
1816
+ virtualFiles.set(import_path3.default.posix.join(root, MIDDLEWARE_FILENAME), "");
1820
1817
  }
1821
- virtualFiles.set("@marko/run/router", "");
1818
+ virtualFiles.set(import_path3.default.posix.join(root, ROUTER_FILENAME), "");
1822
1819
  resolve(routes);
1823
1820
  } catch (err) {
1824
1821
  reject(err);
@@ -1829,11 +1826,12 @@ function markoRun(opts = {}) {
1829
1826
  function renderVirtualFiles(context) {
1830
1827
  return renderVirtualFilesResult ?? (renderVirtualFilesResult = new Promise(async (resolve) => {
1831
1828
  var _a;
1832
- const routerOptions = {
1833
- trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1834
- };
1835
1829
  try {
1836
1830
  const routes2 = await buildVirtualFiles();
1831
+ let entryFilesDirExists = false;
1832
+ if (import_fs3.default.existsSync(entryFilesDir)) {
1833
+ import_fs3.default.rmSync(entryFilesDir, { recursive: true });
1834
+ }
1837
1835
  for (const route of routes2.list) {
1838
1836
  if (route.handler) {
1839
1837
  const exports2 = await getExportsFromFile(
@@ -1853,22 +1851,30 @@ function markoRun(opts = {}) {
1853
1851
  );
1854
1852
  }
1855
1853
  }
1856
- if (route.page) {
1857
- virtualFiles.set(
1858
- import_path3.default.posix.join(root, `${route.entryName}.marko`),
1859
- renderRouteTemplate(route)
1854
+ if (route.page && route.layouts.length) {
1855
+ entryFilesDirExists || (entryFilesDirExists = !!import_fs3.default.mkdirSync(entryFilesDir, {
1856
+ recursive: true
1857
+ }));
1858
+ import_fs3.default.writeFileSync(
1859
+ import_path3.default.posix.join(entryFilesDir, `${route.entryName}.marko`),
1860
+ renderRouteTemplate(route, getEntryFileRelativePath)
1860
1861
  );
1861
1862
  }
1862
1863
  virtualFiles.set(
1863
1864
  import_path3.default.posix.join(root, `${route.entryName}.js`),
1864
- renderRouteEntry(route)
1865
+ renderRouteEntry(route, relativeEntryFilesDir)
1865
1866
  );
1866
1867
  }
1867
1868
  for (const route of Object.values(routes2.special)) {
1868
- virtualFiles.set(
1869
- import_path3.default.posix.join(root, `${route.entryName}.marko`),
1870
- renderRouteTemplate(route)
1871
- );
1869
+ if (route.layouts.length) {
1870
+ entryFilesDirExists || (entryFilesDirExists = !!import_fs3.default.mkdirSync(entryFilesDir, {
1871
+ recursive: true
1872
+ }));
1873
+ import_fs3.default.writeFileSync(
1874
+ import_path3.default.posix.join(entryFilesDir, `${route.entryName}.marko`),
1875
+ renderRouteTemplate(route, getEntryFileRelativePath)
1876
+ );
1877
+ }
1872
1878
  }
1873
1879
  if (routes2.middleware.length) {
1874
1880
  for (const middleware of routes2.middleware) {
@@ -1879,13 +1885,15 @@ function markoRun(opts = {}) {
1879
1885
  }
1880
1886
  }
1881
1887
  virtualFiles.set(
1882
- import_path3.default.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1888
+ import_path3.default.posix.join(root, MIDDLEWARE_FILENAME),
1883
1889
  renderMiddleware(routes2.middleware)
1884
1890
  );
1885
1891
  }
1886
1892
  virtualFiles.set(
1887
- "@marko/run/router",
1888
- renderRouter(routes2, routerOptions)
1893
+ import_path3.default.posix.join(root, ROUTER_FILENAME),
1894
+ renderRouter(routes2, relativeEntryFilesDir, {
1895
+ trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1896
+ })
1889
1897
  );
1890
1898
  await writeTypesFile(routes2);
1891
1899
  if (adapter == null ? void 0 : adapter.routesGenerated) {
@@ -1906,7 +1914,7 @@ function markoRun(opts = {}) {
1906
1914
  throw err;
1907
1915
  }
1908
1916
  virtualFiles.set(
1909
- "@marko/run/router",
1917
+ import_path3.default.posix.join(root, ROUTER_FILENAME),
1910
1918
  `throw ${JSON.stringify(prepareError(err))}`
1911
1919
  );
1912
1920
  }
@@ -1949,6 +1957,13 @@ function markoRun(opts = {}) {
1949
1957
  markoVitePluginOptions.runtimeId = opts.runtimeId;
1950
1958
  markoVitePluginOptions.basePathVar = opts.basePathVar;
1951
1959
  resolvedRoutesDir = import_path3.default.resolve(root, routesDir);
1960
+ const modulesDir = getModulesDir() || import_path3.default.join(root, "node_modules");
1961
+ entryFilesDir = import_path3.default.join(
1962
+ modulesDir,
1963
+ ".marko",
1964
+ (0, import_crypto.createHash)("shake256", { outputLength: 4 }).update(root).digest("hex")
1965
+ );
1966
+ relativeEntryFilesDir = import_path3.default.relative(root, entryFilesDir);
1952
1967
  typesDir = import_path3.default.join(root, ".marko-run");
1953
1968
  devEntryFile = import_path3.default.join(root, "index.html");
1954
1969
  devEntryFilePosix = normalizePath(devEntryFile);
@@ -2134,7 +2149,9 @@ function markoRun(opts = {}) {
2134
2149
  async resolveId(importee, importer) {
2135
2150
  let resolved;
2136
2151
  let virtualFilePath;
2137
- if (importee.startsWith(virtualFilePrefix)) {
2152
+ if (importee === "@marko/run/router") {
2153
+ importee = import_path3.default.resolve(root, ROUTER_FILENAME);
2154
+ } else if (importee.startsWith(virtualFilePrefix)) {
2138
2155
  virtualFilePath = importee.slice(virtualFilePrefix.length + 1);
2139
2156
  importee = import_path3.default.resolve(root, virtualFilePath);
2140
2157
  } else if (!isBuild && importer && (importer === devEntryFile || normalizePath(importer) === devEntryFilePosix) && importee.startsWith(`/${markoRunFilePrefix}`)) {
@@ -2164,7 +2181,7 @@ function markoRun(opts = {}) {
2164
2181
  }
2165
2182
  if (virtualFiles.has(id)) {
2166
2183
  return virtualFiles.get(id);
2167
- } else if (/[/\\]__marko-run__[^?/\\]+\.(js|marko)$/.exec(id)) {
2184
+ } else if (!id.startsWith(entryFilesDir) && /[/\\]__marko-run__[^?/\\]+\.(js|marko)$/.exec(id)) {
2168
2185
  return "";
2169
2186
  }
2170
2187
  }
@@ -2298,6 +2315,12 @@ function getImporters(module2, fileName, seen = /* @__PURE__ */ new Set()) {
2298
2315
  }
2299
2316
  return seen;
2300
2317
  }
2318
+ function getModulesDir(dir = __dirname) {
2319
+ const index = dir.indexOf("node_modules");
2320
+ if (index >= 0) {
2321
+ return dir.slice(0, index + 12);
2322
+ }
2323
+ }
2301
2324
 
2302
2325
  // src/vite/utils/server.ts
2303
2326
  var import_net = __toESM(require("net"), 1);