Skip to content

Commit d45693a

Browse files
committed
refactor(@angular/cli): support copying config files to temp package directory
This change adds support for copying package manager configuration files (like `bunfig.toml`) from the project root to the temporary directory used for acquiring packages. This is particularly necessary for Bun, which does not automatically inherit configuration from parent directories when running in a separate temporary location. (cherry picked from commit d58c714)
1 parent 84d82eb commit d45693a

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

packages/angular/cli/src/package-managers/host.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
*/
1515

1616
import { type SpawnOptions, spawn } from 'node:child_process';
17-
import { Stats } from 'node:fs';
18-
import { mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
17+
import { Stats, constants } from 'node:fs';
18+
import { copyFile, mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
1919
import { platform, tmpdir } from 'node:os';
2020
import { join } from 'node:path';
2121
import { PackageManagerError } from './error';
@@ -45,6 +45,14 @@ export interface Host {
4545
*/
4646
readFile(path: string): Promise<string>;
4747

48+
/**
49+
* Copies a file from the source path to the destination path.
50+
* @param src The path to the source file.
51+
* @param dest The path to the destination file.
52+
* @returns A promise that resolves when the copy is complete.
53+
*/
54+
copyFile(src: string, dest: string): Promise<void>;
55+
4856
/**
4957
* Creates a new, unique temporary directory.
5058
* @param baseDir The base directory in which to create the temporary directory.
@@ -94,6 +102,7 @@ export const NodeJS_HOST: Host = {
94102
stat,
95103
readdir,
96104
readFile: (path: string) => readFile(path, { encoding: 'utf8' }),
105+
copyFile: (src, dest) => copyFile(src, dest, constants.COPYFILE_FICLONE),
97106
writeFile,
98107
createTempDirectory: (baseDir?: string) => mkdtemp(join(baseDir ?? tmpdir(), 'angular-cli-')),
99108
deleteDirectory: (path: string) => rm(path, { recursive: true, force: true }),

packages/angular/cli/src/package-managers/package-manager-descriptor.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ export interface PackageManagerDescriptor {
6565
/** The flag to ignore peer dependency warnings/errors. */
6666
readonly ignorePeerDependenciesFlag?: string;
6767

68+
/** The configuration files used by the package manager. */
69+
readonly configFiles: readonly string[];
70+
71+
/**
72+
* Whether to copy configuration files from the project root to the temporary directory.
73+
* This is necessary for package managers that do not inherit configuration from parent directories (e.g., bun).
74+
*/
75+
readonly copyConfigFromProject?: boolean;
76+
6877
/** A function that returns the arguments and environment variables to use a custom registry. */
6978
readonly getRegistryOptions?: (registry: string) => {
7079
args?: string[];
@@ -144,6 +153,7 @@ export const SUPPORTED_PACKAGE_MANAGERS = {
144153
noLockfileFlag: '--no-package-lock',
145154
ignoreScriptsFlag: '--ignore-scripts',
146155
ignorePeerDependenciesFlag: '--force',
156+
configFiles: ['.npmrc'],
147157
getRegistryOptions: (registry: string) => ({ args: ['--registry', registry] }),
148158
versionCommand: ['--version'],
149159
listDependenciesCommand: ['list', '--depth=0', '--json=true', '--all=true'],
@@ -168,6 +178,7 @@ export const SUPPORTED_PACKAGE_MANAGERS = {
168178
saveDevFlag: '--dev',
169179
noLockfileFlag: '',
170180
ignoreScriptsFlag: '--mode=skip-build',
181+
configFiles: ['.yarnrc.yml', '.yarnrc.yaml'],
171182
getRegistryOptions: (registry: string) => ({ env: { YARN_NPM_REGISTRY_SERVER: registry } }),
172183
versionCommand: ['--version'],
173184
listDependenciesCommand: ['list', '--depth=0', '--json', '--recursive=false'],
@@ -195,6 +206,7 @@ export const SUPPORTED_PACKAGE_MANAGERS = {
195206
saveDevFlag: '--dev',
196207
noLockfileFlag: '--no-lockfile',
197208
ignoreScriptsFlag: '--ignore-scripts',
209+
configFiles: ['.yarnrc', '.npmrc'],
198210
getRegistryOptions: (registry: string) => ({ args: ['--registry', registry] }),
199211
versionCommand: ['--version'],
200212
listDependenciesCommand: ['list', '--depth=0', '--json'],
@@ -220,6 +232,7 @@ export const SUPPORTED_PACKAGE_MANAGERS = {
220232
noLockfileFlag: '--no-lockfile',
221233
ignoreScriptsFlag: '--ignore-scripts',
222234
ignorePeerDependenciesFlag: '--strict-peer-dependencies=false',
235+
configFiles: ['.npmrc', 'pnpm-workspace.yaml'],
223236
getRegistryOptions: (registry: string) => ({ args: ['--registry', registry] }),
224237
versionCommand: ['--version'],
225238
listDependenciesCommand: ['list', '--depth=0', '--json'],
@@ -244,6 +257,8 @@ export const SUPPORTED_PACKAGE_MANAGERS = {
244257
saveDevFlag: '--development',
245258
noLockfileFlag: '', // Bun does not have a flag for this.
246259
ignoreScriptsFlag: '--ignore-scripts',
260+
configFiles: ['bunfig.toml', '.npmrc'],
261+
copyConfigFromProject: true,
247262
getRegistryOptions: (registry: string) => ({ args: ['--registry', registry] }),
248263
versionCommand: ['--version'],
249264
listDependenciesCommand: ['pm', 'ls', '--json'],

packages/angular/cli/src/package-managers/package-manager.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,18 @@ export class PackageManager {
552552
// Writing an empty package.json file beforehand prevents this.
553553
await this.host.writeFile(join(workingDirectory, 'package.json'), '{}');
554554

555+
// Copy configuration files if the package manager requires it (e.g., bun).
556+
if (this.descriptor.copyConfigFromProject) {
557+
for (const configFile of this.descriptor.configFiles) {
558+
try {
559+
const configPath = join(this.cwd, configFile);
560+
await this.host.copyFile(configPath, join(workingDirectory, configFile));
561+
} catch {
562+
// Ignore missing config files.
563+
}
564+
}
565+
}
566+
555567
const flags = [options.ignoreScripts ? this.descriptor.ignoreScriptsFlag : ''].filter(
556568
(flag) => flag,
557569
);

packages/angular/cli/src/package-managers/testing/mock-host.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,8 @@ export class MockHost implements Host {
6262
readFile(): Promise<string> {
6363
throw new Error('Method not implemented.');
6464
}
65+
66+
copyFile(): Promise<void> {
67+
throw new Error('Method not implemented.');
68+
}
6569
}

0 commit comments

Comments
 (0)