Skip to content

Instantly share code, notes, and snippets.

@kapouer
Created August 19, 2020 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kapouer/c29feb7ae9ee9d46f77947e80a7ffef5 to your computer and use it in GitHub Desktop.
Save kapouer/c29feb7ae9ee9d46f77947e80a7ffef5 to your computer and use it in GitHub Desktop.
const path = require('path');
const readFile = require('fs').promises.readFile;
const serveStatic = require('serve-static');
/* ES Modules path resolution for browsers */
/* uses fields in package.json (exports,module,jsnext:main,main) */
/* mount is the base path, and it needs a whitelist of modules names */
module.exports = async function(mount, whitelist = []) {
const node_path = path.join('.', 'node_modules');
const serveHandler = serveStatic(path.resolve(node_path), {
index: false,
redirect: false,
dotfiles: 'ignore',
fallthrough: false
});
const modules = {};
const bases = [];
for (let name of whitelist) {
const modulePath = path.join(node_path, name);
const pkg = JSON.parse(await readFile(path.join(modulePath, 'package.json')));
const exp = pkg.exports && pkg.exports.import
|| pkg.module
|| pkg['jsnext:main']
|| pkg.main
|| '';
const objExp = path.parse(exp);
const base = mount + '/' + name;
modules[base] = {
dir: objExp.dir,
base: objExp.base,
name: name
};
bases.push(base);
}
return function serveModules(req, res, next) {
if (!req.path.startsWith(mount + '/')) {
return next('route');
}
const base = bases.find((base) => req.path.startsWith(base));
if (!base) throw new HttpError.NotFound("No such module");
const mod = modules[base];
let rest = "./" + req.path.substring(base.length + 1);
const objRest = path.parse(rest);
let redir = true;
let restBase = objRest.base;
if (restBase == "" || restBase == ".") {
restBase = mod.base;
} else if (!objRest.ext) {
restBase += ".js";
} else {
redir = false;
}
let restDir = objRest.dir;
if (!restDir.startsWith(mod.dir)) {
restDir = mod.dir + '/' + objRest.dir;
redir = true;
}
if (redir) {
res.redirect(path.join(base, restDir, restBase));
} else {
req.url = '/' + path.join(mod.name, rest);
serveHandler(req, res, next);
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment