This has been discussed on github for sphere 2.0:
https://github.com/sphere-group/pegasus/issues/9I think all the current engines should move to implement require as a built-in as soon as possible, and Sphere libraries should begin to be shipped as simple npm-like packages that can be used with require. With a forked `npm` using a custom package index we can make Sphere libraries easy to install and use, with proper dependency management. In short, modern.
We can still shim support without built-in require for backwards compatibility - writing a module loader isn't that complicated, and we're only going to be loading JavaScript.
I have been working with minisphere and Duktape has half of it built in - it performs path resolution and you have to supply it with the module. I wrote a loader that enables use of require('module') that will look for four things:
1. module.js
2. module.json
3. module/index.js
4. module/package.json
The final check is for packages. We open the package.json and find out what the main file is called, then load that. We also have a convenience loader for JSON files.
It will look for files in your scripts directory, then in the modules directory. This is the directory that Sphere libraries would be installed to by the package manager.
(function() {
var extensions, fileExists, jsHandler, jsonHandler, packageHandler, paths,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
jsHandler = function(filePath, file) {
return file;
};
jsonHandler = function(filePath, file, exports) {
var json, key, value;
json = JSON.parse(file);
for (key in json) {
value = json[key];
exports[key] = value;
}
};
packageHandler = function(filePath, file) {
var json, script;
json = JSON.parse(file);
file = OpenRawFile(filePath.substr(0, filePath.length - 12) + json.main);
script = CreateStringFromByteArray(file.read(file.getSize()));
return script;
};
fileExists = function(path) {
var check, checked, entries, parts, testPath;
if (path.substr(0, 3) === '../') {
path = path.substr(3);
}
parts = path.split('/');
checked = [];
while (true) {
testPath = checked.join('/');
entries = GetDirectoryList(testPath);
entries = entries.concat(GetFileList(testPath));
check = parts.shift();
if (indexOf.call(entries, check) >= 0) {
checked.push(check);
if (parts.length === 0) {
return true;
}
} else {
return false;
}
}
};
extensions = {
'.js': jsHandler,
'.json': jsonHandler,
'/index.js': jsHandler,
'/package.json': packageHandler
};
paths = ['../scripts', '../modules'];
Duktape.modSearch = function(id, require, exports, module) {
var extension, file, filePath, handler, i, len, path, script;
for (i = 0, len = paths.length; i < len; i++) {
path = paths[i];
for (extension in extensions) {
handler = extensions[extension];
filePath = path + "/" + id + extension;
if (fileExists(filePath)) {
file = OpenRawFile(filePath);
script = CreateStringFromByteArray(file.read(file.getSize()));
return handler(filePath, script, exports);
}
}
}
throw new Error("Cannot find module " + id);
};
}).call(this);
Duktape is currently limited and assigning module.exports doesn't work, only properties on exports. It also has limitations that mean we can't load package files from a subdirectory in the package. A replacement is being considered to make it more flexible, but this works otherwise. We can still shim instead of using Duktape until then.
Let's make this the first step to Sphere 2.0. A real module loader and a real package manager.