mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
1860632d87
* refactor: migrate the CLI cluster path handling to pathslash * refactor(routing): migrate the routing cluster path handling to pathslash * refactor(plugins): migrate the plugins cluster path handling to pathslash * refactor(server): migrate the server cluster path handling to pathslash * refactor(build): migrate the build cluster path handling to pathslash * refactor(core): migrate entries, config, and shared utils to pathslash * refactor(plugin): migrate index.ts path handling to pathslash * refactor: finish the pathslash migration — test sweep, stragglers, lint guard * refactor: address final-review findings on the pathslash migration * docs(agents): document the pathslash path-handling convention * fix(build): emit inlined dependencies outside dist/node_modules * fix: normalize wire- and bundler-shaped ids unconditionally * docs(agents): document the unconditional-normalization exception * fix: gate Windows-shaped path fixtures to Windows * docs(agents): gate Windows-shaped fixtures with runIf * refactor: migrate upstream prerender path discovery to pathslash * fix(create-vinext-app): bundle pathslash into the scaffolder dist --------- Co-authored-by: James <james@eli.cx>
196 lines
8.7 KiB
TypeScript
196 lines
8.7 KiB
TypeScript
import { afterAll, beforeAll, describe, expect, it } from "vite-plus/test";
|
|
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { OgAssetOwnership } from "../packages/vinext/src/plugins/og-asset-ownership.js";
|
|
import { toSlash } from "pathslash";
|
|
|
|
/** Expected canonical (forward-slash) path for boundary assertions. */
|
|
function canonical(p: string): string {
|
|
return toSlash(p);
|
|
}
|
|
|
|
let tmpDir: string;
|
|
|
|
beforeAll(async () => {
|
|
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "og-asset-ownership-"));
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("OgAssetOwnership", () => {
|
|
it("uses the project root for application modules", async () => {
|
|
const projectRoot = path.join(tmpDir, "application");
|
|
const modulePath = path.join(projectRoot, "app", "route.js");
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, []);
|
|
const realProjectRoot = await fs.realpath(projectRoot);
|
|
const realModuleDir = await fs.realpath(path.dirname(modulePath));
|
|
|
|
const boundary = await ownership.resolveModuleBoundary(modulePath);
|
|
|
|
expect(boundary).toEqual({
|
|
assetRoot: canonical(realProjectRoot),
|
|
moduleDir: canonical(realModuleDir),
|
|
});
|
|
});
|
|
|
|
it("records an aliased external package as its own boundary", async () => {
|
|
const projectRoot = path.join(tmpDir, "aliased-app");
|
|
const packageRoot = path.join(tmpDir, "aliased-package");
|
|
const modulePath = path.join(packageRoot, "dist", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"design-system"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [{ find: "@ui", replacement: packageRoot }]);
|
|
await ownership.recordResolvedImport("@ui/dist/chunk.js", modulePath);
|
|
const realPackageRoot = await fs.realpath(packageRoot);
|
|
|
|
const boundary = await ownership.resolveModuleBoundary(modulePath);
|
|
|
|
expect(boundary?.assetRoot).toBe(canonical(realPackageRoot));
|
|
});
|
|
|
|
it("recognizes an external package from its resolved directory alias path", async () => {
|
|
const projectRoot = path.join(tmpDir, "resolved-alias-app");
|
|
const packageRoot = path.join(tmpDir, "resolved-alias-package");
|
|
const modulePath = path.join(packageRoot, "dist", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"@test/og-font"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [
|
|
{ find: "@test/og-font", replacement: path.join(packageRoot, "dist") },
|
|
]);
|
|
const realPackageRoot = await fs.realpath(packageRoot);
|
|
|
|
const boundary = await ownership.resolveModuleBoundary(modulePath);
|
|
|
|
expect(boundary?.assetRoot).toBe(canonical(realPackageRoot));
|
|
});
|
|
|
|
it("does not broaden a resolved alias to an external non-package directory", async () => {
|
|
const workspaceRoot = path.join(tmpDir, "resolved-non-package-workspace");
|
|
const projectRoot = path.join(workspaceRoot, "app");
|
|
const aliasRoot = path.join(workspaceRoot, "components");
|
|
const modulePath = path.join(aliasRoot, "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(aliasRoot, { recursive: true });
|
|
await fs.writeFile(path.join(workspaceRoot, "package.json"), '{"name":"workspace"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [{ find: "@components", replacement: aliasRoot }]);
|
|
|
|
await expect(ownership.resolveModuleBoundary(modulePath)).resolves.toBeNull();
|
|
});
|
|
|
|
it("recognizes a resolved scoped package through a regex capture alias", async () => {
|
|
const projectRoot = path.join(tmpDir, "resolved-regex-app");
|
|
const packagesRoot = path.join(tmpDir, "resolved-regex-packages");
|
|
const packageRoot = path.join(packagesRoot, "ui");
|
|
const modulePath = path.join(packageRoot, "lib", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"@scope/ui"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [
|
|
{ find: /^@scope\/(.*)$/, replacement: `${packagesRoot}/$1/lib` },
|
|
]);
|
|
const realPackageRoot = await fs.realpath(packageRoot);
|
|
|
|
await expect(ownership.resolveModuleBoundary(modulePath)).resolves.toEqual({
|
|
assetRoot: canonical(realPackageRoot),
|
|
moduleDir: canonical(await fs.realpath(path.dirname(modulePath))),
|
|
});
|
|
});
|
|
|
|
it("does not apply a regex capture alias to an unrelated sibling package", async () => {
|
|
const projectRoot = path.join(tmpDir, "resolved-regex-sibling-app");
|
|
const packagesRoot = path.join(tmpDir, "resolved-regex-sibling-packages");
|
|
const packageRoot = path.join(packagesRoot, "other");
|
|
const modulePath = path.join(packageRoot, "src", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"unrelated-package"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [
|
|
{ find: /^@scope\/(.*)$/, replacement: `${packagesRoot}/$1/lib` },
|
|
]);
|
|
|
|
await expect(ownership.resolveModuleBoundary(modulePath)).resolves.toBeNull();
|
|
});
|
|
|
|
it("does not broaden a regex capture directory within the owning package", async () => {
|
|
const projectRoot = path.join(tmpDir, "resolved-regex-outside-app");
|
|
const packagesRoot = path.join(tmpDir, "resolved-regex-outside-packages");
|
|
const packageRoot = path.join(packagesRoot, "ui");
|
|
const modulePath = path.join(packageRoot, "src", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.join(packageRoot, "lib"), { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"@scope/ui"}');
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [
|
|
{ find: /^@scope\/(.*)$/, replacement: `${packagesRoot}/$1/lib` },
|
|
]);
|
|
|
|
await expect(ownership.resolveModuleBoundary(modulePath)).resolves.toBeNull();
|
|
});
|
|
|
|
it("does not broaden a regex capture file target within the owning package", async () => {
|
|
const projectRoot = path.join(tmpDir, "resolved-regex-file-app");
|
|
const packagesRoot = path.join(tmpDir, "resolved-regex-file-packages");
|
|
const packageRoot = path.join(packagesRoot, "ui");
|
|
const entryPath = path.join(packageRoot, "lib", "index.js");
|
|
const modulePath = path.join(packageRoot, "lib", "chunk.js");
|
|
await fs.mkdir(projectRoot, { recursive: true });
|
|
await fs.mkdir(path.dirname(modulePath), { recursive: true });
|
|
await fs.writeFile(path.join(packageRoot, "package.json"), '{"name":"@scope/ui"}');
|
|
await fs.writeFile(entryPath, "export {};");
|
|
await fs.writeFile(modulePath, "export {};");
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
ownership.configure(projectRoot, [
|
|
{ find: /^@scope\/(.*)$/, replacement: `${packagesRoot}/$1/lib/index.js` },
|
|
]);
|
|
|
|
await expect(ownership.resolveModuleBoundary(modulePath)).resolves.toBeNull();
|
|
await expect(ownership.resolveModuleBoundary(entryPath)).resolves.not.toBeNull();
|
|
});
|
|
|
|
it("rejects assets outside the resolved package boundary", async () => {
|
|
const packageRoot = path.join(tmpDir, "contained-package");
|
|
const assetPath = path.join(packageRoot, "font.ttf");
|
|
const outsidePath = path.join(tmpDir, "secret.txt");
|
|
await fs.mkdir(packageRoot, { recursive: true });
|
|
await fs.writeFile(assetPath, "font");
|
|
await fs.writeFile(outsidePath, "secret");
|
|
const realPackageRoot = await fs.realpath(packageRoot);
|
|
const realAssetPath = await fs.realpath(assetPath);
|
|
|
|
const ownership = new OgAssetOwnership();
|
|
|
|
await expect(ownership.resolveContainedAsset(realPackageRoot, assetPath)).resolves.toBe(
|
|
canonical(realAssetPath),
|
|
);
|
|
await expect(ownership.resolveContainedAsset(realPackageRoot, outsidePath)).resolves.toBeNull();
|
|
});
|
|
});
|