Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@manypkg/find-root

Package Overview
Dependencies
Maintainers
2
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@manypkg/find-root - npm Package Compare versions

Comparing version 1.1.0 to 2.0.0

dist/manypkg-find-root.cjs.d.ts

15

CHANGELOG.md
# @manypkg/find-root
## 2.0.0
### Major Changes
- [#151](https://github.com/Thinkmill/manypkg/pull/151) [`a01efc9`](https://github.com/Thinkmill/manypkg/commit/a01efc9c25900b7d21b6d517a2021b021f8b3922) Thanks [@elliot-nelson](https://github.com/elliot-nelson)! - The `find-root` package now returns a new `MonorepoRoot` interface, instead of a string. This interface provides a `rootDir` for the discovered monorepo, and a `tool` object, which is an object using the new `Tool` interface provided by `@manypkg/tools`.
* [#165](https://github.com/Thinkmill/manypkg/pull/165) [`7b9c4f6`](https://github.com/Thinkmill/manypkg/commit/7b9c4f6d9a73de8b3cc45af5abc8af47f6b9206c) Thanks [@Andarist](https://github.com/Andarist)! - Removed support for Bolt monorepos.
- [#162](https://github.com/Thinkmill/manypkg/pull/162) [`f046017`](https://github.com/Thinkmill/manypkg/commit/f046017af2349f0c1bbc5b25224da0ede8ddc2d6) Thanks [@Andarist](https://github.com/Andarist)! - Increased the transpilation target of the source files to `node@14.x`. At the same time added this as `package.json#engines` to explicitly declare the minimum node version supported by this package.
### Patch Changes
- Updated dependencies [[`a01efc9`](https://github.com/Thinkmill/manypkg/commit/a01efc9c25900b7d21b6d517a2021b021f8b3922)]:
- @manypkg/tools@1.0.0
## 1.1.0

@@ -4,0 +19,0 @@

5

dist/declarations/src/index.d.ts

@@ -0,1 +1,2 @@

import { MonorepoRoot } from "@manypkg/tools";
export declare class NoPkgJsonFound extends Error {

@@ -5,3 +6,3 @@ directory: string;

}
export declare function findRoot(cwd: string): Promise<string>;
export declare function findRootSync(cwd: string): string;
export declare function findRoot(cwd: string): Promise<MonorepoRoot>;
export declare function findRootSync(cwd: string): MonorepoRoot;

11

package.json
{
"name": "@manypkg/find-root",
"version": "1.1.0",
"main": "dist/find-root.cjs.js",
"module": "dist/find-root.esm.js",
"version": "2.0.0",
"license": "MIT",
"main": "dist/manypkg-find-root.cjs.js",
"module": "dist/manypkg-find-root.esm.js",
"dependencies": {
"@babel/runtime": "^7.5.5",
"@manypkg/tools": "^1.0.0",
"@types/node": "^12.7.1",

@@ -15,3 +15,6 @@ "find-up": "^4.1.0",

"fixturez": "^1.1.0"
},
"engines": {
"node": ">=14.18.0"
}
}
# @manypkg/find-root
> Find the root of a monorepo with Yarn workspaces, Bolt or pnpm
> Find the root of a monorepo with Yarn workspaces, Lerna, pnpm or Rush

@@ -5,0 +5,0 @@ ## Install

import { findRoot, findRootSync } from ".";
import fixturez from "fixturez";
import path from "path";
import fs from "fs-extra";
import { LernaTool, PnpmTool, RootTool, YarnTool } from "@manypkg/tools";
let f = fixturez(__dirname);

@@ -13,6 +14,9 @@

let tmpPath = f.copy("basic");
let packagesRoot = await findRoot(
let monorepoRoot = await findRoot(
path.join(tmpPath, "packages", "package-one", "src")
);
expect(packagesRoot).toBe(tmpPath);
expect(monorepoRoot).toEqual({
tool: YarnTool,
rootDir: tmpPath,
});
});

@@ -22,9 +26,12 @@

let tmpPath = f.copy("basic-lerna");
let packagesRoot = await findRoot(
let monorepoRoot = await findRoot(
path.join(tmpPath, "packages", "package-one", "src")
);
expect(packagesRoot).toBe(tmpPath);
expect(monorepoRoot).toEqual({
tool: LernaTool,
rootDir: tmpPath,
});
});
test("it returns the root of a lerna monorepo with useWorkspaces=true", async () => {
test("treats a lerna monorepo with useWorkspaces on as a yarn monorepo", async () => {
let tmpPath = f.copy("basic");

@@ -34,7 +41,9 @@ // technically legal placement for lerna.json, but broken in practice

// to be encountered "before" the root manifest and its valid workspaces config.
await fs.outputJSON(path.join(tmpPath, "packages", "lerna.json"), {useWorkspaces: true})
let packagesRoot = await findRoot(
let monorepoRoot = await findRoot(
path.join(tmpPath, "packages", "package-one", "src")
);
expect(packagesRoot).toBe(tmpPath);
expect(monorepoRoot).toEqual({
tool: YarnTool,
rootDir: tmpPath,
});
});

@@ -44,6 +53,9 @@

let tmpPath = f.copy("basic-pnpm");
let packagesRoot = await findRoot(
let monorepoRoot = await findRoot(
path.join(tmpPath, "packages", "package-one", "src")
);
expect(packagesRoot).toBe(tmpPath);
expect(monorepoRoot).toEqual({
tool: PnpmTool,
rootDir: tmpPath,
});
});

@@ -53,4 +65,7 @@

let tmpPath = f.copy("single-pkg");
let packagesRoot = await findRoot(path.join(tmpPath, "src"));
expect(packagesRoot).toBe(tmpPath);
let monorepoRoot = await findRoot(path.join(tmpPath, "src"));
expect(monorepoRoot).toEqual({
tool: RootTool,
rootDir: tmpPath,
});
});

@@ -57,0 +72,0 @@ };

@@ -5,2 +5,24 @@ import findUp, { sync as findUpSync } from "find-up";

import {
Tool,
RootTool,
MonorepoRoot,
LernaTool,
PnpmTool,
RushTool,
YarnTool,
} from "@manypkg/tools";
/**
* A default ordering for monorepo tool checks.
*
* This ordering is designed to check the most typical package.json-based
* monorepo implementations first, with tools based on custom file schemas
* checked last.
*/
const defaultOrder: Tool[] = [YarnTool, PnpmTool, LernaTool, RushTool];
const isNoEntryError = (err: unknown): boolean =>
!!err && typeof err === "object" && "code" in err && err.code === "ENOENT";
export class NoPkgJsonFound extends Error {

@@ -16,121 +38,88 @@ directory: string;

async function hasWorkspacesConfiguredViaPkgJson(
directory: string,
firstPkgJsonDirRef: { current: string | undefined }
) {
try {
let pkgJson = await fs.readJson(path.join(directory, "package.json"));
if (firstPkgJsonDirRef.current === undefined) {
firstPkgJsonDirRef.current = directory;
}
if (pkgJson.workspaces || pkgJson.bolt) {
return directory;
}
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
}
}
export async function findRoot(cwd: string): Promise<MonorepoRoot> {
let monorepoRoot: MonorepoRoot | undefined;
async function hasWorkspacesConfiguredViaLerna(directory: string) {
try {
let lernaJson = await fs.readJson(path.join(directory, "lerna.json"));
if (lernaJson.useWorkspaces !== true) {
return directory;
}
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
}
}
await findUp(
async (directory) => {
return Promise.all(
defaultOrder.map(async (tool): Promise<MonorepoRoot | undefined> => {
if (await tool.isMonorepoRoot(directory)) {
return {
tool: tool,
rootDir: directory,
};
}
})
)
.then((x) => x.find((value) => value))
.then((result) => {
if (result) {
monorepoRoot = result;
return directory;
}
});
},
{ cwd, type: "directory" }
);
async function hasWorkspacesConfiguredViaPnpm(directory: string) {
// @ts-ignore
let pnpmWorkspacesFileExists = await fs.exists(
path.join(directory, "pnpm-workspace.yaml")
);
if (pnpmWorkspacesFileExists) {
return directory;
if (monorepoRoot) {
return monorepoRoot;
}
}
export async function findRoot(cwd: string): Promise<string> {
let firstPkgJsonDirRef: { current: string | undefined } = {
current: undefined
};
let dir = await findUp(
directory => {
return Promise.all([
hasWorkspacesConfiguredViaLerna(directory),
hasWorkspacesConfiguredViaPkgJson(directory, firstPkgJsonDirRef),
hasWorkspacesConfiguredViaPnpm(directory)
]).then(x => x.find(dir => dir));
// If there is no monorepo root, but we can find a single package json file, we will
// return a "RootTool" repo, which is the special case where we just have a root package
// with no monorepo implementation (i.e.: a normal package folder).
let rootDir = await findUp(
async (directory) => {
try {
await fs.access(path.join(directory, "package.json"));
return directory;
} catch (err) {
if (!isNoEntryError(err)) {
throw err;
}
}
},
{ cwd, type: "directory" }
);
if (firstPkgJsonDirRef.current === undefined) {
if (!rootDir) {
throw new NoPkgJsonFound(cwd);
}
if (dir === undefined) {
return firstPkgJsonDirRef.current;
}
return dir;
}
function hasWorkspacesConfiguredViaPkgJsonSync(
directory: string,
firstPkgJsonDirRef: { current: string | undefined }
) {
try {
const pkgJson = fs.readJsonSync(path.join(directory, "package.json"));
if (firstPkgJsonDirRef.current === undefined) {
firstPkgJsonDirRef.current = directory;
}
if (pkgJson.workspaces || pkgJson.bolt) {
return directory;
}
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
}
return {
tool: RootTool,
rootDir,
};
}
function hasWorkspacesConfiguredViaLernaSync(directory: string) {
try {
let lernaJson = fs.readJsonSync(path.join(directory, "lerna.json"));
if (lernaJson.useWorkspaces !== true) {
return directory;
}
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
}
}
export function findRootSync(cwd: string): MonorepoRoot {
let monorepoRoot: MonorepoRoot | undefined;
function hasWorkspacesConfiguredViaPnpmSync(directory: string) {
// @ts-ignore
let pnpmWorkspacesFileExists = fs.existsSync(
path.join(directory, "pnpm-workspace.yaml")
findUpSync(
(directory) => {
for (const tool of defaultOrder) {
if (tool.isMonorepoRootSync(directory)) {
monorepoRoot = {
tool: tool,
rootDir: directory,
};
return directory;
}
}
},
{ cwd, type: "directory" }
);
if (pnpmWorkspacesFileExists) {
return directory;
if (monorepoRoot) {
return monorepoRoot;
}
}
export function findRootSync(cwd: string) {
let firstPkgJsonDirRef: { current: string | undefined } = {
current: undefined
};
let dir = findUpSync(
directory => {
return [
hasWorkspacesConfiguredViaLernaSync(directory),
hasWorkspacesConfiguredViaPkgJsonSync(directory, firstPkgJsonDirRef),
hasWorkspacesConfiguredViaPnpmSync(directory)
].find(dir => dir);
// If there is no monorepo root, but we can find a single package json file, we will
// return a "RootTool" repo, which is the special case where we just have a root package
// with no monorepo implementation (i.e.: a normal package folder).
const rootDir = findUpSync(
(directory) => {
const exists = fs.existsSync(path.join(directory, "package.json"));
return exists ? directory : undefined;
},

@@ -140,9 +129,10 @@ { cwd, type: "directory" }

if (firstPkgJsonDirRef.current === undefined) {
if (!rootDir) {
throw new NoPkgJsonFound(cwd);
}
if (dir === undefined) {
return firstPkgJsonDirRef.current;
}
return dir;
return {
tool: RootTool,
rootDir,
};
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc