The title looks exaggerated. I thought NodeJS cannot just run on Windows anymore. It's not the case though, it does - it's just it creates folders that are nested.
Totally. This is actually a trivially solvable problem (I've been working on a meta package manager compatible with npm, bower and component).
The strategy I took with node_modules/, components/ and bower_modules/ was to just follow whatever folder structure it found as far as necessary and look for manifest files (package.json, bower.json and component.json) and register modules at the path of wherever one of those three file types is found. This approach allows any folder organization whatsoever. This information was then saved to a key-value store and the store is only updated when the mtime of the folder changes. This makes startup relatively fast since folders are only re-indexed if something has genuinely changed.
Writing an algorithm that is dependent on the folder structure to me is a fundamentally bad idea most of the time, especially when you have a manifest file that better identifies a module. Additionally, for modules with semver ranges or installed from unusual locations (i.e. URIs: git:// git+ssh://, https://, etc.), you can write an additional metadata file with install information and version locking information (like gemfile.lock)
If people don't rely on the file system organization as an API, npm and node's require() algorithm can trivially reorganize or even use different folder organization schemes on different operating systems if there were a good reason to do so.
I respect where you're coming from, but I disagree. One of the huge advantages of npm for me is that it's so transparent and I can see exactly how it's mapping to the file system. I know exactly which code is being run, from where—because it's incredibly easy to traverse the dependency tree. If you abstract away the fs level and flatten the dependencies into a single folder, you take this away, and you make the dependency tree essentially a big intimidating blob of code that requires slogging through package lists to determine what is actually being used.
Nothing in what I'm doing prevents what you like about npm. In fact npm already abstracts away what you want in a little known command called `npm explore`.
Let's say you want to explore the dependency `foo` in your project. At the root of your project type `npm explore foo` and press enter and you'll be in a shell exploring the foo module. Then if you want to return, type `exit` and return and you'll be back in your project. Or if you want to go down the rabbit hole to a dependency of foo called bar, type `npm explore bar` and press enter.
`npm explore` is a great way to explore things and navigate to the dependencies used by the dependency you want to investigate. It basically uses the information in the current package.json to find the dependency you want.
The strategy I took with node_modules/, components/ and bower_modules/ was to just follow whatever folder structure it found as far as necessary and look for manifest files (package.json, bower.json and component.json) and register modules at the path of wherever one of those three file types is found. This approach allows any folder organization whatsoever. This information was then saved to a key-value store and the store is only updated when the mtime of the folder changes. This makes startup relatively fast since folders are only re-indexed if something has genuinely changed.
Writing an algorithm that is dependent on the folder structure to me is a fundamentally bad idea most of the time, especially when you have a manifest file that better identifies a module. Additionally, for modules with semver ranges or installed from unusual locations (i.e. URIs: git:// git+ssh://, https://, etc.), you can write an additional metadata file with install information and version locking information (like gemfile.lock)
If people don't rely on the file system organization as an API, npm and node's require() algorithm can trivially reorganize or even use different folder organization schemes on different operating systems if there were a good reason to do so.