diff --git a/libs/qwikdev-astro/src/scan.ts b/libs/qwikdev-astro/src/scan.ts index d60ff1f3..e46beecf 100644 --- a/libs/qwikdev-astro/src/scan.ts +++ b/libs/qwikdev-astro/src/scan.ts @@ -1,5 +1,6 @@ import { execFile } from "node:child_process"; import { relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; import { promisify } from "node:util"; import type { AstroConfig } from "astro"; import { QWIK_ENTRYPOINT_PATTERN, SCAN_EXTENSIONS } from "./constants"; @@ -47,7 +48,9 @@ export async function scanQwikEntrypoints( filter: (id: string) => boolean, debug?: boolean ): Promise> { - const rootDir = config.root.pathname; + // fileURLToPath, not .pathname: on Windows .pathname is "/C:/project/", + // which is not a valid cwd (spawn fails with ENOENT) or resolve() base. + const rootDir = fileURLToPath(config.root); const stdout = await grepQwikFiles(rootDir); if (!stdout) return new Set(); diff --git a/libs/qwikdev-astro/tests/unit/scan.test.ts b/libs/qwikdev-astro/tests/unit/scan.test.ts index 318822cb..8367c12f 100644 --- a/libs/qwikdev-astro/tests/unit/scan.test.ts +++ b/libs/qwikdev-astro/tests/unit/scan.test.ts @@ -1,5 +1,9 @@ -import { describe, expect, it } from "vitest"; -import { createQwikFileFilter, resolveQwikPaths } from "../../src/scan"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { pathToFileURL } from "node:url"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; +import { createQwikFileFilter, resolveQwikPaths, scanQwikEntrypoints } from "../../src/scan"; describe("resolveQwikPaths", () => { function makeConfig(overrides: { adapter?: { name: string } } = {}) { @@ -33,6 +37,35 @@ describe("resolveQwikPaths", () => { }); }); +describe("scanQwikEntrypoints", () => { + let root: string; + + beforeEach(() => { + root = mkdtempSync(join(tmpdir(), "qwik-astro-scan-")); + mkdirSync(join(root, "src")); + mkdirSync(join(root, "node_modules", "dep"), { recursive: true }); + writeFileSync(join(root, "src", "counter.tsx"), 'import { component$ } from "@qwik.dev/core";\n'); + writeFileSync(join(root, "src", "plain.tsx"), "export const x = 1;\n"); + writeFileSync(join(root, "node_modules", "dep", "index.js"), 'require("@qwik.dev/core");\n'); + }); + + afterEach(() => { + rmSync(root, { recursive: true, force: true }); + }); + + it("finds entrypoints as native absolute paths from a file URL root", async () => { + const config = { root: pathToFileURL(`${root}/`) } as any; + const entrypoints = await scanQwikEntrypoints(config, () => true); + expect([...entrypoints]).toEqual([join(root, "src", "counter.tsx")]); + }); + + it("respects the filter", async () => { + const config = { root: pathToFileURL(`${root}/`) } as any; + const entrypoints = await scanQwikEntrypoints(config, () => false); + expect(entrypoints.size).toBe(0); + }); +}); + describe("createQwikFileFilter", () => { it("always returns true for non-transform hooks", () => { const filter = createQwikFileFilter(() => true);