Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support workspaces #100

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions lib/utils/npm-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,23 @@ function findPackageJson(startDir) {
return null;
}

/**
Copy link
Member

@aladdin-add aladdin-add Apr 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can write this as a function(possible isRootWorkspace()), something like:

function isRootWorkspace(packageJsonPath){
  const pkg = JSON.parse(...)
  if(pkg.private === true && pkg.workspaces !== void 0) return true;
  return fs.existsSync(path.join(packageJsonPath, "../pnpm-workspace.yaml");
}

it can be evalutated in the constructor, so you can just use it when you need it:

this.isRootWorkspace = isRootWorkspace();

* Find the pnpm-workspace.yaml at package root.
* @param {string} [startDir=process.cwd()] Starting directory, default is process.cwd()
* @returns {boolean} Whether a pnpm-workspace.yaml is found in current path.
*/
function findPnpmWorkspaceYaml(startDir) {
const dir = path.resolve(startDir || process.cwd());

const yamlFile = path.join(dir, "pnpm-workspace.yaml");

if (!fs.existsSync(yamlFile) || !fs.statSync(yamlFile).isFile()) {
return false;
}

return true;
}

//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------
Expand All @@ -51,8 +68,10 @@ function findPackageJson(startDir) {
*/
function installSyncSaveDev(packages, packageManager = "npm") {
const packageList = Array.isArray(packages) ? packages : [packages];
const installCmd = packageManager === "yarn" ? "add" : "install";
const installProcess = spawn.sync(packageManager, [installCmd, "-D"].concat(packageList), { stdio: "inherit" });
const installCmd = packageManager === "npm" ? "install" : "add";

const pnpmWorkspaceRootOption = packageManager === "pnpm" && findPnpmWorkspaceYaml() ? "-w" : "";
const installProcess = spawn.sync(packageManager, [installCmd, "-D"].concat(packageList), pnpmWorkspaceRootOption, { stdio: "inherit" });
const error = installProcess.error;

if (error && error.code === "ENOENT") {
Expand Down Expand Up @@ -189,6 +208,7 @@ export {
installSyncSaveDev,
fetchPeerDependencies,
findPackageJson,
findPnpmWorkspaceYaml,
checkDeps,
checkDevDeps,
checkPackageJson,
Expand Down
13 changes: 13 additions & 0 deletions tests/fixtures/pnpm-workspace-project/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "pnpm-workspace-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"type": "module",
"keywords": [],
"author": "",
"license": "ISC"
}
12 changes: 12 additions & 0 deletions tests/fixtures/pnpm-workspace-project/packages/sub/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "sub",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
11 changes: 11 additions & 0 deletions tests/fixtures/pnpm-workspace-project/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
36 changes: 36 additions & 0 deletions tests/pnpm-workspace.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @fileoverview tests for pnpm workspace install packages at root
* @author Wataru Nishimura<[email protected]>
*/

import { describe, it, expect, assert, afterEach } from "vitest";
import { fileURLToPath } from "node:url";
import { join } from "path";
import { findPnpmWorkspaceYaml, installSyncSaveDev } from "../lib/utils/npm-utils.js";
import sinon from "sinon";
import spawn from "cross-spawn";

const __filename = fileURLToPath(import.meta.url); // eslint-disable-line no-underscore-dangle -- commonjs convention

describe("pnpm workspace install packages at root", () => {
const pnpmWithWorkspaceDir = join(__filename, "../fixtures/pnpm-workspace-project");

afterEach(() => {
sinon.verifyAndRestore();
});

it("find pnpm-workspace.yaml", () => {
const pnpmWorkspaceYaml = findPnpmWorkspaceYaml(pnpmWithWorkspaceDir);

expect(pnpmWorkspaceYaml).toBeTruthy();
});

it("should invoke pnpm to install a single desired package", () => {
const stub = sinon.stub(spawn, "sync").returns({ stdout: 0 });

installSyncSaveDev("desired-package", "pnpm");
assert(stub.calledOnce);
assert.strictEqual(stub.firstCall.args[0], "pnpm");
assert.deepStrictEqual(stub.firstCall.args[1], ["add", "-D", "desired-package"]);
});
});