diff options
Diffstat (limited to 'packages/integrations/vercel/src/lib/fs.ts')
-rw-r--r-- | packages/integrations/vercel/src/lib/fs.ts | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index 64c4c69ba..47b218ce5 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,5 +1,7 @@ import type { PathLike } from 'node:fs'; import * as fs from 'node:fs/promises'; +import nodePath from 'node:path'; +import { fileURLToPath } from 'node:url'; export async function writeJson<T>(path: PathLike, data: T) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); @@ -15,3 +17,58 @@ export async function emptyDir(dir: PathLike): Promise<void> { } export const getVercelOutput = (root: URL) => new URL('./.vercel/output/', root); + +/** + * Copies files into a folder keeping the folder structure intact. + * The resulting file tree will start at the common ancestor. + * + * @param {URL[]} files A list of files to copy (absolute path). + * @param {URL} outDir Destination folder where to copy the files to (absolute path). + * @param {URL[]} [exclude] A list of files to exclude (absolute path). + * @returns {Promise<string>} The common ancestor of the copied files. + */ +export async function copyFilesToFunction( + files: URL[], + outDir: URL, + exclude: URL[] = [] +): Promise<string> { + const excludeList = exclude.map(fileURLToPath); + const fileList = files.map(fileURLToPath).filter((f) => !excludeList.includes(f)); + + if (files.length === 0) throw new Error('[@astrojs/vercel] No files found to copy'); + + let commonAncestor = nodePath.dirname(fileList[0]); + for (const file of fileList.slice(1)) { + while (!file.startsWith(commonAncestor)) { + commonAncestor = nodePath.dirname(commonAncestor); + } + } + + for (const origin of fileList) { + const dest = new URL(nodePath.relative(commonAncestor, origin), outDir); + + const realpath = await fs.realpath(origin); + const isSymlink = realpath !== origin; + const isDir = (await fs.stat(origin)).isDirectory(); + + // Create directories recursively + if (isDir && !isSymlink) { + await fs.mkdir(new URL('..', dest), { recursive: true }); + } else { + await fs.mkdir(new URL('.', dest), { recursive: true }); + } + + if (isSymlink) { + const realdest = fileURLToPath(new URL(nodePath.relative(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 commonAncestor; +} |