diff --git a/packages/wrangler/src/__tests__/module-collection.test.ts b/packages/wrangler/src/__tests__/module-collection.test.ts new file mode 100644 index 000000000000..5940c237f697 --- /dev/null +++ b/packages/wrangler/src/__tests__/module-collection.test.ts @@ -0,0 +1,17 @@ +import { extractPackageName } from "../deployment-bundle/module-collection"; + +describe("Module Collection", () => { + describe("extractPackageName", () => { + test.each` + importString | packageName + ${"wrangler"} | ${"wrangler"} + ${"wrangler/example"} | ${"wrangler"} + ${"wrangler/example.wasm"} | ${"wrangler"} + ${"@cloudflare/wrangler"} | ${"@cloudflare/wrangler"} + ${"@cloudflare/wrangler/example"} | ${"@cloudflare/wrangler"} + ${"@cloudflare/wrangler/example.wasm"} | ${"@cloudflare/wrangler"} + `("$importString --> $packageName", ({ importString, packageName }) => { + expect(extractPackageName(importString)).toBe(packageName); + }); + }); +}); diff --git a/packages/wrangler/src/deployment-bundle/module-collection.ts b/packages/wrangler/src/deployment-bundle/module-collection.ts index 76fa80bc162a..44554dd694b1 100644 --- a/packages/wrangler/src/deployment-bundle/module-collection.ts +++ b/packages/wrangler/src/deployment-bundle/module-collection.ts @@ -65,6 +65,21 @@ export const noopModuleCollector: ModuleCollector = { }, }; +// Extracts a package name from a string that may be a file path +// or a package name. Returns null if the string is not a valid +// Handles `wrangler`, `wrangler/example`, `wrangler/example.wasm`, +// `@cloudflare/wrangler`, `@cloudflare/wrangler/example`, etc. +export function extractPackageName(packagePath: string) { + const match = packagePath.match(/^(@[^/]+\/)?([^/]+)/); + + if (match) { + const scoped = match[1] || ""; + const packageName = match[2]; + return `${scoped}${packageName}`; + } + return null; +} + export function createModuleCollector(props: { entry: Entry; findAdditionalModules: boolean; @@ -255,12 +270,18 @@ export function createModuleCollector(props: { // Check if this file is possibly from an npm package // and if so, validate the import against the package.json exports // and resolve the file path to the correct file. - if (args.path.includes("/") && !args.path.startsWith("./")) { - const dirName = path.dirname(args.path); + if (args.path.includes("/") && !args.path.startsWith(".")) { + // get npm package name from string, taking into account scoped packages + const packageName = extractPackageName(args.path); + if (!packageName) { + throw new Error( + `Unable to extract npm package name from ${args.path}` + ); + } const packageJsonPath = path.join( args.resolveDir, "node_modules", - dirName, + packageName, "package.json" ); // Try and read the npm package's package.json @@ -272,13 +293,13 @@ export function createModuleCollector(props: { ); const testResolved = resolveExports( packageJson, - args.path.replace(`${dirName}/`, "") + args.path.replace(`${packageName}/`, "") ); if (testResolved) { filePath = path.join( args.resolveDir, "node_modules", - dirName, + packageName, testResolved[0] ); }