mirror of
https://github.com/morluto/rea.git
synced 2026-11-03 21:36:13 +00:00
fix(javascript): preserve unknown Next package ownership
This commit is contained in:
1 parent
6a9911ea77
commit
c74059d89f
4 files changed
+221
-17
No files matched your search
@@ -305,9 +305,10 @@ export const reconstructJavaScriptArtifact = async (
|
||||
.map(({ logical_path }) => logical_path),
|
||||
);
|
||||
const nextAppContext = createJavaScriptNextAppContext(
|
||||
files.files,
|
||||
files,
|
||||
analysis.jsonDocuments,
|
||||
directoryPaths,
|
||||
snapshot.coverage,
|
||||
);
|
||||
const completed = {
|
||||
route_inventory: await completeJavaScriptAnalysisSteps(
|
||||
|
||||
@@ -4,6 +4,18 @@ import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptA
|
||||
import { JavaScriptJsonDocuments } from "./JavaScriptJsonDocuments.js";
|
||||
import { createJavaScriptNextAppContext } from "./JavaScriptNextAppContext.js";
|
||||
|
||||
const contextFor = (
|
||||
files: readonly JavaScriptArtifactFile[],
|
||||
documents: JavaScriptJsonDocuments,
|
||||
directories: ReadonlySet<string>,
|
||||
) =>
|
||||
createJavaScriptNextAppContext(
|
||||
{ files, unavailable_relevant_files: [] },
|
||||
documents,
|
||||
directories,
|
||||
{ scope: "container-entries", status: "complete" },
|
||||
);
|
||||
|
||||
const file = (path: string, text = ""): JavaScriptArtifactFile => ({
|
||||
path,
|
||||
container_sha256: "a".repeat(64),
|
||||
@@ -23,7 +35,7 @@ it("keeps package applicability and its root cache scoped to the source containe
|
||||
};
|
||||
const page = file("app/page.js");
|
||||
const foreignPage = { ...page, container_sha256: foreign.container_sha256 };
|
||||
const context = createJavaScriptNextAppContext(
|
||||
const context = contextFor(
|
||||
[manifest, foreign, page, foreignPage],
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["app"]),
|
||||
@@ -49,7 +61,7 @@ it("uses the nearest declared Next package and root directory precedence", () =>
|
||||
file("node_modules/ordinary/package.json", '{"name":"ordinary"}'),
|
||||
file("node_modules/ordinary/app/page.js"),
|
||||
];
|
||||
const context = createJavaScriptNextAppContext(
|
||||
const context = contextFor(
|
||||
files,
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set([
|
||||
@@ -76,7 +88,7 @@ it("uses the nearest declared Next package and root directory precedence", () =>
|
||||
it("keeps default compiled output under its declared package and unrelated chunk-like paths unknown", () => {
|
||||
const manifest = file("package.json", '{"dependencies":{"next":"16.4.2"}}');
|
||||
const chunk = file(".next/static/chunks/app/build/page-abc.js");
|
||||
const context = createJavaScriptNextAppContext(
|
||||
const context = contextFor(
|
||||
[manifest, chunk],
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(),
|
||||
@@ -86,11 +98,7 @@ it("keeps default compiled output under its declared package and unrelated chunk
|
||||
directory: ".next/static/chunks/app",
|
||||
});
|
||||
expect(
|
||||
createJavaScriptNextAppContext(
|
||||
[chunk],
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(),
|
||||
)(chunk),
|
||||
contextFor([chunk], new JavaScriptJsonDocuments(), new Set())(chunk),
|
||||
).toMatchObject({ kind: "unknown" });
|
||||
});
|
||||
|
||||
@@ -101,17 +109,97 @@ it("supports src/app only when app is not inventoried and retains missing framew
|
||||
);
|
||||
const page = file("src/app/control/page.js");
|
||||
expect(
|
||||
createJavaScriptNextAppContext(
|
||||
contextFor(
|
||||
[manifest, page],
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["src/app"]),
|
||||
)(page),
|
||||
).toMatchObject({ kind: "app-directory", directory: "src/app" });
|
||||
expect(
|
||||
createJavaScriptNextAppContext(
|
||||
contextFor(
|
||||
[page],
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["src/app"]),
|
||||
)(page),
|
||||
).toMatchObject({ kind: "unknown", package: null });
|
||||
});
|
||||
|
||||
it("does not infer absent manifests or higher-priority directories from incomplete traversal", () => {
|
||||
const manifest = file("package.json", '{"dependencies":{"next":"16.4.2"}}');
|
||||
const page = file("src/app/control/page.js");
|
||||
const files = { files: [manifest, page], unavailable_relevant_files: [] };
|
||||
const context = createJavaScriptNextAppContext(
|
||||
files,
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["src/app"]),
|
||||
{ scope: "container-entries", status: "unknown" },
|
||||
);
|
||||
expect(context(page)).toMatchObject({
|
||||
kind: "unknown",
|
||||
package: null,
|
||||
reason: expect.stringContaining("src/app/control/package.json"),
|
||||
});
|
||||
const rootPage = file("page.js");
|
||||
expect(
|
||||
createJavaScriptNextAppContext(
|
||||
files,
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["src/app"]),
|
||||
{ scope: "container-entries", status: "unknown" },
|
||||
)(rootPage),
|
||||
).toMatchObject({
|
||||
kind: "unknown",
|
||||
package: { path: "package.json" },
|
||||
reason: expect.stringContaining("higher-priority app directory"),
|
||||
});
|
||||
});
|
||||
|
||||
it("retains the nearest unavailable manifest's evidence instead of borrowing an ancestor's Next declaration", () => {
|
||||
const parent = file("package.json", '{"dependencies":{"next":"16.4.2"}}');
|
||||
const page = file("app/widget/app/page.js");
|
||||
const unavailable = {
|
||||
path: "app/widget/package.json",
|
||||
container_sha256: parent.container_sha256,
|
||||
sha256: null,
|
||||
bytes: 42,
|
||||
inventory_artifact_id: null,
|
||||
inventory_occurrence_id: "unreadable-nested-package",
|
||||
kind: "package-json" as const,
|
||||
limitations: ["The unpacked package companion is missing."],
|
||||
};
|
||||
const context = createJavaScriptNextAppContext(
|
||||
{ files: [parent, page], unavailable_relevant_files: [unavailable] },
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["app", "app/widget/app"]),
|
||||
{ scope: "container-entries", status: "complete" },
|
||||
);
|
||||
expect(context(page)).toMatchObject({
|
||||
kind: "unknown",
|
||||
package: null,
|
||||
reason: expect.stringContaining(unavailable.path),
|
||||
});
|
||||
const result = context(page);
|
||||
if (result.kind !== "unknown")
|
||||
throw new Error("Expected unknown package ownership");
|
||||
expect(result.reason).toContain(unavailable.inventory_occurrence_id);
|
||||
expect(result.reason).toContain(unavailable.limitations[0]);
|
||||
expect(context(file("app/page.js"))).toMatchObject({
|
||||
kind: "app-directory",
|
||||
package: { path: parent.path },
|
||||
});
|
||||
const foreign = createJavaScriptNextAppContext(
|
||||
{
|
||||
files: [parent, page],
|
||||
unavailable_relevant_files: [
|
||||
{ ...unavailable, container_sha256: "c".repeat(64) },
|
||||
],
|
||||
},
|
||||
new JavaScriptJsonDocuments(),
|
||||
new Set(["app", "app/widget/app"]),
|
||||
{ scope: "container-entries", status: "complete" },
|
||||
);
|
||||
expect(foreign(page)).toMatchObject({
|
||||
kind: "app-directory",
|
||||
package: { path: parent.path },
|
||||
});
|
||||
});
|
||||
@@ -1,20 +1,36 @@
|
||||
import { posix } from "node:path";
|
||||
|
||||
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
|
||||
import type { ArtifactInventoryCoverage } from "../../domain/artifactGraph.js";
|
||||
import type {
|
||||
JavaScriptArtifactFileSet,
|
||||
JavaScriptArtifactFile,
|
||||
} from "../../domain/javascript/javascriptArtifactFiles.js";
|
||||
import type { NextAppSourceContext } from "../../domain/javascript/javascriptRoutePaths.js";
|
||||
import { compositeKey } from "../../domain/unicodeCodePointOrder.js";
|
||||
import type { JavaScriptJsonDocuments } from "./JavaScriptJsonDocuments.js";
|
||||
|
||||
/** Package declarations and inventoried directories own source-router applicability. */
|
||||
export const createJavaScriptNextAppContext = (
|
||||
files: readonly JavaScriptArtifactFile[],
|
||||
fileSet: Pick<
|
||||
JavaScriptArtifactFileSet,
|
||||
"files" | "unavailable_relevant_files"
|
||||
>,
|
||||
documents: JavaScriptJsonDocuments,
|
||||
directories: ReadonlySet<string>,
|
||||
coverage: ArtifactInventoryCoverage,
|
||||
): ((
|
||||
file: Pick<JavaScriptArtifactFile, "path" | "container_sha256">,
|
||||
) => NextAppSourceContext) => {
|
||||
const packages = new Map(
|
||||
files
|
||||
fileSet.files
|
||||
.filter(({ kind }) => kind === "package-json")
|
||||
.map((file) => [
|
||||
compositeKey([file.container_sha256, posix.dirname(file.path)]),
|
||||
file,
|
||||
]),
|
||||
);
|
||||
const unavailablePackages = new Map(
|
||||
fileSet.unavailable_relevant_files
|
||||
.filter(({ kind }) => kind === "package-json")
|
||||
.map((file) => [
|
||||
compositeKey([file.container_sha256, posix.dirname(file.path)]),
|
||||
@@ -28,9 +44,15 @@ export const createJavaScriptNextAppContext = (
|
||||
;
|
||||
directory = posix.dirname(directory)
|
||||
) {
|
||||
const manifest = packages.get(
|
||||
compositeKey([file.container_sha256, directory]),
|
||||
);
|
||||
const key = compositeKey([file.container_sha256, directory]);
|
||||
const unavailable = unavailablePackages.get(key);
|
||||
if (unavailable !== undefined)
|
||||
return {
|
||||
kind: "unknown",
|
||||
package: null,
|
||||
reason: `The nearest owning package manifest ${unavailable.path}${unavailable.inventory_occurrence_id === undefined ? "" : ` (inventory occurrence ${unavailable.inventory_occurrence_id})`} is unavailable: ${unavailable.limitations?.join("; ") || "Inventoried package bytes are unavailable."}`,
|
||||
};
|
||||
const manifest = packages.get(key);
|
||||
if (manifest !== undefined) {
|
||||
const identity = {
|
||||
path: manifest.path,
|
||||
@@ -53,6 +75,14 @@ export const createJavaScriptNextAppContext = (
|
||||
directory: compiled,
|
||||
package: identity,
|
||||
};
|
||||
// Selecting src/app requires proving that the higher-priority app is absent.
|
||||
if (coverage.status !== "complete" && !directories.has(`${prefix}app`))
|
||||
return {
|
||||
kind: "unknown",
|
||||
package: identity,
|
||||
reason:
|
||||
"Incomplete artifact traversal does not establish whether the owning package has a higher-priority app directory.",
|
||||
};
|
||||
let root = roots.get(manifest);
|
||||
if (root === undefined) {
|
||||
root =
|
||||
@@ -65,6 +95,12 @@ export const createJavaScriptNextAppContext = (
|
||||
? { kind: "app-directory", directory: root, package: identity }
|
||||
: { kind: "outside-app-directory", package: identity };
|
||||
}
|
||||
if (coverage.status !== "complete")
|
||||
return {
|
||||
kind: "unknown",
|
||||
package: null,
|
||||
reason: `Incomplete artifact traversal does not establish whether ${directory === "." ? "" : `${directory}/`}package.json owns this source.`,
|
||||
};
|
||||
if (directory === "." || directory === "/") break;
|
||||
}
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user