From d669cfd2da475be802d7b610dbdcbe7ed3100e5f Mon Sep 17 00:00:00 2001 From: Kevin Schmidt Date: Wed, 7 Mar 2018 07:03:02 -0700 Subject: [PATCH] feat(utils): Resolve paths for scoped node modules. --- test/utils.test.js | 10 ++++++++++ utils.js | 12 ++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/test/utils.test.js b/test/utils.test.js index 2ca645a..87bfa6a 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -144,4 +144,14 @@ describe('utils', () => { var chaiJsPath = utils.resolveModulePath(path.join('chai', 'lib', 'chai.js')); expect(chaiJsPath).to.equal(path.join(chaiPath, 'lib', 'chai.js')); }); + + it('should get the path for a scoped module', () => { + expect(utils.resolveModulePath('@some-scope/not-a-real-package')).to.be.undefined; + + var modulePath = utils.resolveModulePath('@semantic-release/changelog'); + expect(modulePath).to.exist; + + var indexPath = utils.resolveModulePath('@semantic-release/changelog/index.js'); + expect(indexPath).to.equal(path.join(modulePath, 'index.js')); + }); }); diff --git a/utils.js b/utils.js index 3ef50fd..794f56b 100644 --- a/utils.js +++ b/utils.js @@ -134,12 +134,16 @@ const getPackage = function(packageName) { */ const resolveModulePath = function(modulePath, optBasedir) { try { - var match = modulePath.match(/([^/]+)\/?(.*)/); - if (match && match[1]) { - var basePath = path.dirname(resolve.sync(path.join(match[1], 'package.json'), { + var parts = modulePath.split(path.sep); + if (parts && parts.length) { + // if the package is scoped, use the first two parts of the path. ie, @scope/package. + var packageName = parts[0].startsWith('@') ? path.join(parts.shift(), parts.shift()) : parts.shift(); + var basePath = path.dirname(resolve.sync(path.join(packageName, 'package.json'), { basedir: optBasedir })); - return path.join(basePath, match[2]); + + // join the remaining path to the resource (if any) + return path.join(basePath, parts.join(path.sep)); } } catch (e) { }