@reckona/mreact-router 0.0.73 → 0.0.75

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.
Files changed (47) hide show
  1. package/README.md +3 -1
  2. package/dist/actions.d.ts +14 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +55 -44
  5. package/dist/actions.js.map +1 -1
  6. package/dist/build.d.ts +12 -0
  7. package/dist/build.d.ts.map +1 -1
  8. package/dist/build.js +151 -52
  9. package/dist/build.js.map +1 -1
  10. package/dist/cli-options.d.ts +13 -0
  11. package/dist/cli-options.d.ts.map +1 -1
  12. package/dist/cli-options.js +73 -0
  13. package/dist/cli-options.js.map +1 -1
  14. package/dist/cli.js +4 -1
  15. package/dist/cli.js.map +1 -1
  16. package/dist/client.d.ts.map +1 -1
  17. package/dist/client.js +17 -8
  18. package/dist/client.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/render.d.ts +2 -1
  23. package/dist/render.d.ts.map +1 -1
  24. package/dist/render.js +4 -0
  25. package/dist/render.js.map +1 -1
  26. package/dist/route-source.d.ts +8 -0
  27. package/dist/route-source.d.ts.map +1 -1
  28. package/dist/route-source.js +15 -1
  29. package/dist/route-source.js.map +1 -1
  30. package/dist/serve.d.ts.map +1 -1
  31. package/dist/serve.js +6 -0
  32. package/dist/serve.js.map +1 -1
  33. package/dist/server-action-inference.d.ts +50 -0
  34. package/dist/server-action-inference.d.ts.map +1 -0
  35. package/dist/server-action-inference.js +488 -0
  36. package/dist/server-action-inference.js.map +1 -0
  37. package/package.json +12 -11
  38. package/src/actions.ts +92 -62
  39. package/src/build.ts +231 -71
  40. package/src/cli-options.ts +103 -0
  41. package/src/cli.ts +6 -0
  42. package/src/client.ts +14 -11
  43. package/src/index.ts +1 -0
  44. package/src/render.ts +9 -0
  45. package/src/route-source.ts +25 -0
  46. package/src/serve.ts +22 -0
  47. package/src/server-action-inference.ts +804 -0
package/src/client.ts CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  } from "./bundle-pipeline.js";
30
30
  import type { AppRoute } from "./routes.js";
31
31
  import { existingRouteShellCandidates } from "./route-shells.js";
32
- import { stripRouteClientOnlyExports } from "./route-source.js";
32
+ import { stripRouteClientSource } from "./route-source.js";
33
33
  import { hasJsxSyntax } from "./source-jsx.js";
34
34
  import { sourceModuleCandidates } from "./source-modules.js";
35
35
  import { escapeHtmlQuotedAttribute as escapeHtmlAttribute } from "@reckona/mreact-shared/html-escape";
@@ -147,7 +147,7 @@ export async function routeToClientManifestEntry(
147
147
 
148
148
  const code = await readFile(route.file, "utf8");
149
149
  const inference = await inferClientRouteModule({
150
- code: stripRouteClientOnlyExports(code),
150
+ code: stripRouteClientSource({ code, filename: route.file }),
151
151
  filename: route.file,
152
152
  routePath: route.path,
153
153
  });
@@ -311,9 +311,10 @@ export async function collectClientRouteReferences(options: {
311
311
  });
312
312
 
313
313
  for (const referenceFile of inference.clientReferenceSourceFiles) {
314
- const code = stripRouteClientOnlyExports(
315
- await readClientRouteSource({ cache, filename: referenceFile, sourceTransform }),
316
- );
314
+ const code = stripRouteClientSource({
315
+ code: await readClientRouteSource({ cache, filename: referenceFile, sourceTransform }),
316
+ filename: referenceFile,
317
+ });
317
318
  await addSource({ code, filename: referenceFile });
318
319
  }
319
320
  };
@@ -327,9 +328,10 @@ export async function collectClientRouteReferences(options: {
327
328
 
328
329
  if (options.appDir !== undefined) {
329
330
  for (const shell of await clientShellFilesForPage(options.appDir, options.filename)) {
330
- const code = stripRouteClientOnlyExports(
331
- await readClientRouteSource({ cache, filename: shell, sourceTransform }),
332
- );
331
+ const code = stripRouteClientSource({
332
+ code: await readClientRouteSource({ cache, filename: shell, sourceTransform }),
333
+ filename: shell,
334
+ });
333
335
  const moduleContext = await compilerModuleContextForSource({
334
336
  cache,
335
337
  code,
@@ -419,13 +421,14 @@ async function inferClientRouteShellModules(options: {
419
421
  }): Promise<ClientRouteInferenceResult[]> {
420
422
  return Promise.all(
421
423
  (await clientShellFilesForPage(options.appDir, options.filename)).map(async (shell) => {
422
- const code = stripRouteClientOnlyExports(
423
- await readClientRouteSource({
424
+ const code = stripRouteClientSource({
425
+ code: await readClientRouteSource({
424
426
  cache: options.cache,
425
427
  filename: shell,
426
428
  sourceTransform: options.sourceTransform,
427
429
  }),
428
- );
430
+ filename: shell,
431
+ });
429
432
  return await inferClientRouteModuleSource({
430
433
  cache: options.cache,
431
434
  code,
package/src/index.ts CHANGED
@@ -157,6 +157,7 @@ export {
157
157
  export type {
158
158
  AppRouterAllowedServerAction,
159
159
  AppRouterServerActionOptions,
160
+ PreparedFormActionReference,
160
161
  } from "./actions.js";
161
162
  /**
162
163
  * @deprecated Import session helpers and types from `@reckona/mreact-auth` instead.
package/src/render.ts CHANGED
@@ -45,6 +45,7 @@ import type { AppRoute, RouteMatcher } from "./routes.js";
45
45
  import { appFileConventionContentType, type AppFileConvention } from "./file-conventions.js";
46
46
  import {
47
47
  type AppRouterServerActionOptions,
48
+ type PreparedFormActionReference,
48
49
  dispatchServerActionRequest,
49
50
  prepareRouteServerActions,
50
51
  } from "./actions.js";
@@ -148,6 +149,10 @@ export interface RenderAppRequestOptions {
148
149
  serverModuleCacheVersion?: string | undefined;
149
150
  serverSourceFiles?: ReadonlyMap<string, string> | undefined;
150
151
  serverActions?: AppRouterServerActionOptions | undefined;
152
+ serverActionReferencesByFile?: ReadonlyMap<
153
+ string,
154
+ readonly PreparedFormActionReference[]
155
+ > | undefined;
151
156
  skipMiddleware?: boolean | undefined;
152
157
  preload?: AppRouterRenderPreload | undefined;
153
158
  vitePlugins?: readonly PluginOption[] | undefined;
@@ -904,9 +909,13 @@ async function renderAppRequestInternal(options: RenderAppRequestOptions): Promi
904
909
  const preparedActions = await prepareRouteServerActions({
905
910
  appDir: options.appDir,
906
911
  code: originalCode,
912
+ formActionReferences: options.serverActionReferencesByFile?.get(matched.route.file),
907
913
  pageFile: matched.route.file,
908
914
  request: options.request,
909
915
  });
916
+ for (const diagnostic of preparedActions.diagnostics ?? []) {
917
+ console.warn(`${diagnostic.code}: ${diagnostic.message}`);
918
+ }
910
919
  finishRenderTimingPhase(timing, phaseStartedAt, "serverActionsMs");
911
920
  const code = preparedActions.code;
912
921
  phaseStartedAt = renderTimingPhaseStartedAt(timing);
@@ -1,5 +1,6 @@
1
1
  import { dirname, isAbsolute, join } from "node:path";
2
2
  import {
3
+ collectFormActionExpressionReferences,
3
4
  collectTopLevelValueExportNames,
4
5
  collectJsxComponentRootNames,
5
6
  collectStaticImportReferences,
@@ -49,6 +50,30 @@ export function stripRouteClientOnlyExports(code: string): string {
49
50
  }));
50
51
  }
51
52
 
53
+ export function stripRouteClientSource(input: {
54
+ code: string;
55
+ filename?: string | undefined;
56
+ }): string {
57
+ return stripRouteClientFormActionExpressions({
58
+ code: stripRouteClientOnlyExports(input.code),
59
+ filename: input.filename,
60
+ });
61
+ }
62
+
63
+ export function stripRouteClientFormActionExpressions(input: {
64
+ code: string;
65
+ filename?: string | undefined;
66
+ }): string {
67
+ const references = collectFormActionExpressionReferences(input);
68
+ let code = input.code;
69
+
70
+ for (const reference of [...references].reverse()) {
71
+ code = `${code.slice(0, reference.expressionStart)}undefined${code.slice(reference.expressionEnd)}`;
72
+ }
73
+
74
+ return code;
75
+ }
76
+
52
77
  export function stripRouteBuildExports(code: string): string {
53
78
  return stripRouteClientOnlyExports(code);
54
79
  }
package/src/serve.ts CHANGED
@@ -50,6 +50,20 @@ interface BuiltRuntime {
50
50
  prerenderedRoutes: Map<string, BuiltPrerenderedRoute>;
51
51
  routeMatcher: RouteMatcher;
52
52
  routes: readonly AppRoute[];
53
+ serverActionReferencesByFile: ReadonlyMap<
54
+ string,
55
+ readonly {
56
+ end: number;
57
+ expression: string;
58
+ expressionEnd: number;
59
+ expressionStart: number;
60
+ moduleId: string;
61
+ exportName: string;
62
+ inferred: boolean;
63
+ sourceHash: string;
64
+ start: number;
65
+ }[]
66
+ >;
53
67
  serverActionManifest?: readonly { moduleId: string; exportName: string; inferred?: boolean }[] | undefined;
54
68
  serverModuleArtifactLoads: Map<string, Promise<void>>;
55
69
  serverModuleFiles: ReadonlyMap<string, string>;
@@ -701,6 +715,12 @@ async function materializeBuiltRuntime(options: {
701
715
  const serverSourceFiles = new Map(
702
716
  Object.entries(serverManifest.files).map(([file, source]) => [join(appDir, file), source]),
703
717
  );
718
+ const serverActionReferencesByFile = new Map(
719
+ Object.entries(serverManifest.routeServerActionReferences ?? {}).map(([file, references]) => [
720
+ join(appDir, file),
721
+ references,
722
+ ]),
723
+ );
704
724
  const routeMatcher = createRouteMatcher(routes);
705
725
  const clientScripts = new Map(
706
726
  clientManifest.routes.flatMap((route) =>
@@ -752,6 +772,7 @@ async function materializeBuiltRuntime(options: {
752
772
  prerenderedRoutes,
753
773
  routeMatcher,
754
774
  routes,
775
+ serverActionReferencesByFile,
755
776
  ...(serverManifest.serverActionManifest === undefined
756
777
  ? {}
757
778
  : { serverActionManifest: serverManifest.serverActionManifest }),
@@ -1070,6 +1091,7 @@ function builtRenderAppRequestOptions(
1070
1091
  serverModules: options.runtime.serverModules,
1071
1092
  serverModuleCacheVersion: options.runtime.serverModuleCacheVersion,
1072
1093
  serverSourceFiles: options.runtime.serverSourceFiles,
1094
+ serverActionReferencesByFile: options.runtime.serverActionReferencesByFile,
1073
1095
  serverActions: mergeBuiltServerActionOptions(
1074
1096
  options.serverActions,
1075
1097
  options.runtime.serverActionManifest,