summaryrefslogtreecommitdiff
path: root/packages/integrations/vercel/src/lib/searchRoot.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations/vercel/src/lib/searchRoot.ts')
-rw-r--r--packages/integrations/vercel/src/lib/searchRoot.ts101
1 files changed, 101 insertions, 0 deletions
diff --git a/packages/integrations/vercel/src/lib/searchRoot.ts b/packages/integrations/vercel/src/lib/searchRoot.ts
new file mode 100644
index 000000000..832f6e498
--- /dev/null
+++ b/packages/integrations/vercel/src/lib/searchRoot.ts
@@ -0,0 +1,101 @@
+// Taken from: https://github.com/vitejs/vite/blob/1a76300cd16827f0640924fdc21747ce140c35fb/packages/vite/src/node/server/searchRoot.ts
+// MIT license
+// See https://github.com/vitejs/vite/blob/1a76300cd16827f0640924fdc21747ce140c35fb/LICENSE
+import fs from 'node:fs';
+import { dirname, join } from 'node:path';
+
+// https://github.com/vitejs/vite/issues/2820#issuecomment-812495079
+const ROOT_FILES = [
+ // '.git',
+
+ // https://pnpm.io/workspaces/
+ 'pnpm-workspace.yaml',
+
+ // https://rushjs.io/pages/advanced/config_files/
+ // 'rush.json',
+
+ // https://nx.dev/latest/react/getting-started/nx-setup
+ // 'workspace.json',
+ // 'nx.json',
+
+ // https://github.com/lerna/lerna#lernajson
+ 'lerna.json',
+];
+
+export function tryStatSync(file: string): fs.Stats | undefined {
+ try {
+ // The "throwIfNoEntry" is a performance optimization for cases where the file does not exist
+ return fs.statSync(file, { throwIfNoEntry: false });
+ } catch {
+ // Ignore errors
+ }
+}
+
+export function isFileReadable(filename: string): boolean {
+ if (!tryStatSync(filename)) {
+ return false;
+ }
+
+ try {
+ // Check if current process has read permission to the file
+ fs.accessSync(filename, fs.constants.R_OK);
+
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+// npm: https://docs.npmjs.com/cli/v7/using-npm/workspaces#installing-workspaces
+// yarn: https://classic.yarnpkg.com/en/docs/workspaces/#toc-how-to-use-it
+function hasWorkspacePackageJSON(root: string): boolean {
+ const path = join(root, 'package.json');
+ if (!isFileReadable(path)) {
+ return false;
+ }
+ try {
+ const content = JSON.parse(fs.readFileSync(path, 'utf-8')) || {};
+ return !!content.workspaces;
+ } catch {
+ return false;
+ }
+}
+
+function hasRootFile(root: string): boolean {
+ return ROOT_FILES.some((file) => fs.existsSync(join(root, file)));
+}
+
+function hasPackageJSON(root: string) {
+ const path = join(root, 'package.json');
+ return fs.existsSync(path);
+}
+
+/**
+ * Search up for the nearest `package.json`
+ */
+export function searchForPackageRoot(current: string, root = current): string {
+ if (hasPackageJSON(current)) return current;
+
+ const dir = dirname(current);
+ // reach the fs root
+ if (!dir || dir === current) return root;
+
+ return searchForPackageRoot(dir, root);
+}
+
+/**
+ * Search up for the nearest workspace root
+ */
+export function searchForWorkspaceRoot(
+ current: string,
+ root = searchForPackageRoot(current)
+): string {
+ if (hasRootFile(current)) return current;
+ if (hasWorkspacePackageJSON(current)) return current;
+
+ const dir = dirname(current);
+ // reach the fs root
+ if (!dir || dir === current) return root;
+
+ return searchForWorkspaceRoot(dir, root);
+}