-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(vercel): now works with monorepos (#5033)
* Upgraded nft * Handle monorepo better * Changeset * Fixed common ancestor * Fixed outdir
- Loading branch information
Showing
6 changed files
with
107 additions
and
248 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@astrojs/vercel': patch | ||
--- | ||
|
||
- Upgraded @vercel/nft to 0.22.1 | ||
- Fix monorepos (#5020) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.