@marko/run 0.2.5 → 0.2.7

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.
@@ -87,14 +87,15 @@ import path2 from "path";
87
87
  import crypto from "crypto";
88
88
  import fs3 from "fs";
89
89
  import glob from "glob";
90
+ import { fileURLToPath } from "url";
91
+ import browserslist from "browserslist";
92
+ import { resolveToEsbuildTarget } from "esbuild-plugin-browserslist";
90
93
  import { mergeConfig } from "vite";
91
94
  import markoVitePlugin, { FileStore } from "@marko/vite";
92
95
 
93
96
  // src/vite/constants.ts
94
97
  var markoRunFilePrefix = "__marko-run__";
95
98
  var virtualFilePrefix = "virtual:marko-run";
96
- var virtualRoutesPrefix = `${virtualFilePrefix}/routes`;
97
- var virtualRuntimePrefix = `${virtualFilePrefix}/internal`;
98
99
  var httpVerbs = ["get", "post", "put", "delete"];
99
100
  var serverEntryQuery = "?marko-server-entry";
100
101
  var RoutableFileTypes = {
@@ -109,7 +110,7 @@ var RoutableFileTypes = {
109
110
 
110
111
  // src/vite/routes/vdir.ts
111
112
  var _dirs, _pathlessDirs;
112
- var _VDir = class {
113
+ var _VDir = class _VDir {
113
114
  constructor(parent, segment, source) {
114
115
  __privateAdd(this, _dirs, void 0);
115
116
  __privateAdd(this, _pathlessDirs, void 0);
@@ -246,9 +247,9 @@ var _VDir = class {
246
247
  return dirs;
247
248
  }
248
249
  };
249
- var VDir = _VDir;
250
250
  _dirs = new WeakMap();
251
251
  _pathlessDirs = new WeakMap();
252
+ var VDir = _VDir;
252
253
 
253
254
  // src/vite/routes/parse.ts
254
255
  function parseFlatRoute(pattern) {
@@ -769,23 +770,35 @@ function renderRouteTemplate(route) {
769
770
  if (!route.page) {
770
771
  throw new Error(`Route ${route.key} has no page to render`);
771
772
  }
773
+ return renderEntryTemplate(
774
+ route.entryName,
775
+ [...route.layouts, route.page].map((file) => `./${file.importPath}`)
776
+ );
777
+ }
778
+ function renderEntryTemplate(name, files) {
779
+ if (!name) {
780
+ throw new Error(`Invalid argument - 'name' cannot be empty`);
781
+ }
782
+ if (!files.length) {
783
+ throw new Error(`Invalid argument - 'files' cannot be empty`);
784
+ }
772
785
  const writer = createStringWriter();
773
- writer.writeLines(`// ${virtualFilePrefix}/${route.entryName}.marko`);
786
+ writer.writeLines(`// ${virtualFilePrefix}/${name}.marko`);
774
787
  writer.branch("imports");
775
788
  writer.writeLines("");
776
- writeRouteTemplateTag(writer, [...route.layouts, route.page]);
789
+ writeEntryTemplateTag(writer, files);
777
790
  return writer.end();
778
791
  }
779
- function writeRouteTemplateTag(writer, [file, ...rest], index = 1) {
792
+ function writeEntryTemplateTag(writer, [file, ...rest], index = 1) {
780
793
  if (file) {
781
794
  const isLast = !rest.length;
782
795
  const tag = isLast ? "page" : `layout${index}`;
783
- writer.branch("imports").writeLines(`import ${tag} from './${file.importPath}';`);
796
+ writer.branch("imports").writeLines(`import ${tag} from '${file}';`);
784
797
  if (isLast) {
785
- writer.writeLines(`<${tag} ...input />`);
798
+ writer.writeLines(`<${tag} ...input/>`);
786
799
  } else {
787
800
  writer.writeBlockStart(`<${tag} ...input>`);
788
- writeRouteTemplateTag(writer, rest, index + 1);
801
+ writeEntryTemplateTag(writer, rest, index + 1);
789
802
  writer.writeBlockEnd(`</>`);
790
803
  }
791
804
  }
@@ -817,7 +830,9 @@ function renderRouteEntry(route) {
817
830
  }
818
831
  if (runtimeImports.length) {
819
832
  imports.writeLines(
820
- `import { ${runtimeImports.join(", ")} } from '${virtualRuntimePrefix}';`
833
+ `import { ${runtimeImports.join(
834
+ ", "
835
+ )} } from '${virtualFilePrefix}/runtime/internal';`
821
836
  );
822
837
  }
823
838
  if (middleware.length) {
@@ -931,6 +946,45 @@ function writeRouteEntryHandler(writer, route, verb) {
931
946
  continuations.join();
932
947
  writer.writeBlockEnd("}");
933
948
  }
949
+ function renderErrorRouter(error, options = {
950
+ trailingSlashes: "RedirectWithout"
951
+ }) {
952
+ const writer = createStringWriter();
953
+ writer.write(`
954
+ // @marko/run/router
955
+ import { createContext } from '${virtualFilePrefix}/runtime/internal';
956
+ import errorPage from '${virtualFilePrefix}/${markoRunFilePrefix}error.marko${serverEntryQuery}';
957
+
958
+ const error = new Error(\`${error.message}\`);
959
+ error.name = '${error.name}';`);
960
+ if (error.stack) {
961
+ writer.write(`
962
+ error.stack = \`${error.stack}\`;`);
963
+ }
964
+ writer.write(`
965
+
966
+ globalThis.__marko_run__ = { match, fetch, invoke };
967
+
968
+ export function match() {
969
+ return { handler: errorPage, params: {}, meta: {}, path: '/*' }; // /$$
970
+ }
971
+
972
+ export async function invoke(route, request, platform, url) {
973
+ const [context, buildInput] = createContext(route, request, platform, url);
974
+ if (context.request.headers.get('Accept')?.includes('text/html')) {
975
+ return new Response(errorPage.stream(buildInput({ error })), {
976
+ status: 500,
977
+ headers: { "content-type": "text/html;charset=UTF-8" },
978
+ });
979
+ }
980
+ return new Response(error, {
981
+ status: 500,
982
+ });
983
+ }
984
+ `);
985
+ renderFetch(writer, options);
986
+ return writer.end();
987
+ }
934
988
  function renderRouter(routes, options = {
935
989
  trailingSlashes: "RedirectWithout"
936
990
  }) {
@@ -938,7 +992,7 @@ function renderRouter(routes, options = {
938
992
  writer.writeLines(`// @marko/run/router`);
939
993
  const imports = writer.branch("imports");
940
994
  imports.writeLines(
941
- `import { NotHandled, NotMatched, createContext } from 'virtual:marko-run/internal';`
995
+ `import { NotHandled, NotMatched, createContext } from '${virtualFilePrefix}/runtime/internal';`
942
996
  );
943
997
  for (const route of routes.list) {
944
998
  const verbs = getVerbs(route);
@@ -974,24 +1028,24 @@ globalThis.__marko_run__ = { match, fetch, invoke };
974
1028
  }
975
1029
  }
976
1030
  writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
977
- writer.write(`
978
- export async function invoke(route, request, platform, url) {
979
- const [context, buildInput] = createContext(route, request, platform, url);
980
- try {
981
- if (route) {
982
- try {
983
- const response = await route.handler(context, buildInput);
984
- if (response) return response;
985
- } catch (error) {
986
- if (error === NotHandled) {
987
- return;
988
- } else if (error !== NotMatched) {
989
- throw error;
990
- }
991
- }
992
- `);
1031
+ writer.writeLines("").writeBlockStart(
1032
+ "export async function invoke(route, request, platform, url) {"
1033
+ ).writeLines(
1034
+ "const [context, buildInput] = createContext(route, request, platform, url);"
1035
+ );
1036
+ const hasErrorPage = Boolean(routes.special[RoutableFileTypes.Error]);
1037
+ if (hasErrorPage) {
1038
+ writer.writeBlockStart("try {");
1039
+ }
1040
+ writer.writeBlockStart("if (route) {").writeBlockStart("try {").writeLines(
1041
+ "const response = await route.handler(context, buildInput);",
1042
+ "if (response) return response;"
1043
+ ).indent--;
1044
+ writer.writeBlockStart("} catch (error) {").writeLines(
1045
+ "if (error === NotHandled) return;",
1046
+ "if (error !== NotMatched) throw error;"
1047
+ ).writeBlockEnd("}").writeBlockEnd("}");
993
1048
  if (routes.special[RoutableFileTypes.NotFound]) {
994
- writer.indent = 2;
995
1049
  imports.writeLines(
996
1050
  `
997
1051
  const page404ResponseInit = {
@@ -999,33 +1053,31 @@ const page404ResponseInit = {
999
1053
  headers: { "content-type": "text/html;charset=UTF-8" },
1000
1054
  };`
1001
1055
  );
1002
- writer.write(
1003
- ` } else {
1004
- }
1056
+ writer.write(`
1005
1057
  if (context.request.headers.get('Accept')?.includes('text/html')) {
1006
1058
  return new Response(page404.stream(buildInput()), page404ResponseInit);
1007
1059
  }
1008
- `
1009
- );
1010
- } else {
1011
- writer.indent = 3;
1012
- writer.writeBlockEnd("}");
1060
+ `);
1013
1061
  }
1014
1062
  writer.indent--;
1015
- writer.writeBlockStart(`} catch (error) {`);
1016
- if (routes.special[RoutableFileTypes.Error]) {
1063
+ if (hasErrorPage) {
1017
1064
  imports.writeLines(`
1018
1065
  const page500ResponseInit = {
1019
1066
  status: 500,
1020
1067
  headers: { "content-type": "text/html;charset=UTF-8" },
1021
1068
  };`);
1022
- writer.writeBlockStart(
1069
+ writer.writeBlockStart(`} catch (error) {`).writeBlockStart(
1023
1070
  `if (context.request.headers.get('Accept')?.includes('text/html')) {`
1024
1071
  ).writeLines(
1025
1072
  `return new Response(page500.stream(buildInput({ error })), page500ResponseInit);`
1026
- ).writeBlockEnd("}");
1073
+ ).writeBlockEnd("}").writeLines("throw error;").writeBlockEnd("}");
1027
1074
  }
1028
- writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
1075
+ writer.writeBlockEnd("}");
1076
+ renderFetch(writer, options);
1077
+ return writer.end();
1078
+ }
1079
+ function renderFetch(writer, options) {
1080
+ writer.write(`
1029
1081
  export async function fetch(request, platform) {
1030
1082
  try {
1031
1083
  const url = new URL(request.url);
@@ -1071,7 +1123,6 @@ export async function fetch(request, platform) {
1071
1123
  });
1072
1124
  }
1073
1125
  }`);
1074
- return writer.end();
1075
1126
  }
1076
1127
  function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1077
1128
  const { route, dynamic, catchAll } = trie;
@@ -1193,7 +1244,12 @@ function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
1193
1244
  }
1194
1245
  if (catchAll) {
1195
1246
  writer.writeLines(
1196
- `return ${renderMatch(verb, catchAll.route, catchAll.path, String(offset))}; // ${catchAll.path.path}`
1247
+ `return ${renderMatch(
1248
+ verb,
1249
+ catchAll.route,
1250
+ catchAll.path,
1251
+ String(offset)
1252
+ )}; // ${catchAll.path.path}`
1197
1253
  );
1198
1254
  } else if (level === 0) {
1199
1255
  writer.writeLines("return null;");
@@ -1235,7 +1291,9 @@ function renderMiddleware(middleware) {
1235
1291
  `// ${virtualFilePrefix}/${markoRunFilePrefix}middleware.js`
1236
1292
  );
1237
1293
  const imports = writer.branch("imports");
1238
- imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
1294
+ imports.writeLines(
1295
+ `import { normalize } from '${virtualFilePrefix}/runtime/internal';`
1296
+ );
1239
1297
  writer.writeLines("");
1240
1298
  for (const { id, importPath } of middleware) {
1241
1299
  const importName = `middleware${id}`;
@@ -1627,7 +1685,6 @@ function prettyPath(path4) {
1627
1685
  }
1628
1686
 
1629
1687
  // src/vite/plugin.ts
1630
- import { fileURLToPath } from "url";
1631
1688
  var __dirname = path2.dirname(fileURLToPath(import.meta.url));
1632
1689
  var PLUGIN_NAME_PREFIX = "marko-run-vite";
1633
1690
  var POSIX_SEP = "/";
@@ -1660,14 +1717,14 @@ function markoRun(opts = {}) {
1660
1717
  routesBuild: 0,
1661
1718
  routesRender: 0
1662
1719
  };
1663
- async function writeTypesFile() {
1664
- if (tsConfigExists ?? (tsConfigExists = await globFileExists(
1720
+ async function writeTypesFile(routes2) {
1721
+ if (routes2 && (tsConfigExists ?? (tsConfigExists = await globFileExists(
1665
1722
  root,
1666
1723
  "{.tsconfig*,tsconfig*.json}"
1667
- ))) {
1724
+ )))) {
1668
1725
  const filepath = path2.join(typesDir, "routes.d.ts");
1669
1726
  const data = await renderRouteTypeInfo(
1670
- routes,
1727
+ routes2,
1671
1728
  normalizePath(path2.relative(typesDir, resolvedRoutesDir)),
1672
1729
  adapter
1673
1730
  );
@@ -1677,65 +1734,95 @@ function markoRun(opts = {}) {
1677
1734
  }
1678
1735
  }
1679
1736
  }
1680
- async function setVirtualFiles(render = false) {
1681
- for (const route of routes.list) {
1682
- if (render && route.handler) {
1683
- route.handler.verbs = await extractVerbs(route.handler.filePath);
1684
- if (!route.handler.verbs.length) {
1685
- console.warn(
1686
- `Did not find any valid exports in middleware entry file:'${route.handler.filePath}' - expected to find any of 'GET', 'POST', 'PUT' or 'DELETE'`
1737
+ const buildVirtualFiles = single(async (render) => {
1738
+ var _a;
1739
+ const routerOptions = {
1740
+ trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1741
+ };
1742
+ if (!render) {
1743
+ virtualFiles.clear();
1744
+ isRendered = false;
1745
+ }
1746
+ try {
1747
+ if (isStale) {
1748
+ const buildStartTime = performance.now();
1749
+ routes = await buildRoutes(
1750
+ createFSWalker(resolvedRoutesDir),
1751
+ routesDir
1752
+ );
1753
+ times.routesBuild = performance.now() - buildStartTime;
1754
+ if (!routes.list.length) {
1755
+ throw new Error("No routes generated");
1756
+ }
1757
+ }
1758
+ const renderStartTime = performance.now();
1759
+ for (const route of routes.list) {
1760
+ if (render && route.handler) {
1761
+ route.handler.verbs = await extractVerbs(route.handler.filePath);
1762
+ if (!route.handler.verbs.length) {
1763
+ throw new Error(
1764
+ `Did not find any valid exports in middleware entry file:'${route.handler.filePath}' - expected to find any of 'GET', 'POST', 'PUT' or 'DELETE'`
1765
+ );
1766
+ }
1767
+ }
1768
+ if (route.page) {
1769
+ virtualFiles.set(
1770
+ path2.posix.join(root, `${route.entryName}.marko`),
1771
+ render ? renderRouteTemplate(route) : ""
1687
1772
  );
1688
1773
  }
1774
+ virtualFiles.set(
1775
+ path2.posix.join(root, `${route.entryName}.js`),
1776
+ render ? renderRouteEntry(route) : ""
1777
+ );
1689
1778
  }
1690
- if (route.page) {
1779
+ for (const route of Object.values(routes.special)) {
1691
1780
  virtualFiles.set(
1692
1781
  path2.posix.join(root, `${route.entryName}.marko`),
1693
1782
  render ? renderRouteTemplate(route) : ""
1694
1783
  );
1695
1784
  }
1785
+ if (routes.middleware.length) {
1786
+ virtualFiles.set(
1787
+ path2.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1788
+ render ? renderMiddleware(routes.middleware) : ""
1789
+ );
1790
+ }
1696
1791
  virtualFiles.set(
1697
- path2.posix.join(root, `${route.entryName}.js`),
1698
- render ? renderRouteEntry(route) : ""
1792
+ "@marko/run/router",
1793
+ render ? renderRouter(routes, routerOptions) : ""
1699
1794
  );
1700
- }
1701
- for (const route of Object.values(routes.special)) {
1795
+ times.routesRender = performance.now() - renderStartTime;
1796
+ if (render) {
1797
+ await writeTypesFile(routes);
1798
+ if (!isBuild) {
1799
+ await ((_a = opts == null ? void 0 : opts.emitRoutes) == null ? void 0 : _a.call(opts, routes.list));
1800
+ }
1801
+ isRendered = true;
1802
+ }
1803
+ } catch (err) {
1804
+ if (isBuild) {
1805
+ throw err;
1806
+ }
1807
+ console.error(err);
1702
1808
  virtualFiles.set(
1703
- path2.posix.join(root, `${route.entryName}.marko`),
1704
- render ? renderRouteTemplate(route) : ""
1809
+ path2.posix.join(root, `${markoRunFilePrefix}error.marko`),
1810
+ renderEntryTemplate(`${markoRunFilePrefix}error`, ["<dev-error-page>"])
1705
1811
  );
1812
+ virtualFiles.set(
1813
+ "@marko/run/router",
1814
+ renderErrorRouter(err, routerOptions)
1815
+ );
1816
+ isRendered = true;
1706
1817
  }
1707
- virtualFiles.set(
1708
- "@marko/run/router",
1709
- render ? renderRouter(routes, {
1710
- trailingSlashes: opts.trailingSlashes || "RedirectWithout"
1711
- }) : ""
1712
- );
1713
- virtualFiles.set(
1714
- path2.posix.join(root, `${markoRunFilePrefix}middleware.js`),
1715
- render ? renderMiddleware(routes.middleware) : ""
1716
- );
1717
- }
1718
- const buildVirtualFiles = single(async () => {
1719
- const startTime = performance.now();
1720
- routes = await buildRoutes(createFSWalker(resolvedRoutesDir), routesDir);
1721
- times.routesBuild = performance.now() - startTime;
1722
- await setVirtualFiles(false);
1723
1818
  isStale = false;
1724
- isRendered = false;
1725
- });
1726
- const renderVirtualFiles = single(async () => {
1727
- const startTime = performance.now();
1728
- await setVirtualFiles(true);
1729
- await writeTypesFile();
1730
- times.routesRender = performance.now() - startTime;
1731
- isRendered = true;
1732
1819
  });
1733
1820
  return [
1734
1821
  {
1735
1822
  name: `${PLUGIN_NAME_PREFIX}:pre`,
1736
1823
  enforce: "pre",
1737
1824
  async config(config2, env) {
1738
- var _a, _b, _c, _d, _e, _f;
1825
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1739
1826
  const externalPluginOptions = getExternalPluginOptions(config2);
1740
1827
  if (externalPluginOptions) {
1741
1828
  opts = mergeConfig(opts, externalPluginOptions);
@@ -1761,6 +1848,11 @@ function markoRun(opts = {}) {
1761
1848
  }
1762
1849
  compiler ?? (compiler = await import(opts.compiler || "@marko/compiler"));
1763
1850
  compiler.taglib.register("@marko/run", {
1851
+ "<dev-error-page>": {
1852
+ template: normalizePath(
1853
+ path2.resolve(__dirname, "../components/dev-error-page.marko")
1854
+ )
1855
+ },
1764
1856
  "<*>": {
1765
1857
  transform: path2.resolve(
1766
1858
  __dirname,
@@ -1825,11 +1917,26 @@ function markoRun(opts = {}) {
1825
1917
  noExternal: /@marko\/run/
1826
1918
  },
1827
1919
  build: {
1920
+ target: isBuild && !((_g = config2.build) == null ? void 0 : _g.target) ? resolveToEsbuildTarget(
1921
+ browserslist(void 0, {
1922
+ path: root
1923
+ }),
1924
+ { printUnknownTargets: false }
1925
+ ) : void 0,
1828
1926
  emptyOutDir: isSSRBuild,
1927
+ // Avoid server & client deleting files from each other.
1829
1928
  rollupOptions: {
1830
1929
  output: rollupOutputOptions
1831
1930
  }
1832
1931
  },
1932
+ optimizeDeps: {
1933
+ entries: !((_h = config2.optimizeDeps) == null ? void 0 : _h.entries) ? [
1934
+ "src/pages/**/*+{page,layout}.marko",
1935
+ "!**/__snapshots__/**",
1936
+ `!**/__tests__/**`,
1937
+ `!**/coverage/**`
1938
+ ] : void 0
1939
+ },
1833
1940
  resolve: isBuild ? {
1834
1941
  browserField: isSSRBuild ? false : void 0,
1835
1942
  conditions: [
@@ -1914,40 +2021,38 @@ function markoRun(opts = {}) {
1914
2021
  },
1915
2022
  async resolveId(importee, importer) {
1916
2023
  let resolved;
1917
- if (importee.startsWith(virtualRuntimePrefix)) {
1918
- return this.resolve(
1919
- path2.resolve(__dirname, "../runtime/internal"),
1920
- importer,
1921
- { skipSelf: true }
1922
- );
1923
- } else if (importee.startsWith(virtualFilePrefix)) {
1924
- importee = path2.resolve(
1925
- root,
1926
- importee.slice(virtualFilePrefix.length + 1)
1927
- );
2024
+ let virtualFilePath;
2025
+ if (importee.startsWith(virtualFilePrefix)) {
2026
+ virtualFilePath = importee.slice(virtualFilePrefix.length + 1);
2027
+ importee = path2.resolve(root, virtualFilePath);
1928
2028
  } else if (!isBuild && importer && (importer === devEntryFile || normalizePath(importer) === devEntryFilePosix) && importee.startsWith(`/${markoRunFilePrefix}`)) {
1929
2029
  importee = path2.resolve(root, "." + importee);
1930
2030
  }
1931
2031
  importee = normalizePath(importee);
1932
2032
  if (isStale) {
1933
- await buildVirtualFiles();
2033
+ await buildVirtualFiles(false);
1934
2034
  }
1935
2035
  if (virtualFiles.has(importee)) {
1936
2036
  resolved = importee;
2037
+ } else if (virtualFilePath) {
2038
+ const resolution = await this.resolve(
2039
+ path2.resolve(__dirname, "..", virtualFilePath),
2040
+ importer,
2041
+ {
2042
+ skipSelf: true
2043
+ }
2044
+ );
2045
+ return resolution;
1937
2046
  }
1938
2047
  return resolved || null;
1939
2048
  },
1940
2049
  async load(id) {
1941
- var _a;
1942
2050
  if (id.endsWith(serverEntryQuery)) {
1943
2051
  id = id.slice(0, -serverEntryQuery.length);
1944
2052
  }
1945
2053
  if (virtualFiles.has(id)) {
1946
2054
  if (!isRendered) {
1947
- await renderVirtualFiles();
1948
- if (!isBuild) {
1949
- await ((_a = opts == null ? void 0 : opts.emitRoutes) == null ? void 0 : _a.call(opts, routes.list));
1950
- }
2055
+ await buildVirtualFiles(true);
1951
2056
  }
1952
2057
  return virtualFiles.get(id);
1953
2058
  }
@@ -1990,12 +2095,12 @@ function markoRun(opts = {}) {
1990
2095
  }
1991
2096
  await store.set(routeDataFilename, JSON.stringify(routeData));
1992
2097
  await ((_a = opts == null ? void 0 : opts.emitRoutes) == null ? void 0 : _a.call(opts, routes.list));
1993
- } else if (isBuild) {
2098
+ } else {
1994
2099
  logRoutesTable(routes, bundle, options);
1995
2100
  }
1996
2101
  },
1997
2102
  async closeBundle() {
1998
- if (isBuild && !isSSRBuild && (adapter == null ? void 0 : adapter.buildEnd)) {
2103
+ if (isBuild && !isSSRBuild && (adapter == null ? void 0 : adapter.buildEnd) && routes) {
1999
2104
  await adapter.buildEnd(
2000
2105
  resolvedConfig,
2001
2106
  routes.list,
@@ -2171,6 +2276,7 @@ async function dev(entry, cwd, configFile, port, envFile, args = []) {
2171
2276
  if (!adapter) {
2172
2277
  throw new Error(
2173
2278
  "No adapter specified for 'dev' command without custom target"
2279
+ // Would the user know what a target is if presented with this error?
2174
2280
  );
2175
2281
  } else if (!adapter.startDev) {
2176
2282
  throw new Error(
@@ -2239,6 +2345,7 @@ async function build(entry, cwd, configFile, outDir, envFile) {
2239
2345
  rollupOptions: {
2240
2346
  output: {
2241
2347
  entryFileNames: "index.mjs"
2348
+ // Would rather build with `.js` extension but that will fail in zero-config projects where node runs in cjs mode
2242
2349
  }
2243
2350
  }
2244
2351
  }
@@ -0,0 +1,14 @@
1
+ export interface Input {
2
+ error: Error
3
+ }
4
+
5
+ <!doctype html>
6
+ <html lang="en">
7
+ <head>
8
+ <meta charset="UTF-8">
9
+ <title>${input.error.message}</title>
10
+ </head>
11
+ <body>
12
+ <pre>${input.error.stack || (input.error.name + ': ' + input.error.message)}</pre>
13
+ </body>
14
+ </html>
@@ -1,6 +1,8 @@
1
1
  import type { Adapter, Route, BuiltRoutes, RoutableFile, RouterOptions } from "../types";
2
2
  export declare function renderRouteTemplate(route: Route): string;
3
+ export declare function renderEntryTemplate(name: string, files: string[]): string;
3
4
  export declare function renderRouteEntry(route: Route): string;
5
+ export declare function renderErrorRouter(error: Error, options?: RouterOptions): string;
4
6
  export declare function renderRouter(routes: BuiltRoutes, options?: RouterOptions): string;
5
7
  export declare function renderMiddleware(middleware: RoutableFile[]): string;
6
8
  export declare function renderRouteTypeInfo(routes: BuiltRoutes, pathPrefix?: string, adapter?: Adapter | null): Promise<string>;
@@ -1,8 +1,6 @@
1
1
  type ValuesOf<T> = T[keyof T];
2
2
  export declare const markoRunFilePrefix = "__marko-run__";
3
3
  export declare const virtualFilePrefix = "virtual:marko-run";
4
- export declare const virtualRoutesPrefix: string;
5
- export declare const virtualRuntimePrefix: string;
6
4
  export declare const httpVerbs: readonly ["get", "post", "put", "delete"];
7
5
  export declare const serverEntryQuery = "?marko-server-entry";
8
6
  export declare const browserEntryQuery = "?marko-browser-entry";