duojs / duo

A next-generation package manager for the front-end
3.42k stars 117 forks source link

duo-pin(1): pin dependencies #76

Open matthewmueller opened 10 years ago

matthewmueller commented 10 years ago

Useful when you're ready to deploy your app and want stricter versioning rules. Would only apply to the top-level dependencies, so you'd probably still want to use images / release commits to ensure deploy consistency.

matthewmueller commented 10 years ago

Could be in core or a plugin

yields commented 10 years ago

like shrinkwrap ? or just to pin them ?

matthewmueller commented 10 years ago

umm... i was thinking just pinning. for example, when I'm getting started on an app, I want to just do * for all the versions, then have something automatically pin them later.

matthewmueller commented 10 years ago

shrinkwrap could be nice, don't want another file though...

matthewmueller commented 10 years ago

we could even write something that pulls components from requires and just adds them to the component.json haha so many possibilities :-D

yields commented 10 years ago

we could even write something that pulls components from requires and just adds them to the component.json haha so many possibilities :-D

that's why i like duo.json plugins can use it directly without having to require('duo') and use the api.

matthewmueller commented 10 years ago

yahh, completely agree. thanks for convincing me :-)

ianstormtaylor commented 10 years ago

Btw, just thinking out load, but been using your guys's idea of not having the component.json at all to see what it feels like after @yields told me about the concept. At first I was worried about it, but it's pretty darn nice :)

If that was the ideal direction to go in, potentially the duo pin command could instead of pinning things in component.json, it could traverse the files for require() and pin them directly in the files itself? Just thinking about how the development workflow would work but basically...

You'd start when hacking with requires like this:

var value = require('component/value');

And then you might want to pin them to major (the default):

$ duo pin major

Which could convert them into this:

var value = require('component/value@^0.1.3');

Or you could pin to minor:

$ duo pin minor

Which would make it:

var value = require('component/value@~0.1.3');

Would be interesting at that point to think about what happens with conflicts. I feel like the ideal is that the CLI makes itself useful and helps you resolve them right there with something like:

$ duo pin minor

  component/assert needs ~0.2.7 and ~0.1.5. 
  Which version do you want? ~0.2.7

  Pinned dependencies:

    component/value ~0.1.3
    component/assert ~0.2.7
ianstormtaylor commented 10 years ago

You could even pin certain modules:

$ duo pin component/value
$ duo unpin component/value

Which could edit the source for you too.

Although maybe editing the source starts getting too convoluted since it makes the files harder to read, and maybe only having a concept of a duo-shrinkwrap.json or similar is best and leave the source version-agnostic

matthewmueller commented 10 years ago

Yahhhh. I haven't thought too much about the pros and cons of something like this but the main point of building duo was to make more reliable frontend code. I'm down to explore any option to achieve this.

Right now none of my old component projects work so I don't want to make that mistake again.

Sent from my iPhone

On Aug 3, 2014, at 15:31, Ian Storm Taylor notifications@github.com wrote:

You could even pin certain modules:

$ duo pin component/value $ duo unpin component/value Which could edit the source for you too.

Although maybe editing the source starts getting too convoluted since it makes the files harder to read, and maybe only having a concept of a duo-shrinkwrap.json or similar is best and leave the source version-agnostic

\ Reply to this email directly or view it on GitHub.

lancejpollard commented 10 years ago

Oh man this would be pretty cool. However, to really make this robust you would have to solve it at the AST level, which might take a lot of thinking (I don't know much about the possibilities for the AST). However, it seems like a solvable problem, would have to prove it though.

So it would handle edge cases like these:

require('component/value');
// or
var type = 'value';
require('component/' + type);
// or
function loadThem(){
  var args = [].slice.call(arguments);
  var obj = {};
  args.forEach(function(arg){
    obj[arg] = require('component/' + arg);
  });
  return obj;
};
loadThem('value', 'emitter');
// or
require(fmt('%s/%s', org, repo));
// or
document.write("<script>require('component/value')</script>");
// or...

Once all of the cases were mapped out, then it would be very easy, we would just find the corresponding AST transformations and then make it so it can properly append the version to it. So they become:

require('component/value@~0.1.3');
// or
var type = 'value';
require('component/' + type + '@~0.1.3');
// or
function loadThem(){
  var args = [].slice.call(arguments);
  var obj = {};
  args.forEach(function(arg){
    obj[arg] = require('component/' + arg); // have to trace syntax tree, but it is possible i think
  });
  return obj;
};
loadThem('value', 'emitter');
// or
require(fmt('%s/%s', org, repo)); // same here
// or
document.write("<script>require('component/value@~0.1.3')</script>"); // this one would be solvable for sure
// or...

As a side note, this would be a very cool thing to be able to do for many other use cases :)

If we didn't solve these edge cases, it seems like we would have to use something like component.json.

lancejpollard commented 10 years ago

Essentially, this would have to use a full script rewriter, along the lines of:

stephenmathieson commented 10 years ago

imo, none of those silly uses of require() should be considered/supported

same with this sort of nonsense:

eval('\x72\x65\x71\x75\x69\x72\x65\x28\x22\x66\x6f\x6f\x2f\x62\x61\x72\x22\x29')
// require("foo/bar")
stephenmathieson commented 10 years ago

ive already written a plugin for this. can we close?

yields commented 10 years ago

ive already written a plugin for this. can we close?

maybe we should add it to core? cc @MatthewMueller

dominicbarnes commented 10 years ago

@stephenmathieson does your plugin only work with a component.json ?

stephenmathieson commented 10 years ago

no, it writes a component.json derived from ./components/duo.json

https://github.com/stephenmathieson/duo-pin

matthewmueller commented 10 years ago

i'm fine adding it to core, up to you guys

stephenmathieson commented 10 years ago

i'd like to leave it out of core. i'll move the plugin to the duojs org if you like though

johntron commented 9 years ago

:+1: move it, mention it in duojs/duo/Readme.md, and close this issue!