@reckona/mreact-router 0.0.196 → 0.0.198
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/README.md +3 -1
- package/dist/boundaries.d.ts +66 -0
- package/dist/boundaries.d.ts.map +1 -0
- package/dist/boundaries.js +168 -0
- package/dist/boundaries.js.map +1 -0
- package/dist/build.d.ts +3 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +18 -1
- package/dist/build.js.map +1 -1
- package/dist/cli-options.d.ts +1 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +30 -0
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/client-route-inference.d.ts +1 -1
- package/dist/client-route-inference.d.ts.map +1 -1
- package/dist/client-route-inference.js.map +1 -1
- package/dist/client.d.ts +11 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +411 -22
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/boundaries.ts +285 -0
- package/src/build.ts +25 -1
- package/src/cli-options.ts +36 -1
- package/src/cli.ts +23 -0
- package/src/client-route-inference.ts +3 -0
- package/src/client.ts +647 -40
- package/src/index.ts +24 -5
package/README.md
CHANGED
|
@@ -53,7 +53,9 @@ export default defineConfig({
|
|
|
53
53
|
|
|
54
54
|
`mreact-router build` reads this config. Pass `--target=node` for plain Node/container output, `--target=aws-lambda` for Lambda artifacts with a generated handler and import policy, or `--target=cloudflare` for Workers artifacts with a generated Worker module. Configure `buildTargets: ["aws-lambda"]`, `["cloudflare"]`, or another explicit target list in `mreactRouter()` when one deployment target should be the project default. Without an explicit target, build output includes only the Node-compatible server/client artifacts; Cloudflare and Lambda artifacts are opt-in. The legacy `appDir` shortcut remains available for tests and older direct programmatic usage, but it is deprecated. Use `projectRoot` + `routesDir` for new code. The shortcut is planned for removal after `0.1.0`.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
Run `mreact-router boundaries` to inspect every route and its statically traceable rendered server and client components without writing build artifacts. The command loads the same Vite project configuration as `build`; pass an explicit app directory for the legacy direct-directory mode, or add `--json` for a deterministic versioned report with project-relative paths.
|
|
57
|
+
|
|
58
|
+
Production builds print the same full route-by-route component boundary report alongside route discovery, server output, client output, artifact writing, and the final route count with total duration. Programmatic builds can pass `onBoundaryReport` to receive the normalized report and `onBuildProgress` to receive coarse phase events without parsing CLI output.
|
|
57
59
|
|
|
58
60
|
Production client source maps are disabled by default. Set `clientSourceMaps: "linked"` to emit public `.js.map` files beside route scripts and include `sourceMappingURL` comments, or set `clientSourceMaps: "hidden"` to emit upload-only maps under `.mreact/source-maps/client/` without exposing them in the client manifest. The CLI accepts the same modes with `mreact-router build --client-source-maps=hidden`, `linked`, or `none`.
|
|
59
61
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { UserConfig } from "vite";
|
|
2
|
+
import type { ClientRouteComponent, ClientRouteComponentClassification, ClientRouteComponentOrigin, ClientRouteInferenceDiagnostic } from "./client-route-inference.js";
|
|
3
|
+
import { type AppRouterProjectOptions } from "./config.js";
|
|
4
|
+
/**
|
|
5
|
+
* Describes one statically traced component in a route boundary report.
|
|
6
|
+
*/
|
|
7
|
+
export interface BoundaryReportComponent {
|
|
8
|
+
classification: ClientRouteComponentClassification;
|
|
9
|
+
exportName: string;
|
|
10
|
+
file: string;
|
|
11
|
+
origin: ClientRouteComponentOrigin;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Describes the rendered component boundary graph for one page route.
|
|
15
|
+
*/
|
|
16
|
+
export interface BoundaryReportRoute {
|
|
17
|
+
classification: "client-route" | "server-render";
|
|
18
|
+
components: readonly BoundaryReportComponent[];
|
|
19
|
+
entry: string;
|
|
20
|
+
path: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Counts route and component classifications across a boundary report.
|
|
24
|
+
*/
|
|
25
|
+
export interface BoundaryReportSummary {
|
|
26
|
+
clientBoundaries: number;
|
|
27
|
+
clientRoutes: number;
|
|
28
|
+
serverOnlyComponents: number;
|
|
29
|
+
serverRenderComponents: number;
|
|
30
|
+
serverRenderRoutes: number;
|
|
31
|
+
sharedComponents: number;
|
|
32
|
+
unknownComponents: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Contains a deterministic, versioned snapshot of app-router component boundaries.
|
|
36
|
+
*/
|
|
37
|
+
export interface BoundaryReport {
|
|
38
|
+
diagnostics: readonly ClientRouteInferenceDiagnostic[];
|
|
39
|
+
routes: readonly BoundaryReportRoute[];
|
|
40
|
+
summary: BoundaryReportSummary;
|
|
41
|
+
version: 1;
|
|
42
|
+
}
|
|
43
|
+
export interface CreateBoundaryReportRouteInput {
|
|
44
|
+
components: readonly ClientRouteComponent[];
|
|
45
|
+
diagnostics: readonly ClientRouteInferenceDiagnostic[];
|
|
46
|
+
entry: string;
|
|
47
|
+
path: string;
|
|
48
|
+
}
|
|
49
|
+
export interface CreateBoundaryReportInput {
|
|
50
|
+
projectRoot: string;
|
|
51
|
+
routes: readonly CreateBoundaryReportRouteInput[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Supplies project and Vite settings for standalone boundary analysis.
|
|
55
|
+
*/
|
|
56
|
+
export interface AnalyzeAppBoundariesOptions extends AppRouterProjectOptions {
|
|
57
|
+
viteConfig?: Pick<UserConfig, "define" | "plugins"> | undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Inspects every page route without writing build artifacts or executing application code.
|
|
61
|
+
*/
|
|
62
|
+
export declare function analyzeAppBoundaries(options: AnalyzeAppBoundariesOptions): Promise<BoundaryReport>;
|
|
63
|
+
export declare function createBoundaryReport(input: CreateBoundaryReportInput): BoundaryReport;
|
|
64
|
+
export declare function formatBoundaryReport(report: BoundaryReport): string;
|
|
65
|
+
export declare function formatBoundaryReportJson(report: BoundaryReport): string;
|
|
66
|
+
//# sourceMappingURL=boundaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.d.ts","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EACV,oBAAoB,EACpB,kCAAkC,EAClC,0BAA0B,EAC1B,8BAA8B,EAC/B,MAAM,6BAA6B,CAAC;AAKrC,OAAO,EAAkC,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAI3F;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,kCAAkC,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,0BAA0B,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,GAAG,eAAe,CAAC;IACjD,UAAU,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,SAAS,8BAA8B,EAAE,CAAC;IACvD,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvC,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC5C,WAAW,EAAE,SAAS,8BAA8B,EAAE,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,8BAA8B,EAAE,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,2BAA4B,SAAQ,uBAAuB;IAC1E,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACjE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,cAAc,CAAC,CAgCzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,cAAc,CAgDrF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAqCnE;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEvE"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { relative, sep } from "node:path";
|
|
3
|
+
import { createClientRouteInferenceCache, inferClientRouteModule, } from "./client-route-inference.js";
|
|
4
|
+
import { resolveAppRouterProjectOptions } from "./config.js";
|
|
5
|
+
import { stripRouteClientSource } from "./route-source.js";
|
|
6
|
+
import { scanAppRoutes } from "./routes.js";
|
|
7
|
+
/**
|
|
8
|
+
* Inspects every page route without writing build artifacts or executing application code.
|
|
9
|
+
*/
|
|
10
|
+
export async function analyzeAppBoundaries(options) {
|
|
11
|
+
const project = resolveAppRouterProjectOptions(options);
|
|
12
|
+
const routes = (await scanAppRoutes({ appDir: project.routesDir })).filter((route) => route.kind === "page");
|
|
13
|
+
const cache = createClientRouteInferenceCache();
|
|
14
|
+
const analyzedRoutes = await Promise.all(routes.map(async (route) => {
|
|
15
|
+
const source = await readFile(route.file, "utf8");
|
|
16
|
+
const inference = await inferClientRouteModule({
|
|
17
|
+
appDir: project.routesDir,
|
|
18
|
+
cache,
|
|
19
|
+
code: stripRouteClientSource({ code: source, filename: route.file }),
|
|
20
|
+
collectComponents: true,
|
|
21
|
+
filename: route.file,
|
|
22
|
+
routePath: route.path,
|
|
23
|
+
vitePlugins: options.viteConfig?.plugins,
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
components: inference.components ?? [],
|
|
27
|
+
diagnostics: inference.diagnostics,
|
|
28
|
+
entry: route.file,
|
|
29
|
+
path: route.path,
|
|
30
|
+
};
|
|
31
|
+
}));
|
|
32
|
+
return createBoundaryReport({
|
|
33
|
+
projectRoot: project.projectRoot,
|
|
34
|
+
routes: analyzedRoutes,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function createBoundaryReport(input) {
|
|
38
|
+
const routes = input.routes
|
|
39
|
+
.map((route) => {
|
|
40
|
+
const entry = projectRelativePath(input.projectRoot, route.entry);
|
|
41
|
+
const components = normalizeComponents(input.projectRoot, entry, route.components);
|
|
42
|
+
return {
|
|
43
|
+
classification: components.some((component) => component.file === entry &&
|
|
44
|
+
component.exportName === "default" &&
|
|
45
|
+
component.classification === "client-route")
|
|
46
|
+
? "client-route"
|
|
47
|
+
: "server-render",
|
|
48
|
+
components,
|
|
49
|
+
entry,
|
|
50
|
+
path: route.path,
|
|
51
|
+
};
|
|
52
|
+
})
|
|
53
|
+
.sort((left, right) => left.path === right.path
|
|
54
|
+
? left.entry.localeCompare(right.entry)
|
|
55
|
+
: left.path.localeCompare(right.path));
|
|
56
|
+
const diagnostics = input.routes
|
|
57
|
+
.flatMap((route) => route.diagnostics)
|
|
58
|
+
.map((diagnostic) => {
|
|
59
|
+
const filename = projectRelativePath(input.projectRoot, diagnostic.filename);
|
|
60
|
+
return {
|
|
61
|
+
...diagnostic,
|
|
62
|
+
filename,
|
|
63
|
+
message: diagnostic.message.split(diagnostic.filename).join(filename),
|
|
64
|
+
};
|
|
65
|
+
})
|
|
66
|
+
.sort((left, right) => left.filename === right.filename
|
|
67
|
+
? left.code.localeCompare(right.code)
|
|
68
|
+
: left.filename.localeCompare(right.filename));
|
|
69
|
+
return {
|
|
70
|
+
diagnostics,
|
|
71
|
+
routes,
|
|
72
|
+
summary: summarizeBoundaryRoutes(routes),
|
|
73
|
+
version: 1,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function formatBoundaryReport(report) {
|
|
77
|
+
const lines = ["Boundaries:"];
|
|
78
|
+
for (const route of report.routes) {
|
|
79
|
+
lines.push(` ${route.path} [${route.classification}]`);
|
|
80
|
+
for (const component of route.components) {
|
|
81
|
+
lines.push(` ${component.file}#${component.exportName} ${component.classification}${formatComponentOrigin(component.origin)}`);
|
|
82
|
+
}
|
|
83
|
+
lines.push("");
|
|
84
|
+
}
|
|
85
|
+
if (report.diagnostics.length > 0) {
|
|
86
|
+
lines.push("Warnings:");
|
|
87
|
+
for (const diagnostic of report.diagnostics) {
|
|
88
|
+
lines.push(` ${diagnostic.code}: ${diagnostic.message}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push("");
|
|
91
|
+
}
|
|
92
|
+
const summary = report.summary;
|
|
93
|
+
lines.push([
|
|
94
|
+
`Summary: ${summary.serverRenderRoutes} ${plural(summary.serverRenderRoutes, "server-render route")}`,
|
|
95
|
+
`${summary.clientRoutes} ${plural(summary.clientRoutes, "client route")}`,
|
|
96
|
+
`${summary.clientBoundaries} ${plural(summary.clientBoundaries, "client boundary")}`,
|
|
97
|
+
`${summary.serverRenderComponents} ${plural(summary.serverRenderComponents, "server-render component")}`,
|
|
98
|
+
`${summary.serverOnlyComponents} ${plural(summary.serverOnlyComponents, "server-only component")}`,
|
|
99
|
+
`${summary.sharedComponents} ${plural(summary.sharedComponents, "shared component")}`,
|
|
100
|
+
`${summary.unknownComponents} ${plural(summary.unknownComponents, "unknown component")}`,
|
|
101
|
+
].join(", "));
|
|
102
|
+
return `${lines.join("\n")}\n`;
|
|
103
|
+
}
|
|
104
|
+
export function formatBoundaryReportJson(report) {
|
|
105
|
+
return `${JSON.stringify(report, null, 2)}\n`;
|
|
106
|
+
}
|
|
107
|
+
function normalizeComponents(projectRoot, entry, components) {
|
|
108
|
+
const unique = new Map();
|
|
109
|
+
for (const component of components) {
|
|
110
|
+
const normalized = {
|
|
111
|
+
...component,
|
|
112
|
+
file: projectRelativePath(projectRoot, component.file),
|
|
113
|
+
};
|
|
114
|
+
unique.set(`${normalized.file}\0${normalized.exportName}\0${normalized.classification}`, normalized);
|
|
115
|
+
}
|
|
116
|
+
return Array.from(unique.values()).sort((left, right) => {
|
|
117
|
+
const leftEntry = left.file === entry;
|
|
118
|
+
const rightEntry = right.file === entry;
|
|
119
|
+
if (leftEntry !== rightEntry) {
|
|
120
|
+
return leftEntry ? -1 : 1;
|
|
121
|
+
}
|
|
122
|
+
return left.file === right.file
|
|
123
|
+
? left.exportName === right.exportName
|
|
124
|
+
? left.classification.localeCompare(right.classification)
|
|
125
|
+
: left.exportName.localeCompare(right.exportName)
|
|
126
|
+
: left.file.localeCompare(right.file);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function summarizeBoundaryRoutes(routes) {
|
|
130
|
+
const components = routes.flatMap((route) => route.components);
|
|
131
|
+
return {
|
|
132
|
+
clientBoundaries: countClassification(components, "client-boundary"),
|
|
133
|
+
clientRoutes: routes.filter((route) => route.classification === "client-route").length,
|
|
134
|
+
serverOnlyComponents: countClassification(components, "server-only"),
|
|
135
|
+
serverRenderComponents: countClassification(components, "server-render"),
|
|
136
|
+
serverRenderRoutes: routes.filter((route) => route.classification === "server-render").length,
|
|
137
|
+
sharedComponents: countClassification(components, "shared"),
|
|
138
|
+
unknownComponents: countClassification(components, "unknown"),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function countClassification(components, classification) {
|
|
142
|
+
return components.filter((component) => component.classification === classification).length;
|
|
143
|
+
}
|
|
144
|
+
function projectRelativePath(projectRoot, file) {
|
|
145
|
+
const value = relative(projectRoot, file).split(sep).join("/");
|
|
146
|
+
return value === "" ? "." : value;
|
|
147
|
+
}
|
|
148
|
+
function formatComponentOrigin(origin) {
|
|
149
|
+
if (origin === "use-client-directive")
|
|
150
|
+
return ' ("use client")';
|
|
151
|
+
if (origin === "use-server-directive")
|
|
152
|
+
return ' ("use server")';
|
|
153
|
+
if (origin === "client-filename")
|
|
154
|
+
return " (.client.*)";
|
|
155
|
+
if (origin === "compat-filename")
|
|
156
|
+
return " (.compat.*)";
|
|
157
|
+
if (origin === "inferred-client-runtime")
|
|
158
|
+
return " (inferred)";
|
|
159
|
+
if (origin === "server-only-import")
|
|
160
|
+
return " (server-only import)";
|
|
161
|
+
if (origin === "unresolved-reference")
|
|
162
|
+
return " (unresolved)";
|
|
163
|
+
return "";
|
|
164
|
+
}
|
|
165
|
+
function plural(count, singular) {
|
|
166
|
+
return count === 1 ? singular : `${singular}s`;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=boundaries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../src/boundaries.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { relative, sep } from \"node:path\";\nimport type { UserConfig } from \"vite\";\nimport type {\n ClientRouteComponent,\n ClientRouteComponentClassification,\n ClientRouteComponentOrigin,\n ClientRouteInferenceDiagnostic,\n} from \"./client-route-inference.js\";\nimport {\n createClientRouteInferenceCache,\n inferClientRouteModule,\n} from \"./client-route-inference.js\";\nimport { resolveAppRouterProjectOptions, type AppRouterProjectOptions } from \"./config.js\";\nimport { stripRouteClientSource } from \"./route-source.js\";\nimport { scanAppRoutes } from \"./routes.js\";\n\n/**\n * Describes one statically traced component in a route boundary report.\n */\nexport interface BoundaryReportComponent {\n classification: ClientRouteComponentClassification;\n exportName: string;\n file: string;\n origin: ClientRouteComponentOrigin;\n}\n\n/**\n * Describes the rendered component boundary graph for one page route.\n */\nexport interface BoundaryReportRoute {\n classification: \"client-route\" | \"server-render\";\n components: readonly BoundaryReportComponent[];\n entry: string;\n path: string;\n}\n\n/**\n * Counts route and component classifications across a boundary report.\n */\nexport interface BoundaryReportSummary {\n clientBoundaries: number;\n clientRoutes: number;\n serverOnlyComponents: number;\n serverRenderComponents: number;\n serverRenderRoutes: number;\n sharedComponents: number;\n unknownComponents: number;\n}\n\n/**\n * Contains a deterministic, versioned snapshot of app-router component boundaries.\n */\nexport interface BoundaryReport {\n diagnostics: readonly ClientRouteInferenceDiagnostic[];\n routes: readonly BoundaryReportRoute[];\n summary: BoundaryReportSummary;\n version: 1;\n}\n\nexport interface CreateBoundaryReportRouteInput {\n components: readonly ClientRouteComponent[];\n diagnostics: readonly ClientRouteInferenceDiagnostic[];\n entry: string;\n path: string;\n}\n\nexport interface CreateBoundaryReportInput {\n projectRoot: string;\n routes: readonly CreateBoundaryReportRouteInput[];\n}\n\n/**\n * Supplies project and Vite settings for standalone boundary analysis.\n */\nexport interface AnalyzeAppBoundariesOptions extends AppRouterProjectOptions {\n viteConfig?: Pick<UserConfig, \"define\" | \"plugins\"> | undefined;\n}\n\n/**\n * Inspects every page route without writing build artifacts or executing application code.\n */\nexport async function analyzeAppBoundaries(\n options: AnalyzeAppBoundariesOptions,\n): Promise<BoundaryReport> {\n const project = resolveAppRouterProjectOptions(options);\n const routes = (await scanAppRoutes({ appDir: project.routesDir })).filter(\n (route) => route.kind === \"page\",\n );\n const cache = createClientRouteInferenceCache();\n const analyzedRoutes = await Promise.all(\n routes.map(async (route): Promise<CreateBoundaryReportRouteInput> => {\n const source = await readFile(route.file, \"utf8\");\n const inference = await inferClientRouteModule({\n appDir: project.routesDir,\n cache,\n code: stripRouteClientSource({ code: source, filename: route.file }),\n collectComponents: true,\n filename: route.file,\n routePath: route.path,\n vitePlugins: options.viteConfig?.plugins,\n });\n\n return {\n components: inference.components ?? [],\n diagnostics: inference.diagnostics,\n entry: route.file,\n path: route.path,\n };\n }),\n );\n\n return createBoundaryReport({\n projectRoot: project.projectRoot,\n routes: analyzedRoutes,\n });\n}\n\nexport function createBoundaryReport(input: CreateBoundaryReportInput): BoundaryReport {\n const routes = input.routes\n .map((route): BoundaryReportRoute => {\n const entry = projectRelativePath(input.projectRoot, route.entry);\n const components = normalizeComponents(input.projectRoot, entry, route.components);\n\n return {\n classification: components.some(\n (component) =>\n component.file === entry &&\n component.exportName === \"default\" &&\n component.classification === \"client-route\",\n )\n ? \"client-route\"\n : \"server-render\",\n components,\n entry,\n path: route.path,\n };\n })\n .sort((left, right) =>\n left.path === right.path\n ? left.entry.localeCompare(right.entry)\n : left.path.localeCompare(right.path),\n );\n const diagnostics = input.routes\n .flatMap((route) => route.diagnostics)\n .map((diagnostic) => {\n const filename = projectRelativePath(input.projectRoot, diagnostic.filename);\n\n return {\n ...diagnostic,\n filename,\n message: diagnostic.message.split(diagnostic.filename).join(filename),\n };\n })\n .sort((left, right) =>\n left.filename === right.filename\n ? left.code.localeCompare(right.code)\n : left.filename.localeCompare(right.filename),\n );\n\n return {\n diagnostics,\n routes,\n summary: summarizeBoundaryRoutes(routes),\n version: 1,\n };\n}\n\nexport function formatBoundaryReport(report: BoundaryReport): string {\n const lines = [\"Boundaries:\"];\n\n for (const route of report.routes) {\n lines.push(` ${route.path} [${route.classification}]`);\n\n for (const component of route.components) {\n lines.push(\n ` ${component.file}#${component.exportName} ${component.classification}${formatComponentOrigin(component.origin)}`,\n );\n }\n\n lines.push(\"\");\n }\n\n if (report.diagnostics.length > 0) {\n lines.push(\"Warnings:\");\n for (const diagnostic of report.diagnostics) {\n lines.push(` ${diagnostic.code}: ${diagnostic.message}`);\n }\n lines.push(\"\");\n }\n\n const summary = report.summary;\n lines.push(\n [\n `Summary: ${summary.serverRenderRoutes} ${plural(summary.serverRenderRoutes, \"server-render route\")}`,\n `${summary.clientRoutes} ${plural(summary.clientRoutes, \"client route\")}`,\n `${summary.clientBoundaries} ${plural(summary.clientBoundaries, \"client boundary\")}`,\n `${summary.serverRenderComponents} ${plural(summary.serverRenderComponents, \"server-render component\")}`,\n `${summary.serverOnlyComponents} ${plural(summary.serverOnlyComponents, \"server-only component\")}`,\n `${summary.sharedComponents} ${plural(summary.sharedComponents, \"shared component\")}`,\n `${summary.unknownComponents} ${plural(summary.unknownComponents, \"unknown component\")}`,\n ].join(\", \"),\n );\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function formatBoundaryReportJson(report: BoundaryReport): string {\n return `${JSON.stringify(report, null, 2)}\\n`;\n}\n\nfunction normalizeComponents(\n projectRoot: string,\n entry: string,\n components: readonly ClientRouteComponent[],\n): BoundaryReportComponent[] {\n const unique = new Map<string, BoundaryReportComponent>();\n\n for (const component of components) {\n const normalized = {\n ...component,\n file: projectRelativePath(projectRoot, component.file),\n };\n unique.set(\n `${normalized.file}\\0${normalized.exportName}\\0${normalized.classification}`,\n normalized,\n );\n }\n\n return Array.from(unique.values()).sort((left, right) => {\n const leftEntry = left.file === entry;\n const rightEntry = right.file === entry;\n\n if (leftEntry !== rightEntry) {\n return leftEntry ? -1 : 1;\n }\n\n return left.file === right.file\n ? left.exportName === right.exportName\n ? left.classification.localeCompare(right.classification)\n : left.exportName.localeCompare(right.exportName)\n : left.file.localeCompare(right.file);\n });\n}\n\nfunction summarizeBoundaryRoutes(routes: readonly BoundaryReportRoute[]): BoundaryReportSummary {\n const components = routes.flatMap((route) => route.components);\n\n return {\n clientBoundaries: countClassification(components, \"client-boundary\"),\n clientRoutes: routes.filter((route) => route.classification === \"client-route\").length,\n serverOnlyComponents: countClassification(components, \"server-only\"),\n serverRenderComponents: countClassification(components, \"server-render\"),\n serverRenderRoutes: routes.filter((route) => route.classification === \"server-render\").length,\n sharedComponents: countClassification(components, \"shared\"),\n unknownComponents: countClassification(components, \"unknown\"),\n };\n}\n\nfunction countClassification(\n components: readonly BoundaryReportComponent[],\n classification: ClientRouteComponentClassification,\n): number {\n return components.filter((component) => component.classification === classification).length;\n}\n\nfunction projectRelativePath(projectRoot: string, file: string): string {\n const value = relative(projectRoot, file).split(sep).join(\"/\");\n return value === \"\" ? \".\" : value;\n}\n\nfunction formatComponentOrigin(origin: ClientRouteComponentOrigin): string {\n if (origin === \"use-client-directive\") return ' (\"use client\")';\n if (origin === \"use-server-directive\") return ' (\"use server\")';\n if (origin === \"client-filename\") return \" (.client.*)\";\n if (origin === \"compat-filename\") return \" (.compat.*)\";\n if (origin === \"inferred-client-runtime\") return \" (inferred)\";\n if (origin === \"server-only-import\") return \" (server-only import)\";\n if (origin === \"unresolved-reference\") return \" (unresolved)\";\n return \"\";\n}\n\nfunction plural(count: number, singular: string): string {\n return count === 1 ? singular : `${singular}s`;\n}\n"]}
|
package/dist/build.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ServerOutputMode } from "@reckona/mreact-compiler";
|
|
2
|
+
import { type BoundaryReport } from "./boundaries.js";
|
|
2
3
|
import type { AppRoute, CompiledRouteMatcherArtifact } from "./routes.js";
|
|
3
4
|
import { type AppRouterProjectOptions, type AppRouterBuildTarget } from "./config.js";
|
|
4
5
|
import type { ModuleMetadata } from "@reckona/mreact-compiler";
|
|
@@ -12,6 +13,8 @@ export type AwsLambdaGeneratedHandlerPreloadMode = "all" | "hot-route-requests"
|
|
|
12
13
|
export interface BuildAppOptions extends AppRouterProjectOptions {
|
|
13
14
|
awsLambdaPreload?: AwsLambdaGeneratedHandlerPreloadMode | undefined;
|
|
14
15
|
awsLambdaPreloadRoutes?: readonly string[] | undefined;
|
|
16
|
+
/** Receives the full route and component boundary report after source analysis. */
|
|
17
|
+
onBoundaryReport?: ((report: BoundaryReport) => void) | undefined;
|
|
15
18
|
onBuildProgress?: ((event: BuildAppProgressEvent) => void) | undefined;
|
|
16
19
|
onBuildPhaseTiming?: ((timing: BuildAppPhaseTiming) => void) | undefined;
|
|
17
20
|
outDir: string;
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
import { collectStaticImportReferences, collectTopLevelValueExportNames, formatDiagnostic, hasModuleDirective, transform, } from "@reckona/mreact-compiler";
|
|
9
9
|
import { transformCompilerModuleContext } from "@reckona/mreact-compiler/internal";
|
|
10
10
|
import { compilerModuleContextForSource, collectClientRouteReferences, createClientRouteInferenceCache, detectAnchorElementUsage, detectClientNavigationOverride, formatClientRouteInferenceDiagnostic, inferClientRouteModule, navigationRuntimeLinkDisabledDiagnostic, resolveNavigationRuntime, } from "./client-route-inference.js";
|
|
11
|
+
import { createBoundaryReport } from "./boundaries.js";
|
|
11
12
|
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, } from "./navigation-runtime.js";
|
|
12
13
|
import { COMPAT_VENDOR_PLACEHOLDER_PREFIX, bundleAppRouterSourceModule, fileImportMetaUrlPlugin, importAppRouterSourceModule, resolveCompatVendorEntryFiles, sourceReferencesCompatVendorSpecifier, } from "./module-runner.js";
|
|
13
14
|
import { compileRouteMatcherArtifact, scanAppRoutes } from "./routes.js";
|
|
@@ -121,6 +122,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
121
122
|
routes,
|
|
122
123
|
vitePlugins,
|
|
123
124
|
}));
|
|
125
|
+
options.onBoundaryReport?.(sourceAnalysis.boundaryReport);
|
|
124
126
|
if (shouldTrackBuildPhases === false) {
|
|
125
127
|
await validateProductionRoutes({
|
|
126
128
|
clientRouteInferenceCache: serverClientRouteInferenceCache,
|
|
@@ -771,6 +773,7 @@ async function analyzeBuildRouteSources(options) {
|
|
|
771
773
|
appDir: options.project.routesDir,
|
|
772
774
|
cache: options.clientRouteInferenceCache,
|
|
773
775
|
code: stripRouteClientSource({ code: source, filename: route.file }),
|
|
776
|
+
collectComponents: true,
|
|
774
777
|
filename: route.file,
|
|
775
778
|
routePath: route.path,
|
|
776
779
|
vitePlugins: options.vitePlugins,
|
|
@@ -785,6 +788,8 @@ async function analyzeBuildRouteSources(options) {
|
|
|
785
788
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
786
789
|
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
787
790
|
clientRoute: clientInference.client,
|
|
791
|
+
components: clientInference.components ?? [],
|
|
792
|
+
diagnostics: clientInference.diagnostics,
|
|
788
793
|
file,
|
|
789
794
|
route,
|
|
790
795
|
routeCode,
|
|
@@ -803,7 +808,19 @@ async function analyzeBuildRouteSources(options) {
|
|
|
803
808
|
byRouteFile.set(entry[0], entry[1]);
|
|
804
809
|
}
|
|
805
810
|
}
|
|
806
|
-
return {
|
|
811
|
+
return {
|
|
812
|
+
boundaryReport: createBoundaryReport({
|
|
813
|
+
projectRoot: options.projectRoot,
|
|
814
|
+
routes: Array.from(byRouteFile.values(), (analysis) => ({
|
|
815
|
+
components: analysis.components,
|
|
816
|
+
diagnostics: analysis.diagnostics,
|
|
817
|
+
entry: analysis.route.file,
|
|
818
|
+
path: analysis.route.path,
|
|
819
|
+
})),
|
|
820
|
+
}),
|
|
821
|
+
byFile,
|
|
822
|
+
byRouteFile,
|
|
823
|
+
};
|
|
807
824
|
}
|
|
808
825
|
function analyzeBuildSource(source, filename) {
|
|
809
826
|
const cachePolicy = routeCachePolicyFromSource(source);
|