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)

   - geoip <https://npmjs.org/package/geoip> 0.4.10 by 
kuno<https://npmjs.org/~kuno> GeoIP 
   binding for node
   - geoip-no-city-leak <https://npmjs.org/package/geoip-no-city-leak> 0.4.9-1 
   by cohara87 <https://npmjs.org/~cohara87> A fork of kuno/geoip where the 
   City.lookupSync leaks have been patched
   - geoip-static <https://npmjs.org/package/geoip-static> 0.4.6 by 
toots<https://npmjs.org/~toots> GeoIP 
   binding for node. Static native library included. Also deployable on heroku.
   - geoip-lite <https://npmjs.org/package/geoip-lite> 1.0.10 by 
bluesmoon<https://npmjs.org/~bluesmoon> A 
   light weight native JavaScript implementation of GeoIP API from MaxMind
   - geoip-native <https://npmjs.org/package/geoip-native> 0.0.8 by 
benlowry<https://npmjs.org/~benlowry> A 
   fast, native JavaScript geoip api. This product includes GeoLite data 
   created by MaxMind, available from http://www.maxmind.com
   - 
geoip-lite-with-city-data<https://npmjs.org/package/geoip-lite-with-city-data> 
1.0.5 
   by stagas <https://npmjs.org/~stagas> A light weight native JavaScript 
   implementation of GeoIP API from MaxMind
   - ...

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<https://npmjs.org/package/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.





-- 
-- 
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