Skip to content

Commit

Permalink
Restore support for Bolt monorepos (#174)
Browse files Browse the repository at this point in the history
* Restore support for Bolt monorepos

* Update packages/get-packages/src/index.ts

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>

* Move BoltTool down

---------

Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
  • Loading branch information
steve-taylor and Andarist committed Jun 9, 2023
1 parent bf7f69f commit de0fff3
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .changeset/rude-squids-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@manypkg/get-packages": minor
"@manypkg/find-root": minor
"@manypkg/tools": minor
"@manypkg/cli": minor
---

Restored support for Bolt monorepos.
11 changes: 11 additions & 0 deletions __fixtures__/bolt-workspace/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"private": true,
"name": "bolt-workspaces",
"description": "bolt-workspaces",
"version": "1.0.0",
"bolt": {
"workspaces": [
"packages/*"
]
}
}
7 changes: 7 additions & 0 deletions __fixtures__/bolt-workspace/packages/pkg-a/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "bolt-workspace-pkg-a",
"version": "1.0.0",
"dependencies": {
"pkg-b": "1.0.0"
}
}
4 changes: 4 additions & 0 deletions __fixtures__/bolt-workspace/packages/pkg-b/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "bolt-workspace-pkg-b",
"version": "1.0.0"
}
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Manypkg

Manypkg is a linter for `package.json` files in Yarn, Lerna, pnpm or Rush monorepos.
Manypkg is a linter for `package.json` files in Yarn, Bolt, Lerna, pnpm or Rush monorepos.

## Install

Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export async function writePackage(pkg: Package) {

export async function install(toolType: string, cwd: string) {
const cliRunners: Record<string, string> = {
bolt: "bolt",
lerna: "lerna",
pnpm: "pnpm",
root: "yarn",
Expand Down
2 changes: 1 addition & 1 deletion packages/find-root/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @manypkg/find-root

> Find the root of a monorepo with Yarn workspaces, Lerna, pnpm or Rush
> Find the root of a monorepo with Yarn workspaces, Bolt, Lerna, pnpm or Rush
## Install

Expand Down
4 changes: 4 additions & 0 deletions packages/find-root/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Tool,
RootTool,
MonorepoRoot,
BoltTool,
LernaTool,
PnpmTool,
RushTool,
Expand All @@ -24,6 +25,7 @@ const DEFAULT_TOOLS: Tool[] = [
PnpmTool,
LernaTool,
RushTool,
BoltTool,
RootTool,
];

Expand All @@ -32,6 +34,7 @@ const isNoEntryError = (err: unknown): boolean =>

export class NoPkgJsonFound extends Error {
directory: string;

constructor(directory: string) {
super(`No package.json could be found upwards from directory ${directory}`);
this.directory = directory;
Expand All @@ -40,6 +43,7 @@ export class NoPkgJsonFound extends Error {

export class NoMatchingMonorepoFound extends Error {
directory: string;

constructor(directory: string) {
super(
`No monorepo matching the list of supported monorepos could be found upwards from directory ${directory}`
Expand Down
28 changes: 21 additions & 7 deletions packages/get-packages/README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
# @manypkg/get-packages

> A simple utility to get the packages from a monorepo, whether they're using Yarn, Lerna, pnpm or Rush
> A simple utility to get the packages from a monorepo, whether they're using Yarn, Bolt, Lerna, pnpm or Rush
This library exports `getPackages` and `getPackagesSync`. It is intended mostly for use of developers building tools that want to support different kinds of monorepos as an easy way to write tools without having to write tool-specific code. It supports Yarn, Lerna, pnpm, Rush and single-package repos(where the only package is the the same as the root package). This library uses `@manypkg/find-root` to search up from the directory that's passed to `getPackages` or `getPackagesSync` to find the project root.
This library exports `getPackages` and `getPackagesSync`. It is intended mostly for use of developers building tools that want to support different kinds of monorepos as an easy way to write tools without having to write tool-specific code. It supports Yarn, Bolt, Lerna, pnpm, Rush and single-package repos(where the only package is the the same as the root package). This library uses `@manypkg/find-root` to search up from the directory that's passed to `getPackages` or `getPackagesSync` to find the project root.

```typescript
import { getPackages, getPackagesSync } from "@manypkg/get-packages";

const { tool, root, packages } = await getPackages(process.cwd());
const { tool, root, packages } = getPackagesSync(process.cwd());
const { tool, packages, rootPackage, rootDir } = await getPackages(process.cwd());
const { tool, packages, rootPackage, rootDir } = getPackagesSync(process.cwd());

type Package = { packageJson: PackageJSON; dir: string };
// From @manypkg/tools

type Packages = {
interface Tool {
readonly type: string;
isMonorepoRoot(directory: string): Promise<boolean>;
isMonorepoRootSync(directory: string): boolean;
getPackages(directory: string): Promise<Packages>;
getPackagesSync(directory: string): Packages;
}

interface Package {
packageJson: PackageJSON;
dir: string;
relativeDir: string;
}

interface Packages {
tool: Tool;
packages: Package[];
rootPackage?: Package;
rootDir: string;
};
}
```
16 changes: 16 additions & 0 deletions packages/get-packages/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ let runTests = (getPackages: GetPackages) => {
expect(allPackages.tool.type).toEqual("yarn");
});

it("should resolve workspaces for bolt", async () => {
const allPackages = await getPackages(f.copy("bolt-workspace"));

if (allPackages.packages === null) {
return expect(allPackages.packages).not.toBeNull();
}

expect(allPackages.packages[0].packageJson.name).toEqual(
"bolt-workspace-pkg-a"
);
expect(allPackages.packages[1].packageJson.name).toEqual(
"bolt-workspace-pkg-b"
);
expect(allPackages.tool.type).toEqual("bolt");
});

it("should resolve workspaces for pnpm", async () => {
const allPackages = await getPackages(f.copy("pnpm-workspace-base"));

Expand Down
2 changes: 2 additions & 0 deletions packages/get-packages/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import path from "path";
import { findRoot, findRootSync, FindRootOptions } from "@manypkg/find-root";
import { Packages, MonorepoRoot, Tool } from "@manypkg/tools";
Expand All @@ -6,6 +7,7 @@ export type { Tool, Package, Packages } from "@manypkg/tools";

export class PackageJsonMissingNameError extends Error {
directories: string[];

constructor(directories: string[]) {
super(
`The following package.jsons are missing the "name" field:\n${directories.join(
Expand Down
120 changes: 120 additions & 0 deletions packages/tools/src/BoltTool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import path from "path";
import fs from "fs-extra";

import { Tool, PackageJSON, Packages, InvalidMonorepoError } from "./Tool";
import {
expandPackageGlobs,
expandPackageGlobsSync,
} from "./expandPackageGlobs";

export interface BoltPackageJSON extends PackageJSON {
bolt?: {
workspaces?: string[];
};
}

export const BoltTool: Tool = {
type: "bolt",

async isMonorepoRoot(directory: string): Promise<boolean> {
try {
const pkgJson = (await fs.readJson(
path.join(directory, "package.json")
)) as BoltPackageJSON;
if (pkgJson.bolt && pkgJson.bolt.workspaces) {
return true;
}
} catch (err) {
if (err && (err as { code: string }).code === "ENOENT") {
return false;
}
throw err;
}
return false;
},

isMonorepoRootSync(directory: string): boolean {
try {
const pkgJson = fs.readJsonSync(
path.join(directory, "package.json")
) as BoltPackageJSON;
if (pkgJson.bolt && pkgJson.bolt.workspaces) {
return true;
}
} catch (err) {
if (err && (err as { code: string }).code === "ENOENT") {
return false;
}
throw err;
}
return false;
},

async getPackages(directory: string): Promise<Packages> {
const rootDir = path.resolve(directory);

try {
const pkgJson = (await fs.readJson(
path.join(rootDir, "package.json")
)) as BoltPackageJSON;
if (!pkgJson.bolt || !pkgJson.bolt.workspaces) {
throw new InvalidMonorepoError(
`Directory ${rootDir} is not a valid ${BoltTool.type} monorepo root: missing bolt.workspaces entry`
);
}
const packageGlobs: string[] = pkgJson.bolt.workspaces;

return {
tool: BoltTool,
packages: await expandPackageGlobs(packageGlobs, rootDir),
rootPackage: {
dir: rootDir,
relativeDir: ".",
packageJson: pkgJson,
},
rootDir,
};
} catch (err) {
if (err && (err as { code: string }).code === "ENOENT") {
throw new InvalidMonorepoError(
`Directory ${rootDir} is not a valid ${BoltTool.type} monorepo root: missing package.json`
);
}
throw err;
}
},

getPackagesSync(directory: string): Packages {
const rootDir = path.resolve(directory);

try {
const pkgJson = fs.readJsonSync(
path.join(rootDir, "package.json")
) as BoltPackageJSON;
if (!pkgJson.bolt || !pkgJson.bolt.workspaces) {
throw new InvalidMonorepoError(
`Directory ${directory} is not a valid ${BoltTool.type} monorepo root: missing bolt.workspaces entry`
);
}
const packageGlobs: string[] = pkgJson.bolt.workspaces;

return {
tool: BoltTool,
packages: expandPackageGlobsSync(packageGlobs, rootDir),
rootPackage: {
dir: rootDir,
relativeDir: ".",
packageJson: pkgJson,
},
rootDir,
};
} catch (err) {
if (err && (err as { code: string }).code === "ENOENT") {
throw new InvalidMonorepoError(
`Directory ${rootDir} is not a valid ${BoltTool.type} monorepo root: missing package.json`
);
}
throw err;
}
},
};
1 change: 1 addition & 0 deletions packages/tools/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./Tool";
export { BoltTool } from "./BoltTool";
export { LernaTool } from "./LernaTool";
export { PnpmTool } from "./PnpmTool";
export { RootTool } from "./RootTool";
Expand Down

0 comments on commit de0fff3

Please sign in to comment.