@reckona/mreact-router 0.0.95 → 0.0.97

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
@@ -1132,7 +1132,7 @@ async function buildServerModuleArtifacts(options: {
1132
1132
  loaderArtifactFiles.add(file);
1133
1133
  }
1134
1134
 
1135
- if (hasMetadataExport(source)) {
1135
+ if (isServerComponentFile(file) && hasMetadataExport(source)) {
1136
1136
  metadataArtifactFiles.add(file);
1137
1137
  }
1138
1138
  }
@@ -1150,7 +1150,7 @@ async function buildServerModuleArtifacts(options: {
1150
1150
  if (loaderArtifactFiles.has(file)) {
1151
1151
  const code = await bundleRouteLoaderModuleCode({
1152
1152
  appDir: options.project.routesDir,
1153
- code: stripRouteLoaderOnlyExports(source),
1153
+ code: stripRouteLoaderOnlyExports(source, absoluteFile),
1154
1154
  filename: absoluteFile,
1155
1155
  importPolicy: requestModuleImportPolicy,
1156
1156
  vitePlugins: options.vitePlugins,
@@ -1164,7 +1164,7 @@ async function buildServerModuleArtifacts(options: {
1164
1164
  if (metadataArtifactFiles.has(file)) {
1165
1165
  const code = await bundleRouteMetadataModuleCode({
1166
1166
  appDir: options.project.routesDir,
1167
- code: stripRouteMetadataOnlyExports(source),
1167
+ code: stripRouteMetadataOnlyExports(source, absoluteFile),
1168
1168
  filename: absoluteFile,
1169
1169
  importPolicy: requestModuleImportPolicy,
1170
1170
  vitePlugins: options.vitePlugins,
@@ -1208,13 +1208,13 @@ async function buildServerModuleArtifacts(options: {
1208
1208
  streamRoute || (route === undefined && closureUsesAwait)
1209
1209
  ? (["stream", "string"] as const)
1210
1210
  : (["string"] as const);
1211
- const code = route === undefined ? source : stripRouteBuildExports(source);
1211
+ const code = route === undefined ? source : stripRouteBuildExports(source, absoluteFile);
1212
1212
  const clientInference = await inferClientRouteModule({
1213
1213
  ...(route === undefined ? {} : { appDir: options.project.routesDir }),
1214
1214
  cache: options.clientRouteInferenceCache,
1215
1215
  code:
1216
1216
  route === undefined
1217
- ? stripRouteClientOnlyExports(source)
1217
+ ? stripRouteClientOnlyExports(source, absoluteFile)
1218
1218
  : stripRouteClientSource({ code: source, filename: route.file }),
1219
1219
  filename: join(options.projectRoot, file),
1220
1220
  ...(route === undefined ? {} : { routePath: route.path }),
@@ -1413,7 +1413,7 @@ async function buildRequestModuleArtifactCode(options: {
1413
1413
 
1414
1414
  return await bundleRouteLoaderModuleCode({
1415
1415
  appDir: options.appDir,
1416
- code: stripRouteRequestOnlyExports(options.source),
1416
+ code: stripRouteRequestOnlyExports(options.source, options.filename),
1417
1417
  filename: options.filename,
1418
1418
  importPolicy: options.importPolicy,
1419
1419
  vitePlugins: options.vitePlugins,
@@ -2271,7 +2271,7 @@ async function bundleCloudflareModule(options: {
2271
2271
  code: options.entry,
2272
2272
  filename: options.filename,
2273
2273
  minify: true,
2274
- platform: "browser",
2274
+ platform: "node",
2275
2275
  preserveExports: true,
2276
2276
  plugins: options.plugins,
2277
2277
  target: "es2022",
@@ -2371,7 +2371,9 @@ function cloudflareServerSourceTransformPlugin(options: {
2371
2371
  }
2372
2372
 
2373
2373
  const source = await readFile(args.path, "utf8");
2374
- const serverSource = isServerComponentFile(args.path) ? stripRouteBuildExports(source) : source;
2374
+ const serverSource = isServerComponentFile(args.path)
2375
+ ? stripRouteBuildExports(source, args.path)
2376
+ : source;
2375
2377
  const sourceHash = hashText(serverSource);
2376
2378
  const routeFile = relative(options.projectRoot, args.path).replaceAll(sep, "/");
2377
2379
  const artifact = options.serverModules[routeFile]?.[options.serverOutput];
@@ -2663,6 +2665,7 @@ async function writeClientRouteBundles(options: {
2663
2665
  code: source,
2664
2666
  filename: route.file,
2665
2667
  references,
2668
+ vitePlugins: options.vitePlugins,
2666
2669
  });
2667
2670
 
2668
2671
  for (const diagnostic of references.diagnostics) {
@@ -3158,7 +3161,7 @@ async function validateProductionRoutes(options: {
3158
3161
  const source = await readFile(route.file, "utf8");
3159
3162
  const filename = relative(options.projectRoot, route.file);
3160
3163
  const output = transform({
3161
- code: stripRouteBuildExports(source),
3164
+ code: stripRouteBuildExports(source, route.file),
3162
3165
  dev: false,
3163
3166
  filename: route.file,
3164
3167
  serverEscape: nativeEscapeTransform,
@@ -370,6 +370,24 @@ function mreactJsxRuntimeAliasPlugin(): VitePlugin {
370
370
  packageName: "@reckona/mreact-compat",
371
371
  }),
372
372
  ],
373
+ [
374
+ "@reckona/mreact/jsx-dev-runtime",
375
+ workspacePackageFile({
376
+ currentFileUrl: import.meta.url,
377
+ entry: "jsx-dev-runtime",
378
+ monorepoDir: "react",
379
+ packageName: "@reckona/mreact",
380
+ }),
381
+ ],
382
+ [
383
+ "@reckona/mreact/jsx-runtime",
384
+ workspacePackageFile({
385
+ currentFileUrl: import.meta.url,
386
+ entry: "jsx-runtime",
387
+ monorepoDir: "react",
388
+ packageName: "@reckona/mreact",
389
+ }),
390
+ ],
373
391
  [
374
392
  "@reckona/mreact-compat/hooks",
375
393
  workspacePackageFile({
package/src/client.ts CHANGED
@@ -520,11 +520,17 @@ export async function resolveNavigationRuntime(options: {
520
520
  vitePlugins?: readonly PluginOption[] | undefined;
521
521
  }): Promise<boolean> {
522
522
  const cache = options.cache ?? createClientRouteInferenceCache();
523
+ const sourceTransform = clientRouteSourceTransformForVitePlugins(options.vitePlugins);
524
+ const code = await transformClientRouteSource({
525
+ code: options.code,
526
+ filename: options.filename,
527
+ sourceTransform,
528
+ });
523
529
  // Read the override from the cached module context so the dev server does not
524
530
  // re-parse every page route on each request.
525
531
  const moduleContext = await compilerModuleContextForSource({
526
532
  cache,
527
- code: options.code,
533
+ code,
528
534
  filename: options.filename,
529
535
  });
530
536
  const override = readTopLevelBooleanExportFromContext(moduleContext, "navigationRuntime");
@@ -2081,6 +2087,10 @@ export async function __mreactPrefetch(url) {
2081
2087
  return false;
2082
2088
  }
2083
2089
 
2090
+ if (!__mreactIsSameOriginNavigationUrl(href)) {
2091
+ return false;
2092
+ }
2093
+
2084
2094
  const script = __mreactRouteScriptForNavigationUrl(href);
2085
2095
 
2086
2096
  if (script === undefined) {
@@ -2666,6 +2676,18 @@ function __mreactNormalizeNavigationUrl(url) {
2666
2676
  }
2667
2677
  }
2668
2678
 
2679
+ function __mreactIsSameOriginNavigationUrl(url) {
2680
+ if (typeof location === "undefined") {
2681
+ return true;
2682
+ }
2683
+
2684
+ try {
2685
+ return new URL(url, location.href).origin === location.origin;
2686
+ } catch {
2687
+ return false;
2688
+ }
2689
+ }
2690
+
2669
2691
  function __mreactNormalizeAssetUrl(url) {
2670
2692
  if (typeof location === "undefined") {
2671
2693
  return typeof url === "string" ? url : undefined;
package/src/render.ts CHANGED
@@ -2525,7 +2525,7 @@ async function analyzeRouteSourceUncached(options: {
2525
2525
  serverSourceFiles?: ReadonlyMap<string, string> | undefined;
2526
2526
  vitePlugins?: readonly PluginOption[] | undefined;
2527
2527
  }): Promise<RouteSourceAnalysis> {
2528
- const routeCode = stripRouteModuleExports(options.code);
2528
+ const routeCode = stripRouteModuleExports(options.code, options.filename);
2529
2529
  const clientInference = await inferClientRouteModule({
2530
2530
  appDir: options.appDir,
2531
2531
  cache: options.clientRouteInferenceCache,
@@ -3464,7 +3464,7 @@ async function renderShellPrefixSuffix(
3464
3464
  ? { client: false, clientBoundaryImports: [], diagnostics: [] }
3465
3465
  : await inferClientRouteModule({
3466
3466
  cache: clientRouteInferenceCache,
3467
- code: stripRouteClientOnlyExports(code),
3467
+ code: stripRouteClientOnlyExports(code, shell.file),
3468
3468
  filename: shell.file,
3469
3469
  vitePlugins,
3470
3470
  });
@@ -3967,7 +3967,7 @@ export async function bundleRouteLoaderModuleCode(options: {
3967
3967
  vitePlugins?: readonly PluginOption[] | undefined;
3968
3968
  }): Promise<string> {
3969
3969
  const output = await bundleRouterModule({
3970
- code: stripRouteLoaderOnlyExports(options.code),
3970
+ code: stripRouteLoaderOnlyExports(options.code, options.filename),
3971
3971
  externalizeAppSourceModuleDirs: options.externalizeAppSourceModuleDirs,
3972
3972
  filename: options.filename,
3973
3973
  platform: "node",
@@ -4111,7 +4111,7 @@ async function bundleRouteMetadataModuleCode(options: {
4111
4111
  vitePlugins?: readonly PluginOption[] | undefined;
4112
4112
  }): Promise<string> {
4113
4113
  const output = await bundleRouterModule({
4114
- code: stripRouteMetadataOnlyExports(options.code),
4114
+ code: stripRouteMetadataOnlyExports(options.code, options.filename),
4115
4115
  filename: options.filename,
4116
4116
  platform: "node",
4117
4117
  vitePlugins: options.vitePlugins,
@@ -37,21 +37,26 @@ const routeRequestExportNames = new Set<string>([
37
37
  const routeLoaderOnlyExportNames = new Set<string>(["loader"]);
38
38
  const routeMetadataOnlyExportNames = new Set<string>(["generateMetadata", "metadata"]);
39
39
 
40
- export function stripRouteModuleExports(code: string): string {
40
+ export function stripRouteModuleExports(code: string, filename?: string | undefined): string {
41
41
  return demoteRouteHelperExports(stripTopLevelExportDeclarations({
42
42
  code,
43
+ filename,
43
44
  names: routeModuleExportNames,
44
- }));
45
+ }), routeRenderExportNames, filename);
45
46
  }
46
47
 
47
- export function stripRouteClientOnlyExports(code: string): string {
48
+ export function stripRouteClientOnlyExports(code: string, filename?: string | undefined): string {
48
49
  return stripUnusedStaticValueImports({
49
50
  code: demoteRouteHelperExports(
50
51
  stripTopLevelExportDeclarations({
51
52
  code,
53
+ filename,
52
54
  names: routeClientOnlyExportNames,
53
55
  }),
56
+ routeRenderExportNames,
57
+ filename,
54
58
  ),
59
+ filename,
55
60
  });
56
61
  }
57
62
 
@@ -60,7 +65,7 @@ export function stripRouteClientSource(input: {
60
65
  filename?: string | undefined;
61
66
  }): string {
62
67
  return stripRouteClientFormActionExpressions({
63
- code: stripRouteClientOnlyExports(input.code),
68
+ code: stripRouteClientOnlyExports(input.code, input.filename),
64
69
  filename: input.filename,
65
70
  });
66
71
  }
@@ -79,43 +84,50 @@ export function stripRouteClientFormActionExpressions(input: {
79
84
  return code;
80
85
  }
81
86
 
82
- export function stripRouteBuildExports(code: string): string {
83
- return stripRouteClientOnlyExports(code);
87
+ export function stripRouteBuildExports(code: string, filename?: string | undefined): string {
88
+ return stripRouteClientOnlyExports(code, filename);
84
89
  }
85
90
 
86
- export function stripRouteRequestOnlyExports(code: string): string {
91
+ export function stripRouteRequestOnlyExports(code: string, filename?: string | undefined): string {
87
92
  return demoteRouteHelperExports(
88
93
  stripTopLevelExportDeclarations({
89
94
  code,
95
+ filename,
90
96
  names: routeRequestRenderExportNames,
91
97
  }),
92
98
  routeRequestExportNames,
99
+ filename,
93
100
  );
94
101
  }
95
102
 
96
- export function stripRouteLoaderOnlyExports(code: string): string {
103
+ export function stripRouteLoaderOnlyExports(code: string, filename?: string | undefined): string {
97
104
  return demoteRouteHelperExports(
98
105
  stripTopLevelExportDeclarations({
99
106
  code,
107
+ filename,
100
108
  names: ["auth", "default", "generateMetadata", "generateStaticParams", "metadata", "middleware", "prerender", "revalidate", "slots", "stream"],
101
109
  }),
102
110
  routeLoaderOnlyExportNames,
111
+ filename,
103
112
  );
104
113
  }
105
114
 
106
- export function stripRouteMetadataOnlyExports(code: string): string {
115
+ export function stripRouteMetadataOnlyExports(code: string, filename?: string | undefined): string {
107
116
  return demoteRouteHelperExports(
108
117
  stripTopLevelExportDeclarations({
109
118
  code,
119
+ filename,
110
120
  names: ["auth", "default", "generateStaticParams", "loader", "middleware", "prerender", "revalidate", "slots", "stream"],
111
121
  }),
112
122
  routeMetadataOnlyExportNames,
123
+ filename,
113
124
  );
114
125
  }
115
126
 
116
- export function stripRouteConfigExports(code: string): string {
127
+ export function stripRouteConfigExports(code: string, filename?: string | undefined): string {
117
128
  return stripTopLevelExportDeclarations({
118
129
  code,
130
+ filename,
119
131
  names: ["auth", "prerender", "revalidate", "stream"],
120
132
  });
121
133
  }
@@ -209,13 +221,14 @@ export function hasLoaderExport(code: string): boolean {
209
221
  function demoteRouteHelperExports(
210
222
  code: string,
211
223
  preservedExportNames: ReadonlySet<string> = routeRenderExportNames,
224
+ filename?: string | undefined,
212
225
  ): string {
213
- const helperNames = collectTopLevelValueExportNames({ code })
226
+ const helperNames = collectTopLevelValueExportNames({ code, filename })
214
227
  .filter((name) => !preservedExportNames.has(name) && startsLowercase(name));
215
228
 
216
229
  return helperNames.length === 0
217
230
  ? code
218
- : demoteTopLevelExportDeclarations({ code, names: helperNames });
231
+ : demoteTopLevelExportDeclarations({ code, filename, names: helperNames });
219
232
  }
220
233
 
221
234
  function startsLowercase(value: string): boolean {
package/src/vite.ts CHANGED
@@ -176,7 +176,7 @@ export function createAppRouterVitePlugin(options: AppRouterVitePluginOptions):
176
176
  enforce: "pre",
177
177
  name: "mreact-router",
178
178
  config(userConfig) {
179
- userVitePlugins = userConfig.plugins;
179
+ userVitePlugins = routeTransformUserVitePlugins(userConfig.plugins);
180
180
 
181
181
  return {
182
182
  optimizeDeps: {
@@ -197,7 +197,7 @@ export function createAppRouterVitePlugin(options: AppRouterVitePluginOptions):
197
197
  return () => {
198
198
  const middlewareOptions: AppRouterViteRuntimeMiddlewareOptions = {
199
199
  ...options,
200
- navigationScanVitePlugins: userVitePlugins,
200
+ navigationScanVitePlugins: userVitePlugins ?? [],
201
201
  viteDevServer: server,
202
202
  vitePlugins: server.config.plugins,
203
203
  };
@@ -370,6 +370,40 @@ function isCompatSourcePath(filename: string): boolean {
370
370
 
371
371
  export const mreactRouter = createAppRouterVitePlugin;
372
372
 
373
+ function routeTransformUserVitePlugins(
374
+ pluginOptions: readonly PluginOption[] | undefined,
375
+ ): PluginOption[] {
376
+ const plugins: PluginOption[] = [];
377
+ const visit = (option: PluginOption | null | false | undefined): void => {
378
+ if (option === false || option === null || option === undefined) {
379
+ return;
380
+ }
381
+
382
+ if (Array.isArray(option)) {
383
+ for (const child of option) {
384
+ visit(child);
385
+ }
386
+ return;
387
+ }
388
+
389
+ if (typeof option === "object" && "then" in option) {
390
+ return;
391
+ }
392
+
393
+ if (typeof option === "object" && mreactRouterConfigKey in option) {
394
+ return;
395
+ }
396
+
397
+ plugins.push(option);
398
+ };
399
+
400
+ for (const option of pluginOptions ?? []) {
401
+ visit(option);
402
+ }
403
+
404
+ return plugins;
405
+ }
406
+
373
407
  export function mreactRouterConfigFromPlugins(
374
408
  plugins: readonly unknown[],
375
409
  ): ResolvedAppRouterProject | undefined {
@@ -450,6 +484,7 @@ async function handleAppRouterViteRequest(
450
484
  }
451
485
 
452
486
  const request = nodeRequestToWebRequest(incoming, origin);
487
+ const routeTransformPlugins = options.navigationScanVitePlugins ?? options.vitePlugins;
453
488
 
454
489
  await sendResponse(
455
490
  outgoing,
@@ -464,11 +499,12 @@ async function handleAppRouterViteRequest(
464
499
  navigationScripts: await devNavigationScripts(
465
500
  project.routesDir,
466
501
  options.clientRouteInferenceCache,
467
- options.navigationScanVitePlugins,
502
+ routeTransformPlugins,
468
503
  ),
469
504
  request,
470
505
  routeCache: options.routeCache,
471
506
  serverActions: options.serverActions,
507
+ vitePlugins: routeTransformPlugins,
472
508
  }),
473
509
  );
474
510
  } catch (error) {
@@ -501,7 +537,7 @@ export async function renderAppRouterClientAsset(
501
537
  }
502
538
 
503
539
  const code = await readFile(route.file, "utf8");
504
- const clientSource = stripRouteClientOnlyExports(code);
540
+ const clientSource = stripRouteClientOnlyExports(code, route.file);
505
541
  let references: Awaited<ReturnType<typeof collectClientRouteReferences>>;
506
542
 
507
543
  try {
@@ -565,7 +601,7 @@ async function renderAppRouterClientRouteDevModule(
565
601
  }
566
602
 
567
603
  const code = await readFile(route.file, "utf8");
568
- const clientSource = stripRouteClientOnlyExports(code);
604
+ const clientSource = stripRouteClientOnlyExports(code, route.file);
569
605
  const references = await collectClientRouteReferences({
570
606
  appDir,
571
607
  code: clientSource,