Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions .changeset/nub-package-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/workers-utils": patch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changeset incorrectly classified as patch instead of minor for a new feature

The new package manager support is classified as a patch release (.changeset/nub-package-manager.md:2) instead of minor, even though it adds a new public export and extends the type union.

Impact: The release version number will not correctly signal to consumers that new API surface was added.

REVIEW.md semver classification rule violation

REVIEW.md explicitly states that "new API capabilities or exports" and "behavior changes that add functionality" should be classified as minor. This PR adds NubPackageManager as a new export from @cloudflare/workers-utils (packages/workers-utils/src/index.ts:153) and extends the PackageManager type union with "nub" (packages/workers-utils/src/package-manager.ts:7). Both of these are new API capabilities.

REVIEW.md also notes: "The description text matters less than the actual change. A changeset described as 'Support X' is adding a new feature (minor)." The changeset description "Add nub to the list of recognised package managers" is clearly adding support for something new.

Suggested change
"@cloudflare/workers-utils": patch
"@cloudflare/workers-utils": minor
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

---

Add nub to the list of recognised package managers

Projects using nub can now be automatically detected by their `nub.lock` file.
1 change: 1 addition & 0 deletions packages/workers-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export {
PnpmPackageManager,
YarnPackageManager,
BunPackageManager,
NubPackageManager,
} from "./package-manager";

export {
Expand Down
12 changes: 11 additions & 1 deletion packages/workers-utils/src/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
export interface PackageManager {
/** The package manager identifier. */
type: "npm" | "yarn" | "pnpm" | "bun";
type: "npm" | "yarn" | "pnpm" | "bun" | "nub";
/** The command used to execute packages (e.g. `npx`, `pnpm`, `bunx`). */
npx: string;
/** The command segments used to download and execute packages (e.g. `["npx"]`, `["pnpm", "dlx"]`). */
Expand Down Expand Up @@ -52,3 +52,13 @@ export const BunPackageManager = {
dlx: ["bunx"],
lockFiles: ["bun.lockb", "bun.lock"],
} as const satisfies PackageManager;

/**
* Manage packages using nub.
*/
export const NubPackageManager = {
type: "nub",
npx: "nubx",
dlx: ["nubx"],
lockFiles: ["nub.lock"],
} as const satisfies PackageManager;
Comment on lines +59 to +64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 Downstream package manager detection logic does not handle nub

The PR adds NubPackageManager as a data constant and export, but none of the downstream detection/resolution code has been updated to recognize nub:

  • Wrangler's getPackageManager() (packages/wrangler/src/package-manager.ts:23-68) checks for npm, yarn, pnpm, and bun only — no supportsNub() check, no user-agent sniffing for nub.
  • Wrangler's sniffUserAgent() (packages/wrangler/src/package-manager.ts:114) returns "npm" | "pnpm" | "yarn" | "bun" | undefined — no "nub" variant.
  • Autoconfig's convertDetectedPackageManager() (packages/autoconfig/src/details/framework-detection.ts:150-168) switches on pnpm/yarn/bun/npm with a default fallback to npm — nub would silently fall back to npm.
  • Create-cloudflare's detectPackageManager() (packages/create-cloudflare/src/helpers/packageManagers.ts:34-87) similarly has no nub case.

This may be intentional if the PR is a first step (adding the constant so consumers can reference it), but if the goal is full nub support, these detection paths need updating. The changeset description says "Projects using nub can now be automatically detected by their nub.lock file" which implies detection should work, but the only detection shown is in the test's local findByLockFile helper — not in any shipped code.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

47 changes: 47 additions & 0 deletions packages/workers-utils/tests/package-manager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { existsSync } from "node:fs";
import { join } from "node:path";
import { describe, it } from "vitest";
import {
BunPackageManager,
NpmPackageManager,
NubPackageManager,
PnpmPackageManager,
YarnPackageManager,
} from "../src/package-manager";
import { runInTempDir, seed } from "../src/test-helpers";
import type { PackageManager } from "../src/package-manager";

const packageManagers: PackageManager[] = [
NpmPackageManager,
PnpmPackageManager,
YarnPackageManager,
BunPackageManager,
NubPackageManager,
];

describe("package managers", () => {
it("describes nub", ({ expect }) => {
expect(NubPackageManager).toEqual({
type: "nub",
npx: "nubx",
dlx: ["nubx"],
lockFiles: ["nub.lock"],
});
});

describe("lock file detection", () => {
runInTempDir();

// Detection is lock-file-based: a project is managed by the package
// manager whose lock file is present, matching how consumers resolve it.
const findByLockFile = (dir: string) =>
packageManagers.find((pm) =>
pm.lockFiles.some((lockFile) => existsSync(join(dir, lockFile)))
);

it("detects nub from nub.lock", async ({ expect }) => {
await seed({ "nub.lock": "" });
expect(findByLockFile(process.cwd())).toBe(NubPackageManager);
});
});
});
Loading