-
Notifications
You must be signed in to change notification settings - Fork 0
/
autoloader.js
79 lines (77 loc) · 2.69 KB
/
autoloader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
var magic = require('../');
function requestChain(cb, chain, prevRequestChain) {
var map = {};
this.map = map;
var thisChain = this;
this.prev = prevRequestChain;
this.chain = chain = (chain && chain.slice(0)) || [];
function getter(name) {
if (typeof map[name] === 'undefined') {
var ret = cb.call(map, name, thisChain);
// if its still undefined, make it magical
if (typeof map[name] === 'undefined') {
map[name] = new requestChain(cb, chain.concat(name), thisChain);
}
if (typeof ret !== 'undefined') return ret;
}
return map[name];
}
function setter(name, value) {
map[name] = value;
}
return magic(getter, setter);
}
/**
* NOTE WITH THIS AUTOLOADER!
*
* Its not perfect and can be confused under some conditions
*
* such as, foo.js and a dir named foo inside same folder, if foo does not export
* an object (exports a function or primitive value), then the foo folder
* will not be accessible.
*
* Even then, if foo IS an object, and exports a variable such as lib/foo.js:
* module.exports = {bar:'baz'};
*
* then the path lib/foo/bar.js will not be accessible due to it picking up
* the bar value from the module foo.
*
* In other words, be careful to not cause path/name conflicts and itll work ok
*/
function getLoader(basedir) {
basedir = (basedir && basedir + '/') || '';
return new requestChain(function _loader(name, chain) {
try {
var newchain = chain.chain.concat(name);
file = (basedir||'') + newchain.join('/');
var mod = require(file);
if (typeof mod == 'object') {
// we could just set this[name] = mod, but then if there is path
// name conflicts such as lib/foo.js then lib/foo/bar.js, then the folder
// version would not be accessible. so make it magical
// note above comment, it is still possible to conflict here if foo.js
// exports a bar property, then lib/foo/bar.js would not be accessible.
this[name] = new requestChain(_loader, newchain, chain);
for (var i in mod) {
this[name][i] = mod[i]
}
} else {
// if its not an object, we cant make it magical :(
this[name] = mod;
}
} catch (e) {
console.log(e.message, file);
}
});
};
// custom dir loader
var loader = getLoader(__dirname+'/autoloader');
// official require() loader.
var node = getLoader();
console.log(loader.foo.value);
console.log(loader.bar.value);
console.log(loader.bar.baz.value);
node.util.print("Foo!\n");
console.log((node.fs.readFileSync(__dirname+'/node_modules/hello.js')+"").trim());
console.log(node.os.hostname());
console.log(node.hello.world); // load node_modules/hello.js and access export world.