Workspace Root Detector
The `workspace-root` package provides a robust utility for programmatically identifying the root directory of a monorepo workspace. It supports various popular package managers and monorepo tools including Yarn, pnpm, Lerna, and Bun. The library exposes both synchronous (`workspaceRootSync`) and asynchronous (`workspaceRoot`) functions, allowing developers to choose the appropriate API for their context, with an optional `cwd` parameter to specify the starting search path. Currently stable at version 3.3.1, the package demonstrates a consistent release cadence with frequent minor updates and patches, and underwent a significant architectural refactor in version 3.0.0. Its primary differentiator is its broad compatibility across different monorepo configurations and package manager specifics, such as Yarn's `nohoist` option, ensuring accurate root detection even in complex setups.
Common errors
-
Error: Cannot find module 'workspace-root'
cause The package is not installed, or the Node.js module resolution path is incorrect.fixEnsure the package is installed: `npm install workspace-root`, `yarn add workspace-root`, or `pnpm add workspace-root`. Check your `node_modules` directory and `NODE_PATH` environment variable if running in a non-standard environment. -
TypeError: workspaceRoot is not a function
cause Incorrect import statement or attempting to destructure a CommonJS `require` call in a context expecting a different module format (e.g., mixing `import { workspaceRoot } from 'workspace-root'` with `require('workspace-root').default`).fixFor ESM, use `import { workspaceRoot } from 'workspace-root';`. For CJS, use `const { workspaceRoot } = require('workspace-root');`. Ensure you are destructuring correctly based on the module type. -
Promise { <pending> }cause The asynchronous `workspaceRoot()` function was called, but its Promise return value was not handled with `await` or `.then()`.fixTo get the resolved value, `await` the function call within an `async` context: `const path = await workspaceRoot();` or use a Promise callback: `workspaceRoot().then(path => console.log(path));`.
Warnings
- breaking Version 3.0.0 introduced significant internal changes to the build process, including using esbuild and new output formats. While core API (`workspaceRoot`, `workspaceRootSync`) remained stable, consumers relying on specific module resolutions, bundler configurations, or deeply internal package structure might require adjustments.
- gotcha Prior to version 3.3.0, the utility might not have correctly identified the workspace root in monorepos utilizing Yarn's `workspaces.nohoist` feature, potentially returning `null` or an incorrect path.
- gotcha The `workspaceRoot` function returns a Promise. Forgetting to `await` its result or chain with `.then()` will lead to handling a Promise object directly instead of the resolved path.
- gotcha While `workspace-root` aims for broad compatibility, complex or non-standard monorepo setups (e.g., deeply nested workspaces, custom `package.json` structures, specific `pnpm` or `yarn` configurations outside conventional patterns) might occasionally result in `null` being returned.
Install
-
npm install workspace-root -
yarn add workspace-root -
pnpm add workspace-root
Imports
- workspaceRoot
const workspaceRoot = require('workspace-root')import { workspaceRoot } from 'workspace-root' - workspaceRootSync
const { workspaceRootSync } = require('workspace-root')import { workspaceRootSync } from 'workspace-root' - WorkspaceRootTypes
import type { WorkspaceRootResult } from 'workspace-root'
Quickstart
import { workspaceRoot, workspaceRootSync } from 'workspace-root';
// Asynchronous usage
async function findAsyncRoot() {
const path = await workspaceRoot();
if (path) {
console.log('The workspace root (async) is: ', path);
} else {
console.log('No workspace root found (async).');
}
}
findAsyncRoot();
// Synchronous usage
const syncPath = workspaceRootSync();
if (syncPath) {
console.log('The workspace root (sync) is: ', syncPath);
} else {
console.log('No workspace root found (sync).');
}
// Example with custom current working directory
// For demonstration, let's assume '/tmp' exists and you want to search from there.
// In a real scenario, you'd pass a path relevant to your project structure.
const customCwd = process.env.TEMP || '/tmp'; // Use a temporary directory for example
console.log(`Searching from custom CWD: ${customCwd}`);
workspaceRoot(customCwd).then(path => {
console.log(`The workspace root from ${customCwd} (async) is: `, path);
});
console.log(`The workspace root from ${customCwd} (sync) is: `, workspaceRootSync(customCwd));