From 41b058b8f9159c1b1621b12fb0d4f5c1cb08bae7 Mon Sep 17 00:00:00 2001 From: Jan Bobisud Date: Sun, 28 Oct 2018 10:40:36 +0100 Subject: [PATCH] Allow to require module path from whitelisted dependency Required module path can be one of - `fs` (built-in Node.js module), - `abortcontroller-polyfill` (external main module), - `abortcontroller-polyfill/dist/cjs-ponyfill` (external submodule). FastBoot's build system requires only dependency whitelisting, thus looking only for the first part of module path. --- package.json | 1 + src/ember-app.js | 35 +++++++++++++++++++++++++---------- src/utils/get-package-name.js | 12 ++++++++++++ test/get-package-name-test.js | 12 ++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 src/utils/get-package-name.js create mode 100644 test/get-package-name-test.js diff --git a/package.json b/package.json index 11bfcfb..3940bfe 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "cookie": "^0.3.1", "debug": "^3.0.0", "najax": "^1.0.2", + "resolve": "^1.8.1", "rsvp": "^4.7.0", "simple-dom": "^1.0.0", "source-map-support": "^0.5.0" diff --git a/src/ember-app.js b/src/ember-app.js index d355600..d943abd 100644 --- a/src/ember-app.js +++ b/src/ember-app.js @@ -6,11 +6,13 @@ const chalk = require('chalk'); const najax = require('najax'); const SimpleDOM = require('simple-dom'); +const resolve = require('resolve'); const debug = require('debug')('fastboot:ember-app'); const FastBootInfo = require('./fastboot-info'); const Result = require('./result'); const FastBootSchemaVersions = require('./fastboot-schema-versions'); +const getPackageName = require('./utils/get-package-name'); /** * @private @@ -116,21 +118,34 @@ class EmberApp { buildWhitelistedRequire(whitelist, distPath) { whitelist.forEach(function(whitelistedModule) { debug("module whitelisted; module=%s", whitelistedModule); + + // Remove after 2.0.0 + let packageName = getPackageName(whitelistedModule); + + if (packageName !== whitelistedModule) { + console.warn("[DEPRECATION] Whitelisting module path '" + whitelistedModule + "' will not be supported after fastboot#2.0.0 and it should be removed from the whitelist."); + + if (whitelist.indexOf(packageName) === -1) { + console.error("Package '" + packageName + "' is required to be in the whitelist."); + } + } }); return function(moduleName) { - if (whitelist.indexOf(moduleName) > -1) { - let nodeModulesPath = path.join(distPath, 'node_modules', moduleName); + let packageName = getPackageName(moduleName); + let isWhitelisted = whitelist.indexOf(packageName) > -1; - if (fs.existsSync(nodeModulesPath)) { - return require(nodeModulesPath); - } else { - // If it's not on disk, assume it's a built-in node package - return require(moduleName); - } - } else { - throw new Error("Unable to require module '" + moduleName + "' because it was not in the whitelist."); + if (isWhitelisted) { + let resolvedModulePath = resolve.sync(moduleName, { basedir: distPath }); + return require(resolvedModulePath); + } + + // Remove after 2.0.0 + if (whitelist.indexOf(moduleName) > -1) { + return require(moduleName); } + + throw new Error("Unable to require module '" + moduleName + "' because its package '" + packageName + "' was not in the whitelist."); }; } diff --git a/src/utils/get-package-name.js b/src/utils/get-package-name.js new file mode 100644 index 0000000..6377324 --- /dev/null +++ b/src/utils/get-package-name.js @@ -0,0 +1,12 @@ +'use strict'; + +function getPackageName(modulePath) { + let parts = modulePath.split('/'); + + if (modulePath[0] === '@') { + return parts[0] + '/' + parts[1]; + } + return parts[0]; +} + +module.exports = getPackageName; \ No newline at end of file diff --git a/test/get-package-name-test.js b/test/get-package-name-test.js new file mode 100644 index 0000000..192f884 --- /dev/null +++ b/test/get-package-name-test.js @@ -0,0 +1,12 @@ +'use strict'; +const expect = require('chai').expect; +const getPackageName = require('../src/utils/get-package-name'); + +describe('utils/get-package-name', function() { + it('gets package name from module path', function() { + expect(getPackageName('foo')).to.equal('foo'); + expect(getPackageName('foo/bar')).to.equal('foo'); + expect(getPackageName('@foo/baz')).to.equal('@foo/baz'); + expect(getPackageName('@foo/baz/bar')).to.equal('@foo/baz'); + }); +}); \ No newline at end of file