Skip to content

Commit

Permalink
fix: Do not fail if pages/apps dir cannot be found
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinpalkovic committed Aug 29, 2024
1 parent 8ce7f2d commit 391a88f
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 deletions.
5 changes: 2 additions & 3 deletions src/plugins/next-swc/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { resolve } from "node:path";
import nextLoadJsConfig from "next/dist/build/load-jsconfig.js";
import { transform } from "next/dist/build/swc/index.js";
import { findPagesDir } from "next/dist/lib/find-pages-dir.js";
import type { NextConfigComplete } from "next/dist/server/config-shared.js";
import { type Plugin, createFilter } from "vite";

Expand All @@ -23,7 +22,7 @@ export function vitePluginNextSwc(
nextConfigResolver: PromiseWithResolvers<NextConfigComplete>,
) {
let loadedJSConfig: Awaited<ReturnType<typeof loadJsConfig>>;
let nextDirectories: ReturnType<typeof findPagesDir>;
let nextDirectories: ReturnType<typeof NextUtils.findNextDirectories>;
let isServerEnvironment: boolean;
let isDev: boolean;
let isEsmProject: boolean;
Expand All @@ -37,7 +36,7 @@ export function vitePluginNextSwc(
enforce: "pre" as const,
async config(config, env) {
const nextConfig = await nextConfigResolver.promise;
nextDirectories = findPagesDir(resolvedDir);
nextDirectories = NextUtils.findNextDirectories(resolvedDir);
loadedJSConfig = await loadJsConfig(resolvedDir, nextConfig);
isDev = env.mode !== "production";
packageJson = await NextUtils.loadClosestPackageJson(resolvedDir);
Expand Down
107 changes: 107 additions & 0 deletions src/utils/nextjs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import fs from "node:fs";
import path from "node:path";
import { findPagesDir } from "next/dist/lib/find-pages-dir.js";
import { describe, expect, it, vi } from "vitest";
import {
findNextDirectories,
loadClosestPackageJson,
loadSWCBindingsEagerly,
shouldOutputCommonJs,
} from "./nextjs";

// Mocking the necessary modules and functions
vi.mock("node:fs");
vi.mock("node:path");
vi.mock("next/dist/build/output/log.js");
vi.mock("@next/env");
vi.mock("next/dist/build/swc/index.js", () => ({
loadBindings: vi.fn(),
lockfilePatchPromise: { cur: Promise.resolve() },
}));
vi.mock("next/dist/lib/find-pages-dir.js");

describe("nextjs.ts", () => {
describe("loadSWCBindingsEagerly", () => {
it("should call loadBindings and lockfilePatchPromise.cur", async () => {
const { loadBindings, lockfilePatchPromise } = await import(
"next/dist/build/swc/index.js"
);

await loadSWCBindingsEagerly();

expect(loadBindings).toHaveBeenCalled();
expect(lockfilePatchPromise.cur).resolves.toBeUndefined();
});
});

describe("shouldOutputCommonJs", () => {
it("should return true for .cjs files", () => {
expect(shouldOutputCommonJs("file.cjs")).toBe(true);
});

it("should return true for next/dist paths", () => {
expect(shouldOutputCommonJs("next/dist/shared/lib/somefile.js")).toBe(
true,
);
});

it("should return false for other files", () => {
expect(shouldOutputCommonJs("file.js")).toBe(false);
});
});

describe("loadClosestPackageJson", () => {
it("should load the closest package.json file", async () => {
const readFileMock = vi.fn().mockResolvedValue('{"name": "test"}');
fs.promises.readFile = readFileMock;

const result = await loadClosestPackageJson("/path/to/dir");

expect(readFileMock).toHaveBeenCalledWith(
path.join("/path/to/dir", "package.json"),
"utf8",
);
expect(result).toEqual({ name: "test" });
});

it("should throw an error after 5 attempts", async () => {
const readFileMock = vi
.fn()
.mockRejectedValue(new Error("File not found"));
fs.promises.readFile = readFileMock;

await expect(loadClosestPackageJson("/path/to/dir")).rejects.toThrow(
"Can't resolve main package.json file",
);
});
});

describe("findNextDirectories", () => {
it("should return directories from findPagesDir", () => {
vi.mocked(findPagesDir).mockReturnValue({
appDir: "/path/to/app",
pagesDir: "/path/to/pages",
});

const result = findNextDirectories("/path/to/dir");

expect(result).toEqual({
appDir: "/path/to/app",
pagesDir: "/path/to/pages",
});
});

it("should return default directories if findPagesDir throws an error", () => {
vi.mocked(findPagesDir).mockImplementation(() => {
throw new Error("Not found");
});

const result = findNextDirectories("/path/to/dir");

expect(result).toEqual({
appDir: path.join("/path/to/dir", "app"),
pagesDir: path.join("/path/to/dir", "pages"),
});
});
});
});
16 changes: 15 additions & 1 deletion src/utils/nextjs.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import fs from "node:fs";
import { join } from "node:path";
import path, { join } from "node:path";
import * as nextEnv from "@next/env";
import Log from "next/dist/build/output/log.js";
import {
loadBindings,
lockfilePatchPromise,
} from "next/dist/build/swc/index.js";
import { findPagesDir } from "next/dist/lib/find-pages-dir.js";
import type { NextConfigComplete } from "next/dist/server/config-shared.js";

const nextDistPath =
Expand Down Expand Up @@ -60,3 +61,16 @@ export async function loadClosestPackageJson(dir: string, attempts = 1) {
return loadClosestPackageJson(dir, attempts + 1);
}
}

export function findNextDirectories(
dir: string,
): ReturnType<typeof findPagesDir> {
try {
return findPagesDir(dir);
} catch (e) {
return {
appDir: path.join(dir, "app"),
pagesDir: path.join(dir, "pages"),
};
}
}

0 comments on commit 391a88f

Please sign in to comment.