patch-package
patch-package copied to clipboard
New patch fails with private registries (RFC)
We've been noticing an issue sporadically with writing new patches and having a private NPM registry. I can reproduce the issue reliably, and I can fix it locally, but I'm not sure what the underlying cause is here. Hoping someone can provide guidance on a better fix for this. If there isn't I'm happy to PR my proposal below.
Reproducing the issue
have a yarn
repo with an .npmrc
in it as follows:
registry=https://my-private-registry-host.example/repository/npm
always-auth=true
and an ~/.npmrc
as follows:
//my-private-registry-host.example/repository/npm/:_auth="myNPMauthTOKEN"
pick any package in node_modules that has not had a patch written for it before and run yarn patch-package the-package
:
▶ yarn patch-package yazl
yarn run v1.22.4
$ /path/to/repo/node_modules/.bin/patch-package the-package
patch-package 6.4.7+cd069d4b
• Creating temporary folder
• Installing [email protected] with yarn
warning package.json: No license field
warning No license field
error An unexpected error occurred: "https://my-private-registry-host.example/repository/npm/the-package/-/the-package-2.5.1.tgz: Request failed \"401 Unauthorized\"".
<<...some garbage output (console.log of some buffers it seems)...>>
If I add some more logs ahead of the yarn install
that patch-package does, the output seems to make sense:
# ls -la in the tmpRepoPath
# the copied .npmrc is as noted above for the project one
total 16
drwx------ 4 me staff 128 19 May 16:07 .
drwx------@ 478 me staff 15296 19 May 16:07 ..
-rw-r--r-- 1 me staff 75 19 May 16:07 .npmrc
-rw-r--r-- 1 me staff 454 19 May 16:07 package.json
# cat package.json in the tmpRepoPath
{"dependencies":{"the-package":"https://my-private-registry-host.example/repository/npm/the-package/-/the-package-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"},"resolutions":{...}}
The Fix
I can fix the 401 by adding --registry https://my-private-registry-host.example/repository/npm
to the yarn install command that patch-package builds. It's not clear why this resolves it, but I assume it has something to do with scoped auth tokens (in my $HOME/.npmrc).
Proposal
I propose making a change to allow passthrough flags that allow me to specify the registry I want to build the patch against.
In this case I'd run yarn patch-package the-package --registry https://my-private-registry-host.example/repository/npm
and patch-package would add that flag to the install command.
I'd love to find a better fix for this but the underlying cause escapes me.
▶ yarn --version
1.22.4
I can fix the 401 by adding --registry https://my-private-registry-host.example/repository/npm to the yarn install
Could you provide the full workaround here?
@Psidium Did you manage it to work?
@Psidium try adding the --registry
argument to this file patch-package/dist/makePatch.js
try {
// try first without ignoring scripts in case they are required
// this works in 99.99% of cases
- spawnSafe_1.spawnSafeSync(`yarn`, ["install", "--ignore-engines"], {
+ spawnSafe_1.spawnSafeSync(`yarn`, ["install", "--ignore-engines", "--registry https://my-private-registry-host.example.com"], {
cwd: tmpRepoNpmRoot,
logStdErrOnError: false,
});
npx patch-package package-name
instead of the yarn command works well as a workaround
May a better solution is to copy
.npmrc than hardcode url to makePatch.js
.
Here a quick hard fix for .npmrc
.
The idea is to add .npmrc
file to env
var.
Should be similar for .yarnrc
.
Create file : patches/patch-package+6.4.7.patch
diff --git a/node_modules/patch-package/dist/makePatch.js b/node_modules/patch-package/dist/makePatch.js
index 985589e..fd24a9a 100644
--- a/node_modules/patch-package/dist/makePatch.js
+++ b/node_modules/patch-package/dist/makePatch.js
@@ -83,6 +83,15 @@ function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths
}
}
else {
+ // @TODO: check if .yarnrc can be treated as .npmrc. If yes move to [".npmrc", ".yarnrc"].forEach((rcFile) => {
+ // @TODO: check if this configuration via env:{ } and spawnSafeSync options is okay
+ const npmrcEnv = { env: {} }
+ const rcFile = '.npmrc'
+ const rcPath = path_1.join(appPath, rcFile);
+ if (fs_extra_1.existsSync(rcPath)) {
+ npmrcEnv.env.npm_config_userconfig = `${tmpRepo.name}${rcFile}`
+ }
+
console.info(chalk_1.default.grey("•"), `Installing ${packageDetails.name}@${packageVersion} with npm`);
try {
// try first without ignoring scripts in case they are required
@@ -91,6 +100,7 @@ function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths
cwd: tmpRepoNpmRoot,
logStdErrOnError: false,
stdio: "ignore",
+ ...npmrcEnv,
});
}
catch (e) {
@@ -99,6 +109,7 @@ function makePatch({ packagePathSpecifier, appPath, packageManager, includePaths
spawnSafe_1.spawnSafeSync(`npm`, ["i", "--ignore-scripts", "--force"], {
cwd: tmpRepoNpmRoot,
stdio: "ignore",
+ ...npmrcEnv,
});
}
}
Thanks for this life saver lib guys !