diff options
Diffstat (limited to 'packages/integrations/vercel/src/lib/nft.ts')
-rw-r--r-- | packages/integrations/vercel/src/lib/nft.ts | 84 |
1 files changed, 68 insertions, 16 deletions
diff --git a/packages/integrations/vercel/src/lib/nft.ts b/packages/integrations/vercel/src/lib/nft.ts index b18cb73ef..ba3677583 100644 --- a/packages/integrations/vercel/src/lib/nft.ts +++ b/packages/integrations/vercel/src/lib/nft.ts @@ -1,38 +1,90 @@ import { nodeFileTrace } from '@vercel/nft'; import * as fs from 'node:fs/promises'; +import nodePath from 'node:path'; import { fileURLToPath } from 'node:url'; export async function copyDependenciesToFunction( - root: URL, - functionFolder: URL, - serverEntry: string -) { - const entryPath = fileURLToPath(new URL(`./${serverEntry}`, functionFolder)); + entry: URL, + outDir: URL +): Promise<{ handler: string }> { + const entryPath = fileURLToPath(entry); + + // Get root of folder of the system (like C:\ on Windows or / on Linux) + let base = entry; + while (fileURLToPath(base) !== fileURLToPath(new URL('../', base))) { + base = new URL('../', base); + } const result = await nodeFileTrace([entryPath], { - base: fileURLToPath(root), + base: fileURLToPath(base), }); - for (const file of result.fileList) { - if (file.startsWith('.vercel/')) continue; - const origin = new URL(file, root); - const dest = new URL(file, functionFolder); + if (result.fileList.size === 0) throw new Error('[@astrojs/vercel] No files found'); + + for (const error of result.warnings) { + if (error.message.startsWith('Failed to resolve dependency')) { + const [, module, file] = /Cannot find module '(.+?)' loaded from (.+)/.exec(error.message)!; + + // The import(astroRemark) sometimes fails to resolve, but it's not a problem + if (module === '@astrojs/') continue; + + if (entryPath === file) { + console.warn( + `[@astrojs/vercel] The module "${module}" couldn't be resolved. This may not be a problem, but it's worth checking.` + ); + } else { + console.warn( + `[@astrojs/vercel] The module "${module}" inside the file "${file}" couldn't be resolved. This may not be a problem, but it's worth checking.` + ); + } + } else { + throw error; + } + } - const meta = await fs.stat(origin); - const isSymlink = (await fs.lstat(origin)).isSymbolicLink(); + const fileList = [...result.fileList]; + + let commonAncestor = nodePath.dirname(fileList[0]); + for (const file of fileList.slice(1)) { + while (!file.startsWith(commonAncestor)) { + commonAncestor = nodePath.dirname(commonAncestor); + } + } + + for (const file of fileList) { + const origin = new URL(file, base); + const dest = new URL(nodePath.relative(commonAncestor, file), outDir); + + const realpath = await fs.realpath(origin); + const isSymlink = realpath !== fileURLToPath(origin); + const isDir = (await fs.stat(origin)).isDirectory(); // Create directories recursively - if (meta.isDirectory() && !isSymlink) { + if (isDir && !isSymlink) { await fs.mkdir(new URL('..', dest), { recursive: true }); } else { await fs.mkdir(new URL('.', dest), { recursive: true }); } if (isSymlink) { - const link = await fs.readlink(origin); - await fs.symlink(link, dest, meta.isDirectory() ? 'dir' : 'file'); - } else { + const realdest = fileURLToPath( + new URL( + nodePath.relative(nodePath.join(fileURLToPath(base), commonAncestor), realpath), + outDir + ) + ); + await fs.symlink( + nodePath.relative(fileURLToPath(new URL('.', dest)), realdest), + dest, + isDir ? 'dir' : 'file' + ); + } else if (!isDir) { await fs.copyFile(origin, dest); } } + + return { + // serverEntry location inside the outDir + handler: nodePath.relative(nodePath.join(fileURLToPath(base), commonAncestor), entryPath), + }; } |