Skip to content

Commit

Permalink
fix: .npmrc not written into workspace root (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister authored Apr 15, 2024
1 parent 5d9b0d7 commit 93b7cd4
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 14 deletions.
16 changes: 11 additions & 5 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,15 @@ export interface InstallOptions extends BaseOptions {
}

export async function install(packages: JsrPackage[], options: InstallOptions) {
const pkgManager = await getPkgManager(process.cwd(), options.pkgManagerName);
const { pkgManager, root } = await getPkgManager(
process.cwd(),
options.pkgManagerName,
);

if (packages.length > 0) {
if (pkgManager instanceof Bun) {
// Bun doesn't support reading from .npmrc yet
await setupBunfigToml(pkgManager.cwd);
await setupBunfigToml(root);
} else if (pkgManager instanceof YarnBerry) {
// Yarn v2+ does not read from .npmrc intentionally
// https://yarnpkg.com/migration/guide#update-your-configuration-to-the-new-settings
Expand All @@ -101,7 +104,7 @@ export async function install(packages: JsrPackage[], options: InstallOptions) {
JSR_NPM_REGISTRY_URL,
);
} else {
await setupNpmRc(pkgManager.cwd);
await setupNpmRc(root);
}

console.log(`Installing ${kl.cyan(packages.join(", "))}...`);
Expand All @@ -111,7 +114,10 @@ export async function install(packages: JsrPackage[], options: InstallOptions) {
}

export async function remove(packages: JsrPackage[], options: BaseOptions) {
const pkgManager = await getPkgManager(process.cwd(), options.pkgManagerName);
const { pkgManager } = await getPkgManager(
process.cwd(),
options.pkgManagerName,
);
console.log(`Removing ${kl.cyan(packages.join(", "))}...`);
await pkgManager.remove(packages);
}
Expand Down Expand Up @@ -186,7 +192,7 @@ export async function runScript(
script: string,
options: BaseOptions,
) {
const pkgManager = await getPkgManager(cwd, options.pkgManagerName);
const { pkgManager } = await getPkgManager(cwd, options.pkgManagerName);
await pkgManager.runScript(script);
}

Expand Down
21 changes: 13 additions & 8 deletions src/pkg_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,27 +195,32 @@ function getPkgManagerFromEnv(value: string): PkgManagerName | null {
export async function getPkgManager(
cwd: string,
pkgManagerName: PkgManagerName | null,
) {
): Promise<{ root: string; pkgManager: PackageManager }> {
const envPkgManager = process.env.npm_config_user_agent;
const fromEnv = envPkgManager !== undefined
? getPkgManagerFromEnv(envPkgManager)
: null;

const { projectDir, pkgManagerName: fromLockfile } = await findProjectDir(
cwd,
);
const { projectDir, pkgManagerName: fromLockfile, root } =
await findProjectDir(
cwd,
);
const rootPath = root || projectDir;

const result = pkgManagerName || fromEnv || fromLockfile || "npm";

let pkgManager: PackageManager;
if (result === "yarn") {
return await isYarnBerry(projectDir)
pkgManager = await isYarnBerry(projectDir)
? new YarnBerry(projectDir)
: new Yarn(projectDir);
} else if (result === "pnpm") {
return new Pnpm(projectDir);
pkgManager = new Pnpm(projectDir);
} else if (result === "bun") {
return new Bun(projectDir);
pkgManager = new Bun(projectDir);
} else {
pkgManager = new Npm(projectDir);
}

return new Npm(projectDir);
return { root: rootPath, pkgManager };
}
15 changes: 15 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface ProjectInfo {
projectDir: string;
pkgManagerName: PkgManagerName | null;
pkgJsonPath: string | null;
root: string | null;
}
export async function findProjectDir(
cwd: string,
Expand All @@ -80,6 +81,7 @@ export async function findProjectDir(
projectDir: cwd,
pkgManagerName: null,
pkgJsonPath: null,
root: null,
},
): Promise<ProjectInfo> {
// Ensure we check for `package.json` first as this defines
Expand All @@ -92,6 +94,18 @@ export async function findProjectDir(
result.projectDir = dir;
result.pkgJsonPath = pkgJsonPath;
}
} else {
const pkgJsonPath = path.join(dir, "package.json");
if (await fileExists(pkgJsonPath)) {
const json = await readJson<PkgJson>(pkgJsonPath);
// npm + yarn + bun workspaces
if (Array.isArray(json.workspaces)) {
result.root = dir;
} // pnpm workspaces
else if (await fileExists(path.join(dir, "pnpm-workspace.yaml"))) {
result.root = dir;
}
}
}

const npmLockfile = path.join(dir, "package-lock.json");
Expand Down Expand Up @@ -245,6 +259,7 @@ export interface PkgJson {
name?: string;
version?: string;
license?: string;
workspaces?: string[];

dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
Expand Down
73 changes: 73 additions & 0 deletions test/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,79 @@ describe("install", () => {
});
});

it("jsr i @std/encoding - inside workspace member", async () => {
await runInTempDir(async (dir) => {
const parentPkgJson = { name: "", private: true, workspaces: ["sub"] };
const parentPkgJsonPath = path.join(dir, "package.json");
await writeJson<PkgJson>(parentPkgJsonPath, parentPkgJson);

// Create sub folder with package.json
const subPkgJsonPath = path.join(dir, "sub", "package.json");
await writeJson(subPkgJsonPath, { name: "foo" });

await runJsr(["i", "@std/encoding"], path.join(dir, "sub"));

assert.deepEqual(
await readJson<PkgJson>(path.join(dir, "package.json")),
parentPkgJson,
);

const pkgJson = await readJson<PkgJson>(subPkgJsonPath);
assert.ok(
pkgJson.dependencies && "@std/encoding" in pkgJson.dependencies,
"Missing dependency entry",
);

assert.match(
pkgJson.dependencies["@std/encoding"],
/^npm:@jsr\/std__encoding@\^\d+\.\d+\.\d+.*$/,
);

const npmRc = await readTextFile(path.join(dir, ".npmrc"));
assert.ok(
npmRc.includes("@jsr:registry=https://npm.jsr.io"),
"Missing npmrc registry",
);
});
});

it("jsr i @std/encoding - inside pnpm workspace member", async () => {
await runInTempDir(async (dir) => {
const parentPkgJson = { name: "", private: true };
const parentPkgJsonPath = path.join(dir, "package.json");
await writeJson<PkgJson>(parentPkgJsonPath, parentPkgJson);
await writeTextFile(path.join(dir, "pnpm-workspace.yaml"), "");

// Create sub folder with package.json
const subPkgJsonPath = path.join(dir, "sub", "package.json");
await writeJson(subPkgJsonPath, { name: "foo" });

await runJsr(["i", "--pnpm", "@std/encoding"], path.join(dir, "sub"));

assert.deepEqual(
await readJson<PkgJson>(path.join(dir, "package.json")),
parentPkgJson,
);

const pkgJson = await readJson<PkgJson>(subPkgJsonPath);
assert.ok(
pkgJson.dependencies && "@std/encoding" in pkgJson.dependencies,
"Missing dependency entry",
);

assert.match(
pkgJson.dependencies["@std/encoding"],
/^npm:@jsr\/std__encoding@\^\d+\.\d+\.\d+.*$/,
);

const npmRc = await readTextFile(path.join(dir, ".npmrc"));
assert.ok(
npmRc.includes("@jsr:registry=https://npm.jsr.io"),
"Missing npmrc registry",
);
});
});

it("jsr i @std/[email protected] - with version", async () => {
await withTempEnv(["i", "@std/[email protected]"], async (dir) => {
const pkgJson = await readJson<PkgJson>(path.join(dir, "package.json"));
Expand Down
38 changes: 37 additions & 1 deletion test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import * as assert from "assert/strict";
import * as path from "node:path";
import { runInTempDir } from "./test_utils";
import { findProjectDir, writeJson, writeTextFile } from "../src/utils";
import {
findProjectDir,
PkgJson,
writeJson,
writeTextFile,
} from "../src/utils";

describe("findProjectDir", () => {
it("should return npm if package-lock.json is found", async () => {
Expand Down Expand Up @@ -57,4 +62,35 @@ describe("findProjectDir", () => {
assert.strictEqual(result.projectDir, sub);
});
});

it("should find workspace root folder", async () => {
await runInTempDir(async (tempDir) => {
const sub = path.join(tempDir, "sub");

await writeJson<PkgJson>(path.join(tempDir, "package.json"), {
workspaces: ["sub"],
});
await writeJson(path.join(sub, "package.json"), {});
const result = await findProjectDir(sub);
assert.strictEqual(
result.root,
tempDir,
);
});
});

it("should find workspace root folder with pnpm workspaces", async () => {
await runInTempDir(async (tempDir) => {
const sub = path.join(tempDir, "sub");

await writeJson<PkgJson>(path.join(tempDir, "package.json"), {});
await writeJson(path.join(sub, "package.json"), {});
await writeTextFile(path.join(tempDir, "pnpm-workspace.yaml"), "");
const result = await findProjectDir(sub);
assert.strictEqual(
result.root,
tempDir,
);
});
});
});

0 comments on commit 93b7cd4

Please sign in to comment.