Skip to content

Commit

Permalink
feat(core): add bun package manager
Browse files Browse the repository at this point in the history
Bun uses yarn lock for it's binary file. Running the binary will produce the content of a yarn lock file (v1)
  • Loading branch information
Jordan-Hall committed Sep 11, 2023
1 parent 2283937 commit d91a1a2
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/generated/devkit/PackageManager.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Type alias: PackageManager

Ƭ **PackageManager**: `"yarn"` \| `"pnpm"` \| `"npm"`
Ƭ **PackageManager**: `"yarn"` \| `"pnpm"` \| `"npm"` \| `"bun"`
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function createApplicationFiles(host: Tree, options: NormalizedSchema) {
npm: 'package-lock.json',
yarn: 'yarn.lock',
pnpm: 'pnpm-lock.yaml',
bun: 'bun.lockb',
};
const packageManager = detectPackageManager(host.root);
const packageLockFile = packageManagerLockFile[packageManager];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default function update(tree: Tree) {
npm: 'package-lock.json',
yarn: 'yarn.lock',
pnpm: 'pnpm-lock.yaml',
bun: 'bun.lockb',
};

for (const [name, config] of projects.entries()) {
Expand Down
11 changes: 9 additions & 2 deletions packages/nx/src/plugins/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { hashArray } from '../../hasher/file-hasher';
import { detectPackageManager } from '../../utils/package-manager';
import { workspaceRoot } from '../../utils/workspace-root';
import { nxVersion } from '../../utils/versions';
import { execSync } from 'child_process';

export const name = 'nx-js-graph-plugin';

Expand All @@ -50,7 +51,10 @@ export const createNodes: CreateNodes = [
}

const lockFilePath = join(workspaceRoot, lockFile);
const lockFileContents = readFileSync(lockFilePath).toString();
const lockFileContents =
packageManager !== 'bun'
? readFileSync(lockFilePath).toString()
: execSync(`./${lockFilePath}`).toString();
const lockFileHash = getLockFileHash(lockFileContents);

if (!lockFileNeedsReprocessing(lockFileHash)) {
Expand Down Expand Up @@ -88,7 +92,10 @@ export const createDependencies: CreateDependencies = (
parsedLockFile
) {
const lockFilePath = join(workspaceRoot, getLockFileName(packageManager));
const lockFileContents = readFileSync(lockFilePath).toString();
const lockFileContents =
packageManager !== 'bun'
? readFileSync(lockFilePath).toString()
: execSync(`./${lockFilePath}`).toString();
const lockFileHash = getLockFileHash(lockFileContents);

if (!lockFileNeedsReprocessing(lockFileHash)) {
Expand Down
30 changes: 29 additions & 1 deletion packages/nx/src/plugins/js/lock-file/lock-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,18 @@ import { readJsonFile } from '../../../utils/fileutils';
const YARN_LOCK_FILE = 'yarn.lock';
const NPM_LOCK_FILE = 'package-lock.json';
const PNPM_LOCK_FILE = 'pnpm-lock.yaml';
export const LOCKFILES = [YARN_LOCK_FILE, NPM_LOCK_FILE, PNPM_LOCK_FILE];
const BUN_LOCK_FILE = 'bun.lockb';
export const LOCKFILES = [
YARN_LOCK_FILE,
NPM_LOCK_FILE,
PNPM_LOCK_FILE,
BUN_LOCK_FILE,
];

const YARN_LOCK_PATH = join(workspaceRoot, YARN_LOCK_FILE);
const NPM_LOCK_PATH = join(workspaceRoot, NPM_LOCK_FILE);
const PNPM_LOCK_PATH = join(workspaceRoot, PNPM_LOCK_FILE);
const BUN_LOCK_PATH = join(workspaceRoot, BUN_LOCK_FILE);

/**
* Parses lock file and maps dependencies and metadata to {@link LockFileGraph}
Expand All @@ -69,6 +76,11 @@ export function getLockFileNodes(
if (packageManager === 'npm') {
return getNpmLockfileNodes(contents, lockFileHash);
}
if (packageManager === 'bun') {
// bun uses yarn v1 for the file format
const packageJson = readJsonFile('package.json');
return getYarnLockfileNodes(contents, lockFileHash, packageJson);
}
} catch (e) {
if (!isPostInstallProcess()) {
output.error({
Expand Down Expand Up @@ -100,6 +112,10 @@ export function getLockFileDependencies(
if (packageManager === 'npm') {
return getNpmLockfileDependencies(contents, lockFileHash, projectGraph);
}
if (packageManager === 'bun') {
// bun uses yarn v1 for the file format
return getYarnLockfileDependencies(contents, lockFileHash, projectGraph);
}
} catch (e) {
if (!isPostInstallProcess()) {
output.error({
Expand All @@ -122,6 +138,9 @@ export function lockFileExists(packageManager: PackageManager): boolean {
if (packageManager === 'npm') {
return existsSync(NPM_LOCK_PATH);
}
if (packageManager === 'bun') {
return existsSync(BUN_LOCK_PATH);
}
throw new Error(
`Unknown package manager ${packageManager} or lock file missing`
);
Expand All @@ -142,6 +161,9 @@ export function getLockFileName(packageManager: PackageManager): string {
if (packageManager === 'npm') {
return NPM_LOCK_FILE;
}
if (packageManager === 'bun') {
return BUN_LOCK_FILE;
}
throw new Error(`Unknown package manager: ${packageManager}`);
}

Expand Down Expand Up @@ -174,6 +196,12 @@ export function createLockFile(
const prunedGraph = pruneProjectGraph(graph, packageJson);
return stringifyNpmLockfile(prunedGraph, content, normalizedPackageJson);
}
if (packageManager === 'bun') {
output.log({
title:
"Unable to create bun lock files. Run bun install it's just as quick",
});
}
} catch (e) {
if (!isPostInstallProcess()) {
const additionalInfo = [
Expand Down
27 changes: 24 additions & 3 deletions packages/nx/src/utils/package-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { readNxJson } from '../config/configuration';

const execAsync = promisify(exec);

export type PackageManager = 'yarn' | 'pnpm' | 'npm';
export type PackageManager = 'yarn' | 'pnpm' | 'npm' | 'bun';

export interface PackageManagerCommands {
preInstall?: string;
Expand All @@ -37,6 +37,8 @@ export function detectPackageManager(dir: string = ''): PackageManager {
? 'yarn'
: existsSync(join(dir, 'pnpm-lock.yaml'))
? 'pnpm'
: existsSync(join(dir, 'bun.lockb'))
? 'bun'
: 'npm')
);
}
Expand Down Expand Up @@ -113,6 +115,19 @@ export function getPackageManagerCommand(
list: 'npm ls',
};
},
bun: () => {
return {
install: 'bun install',
ciInstall: 'bun install --frozen-lockfile',
add: 'bun add',
addDev: 'bun add -D',
rm: 'bun remove',
exec: 'bunx',
run: (script: string, args: string) => `bun ${script} ${args}`,
// list not aviable yet. But cant see wherte its used
list: '',
};
},
};

return commands[packageManager]();
Expand Down Expand Up @@ -314,12 +329,16 @@ export async function packageRegistryView(
args: string
): Promise<string> {
let pm = detectPackageManager();
if (pm === 'yarn') {
if (pm === 'yarn' || pm === 'bun') {
/**
* yarn has `yarn info` but it behaves differently than (p)npm,
* which makes it's usage unreliable
*
* @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994
*
* inregards to bun. Bun is highly modelled after yarn v1
* bun info is a "subcommand reserved for future use by Bun."
* currently nothing like npm view/list exists
*/
pm = 'npm';
}
Expand All @@ -334,13 +353,15 @@ export async function packageRegistryPack(
version: string
): Promise<{ tarballPath: string }> {
let pm = detectPackageManager();
if (pm === 'yarn') {
if (pm === 'yarn' || pm === 'bun') {
/**
* `(p)npm pack` will download a tarball of the specified version,
* whereas `yarn` pack creates a tarball of the active workspace, so it
* does not work for getting the content of a library.
*
* @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994
*
* bun doesn't current support pack
*/
pm = 'npm';
}
Expand Down

0 comments on commit d91a1a2

Please sign in to comment.