as/for: thoughts on adding aliases to npm as an alternative to dependency injection

116 views
Skip to first unread message

Ken

unread,
May 13, 2013, 8:15:06 PM5/13/13
to nod...@googlegroups.com
I've been mulling this problem space a while and decided to "think out loud" here to see whether anyone else is exploring similar avenues.  There's obviously some good work being done in dependency injection for node apps, but I have some instinctual cringe at any dependency injection systems that make an appearance within source code, and this seems to be common to all of the current ones vying for mindshare in the node community (nject, Injector,  dependable, etc.).

As an alternative I've been considering how to solve (some of) this with (hopefully) simple extensions to npm to allow installing one module as an alias for another.  Might be clearest to start with an example--consider some of the many modules providing bindings of MaxMind's GeoIP data (https://npmjs.org/search?q=geoip)
All of these are similar in purpose and several of them have identical exports (or are supersets of another). They vary significantly in implementation however, including C bindings to a dynamically linked library that must be installed separately, static links to that library, and some pure JavaScript with differing performance characteristics.  There's also a nice little bit of of connect middleware (connect-geoip) that originally depended on geoip (which is the dynamically linked C version) but now depends on geoip-lite (a pure JavaScript version).  Since there are significant tradeoffs involved in the various geoip implementations it's likely that this decision might not be appropriate for everyone, but it seems silly to create and maintain 6 forks of connect-geoip just because there are 6 nearly identical libraries it could depend on.  (This is also a very natural place to want to inject a mock library for tests since actual IP geolocation isn't very deterministic, which is how I got to thinking about this in the first place...).   This leads to my "as/for" proposal, which would allow a package.json in a dependent project to specify the name that a dependency gets installed as, e.g. to use geoip-native instead of geoip-lite in your express/connect project you could do the following

{
  "name": "example-project",
  "version": "0.0.1",
  "dependencies" : {
    "express": "*",
    "connect-geoip": ">= 0.0.4",
    "geoip-native": { "version": "*", "as": "geoip-lite", "for": "connect-geoip" },
    ...
  }
}

Aliased packages are distinguished by an object value instead of a string.  Within the object the version key serves the same purpose as the original.  When encountering an as statement npm would install the package into a directory with the given name, rather than its default.  If a for statement is used then the module is installed into the node_modules subfolder of that module rather than the root (in this case the code for geoip-native would go into .../node_modules/connect-geoip/node_modules/geoip-lite).

I'm not at all clear how much work this would be in npm, and there are a lot of edge cases to worry about, but from the perspective of node itself, if the aliased package behaves closely enough to the original then this should "just work", since the arguments to require are just paths, and the actual names of packages don't seem to matter.  The greatest appeal to me of this system is that it lives entirely outside of code, and thus could be applied to the thousands of existing modules without needing to rewrite them.





Tim Caswell

unread,
May 13, 2013, 11:32:03 PM5/13/13
to nod...@googlegroups.com
I often have a similar need.  In debian systems, I'm noticed that sometimes there are "virtual" packages that several competing packages all "provide" the concrete representation for.  Maybe a simpler syntax using the idea of "provides" could be used here.

My concrete example, is my js-git demo.  I'm using Chris Dickinson's bops library to have a common binary data type interface between node Buffers and browser Uint8Arrays.  His library is very thorough and even depends on a utf8 codec since the browser hack for utf8 only works if your script tag it interpreted with the utf8 charset. (other examples are lodash, zepto, etc)

For some projects, I just want a subset of what bops provides that I can implement using much less code.  Right now, my plan is to manually install my module in node_modules "as" the module I'm providing an implementation for.  But it would be great if npm or some wrapper could know to do this automatically if I configured my app to use the replacement.


--
--
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 nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
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 nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

greelgorke

unread,
May 15, 2013, 4:31:27 AM5/15/13
to nod...@googlegroups.com
looks like establishing symlinks to me, may be as post instal hook?
Reply all
Reply to author
Forward
0 new messages