@reckona/mreact-router 0.0.119 → 0.0.121

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/build.ts CHANGED
@@ -39,9 +39,7 @@ import {
39
39
  } from "./module-runner.js";
40
40
  import { scanAppRoutes } from "./routes.js";
41
41
  import type { AppRoute } from "./routes.js";
42
- import {
43
- appFileConventionForRootFilename,
44
- } from "./file-conventions.js";
42
+ import { appFileConventionForRootFilename } from "./file-conventions.js";
45
43
  import {
46
44
  resolveAppRouterProjectOptions,
47
45
  resolveBuildTargets,
@@ -98,7 +96,7 @@ export interface BuildAppOptions extends AppRouterProjectOptions {
98
96
  onBuildPhaseTiming?: ((timing: BuildAppPhaseTiming) => void) | undefined;
99
97
  outDir: string;
100
98
  targets?: readonly AppRouterBuildTarget[] | undefined;
101
- viteConfig?: Pick<UserConfig, "plugins"> | undefined;
99
+ viteConfig?: Pick<UserConfig, "define" | "plugins"> | undefined;
102
100
  }
103
101
 
104
102
  export type BuildAppPhase =
@@ -210,6 +208,7 @@ export interface BuiltRouteSourceAnalysisSummary {
210
208
  authIncludesClaims: boolean;
211
209
  cachePolicy?: RouteCachePolicy | undefined;
212
210
  clientBoundaryImports: readonly string[];
211
+ clientBoundaryFallbackImports: readonly string[];
213
212
  clientRoute: boolean;
214
213
  hasLoader: boolean;
215
214
  routeCode: string;
@@ -233,6 +232,7 @@ interface BuildSourceAnalysis {
233
232
 
234
233
  interface BuildRouteSourceAnalysis extends BuildSourceAnalysis {
235
234
  clientBoundaryImports: readonly string[];
235
+ clientBoundaryFallbackImports: readonly string[];
236
236
  clientRoute: boolean;
237
237
  file: string;
238
238
  route: AppRoute & { kind: "page" };
@@ -273,6 +273,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
273
273
  : await timeBuildPhase(timingSink, "scan", () =>
274
274
  scanAppRoutes({ appDir: project.routesDir }),
275
275
  );
276
+ const viteDefine = options.viteConfig?.define;
276
277
  const vitePlugins = options.viteConfig?.plugins;
277
278
  const files =
278
279
  timingSink === undefined
@@ -427,7 +428,11 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
427
428
  }));
428
429
  const [serverModuleArtifacts, clientBundle] = await Promise.all([
429
430
  timingSink === undefined
430
- ? writeServerModuleArtifactFiles(serverDir, serverModules, generatedImportPolicy.runtimePackages)
431
+ ? writeServerModuleArtifactFiles(
432
+ serverDir,
433
+ serverModules,
434
+ generatedImportPolicy.runtimePackages,
435
+ )
431
436
  : timeBuildPhase(timingSink, "serverModuleArtifacts", () =>
432
437
  writeServerModuleArtifactFiles(
433
438
  serverDir,
@@ -519,6 +524,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
519
524
  timingSink === undefined
520
525
  ? await writeCloudflareRouteModules({
521
526
  cloudflareDir,
527
+ define: viteDefine,
522
528
  files,
523
529
  prerenderedRoutes,
524
530
  projectRoot: project.projectRoot,
@@ -531,6 +537,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
531
537
  : await timeBuildPhase(timingSink, "cloudflare", () =>
532
538
  writeCloudflareRouteModules({
533
539
  cloudflareDir,
540
+ define: viteDefine,
534
541
  files,
535
542
  prerenderedRoutes,
536
543
  projectRoot: project.projectRoot,
@@ -740,6 +747,7 @@ async function analyzeBuildRouteSources(options: {
740
747
  {
741
748
  ...analyzeBuildSource(source, route.file),
742
749
  clientBoundaryImports: clientInference.clientBoundaryImports,
750
+ clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
743
751
  clientRoute: clientInference.client,
744
752
  file,
745
753
  route,
@@ -1201,7 +1209,11 @@ async function collectRuntimeOptionalPackages(options: {
1201
1209
  { packageName: options.packageName, optional: false, startDir: options.projectRoot },
1202
1210
  ];
1203
1211
 
1204
- for (let index = 0; index < queue.length && seenPackageJson.size < maxRuntimePackageManifestReads; index += 1) {
1212
+ for (
1213
+ let index = 0;
1214
+ index < queue.length && seenPackageJson.size < maxRuntimePackageManifestReads;
1215
+ index += 1
1216
+ ) {
1205
1217
  const item = queue[index];
1206
1218
  if (item === undefined || !isValidRuntimePackageName(item.packageName)) {
1207
1219
  continue;
@@ -1297,7 +1309,11 @@ async function findRuntimePackageJson(
1297
1309
  }
1298
1310
 
1299
1311
  function isRuntimePackageSpecifier(specifier: string): boolean {
1300
- if (specifier.startsWith(".") || specifier.startsWith("/") || /^[A-Za-z][A-Za-z0-9+.-]*:/.test(specifier)) {
1312
+ if (
1313
+ specifier.startsWith(".") ||
1314
+ specifier.startsWith("/") ||
1315
+ /^[A-Za-z][A-Za-z0-9+.-]*:/.test(specifier)
1316
+ ) {
1301
1317
  return false;
1302
1318
  }
1303
1319
 
@@ -1425,7 +1441,11 @@ function isSourceModuleFile(file: string): boolean {
1425
1441
  }
1426
1442
 
1427
1443
  function isAppRelativeFile(file: string, relativeRoutesDir: string): boolean {
1428
- return relativeRoutesDir === "" || file === relativeRoutesDir || file.startsWith(`${relativeRoutesDir}/`);
1444
+ return (
1445
+ relativeRoutesDir === "" ||
1446
+ file === relativeRoutesDir ||
1447
+ file.startsWith(`${relativeRoutesDir}/`)
1448
+ );
1429
1449
  }
1430
1450
 
1431
1451
  function moduleIdForBuildFile(file: string, relativeRoutesDir: string): string {
@@ -1465,10 +1485,7 @@ async function collectPublicAssetPaths(publicDir: string): Promise<string[]> {
1465
1485
  return paths.sort();
1466
1486
  }
1467
1487
 
1468
- async function copyAppFileConventionAssets(
1469
- appDir: string,
1470
- outDir: string,
1471
- ): Promise<string[]> {
1488
+ async function copyAppFileConventionAssets(appDir: string, outDir: string): Promise<string[]> {
1472
1489
  let entries: Dirent[];
1473
1490
  try {
1474
1491
  entries = await readdir(appDir, { withFileTypes: true });
@@ -1493,9 +1510,7 @@ async function copyAppFileConventionAssets(
1493
1510
  continue;
1494
1511
  }
1495
1512
 
1496
- const outputPath = convention.path.startsWith("/")
1497
- ? convention.path.slice(1)
1498
- : convention.path;
1513
+ const outputPath = convention.path.startsWith("/") ? convention.path.slice(1) : convention.path;
1499
1514
  await copyFile(join(appDir, entry.name), join(outDir, outputPath));
1500
1515
  paths.push(convention.path);
1501
1516
  }
@@ -1745,205 +1760,219 @@ async function buildServerModuleArtifacts(options: {
1745
1760
  }
1746
1761
  }
1747
1762
 
1748
- const requestBatchOutputs = requestBatchEntries.length >= 3
1749
- ? await bundleRouteRequestModuleBatchCode({
1750
- appDir: options.project.routesDir,
1751
- bundleCache: options.bundleCache,
1752
- cacheDir: options.cacheDir,
1753
- entries: requestBatchEntries,
1754
- importPolicy: requestModuleImportPolicy,
1755
- vitePlugins: options.vitePlugins,
1756
- })
1757
- : new Map<string, string>();
1758
-
1759
- const artifactEntries = await mapWithBuildConcurrency(Object.entries(options.files), async ([file, source]) => {
1760
- const absoluteFile = join(options.projectRoot, file);
1761
- const route = routeByFile.get(file);
1762
- const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
1763
- const artifact: BuiltServerModuleArtifact = {};
1763
+ const requestBatchOutputs =
1764
+ requestBatchEntries.length >= 3
1765
+ ? await bundleRouteRequestModuleBatchCode({
1766
+ appDir: options.project.routesDir,
1767
+ bundleCache: options.bundleCache,
1768
+ cacheDir: options.cacheDir,
1769
+ entries: requestBatchEntries,
1770
+ importPolicy: requestModuleImportPolicy,
1771
+ vitePlugins: options.vitePlugins,
1772
+ })
1773
+ : new Map<string, string>();
1764
1774
 
1765
- if (
1766
- requestArtifactFiles.has(file) ||
1767
- loaderArtifactFiles.has(file) ||
1768
- metadataArtifactFiles.has(file)
1769
- ) {
1770
- if (loaderArtifactFiles.has(file)) {
1771
- const code = requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "loader")) ??
1772
- await bundleRouteLoaderModuleCode({
1773
- appDir: options.project.routesDir,
1774
- bundleCache: options.bundleCache,
1775
- cacheDir: options.cacheDir,
1776
- code: stripRouteLoaderOnlyExports(source, absoluteFile),
1777
- filename: absoluteFile,
1778
- importPolicy: requestModuleImportPolicy,
1779
- vitePlugins: options.vitePlugins,
1780
- });
1781
- artifact.loader = {
1782
- code,
1783
- sourceHash: hashText(source),
1784
- };
1785
- }
1775
+ const artifactEntries = await mapWithBuildConcurrency(
1776
+ Object.entries(options.files),
1777
+ async ([file, source]) => {
1778
+ const absoluteFile = join(options.projectRoot, file);
1779
+ const route = routeByFile.get(file);
1780
+ const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
1781
+ const artifact: BuiltServerModuleArtifact = {};
1786
1782
 
1787
- if (metadataArtifactFiles.has(file)) {
1788
- const code = requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "metadata")) ??
1789
- await bundleRouteRequestModuleCode({
1790
- appDir: options.project.routesDir,
1791
- bundleCache: options.bundleCache,
1792
- cacheDir: options.cacheDir,
1793
- code: stripRouteMetadataOnlyExports(source, absoluteFile),
1794
- filename: absoluteFile,
1795
- importPolicy: requestModuleImportPolicy,
1796
- label: "Metadata",
1797
- vitePlugins: options.vitePlugins,
1798
- });
1799
- artifact.routeMetadata = {
1800
- code,
1801
- sourceHash: hashText(source),
1802
- };
1803
- }
1783
+ if (
1784
+ requestArtifactFiles.has(file) ||
1785
+ loaderArtifactFiles.has(file) ||
1786
+ metadataArtifactFiles.has(file)
1787
+ ) {
1788
+ if (loaderArtifactFiles.has(file)) {
1789
+ const code =
1790
+ requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "loader")) ??
1791
+ (await bundleRouteLoaderModuleCode({
1792
+ appDir: options.project.routesDir,
1793
+ bundleCache: options.bundleCache,
1794
+ cacheDir: options.cacheDir,
1795
+ code: stripRouteLoaderOnlyExports(source, absoluteFile),
1796
+ filename: absoluteFile,
1797
+ importPolicy: requestModuleImportPolicy,
1798
+ vitePlugins: options.vitePlugins,
1799
+ }));
1800
+ artifact.loader = {
1801
+ code,
1802
+ sourceHash: hashText(source),
1803
+ };
1804
+ }
1804
1805
 
1805
- if (requestArtifactFiles.has(file)) {
1806
- const batchedRequestCode = requestBatchOutputs.get(
1807
- routeRequestArtifactBatchKey(file, "request"),
1808
- );
1809
- artifact.request = {
1810
- code: batchedRequestCode ??
1811
- await buildRequestModuleArtifactCode({
1806
+ if (metadataArtifactFiles.has(file)) {
1807
+ const code =
1808
+ requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "metadata")) ??
1809
+ (await bundleRouteRequestModuleCode({
1812
1810
  appDir: options.project.routesDir,
1813
1811
  bundleCache: options.bundleCache,
1814
1812
  cacheDir: options.cacheDir,
1813
+ code: stripRouteMetadataOnlyExports(source, absoluteFile),
1815
1814
  filename: absoluteFile,
1816
1815
  importPolicy: requestModuleImportPolicy,
1817
- routeKind: route?.kind,
1818
- source,
1816
+ label: "Metadata",
1819
1817
  vitePlugins: options.vitePlugins,
1820
- }),
1821
- sourceHash: hashText(source),
1822
- };
1818
+ }));
1819
+ artifact.routeMetadata = {
1820
+ code,
1821
+ sourceHash: hashText(source),
1822
+ };
1823
+ }
1824
+
1825
+ if (requestArtifactFiles.has(file)) {
1826
+ const batchedRequestCode = requestBatchOutputs.get(
1827
+ routeRequestArtifactBatchKey(file, "request"),
1828
+ );
1829
+ artifact.request = {
1830
+ code:
1831
+ batchedRequestCode ??
1832
+ (await buildRequestModuleArtifactCode({
1833
+ appDir: options.project.routesDir,
1834
+ bundleCache: options.bundleCache,
1835
+ cacheDir: options.cacheDir,
1836
+ filename: absoluteFile,
1837
+ importPolicy: requestModuleImportPolicy,
1838
+ routeKind: route?.kind,
1839
+ source,
1840
+ vitePlugins: options.vitePlugins,
1841
+ })),
1842
+ sourceHash: hashText(source),
1843
+ };
1844
+ }
1823
1845
  }
1824
- }
1825
1846
 
1826
- if (!isServerComponentFile(file)) {
1827
- return Object.keys(artifact).length > 0 ? ([file, artifact] as const) : undefined;
1828
- }
1847
+ if (!isServerComponentFile(file)) {
1848
+ return Object.keys(artifact).length > 0 ? ([file, artifact] as const) : undefined;
1849
+ }
1829
1850
 
1830
- const closureUsesAwait = routeAnalysis?.streamRoute ??
1831
- shouldBuildRouteAsStream({
1832
- filename: file,
1833
- files: options.files,
1834
- projectRoot: options.projectRoot,
1835
- source,
1836
- });
1837
- const streamRoute = route !== undefined && closureUsesAwait;
1838
- const serverOutputs =
1839
- streamRoute || (route === undefined && closureUsesAwait)
1840
- ? (["stream", "string"] as const)
1841
- : (["string"] as const);
1842
- const code = routeAnalysis?.routeCode ??
1843
- (route === undefined ? source : stripRouteBuildExports(source, absoluteFile));
1844
- const clientInference = routeAnalysis === undefined
1845
- ? await inferClientRouteModule({
1846
- ...(route === undefined ? {} : { appDir: options.project.routesDir }),
1847
- cache: options.clientRouteInferenceCache,
1848
- code:
1849
- route === undefined
1850
- ? stripRouteClientOnlyExports(source, absoluteFile)
1851
- : stripRouteClientSource({ code: source, filename: route.file }),
1852
- filename: join(options.projectRoot, file),
1853
- ...(route === undefined ? {} : { routePath: route.path }),
1854
- vitePlugins: options.vitePlugins,
1855
- })
1856
- : undefined;
1857
- const clientBoundaryImports = routeAnalysis?.clientBoundaryImports ??
1858
- clientInference?.clientBoundaryImports ??
1859
- [];
1851
+ const closureUsesAwait =
1852
+ routeAnalysis?.streamRoute ??
1853
+ shouldBuildRouteAsStream({
1854
+ filename: file,
1855
+ files: options.files,
1856
+ projectRoot: options.projectRoot,
1857
+ source,
1858
+ });
1859
+ const streamRoute = route !== undefined && closureUsesAwait;
1860
+ const serverOutputs =
1861
+ streamRoute || (route === undefined && closureUsesAwait)
1862
+ ? (["stream", "string"] as const)
1863
+ : (["string"] as const);
1864
+ const code =
1865
+ routeAnalysis?.routeCode ??
1866
+ (route === undefined ? source : stripRouteBuildExports(source, absoluteFile));
1867
+ const clientInference =
1868
+ routeAnalysis === undefined
1869
+ ? await inferClientRouteModule({
1870
+ ...(route === undefined ? {} : { appDir: options.project.routesDir }),
1871
+ cache: options.clientRouteInferenceCache,
1872
+ code:
1873
+ route === undefined
1874
+ ? stripRouteClientOnlyExports(source, absoluteFile)
1875
+ : stripRouteClientSource({ code: source, filename: route.file }),
1876
+ filename: join(options.projectRoot, file),
1877
+ ...(route === undefined ? {} : { routePath: route.path }),
1878
+ vitePlugins: options.vitePlugins,
1879
+ })
1880
+ : undefined;
1881
+ const clientBoundaryImports =
1882
+ routeAnalysis?.clientBoundaryImports ?? clientInference?.clientBoundaryImports ?? [];
1883
+ const clientBoundaryFallbackImports =
1884
+ routeAnalysis?.clientBoundaryFallbackImports ??
1885
+ clientInference?.clientBoundaryFallbackImports ??
1886
+ [];
1887
+
1888
+ for (const diagnostic of clientInference?.diagnostics ?? []) {
1889
+ console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
1890
+ }
1860
1891
 
1861
- for (const diagnostic of clientInference?.diagnostics ?? []) {
1862
- console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
1863
- }
1892
+ if (routeAnalysis !== undefined) {
1893
+ artifact.analysis = builtRouteSourceAnalysisSummary({
1894
+ analysis: routeAnalysis,
1895
+ });
1896
+ }
1864
1897
 
1865
- if (routeAnalysis !== undefined) {
1866
- artifact.analysis = builtRouteSourceAnalysisSummary({
1867
- analysis: routeAnalysis,
1868
- });
1869
- }
1898
+ const serverOutputArtifacts = await mapWithBuildConcurrency(
1899
+ serverOutputs,
1900
+ async (serverOutput) => {
1901
+ const output = await transformServerRouteSource({
1902
+ cache: options.serverTransformCache,
1903
+ code,
1904
+ clientBoundaryImports,
1905
+ clientBoundaryFallbackImports,
1906
+ filename: join(options.projectRoot, file),
1907
+ moduleContextCache: options.clientRouteInferenceCache,
1908
+ serverOutput,
1909
+ });
1910
+ const fatalDiagnostics = output.diagnostics.filter(
1911
+ (diagnostic) => diagnostic.code !== "MR_UNSUPPORTED_SERVER_EVENT_HANDLER",
1912
+ );
1870
1913
 
1871
- const serverOutputArtifacts = await mapWithBuildConcurrency(
1872
- serverOutputs,
1873
- async (serverOutput) => {
1874
- const output = await transformServerRouteSource({
1875
- cache: options.serverTransformCache,
1876
- code,
1877
- clientBoundaryImports,
1878
- filename: join(options.projectRoot, file),
1879
- moduleContextCache: options.clientRouteInferenceCache,
1880
- serverOutput,
1881
- });
1882
- const fatalDiagnostics = output.diagnostics.filter(
1883
- (diagnostic) => diagnostic.code !== "MR_UNSUPPORTED_SERVER_EVENT_HANDLER",
1884
- );
1914
+ if (fatalDiagnostics.length > 0) {
1915
+ if (
1916
+ serverOutput === "string" &&
1917
+ streamRoute &&
1918
+ route?.kind === "page" &&
1919
+ fatalDiagnostics.every(
1920
+ (diagnostic) => diagnostic.code === "MR_UNSUPPORTED_AWAIT_INNER_COMPONENT",
1921
+ )
1922
+ ) {
1923
+ return undefined;
1924
+ }
1925
+
1926
+ throw new Error(
1927
+ fatalDiagnostics.map((diagnostic) => formatDiagnostic(file, diagnostic)).join("\n"),
1928
+ );
1929
+ }
1885
1930
 
1886
- if (fatalDiagnostics.length > 0) {
1887
1931
  if (
1888
1932
  serverOutput === "string" &&
1889
1933
  streamRoute &&
1890
1934
  route?.kind === "page" &&
1891
- fatalDiagnostics.every(
1892
- (diagnostic) => diagnostic.code === "MR_UNSUPPORTED_AWAIT_INNER_COMPONENT",
1893
- )
1935
+ source.includes("<Await") &&
1936
+ /\bLink\b/.test(source)
1894
1937
  ) {
1938
+ // Native Link renders pre-rendered children as HTML. Keep direct
1939
+ // Await renderers on the stream artifact so the string artifact
1940
+ // cannot drop deferred Link content before the boundary resolves.
1895
1941
  return undefined;
1896
1942
  }
1897
1943
 
1898
- throw new Error(
1899
- fatalDiagnostics.map((diagnostic) => formatDiagnostic(file, diagnostic)).join("\n"),
1900
- );
1901
- }
1944
+ return [
1945
+ serverOutput,
1946
+ {
1947
+ ...(options.prebundleServerComponents
1948
+ ? {
1949
+ bundleCode: await buildServerComponentBundleArtifactCode({
1950
+ clientRouteInferenceCache: options.clientRouteInferenceCache,
1951
+ code: output.code,
1952
+ filename: absoluteFile,
1953
+ root: options.projectRoot,
1954
+ serverOutput,
1955
+ vitePlugins: options.vitePlugins,
1956
+ }),
1957
+ }
1958
+ : {}),
1959
+ code: output.code,
1960
+ metadata: output.metadata,
1961
+ sourceHash: hashText(code),
1962
+ },
1963
+ ] as const;
1964
+ },
1965
+ );
1902
1966
 
1903
- if (
1904
- serverOutput === "string" &&
1905
- streamRoute &&
1906
- route?.kind === "page" &&
1907
- source.includes("<Await") &&
1908
- /\bLink\b/.test(source)
1909
- ) {
1910
- // Native Link renders pre-rendered children as HTML. Keep direct
1911
- // Await renderers on the stream artifact so the string artifact
1912
- // cannot drop deferred Link content before the boundary resolves.
1913
- return undefined;
1967
+ for (const entry of serverOutputArtifacts) {
1968
+ if (entry !== undefined) {
1969
+ artifact[entry[0]] = entry[1];
1914
1970
  }
1915
-
1916
- return [
1917
- serverOutput,
1918
- {
1919
- ...(options.prebundleServerComponents
1920
- ? {
1921
- bundleCode: await buildServerComponentBundleArtifactCode({
1922
- clientRouteInferenceCache: options.clientRouteInferenceCache,
1923
- code: output.code,
1924
- filename: absoluteFile,
1925
- root: options.projectRoot,
1926
- serverOutput,
1927
- vitePlugins: options.vitePlugins,
1928
- }),
1929
- }
1930
- : {}),
1931
- code: output.code,
1932
- metadata: output.metadata,
1933
- sourceHash: hashText(code),
1934
- },
1935
- ] as const;
1936
- },
1937
- );
1938
-
1939
- for (const entry of serverOutputArtifacts) {
1940
- if (entry !== undefined) {
1941
- artifact[entry[0]] = entry[1];
1942
1971
  }
1943
- }
1944
1972
 
1945
- return [file, artifact] as const;
1946
- });
1973
+ return [file, artifact] as const;
1974
+ },
1975
+ );
1947
1976
 
1948
1977
  for (const entry of artifactEntries) {
1949
1978
  if (entry !== undefined) {
@@ -1981,6 +2010,7 @@ async function buildServerComponentBundleArtifactCode(options: {
1981
2010
  async function transformServerRouteSource(options: {
1982
2011
  cache: ServerTransformCache;
1983
2012
  clientBoundaryImports: readonly string[];
2013
+ clientBoundaryFallbackImports?: readonly string[];
1984
2014
  code: string;
1985
2015
  filename: string;
1986
2016
  moduleContextCache: ClientRouteInferenceCache;
@@ -1988,6 +2018,7 @@ async function transformServerRouteSource(options: {
1988
2018
  }): Promise<ServerTransformOutput> {
1989
2019
  const cacheKey = stableCacheKey({
1990
2020
  clientBoundaryImports: options.clientBoundaryImports,
2021
+ clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
1991
2022
  codeHash: hashText(options.code),
1992
2023
  filename: resolve(options.filename),
1993
2024
  serverOutput: options.serverOutput,
@@ -2009,6 +2040,7 @@ async function transformServerRouteSource(options: {
2009
2040
  return transformCompilerModuleContext({
2010
2041
  code: options.code,
2011
2042
  clientBoundaryImports: options.clientBoundaryImports,
2043
+ clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
2012
2044
  dev: false,
2013
2045
  filename: options.filename,
2014
2046
  moduleContext,
@@ -2026,8 +2058,11 @@ function builtRouteSourceAnalysisSummary(options: {
2026
2058
  }): BuiltRouteSourceAnalysisSummary {
2027
2059
  return {
2028
2060
  authIncludesClaims: options.analysis.authIncludesClaims,
2029
- ...(options.analysis.cachePolicy === undefined ? {} : { cachePolicy: options.analysis.cachePolicy }),
2061
+ ...(options.analysis.cachePolicy === undefined
2062
+ ? {}
2063
+ : { cachePolicy: options.analysis.cachePolicy }),
2030
2064
  clientBoundaryImports: options.analysis.clientBoundaryImports,
2065
+ clientBoundaryFallbackImports: options.analysis.clientBoundaryFallbackImports,
2031
2066
  clientRoute: options.analysis.clientRoute,
2032
2067
  hasLoader: options.analysis.hasLoader,
2033
2068
  routeCode: options.analysis.routeCode,
@@ -2086,7 +2121,10 @@ function usesRuntimeCacheControl(code: string): boolean {
2086
2121
  return /\bcacheControl\s*\(/.test(code);
2087
2122
  }
2088
2123
 
2089
- function routeRequestArtifactBatchKey(file: string, kind: "loader" | "metadata" | "request"): string {
2124
+ function routeRequestArtifactBatchKey(
2125
+ file: string,
2126
+ kind: "loader" | "metadata" | "request",
2127
+ ): string {
2090
2128
  return `${kind}:${file}`;
2091
2129
  }
2092
2130
 
@@ -2126,15 +2164,15 @@ async function buildRequestModuleArtifactCode(options: {
2126
2164
  });
2127
2165
  }
2128
2166
 
2129
- return await bundleRouteLoaderModuleCode({
2130
- appDir: options.appDir,
2131
- bundleCache: options.bundleCache,
2132
- cacheDir: options.cacheDir,
2133
- code: stripRouteRequestOnlyExports(options.source, options.filename),
2134
- filename: options.filename,
2135
- importPolicy: options.importPolicy,
2136
- vitePlugins: options.vitePlugins,
2137
- });
2167
+ return await bundleRouteLoaderModuleCode({
2168
+ appDir: options.appDir,
2169
+ bundleCache: options.bundleCache,
2170
+ cacheDir: options.cacheDir,
2171
+ code: stripRouteRequestOnlyExports(options.source, options.filename),
2172
+ filename: options.filename,
2173
+ importPolicy: options.importPolicy,
2174
+ vitePlugins: options.vitePlugins,
2175
+ });
2138
2176
  }
2139
2177
 
2140
2178
  async function bundleRouteLoaderModuleCode(options: {
@@ -2211,24 +2249,29 @@ async function bundleRouteRequestModuleBatchCode(options: {
2211
2249
  label: "Request artifact",
2212
2250
  }),
2213
2251
  ],
2214
- root: options.importPolicy?.projectRoot ?? dirname(options.entries[0]?.filename ?? options.appDir),
2252
+ root:
2253
+ options.importPolicy?.projectRoot ?? dirname(options.entries[0]?.filename ?? options.appDir),
2215
2254
  vitePlugins: options.vitePlugins,
2216
2255
  });
2217
2256
 
2218
2257
  if (output.chunks.some((chunk) => !chunk.isEntry)) {
2219
- const fallbackEntries = await mapWithBuildConcurrency(options.entries, async (entry) => [
2220
- entry.key,
2221
- await bundleRouteRequestModuleCode({
2222
- appDir: options.appDir,
2223
- bundleCache: options.bundleCache,
2224
- cacheDir: options.cacheDir,
2225
- code: entry.code,
2226
- filename: entry.filename,
2227
- importPolicy: options.importPolicy,
2228
- label: entry.label,
2229
- vitePlugins: options.vitePlugins,
2230
- }),
2231
- ] as const);
2258
+ const fallbackEntries = await mapWithBuildConcurrency(
2259
+ options.entries,
2260
+ async (entry) =>
2261
+ [
2262
+ entry.key,
2263
+ await bundleRouteRequestModuleCode({
2264
+ appDir: options.appDir,
2265
+ bundleCache: options.bundleCache,
2266
+ cacheDir: options.cacheDir,
2267
+ code: entry.code,
2268
+ filename: entry.filename,
2269
+ importPolicy: options.importPolicy,
2270
+ label: entry.label,
2271
+ vitePlugins: options.vitePlugins,
2272
+ }),
2273
+ ] as const,
2274
+ );
2232
2275
  return new Map(fallbackEntries);
2233
2276
  }
2234
2277
 
@@ -2343,9 +2386,11 @@ function isMiddlewareFile(appDir: string, file: string): boolean {
2343
2386
  }
2344
2387
 
2345
2388
  function hasMetadataExport(code: string): boolean {
2346
- return /\bexport\s+const\s+metadata\s*=/.test(code) ||
2389
+ return (
2390
+ /\bexport\s+const\s+metadata\s*=/.test(code) ||
2347
2391
  /\bexport\s+(?:async\s+)?function\s+generateMetadata\b/.test(code) ||
2348
- /\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code);
2392
+ /\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code)
2393
+ );
2349
2394
  }
2350
2395
 
2351
2396
  async function readDeclaredProjectPackages(projectRoot: string): Promise<string[]> {
@@ -2409,6 +2454,7 @@ interface RouteRequestModuleBatchEntry {
2409
2454
  async function writeCloudflareRouteModules(options: {
2410
2455
  cacheDir?: string | undefined;
2411
2456
  cloudflareDir: string;
2457
+ define?: UserConfig["define"] | undefined;
2412
2458
  files: Record<string, string>;
2413
2459
  prerenderedRoutes: Record<string, BuiltPrerenderedRoute>;
2414
2460
  projectRoot: string;
@@ -2428,11 +2474,13 @@ async function writeCloudflareRouteModules(options: {
2428
2474
 
2429
2475
  return analysis === undefined
2430
2476
  ? []
2431
- : [{
2432
- route,
2433
- routeFile,
2434
- routeId: routeIdForPath(route.path),
2435
- }];
2477
+ : [
2478
+ {
2479
+ route,
2480
+ routeFile,
2481
+ routeId: routeIdForPath(route.path),
2482
+ },
2483
+ ];
2436
2484
  }),
2437
2485
  );
2438
2486
 
@@ -2440,6 +2488,7 @@ async function writeCloudflareRouteModules(options: {
2440
2488
 
2441
2489
  const serverRouteModules = await buildCloudflareServerRouteModuleBatch({
2442
2490
  cacheDir: options.cacheDir,
2491
+ define: options.define,
2443
2492
  routes: requiredRoutes
2444
2493
  .filter(({ route }) => route.kind === "server" || route.kind === "metadata")
2445
2494
  .map(({ route, routeId }) => ({ filename: route.file, routeId })),
@@ -2448,9 +2497,12 @@ async function writeCloudflareRouteModules(options: {
2448
2497
  });
2449
2498
  const loaderRouteModules = await buildCloudflareRouteLoaderModuleBatch({
2450
2499
  cacheDir: options.cacheDir,
2500
+ define: options.define,
2451
2501
  routes: requiredRoutes
2452
- .filter(({ route, routeFile }) =>
2453
- route.kind === "page" && options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true
2502
+ .filter(
2503
+ ({ route, routeFile }) =>
2504
+ route.kind === "page" &&
2505
+ options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true,
2454
2506
  )
2455
2507
  .map(({ route, routeId }) => ({ filename: route.file, routeId })),
2456
2508
  root: options.projectRoot,
@@ -2474,6 +2526,7 @@ async function writeCloudflareRouteModules(options: {
2474
2526
  );
2475
2527
  const directComponentModules = await buildCloudflareServerComponentModuleBatch({
2476
2528
  cacheDir: options.cacheDir,
2529
+ define: options.define,
2477
2530
  projectRoot: options.projectRoot,
2478
2531
  routes: directComponentRoutes,
2479
2532
  serverModules: options.serverModules,
@@ -2482,6 +2535,7 @@ async function writeCloudflareRouteModules(options: {
2482
2535
  });
2483
2536
  const stringShellComponentModules = await buildCloudflareStringRouteComponentModuleBatch({
2484
2537
  cacheDir: options.cacheDir,
2538
+ define: options.define,
2485
2539
  projectRoot: options.projectRoot,
2486
2540
  routes: stringShellComponentRoutes,
2487
2541
  serverModules: options.serverModules,
@@ -2496,112 +2550,120 @@ async function writeCloudflareRouteModules(options: {
2496
2550
  writeCloudflareBatchedRouteModuleChunks(options.cloudflareDir, stringShellComponentModules),
2497
2551
  ]);
2498
2552
 
2499
- const registryEntries = await mapWithBuildConcurrency(requiredRoutes, async ({ route, routeFile, routeId }) => {
2500
- const routeModuleFile = `routes/${routeId}.mjs`;
2501
- let routeModuleExports: string[];
2553
+ const registryEntries = await mapWithBuildConcurrency(
2554
+ requiredRoutes,
2555
+ async ({ route, routeFile, routeId }) => {
2556
+ const routeModuleFile = `routes/${routeId}.mjs`;
2557
+ let routeModuleExports: string[];
2502
2558
 
2503
- if (route.kind === "server" || route.kind === "metadata") {
2504
- try {
2505
- const serverRouteModule = serverRouteModules.entries.get(routeId);
2559
+ if (route.kind === "server" || route.kind === "metadata") {
2560
+ try {
2561
+ const serverRouteModule = serverRouteModules.entries.get(routeId);
2506
2562
 
2507
- if (serverRouteModule === undefined) {
2508
- throw new Error(`Missing bundled Cloudflare ${route.kind} route module.`);
2563
+ if (serverRouteModule === undefined) {
2564
+ throw new Error(`Missing bundled Cloudflare ${route.kind} route module.`);
2565
+ }
2566
+
2567
+ const serverRouteFile = serverRouteModule.fileName;
2568
+ const serverRouteImport = `./${serverRouteFile.split("/").pop() ?? serverRouteFile}`;
2569
+ routeModuleExports = [
2570
+ `export * from ${JSON.stringify(serverRouteImport)};`,
2571
+ ...(route.kind === "metadata"
2572
+ ? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
2573
+ : []),
2574
+ ];
2575
+ } catch (error) {
2576
+ throw new Error(
2577
+ `Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
2578
+ );
2509
2579
  }
2510
2580
 
2511
- const serverRouteFile = serverRouteModule.fileName;
2512
- const serverRouteImport = `./${serverRouteFile.split("/").pop() ?? serverRouteFile}`;
2513
- routeModuleExports = [
2514
- `export * from ${JSON.stringify(serverRouteImport)};`,
2515
- ...(route.kind === "metadata"
2516
- ? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
2517
- : []),
2518
- ];
2519
- } catch (error) {
2520
- throw new Error(
2521
- `Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
2581
+ await writeFile(
2582
+ join(options.cloudflareDir, routeModuleFile),
2583
+ `${routeModuleExports.join("\n")}\n`,
2522
2584
  );
2585
+ return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
2523
2586
  }
2524
2587
 
2525
- await writeFile(join(options.cloudflareDir, routeModuleFile), `${routeModuleExports.join("\n")}\n`);
2526
- return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
2527
- }
2528
-
2529
- const serverOutput =
2530
- options.serverModules[routeFile]?.analysis?.streamRoute === true ||
2531
- options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
2532
- ? "stream"
2533
- : "string";
2588
+ const serverOutput =
2589
+ options.serverModules[routeFile]?.analysis?.streamRoute === true ||
2590
+ options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
2591
+ ? "stream"
2592
+ : "string";
2534
2593
 
2535
- try {
2536
- const batchedComponent =
2537
- stringShellComponentRouteIds.has(routeId)
2594
+ try {
2595
+ const batchedComponent = stringShellComponentRouteIds.has(routeId)
2538
2596
  ? stringShellComponentModules.entries.get(routeId)
2539
2597
  : directComponentRouteIds.has(routeId)
2540
2598
  ? directComponentModules.entries.get(routeId)
2541
2599
  : undefined;
2542
- let componentFile = batchedComponent?.fileName;
2543
-
2544
- if (batchedComponent === undefined) {
2545
- const componentOutput =
2546
- serverOutput === "stream"
2547
- ? await buildCloudflareStreamRouteComponentModule({
2548
- cacheDir: options.cacheDir,
2549
- filename: route.file,
2550
- projectRoot: options.projectRoot,
2551
- routesDir: options.routesDir,
2552
- serverModules: options.serverModules,
2553
- sourceAnalysis: options.sourceAnalysis,
2554
- vitePlugins: options.vitePlugins,
2555
- })
2556
- : await buildCloudflareStringRouteComponentModule({
2557
- cacheDir: options.cacheDir,
2558
- filename: route.file,
2559
- projectRoot: options.projectRoot,
2560
- routesDir: options.routesDir,
2561
- serverModules: options.serverModules,
2562
- sourceAnalysis: options.sourceAnalysis,
2563
- vitePlugins: options.vitePlugins,
2564
- });
2600
+ let componentFile = batchedComponent?.fileName;
2601
+
2602
+ if (batchedComponent === undefined) {
2603
+ const componentOutput =
2604
+ serverOutput === "stream"
2605
+ ? await buildCloudflareStreamRouteComponentModule({
2606
+ cacheDir: options.cacheDir,
2607
+ define: options.define,
2608
+ filename: route.file,
2609
+ projectRoot: options.projectRoot,
2610
+ routesDir: options.routesDir,
2611
+ serverModules: options.serverModules,
2612
+ sourceAnalysis: options.sourceAnalysis,
2613
+ vitePlugins: options.vitePlugins,
2614
+ })
2615
+ : await buildCloudflareStringRouteComponentModule({
2616
+ cacheDir: options.cacheDir,
2617
+ define: options.define,
2618
+ filename: route.file,
2619
+ projectRoot: options.projectRoot,
2620
+ routesDir: options.routesDir,
2621
+ serverModules: options.serverModules,
2622
+ sourceAnalysis: options.sourceAnalysis,
2623
+ vitePlugins: options.vitePlugins,
2624
+ });
2625
+
2626
+ componentFile = `routes/${routeId}.${hashText(componentOutput).slice(0, 8)}.component.mjs`;
2627
+ await writeFile(join(options.cloudflareDir, componentFile), componentOutput);
2628
+ }
2565
2629
 
2566
- componentFile = `routes/${routeId}.${hashText(componentOutput).slice(0, 8)}.component.mjs`;
2567
- await writeFile(join(options.cloudflareDir, componentFile), componentOutput);
2568
- }
2630
+ if (componentFile === undefined) {
2631
+ throw new Error("Missing bundled Cloudflare component module.");
2632
+ }
2569
2633
 
2570
- if (componentFile === undefined) {
2571
- throw new Error("Missing bundled Cloudflare component module.");
2634
+ const componentImport = `./${componentFile.split("/").pop() ?? componentFile}`;
2635
+ routeModuleExports = [cloudflarePageRouteFacadeModuleSource(componentImport)];
2636
+ } catch (error) {
2637
+ throw new Error(
2638
+ `Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
2639
+ );
2572
2640
  }
2573
2641
 
2574
- const componentImport = `./${componentFile.split("/").pop() ?? componentFile}`;
2575
- routeModuleExports = [
2576
- cloudflarePageRouteFacadeModuleSource(componentImport),
2577
- ];
2578
- } catch (error) {
2579
- throw new Error(
2580
- `Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
2581
- );
2582
- }
2642
+ if (options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true) {
2643
+ try {
2644
+ const loaderModule = loaderRouteModules.entries.get(routeId);
2583
2645
 
2584
- if (options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true) {
2585
- try {
2586
- const loaderModule = loaderRouteModules.entries.get(routeId);
2646
+ if (loaderModule === undefined) {
2647
+ throw new Error("Missing bundled Cloudflare loader module.");
2648
+ }
2587
2649
 
2588
- if (loaderModule === undefined) {
2589
- throw new Error("Missing bundled Cloudflare loader module.");
2650
+ const loaderFile = loaderModule.fileName;
2651
+ const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
2652
+ routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
2653
+ } catch (error) {
2654
+ throw new Error(
2655
+ `Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
2656
+ );
2590
2657
  }
2591
-
2592
- const loaderFile = loaderModule.fileName;
2593
- const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
2594
- routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
2595
- } catch (error) {
2596
- throw new Error(
2597
- `Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
2598
- );
2599
2658
  }
2600
- }
2601
2659
 
2602
- await writeFile(join(options.cloudflareDir, routeModuleFile), `${routeModuleExports.join("\n")}\n`);
2603
- return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
2604
- });
2660
+ await writeFile(
2661
+ join(options.cloudflareDir, routeModuleFile),
2662
+ `${routeModuleExports.join("\n")}\n`,
2663
+ );
2664
+ return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
2665
+ },
2666
+ );
2605
2667
 
2606
2668
  const registrySource = [
2607
2669
  `export const routeModules = {`,
@@ -2754,6 +2816,7 @@ interface CloudflareShellFile {
2754
2816
 
2755
2817
  async function buildCloudflareServerComponentModuleBatch(options: {
2756
2818
  cacheDir?: string | undefined;
2819
+ define?: UserConfig["define"] | undefined;
2757
2820
  projectRoot: string;
2758
2821
  routes: readonly CloudflareBatchedComponentRoute[];
2759
2822
  serverModules: Record<string, BuiltServerModuleArtifact>;
@@ -2769,6 +2832,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
2769
2832
  options.routes.map(async (route) => {
2770
2833
  const metadataModule = await buildCloudflareRouteMetadataExportModule({
2771
2834
  cacheDir: options.cacheDir,
2835
+ define: options.define,
2772
2836
  filename: route.filename,
2773
2837
  hasMetadata: buildSourceAnalysisForFile(
2774
2838
  options.sourceAnalysis,
@@ -2801,6 +2865,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
2801
2865
  const output = await bundleRouterModules({
2802
2866
  cacheDir: options.cacheDir,
2803
2867
  chunkFileNames: "routes/chunks/[name].[hash].mjs",
2868
+ define: options.define,
2804
2869
  entries: bundleEntries,
2805
2870
  entryFileNames: "routes/[name].[hash].mjs",
2806
2871
  minify: true,
@@ -2844,6 +2909,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
2844
2909
 
2845
2910
  async function buildCloudflareStringRouteComponentModuleBatch(options: {
2846
2911
  cacheDir?: string | undefined;
2912
+ define?: UserConfig["define"] | undefined;
2847
2913
  projectRoot: string;
2848
2914
  routes: readonly CloudflareBatchedStringRoute[];
2849
2915
  serverModules: Record<string, BuiltServerModuleArtifact>;
@@ -2861,6 +2927,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
2861
2927
  const pageMetadataId = `mreact:metadata:${route.routeId}:page`;
2862
2928
  const pageMetadataModule = await buildCloudflareRouteMetadataExportModule({
2863
2929
  cacheDir: options.cacheDir,
2930
+ define: options.define,
2864
2931
  filename: route.filename,
2865
2932
  hasMetadata: buildSourceAnalysisForFile(
2866
2933
  options.sourceAnalysis,
@@ -2878,7 +2945,9 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
2878
2945
  contents: pageMetadataModule,
2879
2946
  resolveDir: dirname(route.filename),
2880
2947
  });
2881
- metadataImports.push(`import * as pageMetadataModule from ${JSON.stringify(pageMetadataId)};`);
2948
+ metadataImports.push(
2949
+ `import * as pageMetadataModule from ${JSON.stringify(pageMetadataId)};`,
2950
+ );
2882
2951
  }
2883
2952
 
2884
2953
  const shellMetadataImports = await Promise.all(
@@ -2886,6 +2955,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
2886
2955
  const shellMetadataId = `mreact:metadata:${route.routeId}:shell:${index}`;
2887
2956
  const shellMetadataModule = await buildCloudflareRouteMetadataExportModule({
2888
2957
  cacheDir: options.cacheDir,
2958
+ define: options.define,
2889
2959
  filename: shell.file,
2890
2960
  hasMetadata: buildSourceAnalysisForFile(
2891
2961
  options.sourceAnalysis,
@@ -2926,6 +2996,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
2926
2996
  const output = await bundleRouterModules({
2927
2997
  cacheDir: options.cacheDir,
2928
2998
  chunkFileNames: "routes/chunks/[name].[hash].mjs",
2999
+ define: options.define,
2929
3000
  entries: bundleEntries,
2930
3001
  entryFileNames: "routes/[name].[hash].mjs",
2931
3002
  minify: true,
@@ -3055,6 +3126,7 @@ ${cloudflareShellRuntimeSource()}`;
3055
3126
 
3056
3127
  async function buildCloudflareServerComponentModule(options: {
3057
3128
  cacheDir?: string | undefined;
3129
+ define?: UserConfig["define"] | undefined;
3058
3130
  filename: string;
3059
3131
  projectRoot: string;
3060
3132
  serverOutput: ServerOutputMode;
@@ -3064,8 +3136,13 @@ async function buildCloudflareServerComponentModule(options: {
3064
3136
  }): Promise<string> {
3065
3137
  const metadataModule = await buildCloudflareRouteMetadataExportModule({
3066
3138
  cacheDir: options.cacheDir,
3139
+ define: options.define,
3067
3140
  filename: options.filename,
3068
- hasMetadata: buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, options.filename)?.hasMetadata,
3141
+ hasMetadata: buildSourceAnalysisForFile(
3142
+ options.sourceAnalysis,
3143
+ options.projectRoot,
3144
+ options.filename,
3145
+ )?.hasMetadata,
3069
3146
  root: options.projectRoot,
3070
3147
  vitePlugins: options.vitePlugins,
3071
3148
  });
@@ -3078,9 +3155,9 @@ async function buildCloudflareServerComponentModule(options: {
3078
3155
  entry,
3079
3156
  filename: `${options.filename}.mreact-cloudflare-component.js`,
3080
3157
  cacheDir: options.cacheDir,
3081
- modules: metadataModule === undefined
3082
- ? new Map()
3083
- : new Map([["mreact:metadata", metadataModule]]),
3158
+ define: options.define,
3159
+ modules:
3160
+ metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
3084
3161
  plugins: [
3085
3162
  cloudflareServerSourceTransformPlugin({
3086
3163
  projectRoot: options.projectRoot,
@@ -3113,6 +3190,7 @@ export const slots = routeModule.slots;`;
3113
3190
 
3114
3191
  async function buildCloudflareStringRouteComponentModule(options: {
3115
3192
  cacheDir?: string | undefined;
3193
+ define?: UserConfig["define"] | undefined;
3116
3194
  filename: string;
3117
3195
  projectRoot: string;
3118
3196
  routesDir: string;
@@ -3125,6 +3203,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
3125
3203
  if (shellFiles.length === 0) {
3126
3204
  return buildCloudflareServerComponentModule({
3127
3205
  cacheDir: options.cacheDir,
3206
+ define: options.define,
3128
3207
  filename: options.filename,
3129
3208
  projectRoot: options.projectRoot,
3130
3209
  serverModules: options.serverModules,
@@ -3136,6 +3215,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
3136
3215
 
3137
3216
  const pageModule = await buildCloudflareComponentExportModule({
3138
3217
  cacheDir: options.cacheDir,
3218
+ define: options.define,
3139
3219
  filename: options.filename,
3140
3220
  projectRoot: options.projectRoot,
3141
3221
  serverModules: options.serverModules,
@@ -3147,6 +3227,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
3147
3227
  shellFiles.map((shell) =>
3148
3228
  buildCloudflareComponentExportModule({
3149
3229
  cacheDir: options.cacheDir,
3230
+ define: options.define,
3150
3231
  filename: shell.file,
3151
3232
  projectRoot: options.projectRoot,
3152
3233
  serverModules: options.serverModules,
@@ -3156,7 +3237,9 @@ async function buildCloudflareStringRouteComponentModule(options: {
3156
3237
  }),
3157
3238
  ),
3158
3239
  );
3159
- const shellImports = shellFiles.map((_, index) => `import * as shell${index} from "mreact:shell-${index}";`);
3240
+ const shellImports = shellFiles.map(
3241
+ (_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
3242
+ );
3160
3243
  const shellDefinitions = shellFiles.map(
3161
3244
  (shell, index) =>
3162
3245
  `{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
@@ -3215,6 +3298,7 @@ ${cloudflareShellRuntimeSource()}`;
3215
3298
  return bundleCloudflareVirtualModule({
3216
3299
  entry,
3217
3300
  cacheDir: options.cacheDir,
3301
+ define: options.define,
3218
3302
  filename: `${options.filename}.mreact-cloudflare-string-route.js`,
3219
3303
  modules: new Map([
3220
3304
  ["mreact:page", pageModule],
@@ -3229,6 +3313,7 @@ ${cloudflareShellRuntimeSource()}`;
3229
3313
 
3230
3314
  async function buildCloudflareStreamRouteComponentModule(options: {
3231
3315
  cacheDir?: string | undefined;
3316
+ define?: UserConfig["define"] | undefined;
3232
3317
  filename: string;
3233
3318
  projectRoot: string;
3234
3319
  routesDir: string;
@@ -3238,6 +3323,7 @@ async function buildCloudflareStreamRouteComponentModule(options: {
3238
3323
  }): Promise<string> {
3239
3324
  const pageModule = await buildCloudflareComponentExportModule({
3240
3325
  cacheDir: options.cacheDir,
3326
+ define: options.define,
3241
3327
  filename: options.filename,
3242
3328
  projectRoot: options.projectRoot,
3243
3329
  serverModules: options.serverModules,
@@ -3250,6 +3336,7 @@ async function buildCloudflareStreamRouteComponentModule(options: {
3250
3336
  shellFiles.map((shell) =>
3251
3337
  buildCloudflareComponentExportModule({
3252
3338
  cacheDir: options.cacheDir,
3339
+ define: options.define,
3253
3340
  filename: shell.file,
3254
3341
  projectRoot: options.projectRoot,
3255
3342
  serverModules: options.serverModules,
@@ -3259,7 +3346,9 @@ async function buildCloudflareStreamRouteComponentModule(options: {
3259
3346
  }),
3260
3347
  ),
3261
3348
  );
3262
- const shellImports = shellFiles.map((_, index) => `import * as shell${index} from "mreact:shell-${index}";`);
3349
+ const shellImports = shellFiles.map(
3350
+ (_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
3351
+ );
3263
3352
  const shellDefinitions = shellFiles.map(
3264
3353
  (shell, index) =>
3265
3354
  `{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
@@ -3336,6 +3425,7 @@ ${cloudflareShellRuntimeSource()}`;
3336
3425
  return bundleCloudflareVirtualModule({
3337
3426
  entry,
3338
3427
  cacheDir: options.cacheDir,
3428
+ define: options.define,
3339
3429
  filename: `${options.filename}.mreact-cloudflare-stream-route.js`,
3340
3430
  modules: new Map([
3341
3431
  ["mreact:page", pageModule],
@@ -3646,6 +3736,7 @@ function escapeHtml(value) {
3646
3736
 
3647
3737
  async function buildCloudflareComponentExportModule(options: {
3648
3738
  cacheDir?: string | undefined;
3739
+ define?: UserConfig["define"] | undefined;
3649
3740
  filename: string;
3650
3741
  projectRoot: string;
3651
3742
  serverModules: Record<string, BuiltServerModuleArtifact>;
@@ -3655,8 +3746,13 @@ async function buildCloudflareComponentExportModule(options: {
3655
3746
  }): Promise<string> {
3656
3747
  const metadataModule = await buildCloudflareRouteMetadataExportModule({
3657
3748
  cacheDir: options.cacheDir,
3749
+ define: options.define,
3658
3750
  filename: options.filename,
3659
- hasMetadata: buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, options.filename)?.hasMetadata,
3751
+ hasMetadata: buildSourceAnalysisForFile(
3752
+ options.sourceAnalysis,
3753
+ options.projectRoot,
3754
+ options.filename,
3755
+ )?.hasMetadata,
3660
3756
  root: options.projectRoot,
3661
3757
  vitePlugins: options.vitePlugins,
3662
3758
  });
@@ -3673,10 +3769,10 @@ export const slots = routeModule.slots;`;
3673
3769
  return bundleCloudflareVirtualModule({
3674
3770
  entry,
3675
3771
  cacheDir: options.cacheDir,
3772
+ define: options.define,
3676
3773
  filename: `${options.filename}.mreact-cloudflare-${options.serverOutput}-component.js`,
3677
- modules: metadataModule === undefined
3678
- ? new Map()
3679
- : new Map([["mreact:metadata", metadataModule]]),
3774
+ modules:
3775
+ metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
3680
3776
  plugins: [
3681
3777
  cloudflareServerSourceTransformPlugin({
3682
3778
  projectRoot: options.projectRoot,
@@ -3707,12 +3803,14 @@ async function writeCloudflareBatchedRouteModuleChunks(
3707
3803
 
3708
3804
  async function buildCloudflareRouteLoaderModuleBatch(options: {
3709
3805
  cacheDir?: string | undefined;
3806
+ define?: UserConfig["define"] | undefined;
3710
3807
  routes: readonly { filename: string; routeId: string }[];
3711
3808
  root: string;
3712
3809
  vitePlugins?: readonly PluginOption[] | undefined;
3713
3810
  }): Promise<CloudflareBatchedRouteModules> {
3714
3811
  return await bundleCloudflareModuleBatch({
3715
3812
  cacheDir: options.cacheDir,
3813
+ define: options.define,
3716
3814
  entries: options.routes.map((route) => ({
3717
3815
  code: cloudflareRouteLoaderModuleEntry(route.filename),
3718
3816
  filename: `${route.filename}.mreact-cloudflare-loader.js`,
@@ -3726,12 +3824,14 @@ async function buildCloudflareRouteLoaderModuleBatch(options: {
3726
3824
 
3727
3825
  export async function __buildCloudflareRouteLoaderModuleBatchForTests(options: {
3728
3826
  cacheDir?: string | undefined;
3827
+ define?: UserConfig["define"] | undefined;
3729
3828
  projectRoot: string;
3730
3829
  routes: readonly { filename: string; routeId: string }[];
3731
3830
  vitePlugins?: readonly PluginOption[] | undefined;
3732
3831
  }): Promise<Record<string, string>> {
3733
3832
  const output = await buildCloudflareRouteLoaderModuleBatch({
3734
3833
  cacheDir: options.cacheDir,
3834
+ define: options.define,
3735
3835
  root: options.projectRoot,
3736
3836
  routes: options.routes,
3737
3837
  vitePlugins: options.vitePlugins,
@@ -3744,12 +3844,14 @@ export async function __buildCloudflareRouteLoaderModuleBatchForTests(options: {
3744
3844
 
3745
3845
  async function buildCloudflareServerRouteModuleBatch(options: {
3746
3846
  cacheDir?: string | undefined;
3847
+ define?: UserConfig["define"] | undefined;
3747
3848
  routes: readonly { filename: string; routeId: string }[];
3748
3849
  root: string;
3749
3850
  vitePlugins?: readonly PluginOption[] | undefined;
3750
3851
  }): Promise<CloudflareBatchedRouteModules> {
3751
3852
  return await bundleCloudflareModuleBatch({
3752
3853
  cacheDir: options.cacheDir,
3854
+ define: options.define,
3753
3855
  entries: options.routes.map((route) => ({
3754
3856
  code: cloudflareServerRouteModuleEntry(route.filename),
3755
3857
  filename: `${route.filename}.mreact-cloudflare-server-route.js`,
@@ -3763,6 +3865,7 @@ async function buildCloudflareServerRouteModuleBatch(options: {
3763
3865
 
3764
3866
  async function bundleCloudflareModuleBatch(options: {
3765
3867
  cacheDir?: string | undefined;
3868
+ define?: UserConfig["define"] | undefined;
3766
3869
  entries: readonly {
3767
3870
  code: string;
3768
3871
  filename: string;
@@ -3779,6 +3882,7 @@ async function bundleCloudflareModuleBatch(options: {
3779
3882
  const output = await bundleRouterModules({
3780
3883
  cacheDir: options.cacheDir,
3781
3884
  chunkFileNames: "routes/chunks/[name].[hash].mjs",
3885
+ define: options.define,
3782
3886
  entries: options.entries,
3783
3887
  entryFileNames: "routes/[name].[hash].mjs",
3784
3888
  minify: true,
@@ -3817,6 +3921,7 @@ function cloudflareRouteLoaderModuleEntry(filename: string): string {
3817
3921
 
3818
3922
  async function buildCloudflareRouteMetadataExportModule(options: {
3819
3923
  cacheDir?: string | undefined;
3924
+ define?: UserConfig["define"] | undefined;
3820
3925
  filename: string;
3821
3926
  hasMetadata?: boolean | undefined;
3822
3927
  root?: string | undefined;
@@ -3833,6 +3938,7 @@ export const metadata = routeMetadataModule.metadata;`;
3833
3938
  return bundleCloudflareModule({
3834
3939
  entry,
3835
3940
  cacheDir: options.cacheDir,
3941
+ define: options.define,
3836
3942
  filename: `${options.filename}.mreact-cloudflare-metadata.js`,
3837
3943
  plugins: [cloudflareWorkspaceRuntimePlugin()],
3838
3944
  resolveDir: dirname(options.filename),
@@ -3858,6 +3964,7 @@ export default defaultHandler;`;
3858
3964
 
3859
3965
  async function bundleCloudflareModule(options: {
3860
3966
  cacheDir?: string | undefined;
3967
+ define?: UserConfig["define"] | undefined;
3861
3968
  entry: string;
3862
3969
  filename: string;
3863
3970
  plugins: RouterCompatPlugin[];
@@ -3868,6 +3975,7 @@ async function bundleCloudflareModule(options: {
3868
3975
  const output = await bundleRouterModule({
3869
3976
  cacheDir: options.cacheDir,
3870
3977
  code: options.entry,
3978
+ define: options.define,
3871
3979
  filename: options.filename,
3872
3980
  minify: true,
3873
3981
  platform: "node",
@@ -3888,6 +3996,7 @@ async function bundleCloudflareModule(options: {
3888
3996
 
3889
3997
  async function bundleCloudflareVirtualModule(options: {
3890
3998
  cacheDir?: string | undefined;
3999
+ define?: UserConfig["define"] | undefined;
3891
4000
  entry: string;
3892
4001
  filename: string;
3893
4002
  modules: ReadonlyMap<string, string>;
@@ -3898,6 +4007,7 @@ async function bundleCloudflareVirtualModule(options: {
3898
4007
  }): Promise<string> {
3899
4008
  return bundleCloudflareModule({
3900
4009
  cacheDir: options.cacheDir,
4010
+ define: options.define,
3901
4011
  entry: options.entry,
3902
4012
  filename: options.filename,
3903
4013
  plugins: [
@@ -4047,6 +4157,7 @@ async function transformCloudflareServerSource(options: {
4047
4157
  const output = transformCompilerModuleContext({
4048
4158
  code: options.source,
4049
4159
  clientBoundaryImports: clientInference.clientBoundaryImports,
4160
+ clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
4050
4161
  dev: false,
4051
4162
  filename: options.filename,
4052
4163
  moduleContext,
@@ -4060,7 +4171,9 @@ async function transformCloudflareServerSource(options: {
4060
4171
 
4061
4172
  if (fatalDiagnostics.length > 0) {
4062
4173
  throw new Error(
4063
- fatalDiagnostics.map((diagnostic) => formatDiagnostic(options.filename, diagnostic)).join("\n"),
4174
+ fatalDiagnostics
4175
+ .map((diagnostic) => formatDiagnostic(options.filename, diagnostic))
4176
+ .join("\n"),
4064
4177
  );
4065
4178
  }
4066
4179
 
@@ -4101,9 +4214,18 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
4101
4214
  "@reckona/mreact-compat/event-priority",
4102
4215
  packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
4103
4216
  ],
4104
- ["@reckona/mreact-compat/flight", packageFile("react-compat", "@reckona/mreact-compat", "flight")],
4105
- ["@reckona/mreact-compat/hooks", packageFile("react-compat", "@reckona/mreact-compat", "hooks-entry")],
4106
- ["@reckona/mreact-compat/internal", packageFile("react-compat", "@reckona/mreact-compat", "internal")],
4217
+ [
4218
+ "@reckona/mreact-compat/flight",
4219
+ packageFile("react-compat", "@reckona/mreact-compat", "flight"),
4220
+ ],
4221
+ [
4222
+ "@reckona/mreact-compat/hooks",
4223
+ packageFile("react-compat", "@reckona/mreact-compat", "hooks-entry"),
4224
+ ],
4225
+ [
4226
+ "@reckona/mreact-compat/internal",
4227
+ packageFile("react-compat", "@reckona/mreact-compat", "internal"),
4228
+ ],
4107
4229
  [
4108
4230
  "@reckona/mreact-compat/jsx-dev-runtime",
4109
4231
  packageFile("react-compat", "@reckona/mreact-compat", "jsx-dev-runtime"),
@@ -4112,9 +4234,15 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
4112
4234
  "@reckona/mreact-compat/jsx-runtime",
4113
4235
  packageFile("react-compat", "@reckona/mreact-compat", "jsx-runtime"),
4114
4236
  ],
4115
- ["@reckona/mreact-compat/scheduler", packageFile("react-compat", "@reckona/mreact-compat", "scheduler")],
4237
+ [
4238
+ "@reckona/mreact-compat/scheduler",
4239
+ packageFile("react-compat", "@reckona/mreact-compat", "scheduler"),
4240
+ ],
4116
4241
  ["@reckona/mreact-query", packageFile("query", "@reckona/mreact-query", "index")],
4117
- ["@reckona/mreact-reactive-core", packageFile("reactive-core", "@reckona/mreact-reactive-core", "index")],
4242
+ [
4243
+ "@reckona/mreact-reactive-core",
4244
+ packageFile("reactive-core", "@reckona/mreact-reactive-core", "index"),
4245
+ ],
4118
4246
  [
4119
4247
  "@reckona/mreact-router/adapters/cloudflare",
4120
4248
  packageFile("router", "@reckona/mreact-router", "adapters/cloudflare"),
@@ -4133,10 +4261,13 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
4133
4261
  return {
4134
4262
  name: "mreact-cloudflare-workspace-runtime",
4135
4263
  setup(buildApi) {
4136
- buildApi.onResolve({ filter: /^@reckona\/mreact-router\/(?:internal\/)?native-escape$/ }, () => ({
4137
- namespace: "mreact-cloudflare-native-escape",
4138
- path: "native-escape",
4139
- }));
4264
+ buildApi.onResolve(
4265
+ { filter: /^@reckona\/mreact-router\/(?:internal\/)?native-escape$/ },
4266
+ () => ({
4267
+ namespace: "mreact-cloudflare-native-escape",
4268
+ path: "native-escape",
4269
+ }),
4270
+ );
4140
4271
  buildApi.onResolve({ filter: /^@reckona\/mreact-router$/ }, () => ({
4141
4272
  namespace: "mreact-cloudflare-router-index",
4142
4273
  path: "index",
@@ -4146,8 +4277,10 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
4146
4277
 
4147
4278
  return path === undefined ? undefined : { path };
4148
4279
  });
4149
- buildApi.onLoad({ filter: /^native-escape$/, namespace: "mreact-cloudflare-native-escape" }, () => ({
4150
- contents: `function escapeHtml(value) {
4280
+ buildApi.onLoad(
4281
+ { filter: /^native-escape$/, namespace: "mreact-cloudflare-native-escape" },
4282
+ () => ({
4283
+ contents: `function escapeHtml(value) {
4151
4284
  return String(value ?? "").replace(/[&<>"']/g, (char) =>
4152
4285
  char === "&" ? "&amp;" : char === "<" ? "&lt;" : char === ">" ? "&gt;" : char === '"' ? "&quot;" : "&#39;"
4153
4286
  );
@@ -4155,8 +4288,9 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
4155
4288
  export function escapeHtmlBatch(values) {
4156
4289
  return values.map(escapeHtml);
4157
4290
  }`,
4158
- loader: "js",
4159
- }));
4291
+ loader: "js",
4292
+ }),
4293
+ );
4160
4294
  buildApi.onLoad({ filter: /^index$/, namespace: "mreact-cloudflare-router-index" }, () => ({
4161
4295
  contents: `export { cacheControl, revalidatePath } from ${JSON.stringify(routerCachePath)};
4162
4296
  export { deleteCookie, parseCookieHeader, serializeCookie, setCookie } from ${JSON.stringify(routerCookiesPath)};
@@ -4170,12 +4304,15 @@ export { getServerRuntimeState } from ${JSON.stringify(routerRuntimeStatePath)};
4170
4304
  loader: "js",
4171
4305
  resolveDir: dirname(routerNavigationPath),
4172
4306
  }));
4173
- buildApi.onLoad({ filter: /(?:^|[/\\])packages[/\\]server[/\\](?:src|dist)[/\\]native-flight\.[jt]s$/ }, () => ({
4174
- contents: `export function getNativeFlight() {
4307
+ buildApi.onLoad(
4308
+ { filter: /(?:^|[/\\])packages[/\\]server[/\\](?:src|dist)[/\\]native-flight\.[jt]s$/ },
4309
+ () => ({
4310
+ contents: `export function getNativeFlight() {
4175
4311
  return undefined;
4176
4312
  }`,
4177
- loader: "js",
4178
- }));
4313
+ loader: "js",
4314
+ }),
4315
+ );
4179
4316
  },
4180
4317
  };
4181
4318
  }
@@ -4377,18 +4514,23 @@ async function writeClientRouteBundles(options: {
4377
4514
  });
4378
4515
  } catch (error) {
4379
4516
  const routeContexts = clientEntries
4380
- .map((entry) => `Failed to build client bundle for ${entry.route.path} (${entry.route.file}).`)
4517
+ .map(
4518
+ (entry) => `Failed to build client bundle for ${entry.route.path} (${entry.route.file}).`,
4519
+ )
4381
4520
  .join("\n");
4382
4521
 
4383
- throw new Error(`${routeContexts}\nFailed to build client route bundles.\n${errorMessage(error)}`, {
4384
- cause: error,
4385
- });
4522
+ throw new Error(
4523
+ `${routeContexts}\nFailed to build client route bundles.\n${errorMessage(error)}`,
4524
+ {
4525
+ cause: error,
4526
+ },
4527
+ );
4386
4528
  }
4387
4529
 
4388
4530
  const routeOutputs = new Map(output.routes.map((route) => [route.routePath, route]));
4389
4531
  const mapAssets = new Map(
4390
4532
  output.chunks.flatMap((chunk) =>
4391
- chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const]
4533
+ chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const],
4392
4534
  ),
4393
4535
  );
4394
4536
 
@@ -4413,9 +4555,7 @@ async function writeClientRouteBundles(options: {
4413
4555
 
4414
4556
  for (const asset of output.assets ?? []) {
4415
4557
  const source =
4416
- typeof asset.source === "string"
4417
- ? asset.source
4418
- : Buffer.from(asset.source).toString("utf8");
4558
+ typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
4419
4559
 
4420
4560
  await mkdir(dirname(join(options.clientDir, asset.fileName)), { recursive: true });
4421
4561
  await writeFile(join(options.clientDir, asset.fileName), source);
@@ -4492,12 +4632,16 @@ async function writeRouteCssAssetBatches(options: {
4492
4632
  appDir: options.appDir,
4493
4633
  pageFile: route.file,
4494
4634
  projectRoot: options.projectRoot,
4495
- readSource: (file) => buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, file)?.source,
4635
+ readSource: (file) =>
4636
+ buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, file)?.source,
4496
4637
  });
4497
4638
 
4498
4639
  return { cssFiles, route };
4499
4640
  });
4500
- const groups = new Map<string, { cssFiles: string[]; routeIds: string[]; routeFiles: string[] }>();
4641
+ const groups = new Map<
4642
+ string,
4643
+ { cssFiles: string[]; routeIds: string[]; routeFiles: string[] }
4644
+ >();
4501
4645
 
4502
4646
  for (const { cssFiles, route } of cssInputs) {
4503
4647
  if (cssFiles.length === 0) {
@@ -4511,18 +4655,22 @@ async function writeRouteCssAssetBatches(options: {
4511
4655
  groups.set(key, group);
4512
4656
  }
4513
4657
 
4514
- const writtenGroups = await mapWithBuildConcurrency([...groups.entries()], async ([key, group]) => [
4515
- key,
4516
- await writeRouteCssAssetsForFiles({
4517
- cacheDir: options.cacheDir,
4518
- clientDir: options.clientDir,
4519
- cssFiles: group.cssFiles,
4520
- pageFile: group.routeFiles[0] ?? options.appDir,
4521
- projectRoot: options.projectRoot,
4522
- routeIds: group.routeIds,
4523
- vitePlugins: options.vitePlugins,
4524
- }),
4525
- ] as const);
4658
+ const writtenGroups = await mapWithBuildConcurrency(
4659
+ [...groups.entries()],
4660
+ async ([key, group]) =>
4661
+ [
4662
+ key,
4663
+ await writeRouteCssAssetsForFiles({
4664
+ cacheDir: options.cacheDir,
4665
+ clientDir: options.clientDir,
4666
+ cssFiles: group.cssFiles,
4667
+ pageFile: group.routeFiles[0] ?? options.appDir,
4668
+ projectRoot: options.projectRoot,
4669
+ routeIds: group.routeIds,
4670
+ vitePlugins: options.vitePlugins,
4671
+ }),
4672
+ ] as const,
4673
+ );
4526
4674
  const cssByGroup = new Map(writtenGroups);
4527
4675
  const cssByRoute = new Map<string, string[]>();
4528
4676
 
@@ -4566,15 +4714,14 @@ async function writeRouteCssAssetsForFiles(options: {
4566
4714
  });
4567
4715
  const cssAssets = (output.assets ?? []).filter((asset) => asset.fileName.endsWith(".css"));
4568
4716
  const written: string[] = [];
4569
- const routeStem = options.routeIds.length === 1
4570
- ? (options.routeIds[0] ?? "index")
4571
- : `shared.${hashText(cssFiles.join("\0")).slice(0, 8)}`;
4717
+ const routeStem =
4718
+ options.routeIds.length === 1
4719
+ ? (options.routeIds[0] ?? "index")
4720
+ : `shared.${hashText(cssFiles.join("\0")).slice(0, 8)}`;
4572
4721
 
4573
4722
  for (const [index, asset] of cssAssets.entries()) {
4574
4723
  const source =
4575
- typeof asset.source === "string"
4576
- ? asset.source
4577
- : Buffer.from(asset.source).toString("utf8");
4724
+ typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
4578
4725
  const hash = createHash("sha256").update(source).digest("hex").slice(0, 8);
4579
4726
  const cssFile = `assets/routes/${routeStem}${cssAssets.length === 1 ? "" : `.${index}`}.${hash}.css`;
4580
4727
 
@@ -4752,7 +4899,9 @@ function isBarePackageImport(specifier: string): boolean {
4752
4899
 
4753
4900
  async function assertAwsLambdaRuntimeDependencies(outDir: string): Promise<void> {
4754
4901
  try {
4755
- const info = await stat(join(outDir, "node_modules", "@reckona", "mreact-router", "package.json"));
4902
+ const info = await stat(
4903
+ join(outDir, "node_modules", "@reckona", "mreact-router", "package.json"),
4904
+ );
4756
4905
  if (info.isFile()) {
4757
4906
  return;
4758
4907
  }
@@ -4845,7 +4994,9 @@ function assertPackageOutputDoesNotReplaceBuildOutput(options: {
4845
4994
  outDir: string;
4846
4995
  }): void {
4847
4996
  if (resolve(options.fromDir) === resolve(options.outDir)) {
4848
- throw new Error("Package output directory must be different from the mreact build output directory.");
4997
+ throw new Error(
4998
+ "Package output directory must be different from the mreact build output directory.",
4999
+ );
4849
5000
  }
4850
5001
  }
4851
5002
 
@@ -4909,7 +5060,9 @@ async function collectArtifactFiles(
4909
5060
  }
4910
5061
  }
4911
5062
 
4912
- return files.sort((left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path));
5063
+ return files.sort(
5064
+ (left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path),
5065
+ );
4913
5066
  }
4914
5067
 
4915
5068
  function awsLambdaHandlerSource(outDirRelativeToHandler: string): string {
@@ -4954,6 +5107,7 @@ async function validateProductionRoutes(options: {
4954
5107
  cache: options.serverTransformCache,
4955
5108
  code: analysis.routeCode,
4956
5109
  clientBoundaryImports: analysis.clientBoundaryImports,
5110
+ clientBoundaryFallbackImports: analysis.clientBoundaryFallbackImports,
4957
5111
  filename: route.file,
4958
5112
  moduleContextCache: options.clientRouteInferenceCache,
4959
5113
  serverOutput: analysis.streamRoute ? "stream" : "string",
@@ -4993,10 +5147,10 @@ async function collectBuildFiles(
4993
5147
 
4994
5148
  return [{ file, relativeFile }];
4995
5149
  });
4996
- const fileContents = await mapWithBuildConcurrency(sourceFiles, async ({ file, relativeFile }) => [
4997
- relativeFile,
4998
- await readFile(file, "utf8"),
4999
- ] as const);
5150
+ const fileContents = await mapWithBuildConcurrency(
5151
+ sourceFiles,
5152
+ async ({ file, relativeFile }) => [relativeFile, await readFile(file, "utf8")] as const,
5153
+ );
5000
5154
 
5001
5155
  for (const [relativeFile, source] of fileContents) {
5002
5156
  files[relativeFile] = source;