The way I see it, the "dependencies"  hash in package.json right now is 
pulling double-duty. In some cases (where the value of a dependencies field 
is a semver), it's there to describe *generally* what module versions it 
expects to be compatible with. In other cases (when the value of a field is 
a URL), it's there to describe the *exact* version of a module it's used 
with.

This mixed-purpose approach has a few shortcomings: for one, packages 
outside the canonical registry can't specify version ranges. What's worse, 
any discussion of these shortcomings inevitably devolves into a 
back-and-forth over the utility of the registry (with arguments over 
everything from naming techniques, to implied triviality, to diplomatic 
protocol).

Putting that aside for the moment, I modestly propose we split these duties 
into two hashes:

   - Make it so the "dependencies" (and "devDependencies") hash is always 
   shrinkwrapped. This keeps the same read semantics "dependencies" always 
   had, so nothing breaks (that wasn't already broken).
   - Use a different hash (let's call it "wants") that handles 
   future-looking package usage, where each package (by 
   node_modules/package.json/require() name) has a hash for a value, that 
   includes its location (npm registry, github repo, HTTP tarball, etc), its 
   acceptable semver range (for (couch and git) servers that can list 
   available versions), peer requirements, and any new package use factors 
   that may arise in the future (much as how the other hashes in package.json 
   are flexible, like "scripts" and the root hash itself).

Loose semver ranges used to be a Big Important Deal, back in the packaging 
flatlands of Python and Ruby. In those worlds, every module in use had to 
agree to share one particular version of any module- every module had to 
accommodate any potentially outdated code. Where a dependency was coming 
from didn't matter, but the ways it would be acceptable to come was.

In Node, however, packages, once installed, will never see their 
dependencies versions any older than the latest they were written (unless 
they're peerDependencies). The one purpose of ranges is to allow potential 
optimizations and bugfixes from any future revisions of dependencies, 
without having to explicitly declare it. At this point, keeping that 
looseness, as a core attribute of the runtime, is a weakness, one that's 
overshadowing the increasingly pressing issue of where that package is 
located.

Here are the gains yielded by splitting these purposes:

   - "dependencies" is tightened up for repository packages (bringing them 
   to the specificity non-repository packages are already subject to). New 
   packages can't rely on ranges that can become invalid (due to either a 
   too-loose semver requirement or a breaking change in a minor version). A 
   guaranteed shrinkwrapped dependencies field means you know *exactly* what 
   revisions the package was developed against at time of publication.
   - Packages outside the registry are no longer second-class citizens. 
   Notably, using them no longer blocks you from specifying a compatible range 
   of versions to update to.
   - Letting packages specify metadata beyond location allows specific 
   installation profiles like "devDependencies" to be specified by 
   black/whitelist, eg. {"exclude":"prod"} or {"include":["doc","build"]}.

These would be transitional changes necessary to NPM:

   - Calling "npm install" or "npm update" with a package.json that uses 
   semver ranges (or tagless git URLs) automatically shrinkwraps 
   "dependencies" and converts the existing "dependencies" values to the 
   equivalent "wants".
   
Here's what would have to change expectations to accommodate this:

   - `npm update` would have to read the "wants" field, and would need 
   additions to find available semver tags in non-registry locations (like 
   tags in a Git repo).
   - For developers, the listed semvers would need to be loosened/tightened 
   appropriately, and `npm update` would be required to update a code's 
   dependencies. (Good.)

The only things that expect the behavior of `npm install` to incorporate 
inherent updates would just need an explicit `npm update` step.

What does the community think? If npm wouldn't be willing to go ahead with 
something like this, any interest in producing some kind of fork?

-- 
-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

--- 
You received this message because you are subscribed to the Google Groups 
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to