How do I override nested dependencies with `yarn`? - node.js

If my package has these dependencies
{ "name": "my-package",
"dependencies": { "foobar":"~1.0.3", "baz":"2.0.9" }
And the foobar package has these dependencies
{ "name": "foobar",
"dependencies": { "baz":"^2.0.0" }
and the most recently released version of baz is 2.1.0, the first run of yarn will install baz#2.1.0 in foobar/node_modules.
How do I force yarn to use the baz#2.0.9 package for foobar?
My understanding is that this would be possible using npm shrinkwrap (a la this question).
The summary of my question probably is: Yarn creates repeatable, deterministic installations, but how do I customize that installation?

If you do in fact have a sub-dependency that is overly restrictive in what versions it will accept, you can override them using yarn.
UPDATED EDIT: Yarn now, as of 1.0, officially supports the "resolutions" block. So the way to override resolutions is to just add a block like this to package.json:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
You'll get warnings for "incompatible" versions sometimes, but I find that some packages (like socket.io) are overly restrictive in what version they accept, and so I'll happily select the latest version when it doesn't actually break things.
Original but outdated answer below.
It sounds like the original question wasn't exactly correct, but the original question was in fact the one I wanted answered, and I found an answer, so here it is for posterity:
I'm using the socket.io library, and it has component-emitter as a dependency. But it has a pair of versions that it requires. This is what the yarn.lock file looked like before I changed anything:
component-emitter#1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3"
component-emitter#1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.0.tgz#ccd113a86388d06482d03de3fc7df98526ba8efe"
So it was including two copies of the component emitter in my client code. I looked, and there didn't appear to be any breaking changes between 1.1.2 and 1.2.0 (or 1.2.1, which was current). I first tried just changing the yarn.lock file:
component-emitter#1.2.1, component-emitter#^1.2.1, component-emitter#1.1.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
This worked, but the file has warnings about it being autogenerated, meaning that every single update or new package I add will stomp on this change. A bit of searching found the yarn --flat option, which will force yarn to choose no more than one of each package in the entire project. That seems like overkill to me, since I'm sure there are actual cases of incompatibility between older and newer packages. I just wanted to eliminate a redundant package from my client code, to make the download smaller; I still want the development packages to all work correctly.
But in the docs to yarn --flat I found a reference to a "resolutions" block that can go in package.json:
"resolutions": {
"package-a": "2.0.0",
"package-b": "5.0.0",
"package-c": "1.5.2"
}
So I tried putting "component-emitter" : "1.2.1" in a new "resolutions" block in my package.json, and it in fact flattened component-emitter to 1.2.1 for all places that required it, and now I have only one copy in my client code.
(And now the resolutions block is completely supported in yarn, so you don't even need to use --flat.)

This is now possible with yarn's selective version resolution feature.
In your project's package.json, use resolutions:
"resolutions": {
"foobar/**/baz": "2.0.9"
}
This overrides package foobar's (and any other packages under it) version of baz, forcing it to be version 2.0.9.

EDIT: This is now deprecated, please read this answer instead:
https://stackoverflow.com/a/46615878/2398593
#SomeCallMeTime's answer is great and we've been doing that for month at work.
Unfortunately, this is not possible anymore since the v0.24.x (see that comment).
There's an opened PR on Github with an RFC proposal to have a simple way of handling that use case without having to keep an eye on the generated lockfile.

Related

How to dynamically install a particular version of a NPM package based on local Node.js version?

I did Google about this but no luck.
Basically, I need a particular version of a NPM package (A) to be installed if the local Node.js version is X, if not then install version B of that NPM package. This needs to be a part of build process, so its all dynamic.
If there was a way to have this config in package.json, then it would have been a straightforward solution for me.
How do I achieve this?
You can achieve this by using Yarn as your dependency management tool in combination with the Selective Versions Resolutions feature.
More specifically in your case you'd use it as described in the "Mapping version specifications" format, based on that your package.json you would include something like the following, assuming that version X=1.0.3 and version B=2.0.0 in the following example:
"devDependencies": {
"a": "1.0.3"
},
"resolutions": {
"a#==1.0.3": "a#2.0.0"
}

Running into "couldn't infer parser" error using vue-cli

I'm getting an error repeatedly when trying to build a new webpack project using vue-cli. I'm following along with the docs on the latest build (3.0.0-beta.11), also tried with an earlier version, which wasn't beta.
When I run yarn serve it attempts to start the dev server and build the project but fails here:
error in ./src/App.vue?vue&type=template&id=7ba5bd90
Module build failed: Error: No parser and no file path given, couldn't infer a parser.
at normalize (/Users/cory/Code/chickadee/my-project/node_modules/prettier/index.js:7051:13)
at formatWithCursor (/Users/cory/Code/chickadee/my-project/node_modules/prettier/index.js:10370:12)
at /Users/cory/Code/chickadee/my-project/node_modules/prettier/index.js:31115:15
at Object.format (/Users/cory/Code/chickadee/my-project/node_modules/prettier/index.js:31134:12)
at actuallyCompile (/Users/cory/Code/chickadee/my-project/node_modules/#vue/component-compiler-utils/dist/compileTemplate.js:93:29)
at compileTemplate (/Users/cory/Code/chickadee/my-project/node_modules/#vue/component-compiler-utils/dist/compileTemplate.js:26:16)
at Object.module.exports (/Users/cory/Code/chickadee/my-project/node_modules/vue-loader/lib/loaders/templateLoader.js:42:20)
# ./src/App.vue?vue&type=template&id=7ba5bd90 1:0-194 1:0-194
# ./src/App.vue
# ./src/main.js
# multi (webpack)-dev-server/client/index.js (webpack)/hot/dev-server.js ./src/main.js
About my setup
Mac OS
I'm running node v8.5.0
packages are installed with yarn
The Things I've Attempted
Different versions of vue-cli to generate a new project. The projects generate and install modules.
Tried removing the prettier module, but the error still seems to come up.
Tried reinstalling all modules.
What else might I try to get past this error?
Removing the current node_modules folder from the project, adding "prettier": "^1.12.1" to package.json and running npm install solved the issue.
Another option is to run npm install prettier#1.12.1 without removeing the node_modules folder before
Update:
For some users, verion 1.12.1 did not work
#Kivin proposed another solution that can be found here: vue webpack template missing parser
Known issue and it will be fixed in the next version of vue-cli
In prettier 1.13.0, default parser was removed with a minor version(used to be babylon)
Issue: https://github.com/vuejs/component-compiler-utils/issues/14
Issue at prettier repo: https://github.com/prettier/prettier/issues/4567
Sorry, we committed the age-old semver sin- we knew this was a breaking change, but because it would only affect a subset of our users, we didn't bump the major version, because we didn't want to create friction for our users to upgrade.
To get the old behavior, add parser: "babylon". You may also want to lock prettier to a specific version in your package.json.
Running npm install prettier#1.12.1 solved it for me. Thanks lsxliron.
Right now, I tried all the options..downloading and updgrading prettier...but none workied. Until I studied what happened carefully.
Apparently, the prettier team removed the default parser which was babylon and in so doing...broke the internet.
Just kidding.
Issue repo
The simplest solution, according to them would be to simply add the parser back.
This has been picked up by the Vue team and its expected to be shipped with the latest fix release.
If you are using Vue Loader/Yarn, dont even bother to try all the suggestions...I tried them all.
What fixed it for me was...go to
node_modules\vue-loader\lib\template-compiler ...open index.js and look for
// prettify render fn
if (!isProduction) {
code = prettier.format(code, { semi: false})
}
and change the lines to:
// prettify render fn
if (!isProduction) {
code = prettier.format(code, { semi: false, parser: 'babylon' })
}
Thats it!
Then once the issue got fixed, everything will just be rolled back and you will still be fine.
Try this...it will save you countless minutes of searches....
As already pointed out by the various resonses, you may need to rollback the version of the prettier package.
in your package.json file, you may need to force npm to use a version (i.e. remove the hat ^)
mine looks something like this
"devDependencies": {
"prettier": "1.12.1",
"typescript": "^2.6.1",
"vue": "^2.5.16",
"vue-styleguidist": "^1.4.4",
"vue-webpack-loaders": "^1.0.6",
"webpack": "^3.1.0"

How to fix broken Typescript definitions when definitions files are updated

I have a project that uses Typescript, using the newer #types/foo style of installing typings packages.
When my build server installs all npm modules, sometimes I get a complete failure when compiling the typescript as some dependent definitions are no longer matching up.
For instance, I now have a problem with #types/gulp. In its package.json, dependencies are listed as:
"dependencies": {
"#types/node": "*",
"#types/orchestrator": "*",
"#types/vinyl": "*"
},
But now #types/orchestrator has updated, and it now breaks the version of #types/gulp that I have defined in my apps package.json.
How am I supposed to lock down version of dependencies like this so I no longer get this problem, or is there another workaround?
Unfortunately, I suddenly get these issues which sets development back by hours trying to sort it out. This makes using Typescript in a fast moving environment difficult.
How am I supposed to lock down version of dependencies like this so I no longer get this problem
Run npm shrinkwrap or just specify an exact version:
"#types/vinyl": "6.3.12"

Specifying Typescript Type Definition Versions

I am a new to TypeScript and a bit confused. If my version of TypeScript is 1.0.1 (say I'm stuck on VS2012), how do I use tsd to find type definitions for a library that given I require tsc 1.0.1.
Without version information, I will often get type definitions for tsc1.4.
I figure there must be a way to do this in tsd, but I have not been able to figure it out.
Cheers!
how do I use tsd to find type definitions for a library that given I require tsc 1.0.1
You can't easily. You need to run tsd install somedefinitionyoucareabout -soa and then change the git sha saved in tsd.json to some thing that is from the 1.x branch: https://github.com/borisyankov/DefinitelyTyped/tree/1.0.1
That said you really should consider updating to TypeScript latest.
If you are trying to download TypeScript type definitions for an older version of TypeScript with tsd, you may do the following.
If you look inside tsd.json you will see the key "ref", which is set to "master".
{
"version": "v4",
"repo": "borisyankov/DefinitelyTyped",
"ref": "master",
...
}
This refers to the master branch of borisyankov/DefinitelyTyped.
There are other branches of borisyankov/DefinitelyTyped such as 1.0.1 which target previous releases of TypeScript.
Simply modify tsd.json to point to another branch, and it will retrieve type definitions specific to that version of TypeScript.
{
"version": "v4",
"repo": "borisyankov/DefinitelyTyped",
"ref": "1.0.1",
...
}
After you have done this, you can install a type definition with --save and inspect the commit hash in tsd.son to confirm.

npm installs dependencies with complete readme in a package.json -- invalid json results

Today I upgraded npm and node. I'm at 1.4.9 and 0.10.28, respectively. (OSX 10.9.2.)
Since then, it seems that npm install is writing "bad" package.json files for all of my dependencies.
Specifically, it is putting sevaral fields into the files that do not seem to be present in the source repo's package.json.
Like this example. I have about 40 dev dependencies and they all have this junk (not to pick on gulp, I just happened to grab it for this example):
"readme": "<p align=\"center\">\n <a href=\"http...",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/gulpjs/gulp/issues"
},
"_id": "gulp#3.6.2",
"_shasum": "ea6b33d768db4a22294fa6339afb61842f5e6fb5",
"_from": "gulp#~3.6.2",
"_resolved": "https://registry.npmjs.org/gulp/-/gulp-3.6.2.tgz"
These are on the root of the package.json object. Note, I've abbreviated the readme -- it's an entire html-ized version of the readme, and in many of the files it's not properly escaped and thus makes package.json invalid and unusable.
Obviously this leaves me dead in the water. My questions are "what did I do"? And how do I undo it? Did I wind up with a version of NPM that I shouldn't have? Could there be something else about my project, my node install, or the rest of my environment that might cause this? I do have nave and a version of node in the 0.11 family, but that's not active and hasn't been in recent history -- could npm update -g npm have discovered that I have 0.11 in a different directory and jumped me into territory to which I should not have gone? If so, how to I go backward? I've tried npm installing npm back down into earlier versions but npm still reports the higher version number as if my install didn't happen, and I can't quite figure out what version I'm supposed to have, anyway.
What I've tried so far -- reinstalling node and npm, wiping out my node_modules for the project, and npm cache clean. Nothing seems to have any effect. I'd be happy to answer any questions that I can about my environment that might help me resolve this.
TIA!
I just poked my way somewhat blindly into a solution.
(although I suspect it didn't matter, I upgraded to the master branch code of npm)
I believe that I fixed this by experimenting with setting long = false in my .npmrc file. No more readmes in package.json files! :)
Aside: the package.json content that I see is quite foreign to me in its arrangement, but I guess that may be a function of being on a newer version.
At the very least, the package.json is now valid json and life is better again. I'm not going to accept this, my own answer, just yet because I hope someone might be able to tell me why I needed to do this. This is an override in my .npmrc file as far as I understand it, so it seems bizarre that out of the blue I needed to add this override by hand based on no documentation....
I'll accept an answer that points me to an explanation of what happened or of what might have happened, if there is such an answer! If none are forthcoming, I'll just accept my own answer so that the SO question loop is closed. Thanks!

Resources