feat(manager): add nub package manager#44422
Conversation
Add a first-party manager for nub (https://nubjs.com), modeled on the bun manager. Detects nub.lock, extracts deps via the shared npm extractor (nub.lock is pnpm-lock v9 under nub's own filename), and regenerates the lockfile with 'nub install --lockfile-only'. Registers nub as a Containerbase tool (npm datasource, @nubjs/nub) so binarySource=install can provision it.
- pass --no-frozen-lockfile so nub re-resolves the bumped manifest
instead of rejecting the drift under its CI-frozen default
- detect the object form `workspaces: { packages: [...] }`
- add nub to ignoreScripts supportedManagers
| let workspaces = res?.managerData?.workspaces; | ||
|
|
||
| // nub also accepts the object form `workspaces: { packages: [...] }`. | ||
| if (typeof workspaces === 'object' && 'packages' in workspaces) { |
There was a problem hiding this comment.
typeof workspaces === 'object' is also true for null, and managerData.workspaces comes straight from the parsed manifest. A "workspaces": null value makes 'packages' in workspaces throw and crashes extract. Use is.plainObject(workspaces), which also matches the prefer-is guideline.
| ): Promise<PackageFile | null> { | ||
| const fileContent = await readLocalFile(packageFile, 'utf8'); | ||
| if (!fileContent) { | ||
| logger.warn({ fileName: packageFile }, 'Could not read file content'); |
There was a problem hiding this comment.
This warns when a nub.lock has no readable sibling package.json, which is an expected case and will be noisy. Use logger.debug here, as the npm manager does.
| } | ||
| const relativeFile = upath | ||
| .relative(pwd, fileName) | ||
| .replace(/\/package\.json$/, ''); |
There was a problem hiding this comment.
Use the regEx() utility from lib/util/regex.ts instead of a regex literal.
| toolConstraints: [ | ||
| { | ||
| toolName: 'nub', | ||
| constraint: updateArtifact?.config?.constraints?.nub, |
There was a problem hiding this comment.
updateArtifact and config are already in scope and always defined. Simplify to config.constraints?.nub.
| Used for updating projects that use [nub](https://nubjs.com) as their package manager. | ||
| nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn. | ||
|
|
||
| nub's `nub.lock` is the pnpm lockfile v9 format under nub's own filename, so dependencies resolve through the same npm datasource as the `npm` and `bun` managers. |
There was a problem hiding this comment.
Avoid possessives like nub's. Rewrite, for example: the nub.lock file uses the pnpm lockfile v9 format under a nub-specific name.
| { manager: 'nub', lockFiles: ['nub.lock'] }, | ||
| ]; | ||
| const oldLock = Buffer.from('old'); | ||
| fs.readFile.mockResolvedValueOnce(oldLock as never); |
There was a problem hiding this comment.
as never bypasses the type system. Prefer typing the mock value or partial<T>() from test/util. The table-driven test lower down also hand-rolls a for loop over testCases; it.each fits better.
- extract: guard workspaces with isPlainObject so a `workspaces: null` value no longer throws on the `'packages' in` check - extract: demote the missing sibling package.json read to logger.debug - utils: wrap the package.json-suffix regex in regEx() - artifacts: use the destructured config for the nub tool constraint - readme: drop the possessive phrasing - tests: mock the fs util instead of fs-extra (drops `as never`), convert the command-execution cases to it.each, and cover null workspaces
|
All six addressed in
Green locally: |
| @@ -0,0 +1,6 @@ | |||
| Used for updating projects that use [nub](https://nubjs.com) as their package manager. | |||
| nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn. | |||
There was a problem hiding this comment.
| nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn. | |
| nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and yarn. |
consistent casing
|
|
||
| The `nub.lock` file uses the pnpm lockfile v9 format under a nub-specific name, so dependencies resolve through the same npm datasource as the `npm` and `bun` managers. | ||
|
|
||
| If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/Yarn lock file is also found. |
There was a problem hiding this comment.
| If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/Yarn lock file is also found. | |
| If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/yarn lock file is also found. |
Changes
Adds a
nubpackage-manager manager.Nub is a Node package manager published as
@nubjs/nubon npm. It has its own lockfile,nub.lock, which is byte-compatible with the pnpm-lock v9 format. This manager gives nub-based projects lockfile-aware update PRs without keeping a foreign lockfile.The manager is modeled on the existing
bunmanager:nub.lock, resolves the siblingpackage.json, and extracts dependencies through the shared npm extractor (extractPackageJson). The datasource staysnpm.updateArtifactsby runningnub install --lockfile-only(with--ignore-scriptsunless scripts are allowed), then diffs the old and newnub.lock.supersedesManagers: ['npm']so nub takes over from the npm manager only whennub.lockis present.toolDefinitions+allToolConfig.nub→ npm@nubjs/nub), so the defaultbinarySource=installruntime can provision it. This depends on the companion Containerbase tool: feat(tool): add nub package manager containerbase/base#7054.Context
Please select one of the following:
AI assistance disclosure
Code, tests, and the manager readme were written with substantive assistance from an AI coding agent (Claude).
Documentation (please check one with an [x])
Adds
lib/modules/manager/nub/readme.md, which is auto-rendered into the docs site.How I've tested my work (please select one)
pnpm vitest run lib/modules/manager/nub --coveragepasses with 100% statement/branch/function/line coverage. The manager, metadata, and fingerprint validators, thelib/util/execandlib/configspecs, andpnpm test-schemaall pass.