- Notifications
You must be signed in to change notification settings - Fork3k
Conversation
Nice! Why new |
The reason for introducing the new specifier are:
Originally there was a plan to actually hard deprecate the |
@iarna Sounds reasonable 👍 Have you considered the impact of having different module resolution paths when using symlinks? |
@timoxley It's a fair question. As it's specced right now it would do that. Maybe, if the linked module is inside the top level install root we should flatten its deps down, instead of keeping them inside the linked module. The module loader would still be able to pick them up and it'd not increase disk usage. |
@iarna that sounds good. Being aware of where symlinks resolve to perhaps could be considered a good general improvement to the dedupe/flattening algorithm. |
doc/spec/file-and-link-specifiers.md Outdated
* Attempting to install a specifer that has a windows drive letter will | ||
produce an error on non-Windows systems. | ||
* A valid `file:` specifier points is: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Did you mean "A validfile:
specifier also is" like in the next item? I am finding it difficult to understand this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would say it should be "Also, a validfile:
specifier is:"
doc/spec/file-and-link-specifiers.md Outdated
Historically, these ambiguous specifiers were also allowed in the | ||
`package.json`. Starting in `npm@5` using an ambiguous specifier in your | ||
shrinkwrap will be depricated and will warn. In `npm@6` it will be an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Typo: depricated -> deprecated
This is great! I would like to know if you considered supporting the current |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This seems like it would really help a lot of people. 🎆
doc/spec/file-and-link-specifiers.md Outdated
* Attempting to install a specifer that has a windows drive letter will | ||
produce an error on non-Windows systems. | ||
* A valid `file:` specifier points is: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would say it should be "Also, a validfile:
specifier is:"
doc/spec/file-and-link-specifiers.md Outdated
* A valid `file:` specifier points is: | ||
* a valid package file. That is, a `.tar`, `.tar.gz` or `.tgz` containing | ||
`<dir>/package.json`. | ||
* OR, a directory that contains a `package.json` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Should that 'OR' be removed or should all of these start with 'OR'? Consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
There are only two of them and the OR separates the two. So I'm not sure what you mean by "all of these".
doc/spec/file-and-link-specifiers.md Outdated
* a valid package file. That is, a `.tar`, `.tar.gz` or `.tgz` containing | ||
`<dir>/package.json`. | ||
* OR, a directory that contains a `package.json` | ||
* And a valid `file:` specifier also is: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Shouldn't this not be a bullet? Or just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It should. It's part of the top level list.
doc/spec/file-and-link-specifiers.md Outdated
The `preinstall` for file-type specifiers MUST be run AFTER the | ||
`finalize` phase as the symlink may be a relative path reaching outside the | ||
current project root and a symlink that resolves in `.staging` won't resolve | ||
in the package's final resting place. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Would thepreinstall
for a package depended on vialink:
be run from it's original folder, or somewhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Basically this is me trying to not screw people who are usingpwd
(which would be relative to where your package root's node_modules).
Folks who are usingcwd
would always get the same answer (the destination of the link).
doc/spec/file-and-link-specifiers.md Outdated
``` | ||
example-package@1.0.0 /path/to/example-package | ||
+-- a -> Copied from: link:../a | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Again, is this repetition intentional?
doc/spec/file-and-link-specifiers.md Outdated
``` | ||
example-package@1.0.0 /path/to/example-package | ||
+-- a -> link:../a | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Why are there two parts with the same thing? Is that intentional?
So after some discussion in air between@zkat and I, we're of a consensus that we should go ahead with just |
coveralls commentedMar 2, 2017
doc/spec/file-and-link-specifiers.md Outdated
``` | ||
example-package@1.0.0 /path/to/example-package | ||
+-- a -> file:../a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Still, is this repetition intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
what repetition? directories and package names can be different:a -> file:../b
is perfectly valid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
One of these is with unicode enabled, one without. I wanted to specify both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Oh. Sorry. I didn't notice that.
doc/spec/file-and-link-specifiers.md Outdated
``` | ||
Package Current Wanted Latest Location | ||
a MISSING LOCAL LOCAL example-package |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would suggest that it should also log where it is looking for the package in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
As zkat says below, changing outdated to be more useful is really a separate RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Ok, cool. Sounds like a really good thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
pretty excited about this. Thanks for writing the spec up <3
doc/spec/file-and-link-specifiers.md Outdated
#### File type specifers pointing at directories | ||
File-type specifiers that point at directories will necessarily not do | ||
anything for `fetch` and `extract` phases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
How do you feel about pacote doing this automagically onpacote.extract
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Hrm. I don't think pacote has quite enough information currently to resolve this sort of thing. The specifier and the target destination aren't enough. You also need to know the location of the module that required it, because the specifier is relative to THAT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Can/should we add this torealize-package-specifier
? We usewhere
there already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Maybe, I mean, we might actually already be resolving come to think. It just requires some end-to-end care.
doc/spec/file-and-link-specifiers.md Outdated
`file:///foo/bar` reference the same package. | ||
* … or a relative path (eg `../path/to/thing`, `path\to\subdir`). Leading | ||
slashes on a file specifier will be removed, that is 'file://../foo/bar` | ||
references the same package as same as `file:../foo/bar`. The latter is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Can you add a quick clarification thatfile://foo/bar
is considered relative, too? At least that's what I assume from reading this. It's a weird, sandwichy corner case, but it's probably worth actuallyspecifying:
file:///foo
-> Absolute/foo
file://foo
-> Relative, same as./foo
file:/foo
-> Absolute/foo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Number of leading slashes changes nothing:
file:///foo
->/foo
file://foo
->/foo
file:/foo
->/foo
With no leading slashes, relative paths are evident:
file:foo
->./foo
file:../
->../foo
I'm proposing that if you have..
as your first path element then we ignore any leading slashes:
file:/../foo
->../foo
file://../foo
->../foo
file:///../foo
->../foo
I think this would eliminate whole classes of likely errors, particularly around users who are trying to make these things work like URLs. Also/../
is not a construct that would ever normally exist. It's a nonsensical noop in and of itself.
doc/spec/file-and-link-specifiers.md Outdated
* Attempting to install a specifer that has a windows drive letter will | ||
produce an error on non-Windows systems. | ||
* A valid `file:` specifier points is: | ||
* a valid package file. That is, a `.tar`, `.tar.gz` or `.tgz` containing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
We should make sure the error message from this is VERY CLEAR that we determine tarballness based on file extension. I know we talked about this a lot, but I still want to avoid linuxy/unixy folks pulling their hair out if they, say, try to install a tarball they downloaded from a webservice that does not specify a filename and they end up with an unsuffixed filename that is still technically a tarball.
Or, for example, if someone tries tonpm install ~/.npm/.pacote/content/deadbeef
, which do not have.tgz
suffixes.
doc/spec/file-and-link-specifiers.md Outdated
#### File type specifiers pointing at tarballs | ||
File-type specifiers pointing at a `.tgz` or `.tar.gz or `.tar` file will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
missing backtick (`) here after .tar.gz
doc/spec/file-and-link-specifiers.md Outdated
dependencies of the linked package will be hoisted to the top level as usual. | ||
If the module is outside the package root then dependencies will be installed inside | ||
the linked module's `node_modules` folder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Is this going to be done as a separate npm run within that project folder (possibly a subprocess?) or will we build a single ideal tree with some special semantics, and do it in a single npm run? This seems trickier to me than what this single sentence describes. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Nah, single thing, it doesn't even require much in the way of special semantics. It's basically the same logic as how we define "global" mode currently.
doc/spec/file-and-link-specifiers.md Outdated
``` | ||
Package Current Wanted Latest Location | ||
a MISSING LOCAL LOCAL example-package |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
oh godLocation
is such a horrible, confusing name when we factor this in. I really bloody wish we had a different name for that column.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Additionally, I wish we had somewhere to put more information about the package getting installed, such asfrom
or something, because the package name by itself doesn't give us much. But that's something for a separate RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yup, I'd love to change that too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Wait, I am confused. Sopackage
is the name, andLocation
is the path on disk? Or is it the path to it through the dependency chain? Or is it the package that depended on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@legodude17npm help outdated
will answer your questions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@zkat thanks for the tip. You are right thatLocation
is a very confusing name for that. MaybeParent
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@legodude17 we'll talk about that once there's an RFC for it. Talking about it in here is bound to get lost in oblivion (and is offtopic for this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sounds like a good idea. Do you have a estimated time for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Nope, not part of the current schedule. I have on my todo-list writing up an up-to-date "state of NPM" blog post to bring everyone up-to-date on our goals and plans and expectations.
mlucool commentedMar 8, 2017
Using symlinks with node, requires a flag set for it to work correctly:nodejs/node#8749 (review). Is the intent to change how node handles symlinks also? One nice feature about how file works today is for peer dependencies. Due to the copy instead of a symlink, peers with global singletons work as expected. When this moves to symlinks only, the resolution will make certain cases impossible to resolve. Example:
Let me know if that example needs more clarification or if I have misunderstood RFC. |
@mlucool my understanding of this case is that it would continue to work so long as Module A is anywhere inside the directory structure for B when you link it. That is:
@iarna it might be worth specifying the logic for |
mlucool commentedMar 8, 2017
@zkat In my case A is outside of B always. We do not have a monorepo. Stillthis seems to imply as long as it is note My current hack (which works quite well) is to create a symlink like util that does:
Now for any change I make it appears nearly instantly. Clearly this is a hack, but it maintains that I can separate components across repos and not worry about dependency issues. |
@mlucool if you're not going to use a monorepo structure, you could literally just run |
and yes, we willalways create symlinks fordirectory specs. The difference is that we hoist deps normallyiff the target package is in a subdir of the current package. |
mlucool commentedMar 8, 2017
@zkat I could do that to keep my hack working. I am still a little unsure about how this hoisting will play out because you can imagine something like:
If I did a Any comments on the node flag required for this to work? P.S. I am a BIG fan of better support for symlinks, per my commit to node. |
@mlucool It's worth noting that it's tremendously unlikely for us at npm to try to change module resolution, including symlink stuff, ourselves. afaik, there's no intent for us to actually go and push for a change on that end in order to land this. More likely, I think, is discussing the possibility of taking that flag into account when deciding how to build the hoisted tree -- some users will want that symlink preservation, some won't. I'll defer to@iarna about whether she thinks this is something worth exploring, with a note that any current hacks around @iarna does it make sense to you to read |
mlucool commentedMar 9, 2017
IMO if something is outside of a module you should never touch its contents. |
@mlucool As@zkat says, changing the default Node.js module loader behavior isn't on the table, which is why 'preserve-symlinks' landed as an option. Thank you for bringing this up! What you described isn't a use-case we had discussed previously. I think having it change install behavior based on So yeah, if you have |
octogonz commentedOct 28, 2017
Hi@iarna, We're having an issue with the "file://" specifier not being handled correctly by NPM 5. We have an automated tool that generates apackage.json with references like this: "dependencies": {"yargs":"~4.6.0","z-schema":"~3.18.3","project1":"file:./projects/project1.tgz","project2":"file:./projects/project2.tgz", The "project1.tgz" archive contains apackage.json file like this: {"name":"project1","version":"0.0.0","private":true, When NPM 4 installs it, thenode_modules/project1/package.json looks like this, as expected: "version":"0.0.0" However, NPM 5 for some reason writes it like this: "version":"file:projects/project1.tgz" Was this an intentional design change? Is it an NPM 5 bug? It's causing trouble becauseread-package-tree chokes on this JSON value. We get an error like this:
|
octogonz commentedOct 30, 2017
I'm pretty sure this is an NPM bug. I've opened#19006 |
…m install` on npm5problem: npm4 install local dependencies by copying over the local package but npm5 install local dependencies as symlink. This cause issues for our TestApp that install local appcenter* packages because "Header Search Paths" can't find react native modules.solution: `npm pack appcenter && npm install appcenter.tgz` will package up and then install the tgz files, which avoid the symlinks. (seenpm/npm#15900 (comment))
* we want to have assets available via simple `npm install`* npm 5 changed `file:` semantics into `link:`, breaks local installs*https://www.npmjs.com/package/install-local is cumbersome to use[1]:npm/npm#15900
* we want to have assets available via simple `npm install`* npm 5 changed `file:` semantics into `link:`, breaks local installs*https://www.npmjs.com/package/install-local is cumbersome to use[1]:npm/npm#15900
This helps avoid publishing broken packages when using npm5's new relative link specifiersnpm/npm#15900
adrian-gierakowski commentedMar 6, 2018
@iarna what happened to this proposal? has it been rejected? btw. looks like something similar has beenimplemented in yarn some time ago |
@adrian-gierakowskiit was merged and implemented as part of |
Easy reading link for the newspecification. This also introduces written specifications for npm features, something we intend to extend out to all of npm's activity.
The Problem We're Solving
File type dependency specifiers are confusing. How they interact across npm's many varied commands (
npm install --save
,npm update
,npm outdated
,npm shrinkwrap
) has never been defined in one place. Most of the behaviors "happened by default". That is, the minimum implementation was done to make them install ok and the rest was left as a side effect.Currently
npm update
andnpm outdated
simply don't do anything for local dependencies. If you've updated the source you have to manually reinstall to get a copy of it. Hownpm shrinkwrap
saves local dependencies tonpm-shrinkwrap.json
and how it resolves them has varied over time as well.Root Causes
When local dependencies were added, we didn't have any process around defining behavior or ensuring that all use cases were specified.
Proposal
In addition to actually specifying behavior (often simply writing down what
things currently do), we propose in important breaking change:
file:
-type specifiers that refer to directories will be soft deprecated, their behavior being identical to the newlink:
specifier and their existence becoming a footnote in the documentation.link:
, will be introduced for linking local directories. For the duration ofnpm@5,
file:specifiers that refer to directories will be treated identically to
link:` specifiers.link:
specifiers will result in a symlink or junction made from the specifier path into yournode_modules
. On Windows try a junction and if that fails, try a symlink. If both fail, the error from the junction should be used.This RFC essentially bringslinklocal's bevior into core.
RISKS
file:
semantics.