repo-url.js
2.86 KB
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
'use strict';
const fs = require('fs');
const path = require('path');
const { URL } = require('url');
const hostedGitInfo = require('hosted-git-info');
// extract the defaultBranchPath so it can be stripped in the final output
const defaultBranchPath = hostedGitInfo.fromUrl('user/repo').browse('').match(/(\/tree\/[a-z]+)/)[0];
const regexDefaultBranchPath = new RegExp(`${defaultBranchPath}$`);
/** Gets the repo url of an installed package. */
function getPackageRepo(packageName) {
let nodeModulePaths = require.resolve.paths(packageName);
const localNodeModules = path.join(process.cwd(), 'node_modules');
nodeModulePaths = [localNodeModules].concat(nodeModulePaths);
for (const basePath of nodeModulePaths) { // eslint-disable-line fp/no-loops
const packageJsonPath = path.join(basePath, packageName, 'package.json');
if (fs.existsSync(packageJsonPath)) {
try {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
return packageJson.repository;
}
catch (e) { }
}
}
return null;
}
/** Remove the default branch path from a git url. */
const cleanRepoUrl = url => url.replace(/\/$/, '').replace(regexDefaultBranchPath, '');
/**
* @param packageName A package name as listed in package.json's dependencies list
* @param packageJson Optional param to specify a object representation of a package.json file instead of loading from node_modules
* @returns A valid url to the root of the package's source or null if a url could not be determined
*/
function getRepoUrl(packageName, packageJson = undefined) {
const repositoryMetadata = !packageJson ? getPackageRepo(packageName)
: packageJson.repository ? packageJson.repository
: null;
if (!repositoryMetadata)
return null;
let gitURL;
let directory = '';
// It may be a string instead of an object
if (typeof repositoryMetadata === 'string') {
gitURL = repositoryMetadata;
try {
// It may already be a valid Repo URL
const url = new URL(gitURL);
// Some packages put a full URL in this field although it's not spec compliant. Let's detect that and use it if present
if (['github.com', 'gitlab.com', 'bitbucket.org'].includes(url.hostname) && url.protocol === 'https:') {
return gitURL;
}
}
catch (e) { }
}
else if (typeof repositoryMetadata.url === 'string') {
gitURL = repositoryMetadata.url;
if (typeof repositoryMetadata.directory === 'string') {
directory = repositoryMetadata.directory;
}
}
return typeof gitURL === 'string' && typeof directory === 'string'
? cleanRepoUrl(hostedGitInfo.fromUrl(gitURL).browse(directory))
: null;
}
module.exports = {
getRepoUrl
};
//# sourceMappingURL=repo-url.js.map