@reckona/mreact-router 0.0.207 → 0.0.209
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 +2 -2
- package/dist/adapters/cloudflare.d.ts +3 -3
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +11 -4
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/boundaries.d.ts +37 -1
- package/dist/boundaries.d.ts.map +1 -1
- package/dist/boundaries.js +125 -4
- package/dist/boundaries.js.map +1 -1
- package/dist/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +269 -24
- package/dist/build.js.map +1 -1
- package/dist/bundle-pipeline.d.ts +1 -0
- package/dist/bundle-pipeline.d.ts.map +1 -1
- package/dist/bundle-pipeline.js +4 -1
- package/dist/bundle-pipeline.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +67 -7
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/module-runner.js +9 -1
- package/dist/module-runner.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +23 -23
- package/dist/render.js.map +1 -1
- package/dist/request-header-tracking.d.ts +19 -0
- package/dist/request-header-tracking.d.ts.map +1 -1
- package/dist/request-header-tracking.js +48 -0
- package/dist/request-header-tracking.js.map +1 -1
- package/dist/tailwind-source.d.ts.map +1 -1
- package/dist/tailwind-source.js +147 -1
- package/dist/tailwind-source.js.map +1 -1
- package/dist/types.d.ts +14 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vite.d.ts +1 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +4 -0
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/cloudflare.ts +14 -5
- package/src/boundaries.ts +224 -4
- package/src/build.ts +383 -24
- package/src/bundle-pipeline.ts +9 -4
- package/src/client.ts +104 -10
- package/src/config.ts +32 -0
- package/src/index.ts +10 -0
- package/src/module-runner.ts +9 -1
- package/src/render.ts +30 -16
- package/src/request-header-tracking.ts +61 -0
- package/src/tailwind-source.ts +164 -1
- package/src/types.ts +15 -2
- package/src/vite.ts +5 -0
package/dist/boundaries.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { relative, sep } from "node:path";
|
|
3
3
|
import { createClientRouteInferenceCache, inferClientRouteModule, } from "./client-route-inference.js";
|
|
4
|
-
import { resolveAppRouterProjectOptions } from "./config.js";
|
|
4
|
+
import { resolveAppRouterProjectOptions, } from "./config.js";
|
|
5
5
|
import { stripRouteClientSource } from "./route-source.js";
|
|
6
6
|
import { scanAppRoutes } from "./routes.js";
|
|
7
7
|
/**
|
|
@@ -27,18 +27,21 @@ export async function analyzeAppBoundaries(options) {
|
|
|
27
27
|
diagnostics: inference.diagnostics,
|
|
28
28
|
entry: route.file,
|
|
29
29
|
path: route.path,
|
|
30
|
+
source,
|
|
30
31
|
};
|
|
31
32
|
}));
|
|
32
|
-
|
|
33
|
+
const report = createBoundaryReport({
|
|
33
34
|
projectRoot: project.projectRoot,
|
|
34
35
|
routes: analyzedRoutes,
|
|
35
36
|
});
|
|
37
|
+
validateBoundaryExecutionContracts(report, project.executionContracts);
|
|
38
|
+
return report;
|
|
36
39
|
}
|
|
37
40
|
export function createBoundaryReport(input) {
|
|
38
41
|
const routes = input.routes
|
|
39
42
|
.map((route) => {
|
|
40
43
|
const entry = projectRelativePath(input.projectRoot, route.entry);
|
|
41
|
-
const components = normalizeComponents(input.projectRoot, entry, route.components);
|
|
44
|
+
const components = normalizeComponents(input.projectRoot, entry, route.components, route.source);
|
|
42
45
|
return {
|
|
43
46
|
classification: components.some((component) => component.file === entry &&
|
|
44
47
|
component.exportName === "default" &&
|
|
@@ -46,7 +49,12 @@ export function createBoundaryReport(input) {
|
|
|
46
49
|
? "client-route"
|
|
47
50
|
: "server-render",
|
|
48
51
|
components,
|
|
52
|
+
cost: route.cost ?? {
|
|
53
|
+
reason: "No production artifact supplied.",
|
|
54
|
+
status: "unavailable",
|
|
55
|
+
},
|
|
49
56
|
entry,
|
|
57
|
+
executionModes: executionModesForComponents(components),
|
|
50
58
|
path: route.path,
|
|
51
59
|
};
|
|
52
60
|
})
|
|
@@ -80,6 +88,7 @@ export function formatBoundaryReport(report) {
|
|
|
80
88
|
for (const component of route.components) {
|
|
81
89
|
lines.push(` ${component.file}#${component.exportName} ${component.classification}${formatComponentOrigin(component.origin)}`);
|
|
82
90
|
}
|
|
91
|
+
lines.push(` modes: ${route.executionModes.join(", ")}`);
|
|
83
92
|
lines.push("");
|
|
84
93
|
}
|
|
85
94
|
if (report.diagnostics.length > 0) {
|
|
@@ -104,11 +113,19 @@ export function formatBoundaryReport(report) {
|
|
|
104
113
|
export function formatBoundaryReportJson(report) {
|
|
105
114
|
return `${JSON.stringify(report, null, 2)}\n`;
|
|
106
115
|
}
|
|
107
|
-
function normalizeComponents(projectRoot, entry, components) {
|
|
116
|
+
function normalizeComponents(projectRoot, entry, components, source) {
|
|
108
117
|
const unique = new Map();
|
|
109
118
|
for (const component of components) {
|
|
110
119
|
const normalized = {
|
|
111
120
|
...component,
|
|
121
|
+
decision: {
|
|
122
|
+
executionMode: executionModeForClassification(component.classification),
|
|
123
|
+
reasonChain: reasonChainForComponent(component, projectRoot, entry),
|
|
124
|
+
...(source === undefined ||
|
|
125
|
+
component.file !== resolveProjectRelativePath(projectRoot, entry)
|
|
126
|
+
? {}
|
|
127
|
+
: sourceRangeField(source, component.exportName)),
|
|
128
|
+
},
|
|
112
129
|
file: projectRelativePath(projectRoot, component.file),
|
|
113
130
|
};
|
|
114
131
|
unique.set(`${normalized.file}\0${normalized.exportName}\0${normalized.classification}`, normalized);
|
|
@@ -126,6 +143,110 @@ function normalizeComponents(projectRoot, entry, components) {
|
|
|
126
143
|
: left.file.localeCompare(right.file);
|
|
127
144
|
});
|
|
128
145
|
}
|
|
146
|
+
/** Validates opt-in execution constraints against the normalized boundary report. */
|
|
147
|
+
export function validateBoundaryExecutionContracts(report, contracts) {
|
|
148
|
+
if (contracts === undefined) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const violations = [];
|
|
152
|
+
const serverOnlyRoutes = contracts.serverOnlyRoutes ?? [];
|
|
153
|
+
const noCompatComponents = contracts.noCompatComponents ?? [];
|
|
154
|
+
for (const route of report.routes) {
|
|
155
|
+
if (serverOnlyRoutes.some((pattern) => globMatches(route.path, pattern))) {
|
|
156
|
+
for (const component of route.components) {
|
|
157
|
+
if (component.decision.executionMode === "client" ||
|
|
158
|
+
component.decision.executionMode === "shared" ||
|
|
159
|
+
component.decision.executionMode === "unknown") {
|
|
160
|
+
violations.push(`server-only route ${JSON.stringify(route.path)} includes ${component.decision.executionMode} execution at ${component.file}#${component.exportName}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const component of route.components) {
|
|
165
|
+
const componentId = `${component.file}#${component.exportName}`;
|
|
166
|
+
if (!noCompatComponents.some((pattern) => globMatches(component.file, pattern) || globMatches(componentId, pattern))) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (component.origin === "compat-filename" || isCompatComponentFile(component.file)) {
|
|
170
|
+
violations.push(`no-compat component ${componentId} uses compat fallback from its filename`);
|
|
171
|
+
}
|
|
172
|
+
else if (component.decision.executionMode === "unknown") {
|
|
173
|
+
violations.push(`no-compat component ${componentId} has an unknown compiler decision`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (violations.length > 0) {
|
|
178
|
+
throw new Error(`mreactRouter execution contract violation(s):\n${violations.map((violation) => `- ${violation}`).join("\n")}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function isCompatComponentFile(file) {
|
|
182
|
+
return /\.compat(?:\.mreact)?\.[cm]?[jt]sx?$/.test(file.replaceAll("\\", "/"));
|
|
183
|
+
}
|
|
184
|
+
function executionModesForComponents(components) {
|
|
185
|
+
const order = ["client", "server", "shared", "unknown"];
|
|
186
|
+
const modes = new Set(components.map((component) => component.decision.executionMode));
|
|
187
|
+
return order.filter((mode) => modes.has(mode));
|
|
188
|
+
}
|
|
189
|
+
function executionModeForClassification(classification) {
|
|
190
|
+
if (classification === "client-boundary" || classification === "client-route") {
|
|
191
|
+
return "client";
|
|
192
|
+
}
|
|
193
|
+
if (classification === "shared") {
|
|
194
|
+
return "shared";
|
|
195
|
+
}
|
|
196
|
+
if (classification === "unknown") {
|
|
197
|
+
return "unknown";
|
|
198
|
+
}
|
|
199
|
+
return "server";
|
|
200
|
+
}
|
|
201
|
+
function reasonChainForComponent(component, projectRoot, entry) {
|
|
202
|
+
const reasons = [`classification:${component.classification}`, `origin:${component.origin}`];
|
|
203
|
+
if (component.origin === "inferred-client-runtime") {
|
|
204
|
+
reasons.push("client-runtime-inference");
|
|
205
|
+
}
|
|
206
|
+
else if (component.origin === "compat-filename") {
|
|
207
|
+
reasons.push("compat-fallback");
|
|
208
|
+
}
|
|
209
|
+
else if (component.origin === "unresolved-reference") {
|
|
210
|
+
reasons.push("unresolved-reference");
|
|
211
|
+
}
|
|
212
|
+
if (projectRelativePath(projectRoot, component.file) !== entry) {
|
|
213
|
+
reasons.push(`reachable-from:${entry}`);
|
|
214
|
+
}
|
|
215
|
+
return reasons;
|
|
216
|
+
}
|
|
217
|
+
function sourceRangeField(source, exportName) {
|
|
218
|
+
const escapedName = escapeRegExp(exportName);
|
|
219
|
+
const pattern = exportName === "default"
|
|
220
|
+
? /\bexport\s+default\b/u
|
|
221
|
+
: new RegExp(`\\bexport\\s+(?:(?:async)\\s+)?(?:function|class|const|let|var)\\s+${escapedName}\\b`, "u");
|
|
222
|
+
const match = pattern.exec(source);
|
|
223
|
+
return match === null || match.index === undefined
|
|
224
|
+
? {}
|
|
225
|
+
: {
|
|
226
|
+
sourceRange: {
|
|
227
|
+
end: sourcePosition(source, match.index + match[0].length),
|
|
228
|
+
start: sourcePosition(source, match.index),
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function sourcePosition(source, offset) {
|
|
233
|
+
const lines = source.slice(0, offset).split("\n");
|
|
234
|
+
return { column: (lines.at(-1)?.length ?? 0) + 1, line: lines.length };
|
|
235
|
+
}
|
|
236
|
+
function escapeRegExp(value) {
|
|
237
|
+
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
238
|
+
}
|
|
239
|
+
function globMatches(value, pattern) {
|
|
240
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/gu, "\\$&");
|
|
241
|
+
const expression = escaped
|
|
242
|
+
.replaceAll("**", "\u0000")
|
|
243
|
+
.replaceAll("*", "[^/]*")
|
|
244
|
+
.replaceAll("\u0000", ".*");
|
|
245
|
+
return new RegExp(`^${expression}$`, "u").test(value);
|
|
246
|
+
}
|
|
247
|
+
function resolveProjectRelativePath(projectRoot, relativePath) {
|
|
248
|
+
return `${projectRoot}/${relativePath}`;
|
|
249
|
+
}
|
|
129
250
|
function summarizeBoundaryRoutes(routes) {
|
|
130
251
|
const components = routes.flatMap((route) => route.components);
|
|
131
252
|
return {
|
package/dist/boundaries.js.map
CHANGED
|
@@ -1 +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"]}
|
|
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 {\n resolveAppRouterProjectOptions,\n type AppRouterExecutionContracts,\n type AppRouterProjectOptions,\n} 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 decision: BoundaryReportDecision;\n exportName: string;\n file: string;\n origin: ClientRouteComponentOrigin;\n}\n\nexport type BoundaryExecutionMode = \"client\" | \"server\" | \"shared\" | \"unknown\";\n\nexport interface BoundaryReportDecision {\n executionMode: BoundaryExecutionMode;\n reasonChain: readonly string[];\n sourceRange?: BoundarySourceRange | undefined;\n}\n\nexport interface BoundarySourcePosition {\n column: number;\n line: number;\n}\n\nexport interface BoundarySourceRange {\n end: BoundarySourcePosition;\n start: BoundarySourcePosition;\n}\n\nexport interface BoundaryReportByteCost {\n gzipEstimateBytes: number;\n observedTransferBytes?: number | undefined;\n rawBytes: number;\n}\n\nexport interface BoundaryReportCost {\n baseline?:\n | {\n initialGzipDeltaBytes?: number | undefined;\n navigationGzipDeltaBytes?: number | undefined;\n }\n | undefined;\n initial?: BoundaryReportByteCost | undefined;\n navigation?: BoundaryReportByteCost | undefined;\n reason?: string | undefined;\n status: \"available\" | \"unavailable\";\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 cost: BoundaryReportCost;\n entry: string;\n executionModes: readonly BoundaryExecutionMode[];\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 cost?: BoundaryReportCost | undefined;\n diagnostics: readonly ClientRouteInferenceDiagnostic[];\n entry: string;\n path: string;\n source?: string | undefined;\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 source,\n };\n }),\n );\n\n const report = createBoundaryReport({\n projectRoot: project.projectRoot,\n routes: analyzedRoutes,\n });\n validateBoundaryExecutionContracts(report, project.executionContracts);\n return report;\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(\n input.projectRoot,\n entry,\n route.components,\n route.source,\n );\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 cost: route.cost ?? {\n reason: \"No production artifact supplied.\",\n status: \"unavailable\",\n },\n entry,\n executionModes: executionModesForComponents(components),\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(` modes: ${route.executionModes.join(\", \")}`);\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 source: string | undefined,\n): BoundaryReportComponent[] {\n const unique = new Map<string, BoundaryReportComponent>();\n\n for (const component of components) {\n const normalized: BoundaryReportComponent = {\n ...component,\n decision: {\n executionMode: executionModeForClassification(component.classification),\n reasonChain: reasonChainForComponent(component, projectRoot, entry),\n ...(source === undefined ||\n component.file !== resolveProjectRelativePath(projectRoot, entry)\n ? {}\n : sourceRangeField(source, component.exportName)),\n },\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\n/** Validates opt-in execution constraints against the normalized boundary report. */\nexport function validateBoundaryExecutionContracts(\n report: BoundaryReport,\n contracts: AppRouterExecutionContracts | undefined,\n): void {\n if (contracts === undefined) {\n return;\n }\n\n const violations: string[] = [];\n const serverOnlyRoutes = contracts.serverOnlyRoutes ?? [];\n const noCompatComponents = contracts.noCompatComponents ?? [];\n\n for (const route of report.routes) {\n if (serverOnlyRoutes.some((pattern) => globMatches(route.path, pattern))) {\n for (const component of route.components) {\n if (\n component.decision.executionMode === \"client\" ||\n component.decision.executionMode === \"shared\" ||\n component.decision.executionMode === \"unknown\"\n ) {\n violations.push(\n `server-only route ${JSON.stringify(route.path)} includes ${component.decision.executionMode} execution at ${component.file}#${component.exportName}`,\n );\n }\n }\n }\n\n for (const component of route.components) {\n const componentId = `${component.file}#${component.exportName}`;\n if (\n !noCompatComponents.some(\n (pattern) => globMatches(component.file, pattern) || globMatches(componentId, pattern),\n )\n ) {\n continue;\n }\n\n if (component.origin === \"compat-filename\" || isCompatComponentFile(component.file)) {\n violations.push(\n `no-compat component ${componentId} uses compat fallback from its filename`,\n );\n } else if (component.decision.executionMode === \"unknown\") {\n violations.push(`no-compat component ${componentId} has an unknown compiler decision`);\n }\n }\n }\n\n if (violations.length > 0) {\n throw new Error(\n `mreactRouter execution contract violation(s):\\n${violations.map((violation) => `- ${violation}`).join(\"\\n\")}`,\n );\n }\n}\n\nfunction isCompatComponentFile(file: string): boolean {\n return /\\.compat(?:\\.mreact)?\\.[cm]?[jt]sx?$/.test(file.replaceAll(\"\\\\\", \"/\"));\n}\n\nfunction executionModesForComponents(\n components: readonly BoundaryReportComponent[],\n): BoundaryExecutionMode[] {\n const order: readonly BoundaryExecutionMode[] = [\"client\", \"server\", \"shared\", \"unknown\"];\n const modes = new Set(components.map((component) => component.decision.executionMode));\n return order.filter((mode) => modes.has(mode));\n}\n\nfunction executionModeForClassification(\n classification: ClientRouteComponentClassification,\n): BoundaryExecutionMode {\n if (classification === \"client-boundary\" || classification === \"client-route\") {\n return \"client\";\n }\n if (classification === \"shared\") {\n return \"shared\";\n }\n if (classification === \"unknown\") {\n return \"unknown\";\n }\n return \"server\";\n}\n\nfunction reasonChainForComponent(\n component: ClientRouteComponent,\n projectRoot: string,\n entry: string,\n): string[] {\n const reasons = [`classification:${component.classification}`, `origin:${component.origin}`];\n\n if (component.origin === \"inferred-client-runtime\") {\n reasons.push(\"client-runtime-inference\");\n } else if (component.origin === \"compat-filename\") {\n reasons.push(\"compat-fallback\");\n } else if (component.origin === \"unresolved-reference\") {\n reasons.push(\"unresolved-reference\");\n }\n\n if (projectRelativePath(projectRoot, component.file) !== entry) {\n reasons.push(`reachable-from:${entry}`);\n }\n\n return reasons;\n}\n\nfunction sourceRangeField(\n source: string,\n exportName: string,\n): { sourceRange?: BoundarySourceRange | undefined } {\n const escapedName = escapeRegExp(exportName);\n const pattern =\n exportName === \"default\"\n ? /\\bexport\\s+default\\b/u\n : new RegExp(\n `\\\\bexport\\\\s+(?:(?:async)\\\\s+)?(?:function|class|const|let|var)\\\\s+${escapedName}\\\\b`,\n \"u\",\n );\n const match = pattern.exec(source);\n\n return match === null || match.index === undefined\n ? {}\n : {\n sourceRange: {\n end: sourcePosition(source, match.index + match[0].length),\n start: sourcePosition(source, match.index),\n },\n };\n}\n\nfunction sourcePosition(source: string, offset: number): BoundarySourcePosition {\n const lines = source.slice(0, offset).split(\"\\n\");\n return { column: (lines.at(-1)?.length ?? 0) + 1, line: lines.length };\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nfunction globMatches(value: string, pattern: string): boolean {\n const escaped = pattern.replace(/[.+^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n const expression = escaped\n .replaceAll(\"**\", \"\\u0000\")\n .replaceAll(\"*\", \"[^/]*\")\n .replaceAll(\"\\u0000\", \".*\");\n return new RegExp(`^${expression}$`, \"u\").test(value);\n}\n\nfunction resolveProjectRelativePath(projectRoot: string, relativePath: string): string {\n return `${projectRoot}/${relativePath}`;\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
|
@@ -7,12 +7,18 @@ import type { RouteCachePolicy } from "./cache.js";
|
|
|
7
7
|
import { type AppRouterImportPolicy } from "./import-policy.js";
|
|
8
8
|
import type { PluginOption, UserConfig } from "vite";
|
|
9
9
|
export type AwsLambdaGeneratedHandlerPreloadMode = "all" | "hot-route-requests" | "middleware" | "none";
|
|
10
|
+
/** Supplies observed dynamic imports when boundary navigation costs are measured. */
|
|
11
|
+
export interface BoundaryCostOptions {
|
|
12
|
+
/** Maps a route path to dynamic import entry files fetched during navigation. */
|
|
13
|
+
fetchedDynamicImports?: Readonly<Record<string, readonly string[]>> | undefined;
|
|
14
|
+
}
|
|
10
15
|
/**
|
|
11
16
|
* Configures an app-router production build and its deployment targets.
|
|
12
17
|
*/
|
|
13
18
|
export interface BuildAppOptions extends AppRouterProjectOptions {
|
|
14
19
|
awsLambdaPreload?: AwsLambdaGeneratedHandlerPreloadMode | undefined;
|
|
15
20
|
awsLambdaPreloadRoutes?: readonly string[] | undefined;
|
|
21
|
+
boundaryCost?: BoundaryCostOptions | undefined;
|
|
16
22
|
/** Receives the full route and component boundary report after source analysis. */
|
|
17
23
|
onBoundaryReport?: ((report: BoundaryReport) => void) | undefined;
|
|
18
24
|
onBuildProgress?: ((event: BuildAppProgressEvent) => void) | undefined;
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|