summaryrefslogtreecommitdiff
path: root/packages/integrations/vercel/src/lib/fs.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/vercel/src/lib/fs.ts')
-rw-r--r--packages/integrations/vercel/src/lib/fs.ts57
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;
+}