UNPKG

@nilppm/npm

Version:

Node's internal lightweight private package manager

168 lines (167 loc) 6.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const nelts_1 = require("@nelts/nelts"); const gravatar_1 = require("gravatar"); const request = require("request"); const cheerio = require("cheerio"); const lru = new nelts_1.LRU(300); const NpmApi = require('npm-api'); const npm = new NpmApi(); class WebService extends nelts_1.Component.Service { constructor(ctx) { super(ctx); this.configs = ctx.app.configs; } async getPackage(pathname, version) { const PackageService = new this.service.PackageService(this.ctx); const result = await PackageService.getPackageInfo({ pathname, version }); this.fixRepo(result); await this.fixUser(result); const properties = []; result._downloads = {}; if (!result._nilppm) { const repo = npm.repo(pathname); if (!result.readme) properties.push(this.fixReadme(pathname, result.version).then(data => result.readme = data)); if (!result.dependencies) properties.push(repo.dependencies(result.version).then((data) => result.dependencies = data)); if (!result.devDependencies) properties.push(repo.devDependencies(result.version).then((data) => result.devDependencies = data)); if (result['dist-tags'].latest === result.version) this.fixStatisticsFromNpm(pathname, properties, result); } else { if (result['dist-tags'].latest === result.version) { this.fixStatisticsFromDBO(pathname, properties, result); } } await Promise.all(properties); return result; } fixStatisticsFromDBO(pathname, properties, result) { const StatisticsService = new this.service.StatisticsService(this.ctx); properties.push(StatisticsService.Month(pathname).then((data) => result._downloads.month = data)); } fixStatisticsFromNpm(pathname, properties, result) { properties.push(this.getNpmDownloadsApi('https://api.npmjs.org/downloads/range/last-month/' + pathname).then((data) => { const _data = JSON.parse(data); if (_data.error) return Promise.reject(new Error(_data.error)); result._downloads.month = _data.downloads; })); } async getNpmDownloadsApi(url) { return await new Promise((resolve, reject) => { request.get(url, (err, response, body) => { if (err) return reject(err); if (response.statusCode >= 300 || response.statusCode < 200) return reject(new Error(response.statusMessage)); resolve(body); }); }); } fixRepo(result) { const repository = result.repository; if (!repository || (repository.type && repository.type !== 'git')) return; let { url } = repository; if (url.startsWith('git+')) url = url.slice('git+'.length); if (url.endsWith('.git')) url = url.slice(0, -'.git'.length); if (url.startsWith('git://')) url = url.slice('git://'.length); if (url.startsWith('ssh://')) url = url.slice('ssh://'.length); if (url.startsWith('git@github.com:')) url = `github.com/${url.slice('git@github.com:'.length)}`; if (url.startsWith('git@github.com/')) url = `github.com/${url.slice('git@github.com/'.length)}`; if (!url.startsWith('https://')) url = `https://${url}`; const exec = /http(s)?:\/\/([^\/]+)/.exec(url); result._repository = { url, type: 'gitlab' }; if (exec) { const host = exec[2].toLowerCase(); if (host.split('.').slice(-2)[0] === 'github') { result._repository.type = 'github'; } } } async fixUser(result) { if (result.author) { if (typeof result.author === 'string') { result.author = { name: result.author }; } if (!result.author.email && result.maintainers && result.maintainers.length) { for (let i = 0; i < result.maintainers.length; i++) { if (result.maintainers[i].name === result.author.name) { result.author.email = result.maintainers[i].email; break; } } } result.author = await this.formatUserAvatar(result.author); } if (result.maintainers && result.maintainers.length) { result.maintainers = await Promise.all(result.maintainers.map((maintainer) => this.formatUserAvatar(maintainer))); } } fixRemoteMaintainers(result) { if (result.maintainers && result.maintainers.length) { result.maintainers = result.maintainers.map((maintainer) => { return { name: maintainer.username, email: maintainer.email, avatar: gravatar_1.url(maintainer.email), nick: maintainer.username, }; }); } } async formatUserAvatar(user) { if (!user || !user.name) { return { name: 'unknow', email: 'unknow@blank.com', avatar: gravatar_1.url('unknow@blank.com'), nick: 'unknow', }; } const UserService = new this.service.UserService(this.ctx); const _user = await UserService.userCache(user.name).get({ account: user.name }); if (_user) { if (_user.email === user.email) return { name: _user.account, email: _user.email, avatar: _user.avatar, nick: _user.name, }; } return { name: user.name, email: user.email, avatar: gravatar_1.url(user.email), nick: user.name, }; } async fixReadme(pathname, version) { const key = `${pathname}:${version}`; const content = lru.get(key); if (content) return content; let url = `https://www.npmjs.com/package/${pathname}`; if (version) url += '/v/' + version; const html = await this.getNpmDownloadsApi(url); const readme = cheerio.load(html)('#readme').html(); lru.set(key, readme); return readme; } } exports.default = WebService;