From e4215762f6c73b6a30508aed89ee184b24b9d66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Fri, 22 Oct 2021 15:16:35 +0100 Subject: [PATCH] feat: resolve modules from `pluginsModulesPath` in NFT (#762) --- src/runtimes/node/bundlers/nft/index.ts | 32 +++++++++++++++++++++++-- tests/main.js | 2 +- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/runtimes/node/bundlers/nft/index.ts b/src/runtimes/node/bundlers/nft/index.ts index 85db103c9..4bef71053 100644 --- a/src/runtimes/node/bundlers/nft/index.ts +++ b/src/runtimes/node/bundlers/nft/index.ts @@ -1,6 +1,7 @@ -import { dirname, normalize, resolve } from 'path' +import { basename, dirname, join, normalize, resolve } from 'path' import { nodeFileTrace } from '@vercel/nft' +import resolveDependency from '@vercel/nft/out/resolve-dependency' import type { BundleFunction } from '..' import type { FunctionConfig } from '../../../../config' @@ -16,7 +17,15 @@ interface NftCache { [key: string]: unknown } -const bundle: BundleFunction = async ({ basePath, config, mainFile, repositoryRoot = basePath }) => { +const appearsToBeModuleName = (name: string) => !name.startsWith('.') + +const bundle: BundleFunction = async ({ + basePath, + config, + mainFile, + pluginsModulesPath, + repositoryRoot = basePath, +}) => { const { includedFiles = [], includedFilesBasePath } = config const { exclude: excludedPaths, paths: includedFilePaths } = await getPathsOfIncludedFiles( includedFiles, @@ -30,6 +39,7 @@ const bundle: BundleFunction = async ({ basePath, config, mainFile, repositoryRo basePath: repositoryRoot, config, mainFile, + pluginsModulesPath, }) const filteredIncludedPaths = filterExcludedPaths([...dependencyPaths, ...includedFilePaths], excludedPaths) const dirnames = filteredIncludedPaths.map((filePath) => normalize(dirname(filePath))).sort() @@ -48,10 +58,12 @@ const traceFilesAndTranspile = async function ({ basePath, config, mainFile, + pluginsModulesPath, }: { basePath?: string config: FunctionConfig mainFile: string + pluginsModulesPath?: string }) { const fsCache: FsCache = {} const cache: NftCache = {} @@ -68,6 +80,22 @@ const traceFilesAndTranspile = async function ({ return null } + throw error + } + }, + resolve: async (specifier, parent, ...args) => { + try { + return await resolveDependency(specifier, parent, ...args) + } catch (error) { + // If we get a `MODULE_NOT_FOUND` error for what appears to be a module + // name, we try to resolve it a second time using `pluginsModulesPath` + // as the base directory. + if (error.code === 'MODULE_NOT_FOUND' && pluginsModulesPath && appearsToBeModuleName(specifier)) { + const newParent = join(pluginsModulesPath, basename(parent)) + + return await resolveDependency(specifier, newParent, ...args) + } + throw error } }, diff --git a/tests/main.js b/tests/main.js index 1d54cb837..ca7aa3309 100644 --- a/tests/main.js +++ b/tests/main.js @@ -335,7 +335,7 @@ testMany( testMany( 'Resolves dependencies from .netlify/plugins/node_modules', - ['bundler_default', 'bundler_esbuild', 'bundler_esbuild_zisi', 'bundler_default_parse_esbuild', 'todo:bundler_nft'], + ['bundler_default', 'bundler_esbuild', 'bundler_esbuild_zisi', 'bundler_default_parse_esbuild', 'bundler_nft'], async (options, t) => { await zipNode(t, 'node-module-next-image', { opts: options }) },