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.
