UNPKG

cnpmcore

Version:

Private NPM Registry for Enterprise

322 lines 24.2 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { errors } from '@elastic/elasticsearch'; import dayjs from 'dayjs'; import { AccessLevel, Inject, SingletonProto } from 'egg'; import { AbstractService } from "../../common/AbstractService.js"; import { formatAuthor, getScopeAndName } from "../../common/PackageUtil.js"; let PackageSearchService = class PackageSearchService extends AbstractService { async syncPackage(fullname, isSync = true) { const [scope, name] = getScopeAndName(fullname); const { blockReason, manifest: latestManifest, pkg, } = await this.packageManagerService.showPackageVersionManifest(scope, name, 'latest', isSync, true); if (!pkg || !latestManifest) { this.logger.warn('[PackageSearchService.syncPackage] findPackage:%s not found', fullname); return; } if (blockReason) { this.logger.warn('[PackageSearchService.syncPackage] package:%s is blocked, try to remove es', fullname); await this.removePackage(fullname); return; } // get last year download data const startDate = dayjs().subtract(1, 'year'); const endDate = dayjs(); const entities = await this.packageVersionDownloadRepository.query(pkg.packageId, startDate.toDate(), endDate.toDate()); let downloadsAll = 0; for (const entity of entities) { for (let i = 1; i <= 31; i++) { const day = String(i).padStart(2, '0'); const field = `d${day}`; const counter = entity[field]; if (!counter) continue; downloadsAll += counter; } } let time = {}; let _rev = ''; let keywords; let description; const builder = await this.distRepository.readDistBytesToJSONBuilder(pkg.manifestsDist); if (builder) { time = builder.getIn(['time']); _rev = builder.getIn(['_rev']); keywords = builder.getIn(['keywords']); description = builder.getIn(['description']); } const versions = await this.packageVersionRepository.findAllVersions(scope, name); const distTags = await this.packageManagerService.distTags(pkg); const packageDoc = { name: latestManifest.name, version: latestManifest.version, _rev, scope: scope ? scope.replace('@', '') : 'unscoped', keywords: keywords || latestManifest.keywords || [], versions, description, license: typeof latestManifest.license === 'object' ? latestManifest.license?.type : latestManifest.license, maintainers: latestManifest.maintainers, author: formatAuthor(latestManifest.author), 'dist-tags': distTags, date: time[latestManifest.version], created: time.created, modified: time.modified, // 归属 registry,keywords 枚举值 _source_registry_name: latestManifest._source_registry_name, // 最新版本发布人 _npmUser: _npmUser: latestManifest?._npmUser, // 最新版本发布信息 publish_time: latestManifest?.publish_time, // deprecated message of the latest version deprecated: latestManifest?.deprecated, }; // http://npmmirror.com/package/npm/files/lib/utils/format-search-stream.js#L147-L148 // npm cli 使用 username 字段 if (packageDoc.maintainers) { packageDoc.maintainers = packageDoc.maintainers.map((maintainer) => { return { username: maintainer.name, ...maintainer, }; }); } const document = { package: packageDoc, downloads: { all: downloadsAll, }, }; return await this.searchRepository.upsertPackage(document); } async searchPackage(text, from, size) { const matchQueries = this._buildMatchQueries(text); const scriptScore = this._buildScriptScore({ text, scoreEffect: 0.25, }); const mustNotQueries = this._buildMustNotQueries(); const filterQueries = this._buildFilterQueries(); const res = await this.searchRepository.searchPackage({ body: { size, from, query: { function_score: { boost_mode: 'replace', query: { bool: { should: matchQueries, minimum_should_match: matchQueries.length > 0 ? 1 : 0, ...(mustNotQueries.length > 0 ? { must_not: mustNotQueries } : {}), ...(filterQueries.length > 0 ? { filter: filterQueries } : {}), }, }, script_score: scriptScore, }, }, }, }); const { hits, total } = res; return { objects: hits?.map((item) => { // 从 https://github.com/npm/cli/pull/7407 (npm cli v10.6.0) 开始,npm cli 使用 publisher 字段(以前使用 maintainers 字段) // 从现有数据来看,_npmUser 字段和 publisher 字段是等价的 // 为了兼容老版本,不删除 _npmUser 字段 if (!item._source?.package.publisher && item._source?.package._npmUser) { item._source.package.publisher = { username: item._source.package._npmUser.name, email: item._source.package._npmUser.email, }; } return item._source; }), total: total.value, }; } async removePackage(fullname) { try { return await this.searchRepository.removePackage(fullname); } catch (error) { // if the package does not exist, returns success if (error instanceof errors.ResponseError && error?.statusCode === 404) { this.logger.warn('[PackageSearchService.removePackage] remove package:%s not found', fullname); return fullname; } throw error; } } // Build must_not queries for filtering deprecated packages // https://github.com/cnpm/cnpmcore/issues/858 _buildMustNotQueries() { // oxlint-disable-next-line typescript-eslint/no-explicit-any const queries = []; if (this.config.cnpmcore.searchFilterDeprecated) { queries.push({ exists: { field: 'package.deprecated', }, }); } return queries; } // Build filter queries for minimum publish duration // https://github.com/cnpm/cnpmcore/issues/858 _buildFilterQueries() { // oxlint-disable-next-line typescript-eslint/no-explicit-any const queries = []; const minDuration = this.config.cnpmcore.searchPublishMinDuration; if (minDuration) { const ms = this._parseDuration(minDuration); if (ms > 0) { const cutoff = new Date(Date.now() - ms); queries.push({ range: { 'package.created': { lte: cutoff.toISOString(), }, }, }); } } return queries; } // Parse duration string like '1h', '1d', '1w', '2w' to milliseconds _parseDuration(duration) { const match = duration.match(/^(\d+)(h|d|w)$/); if (!match) { if (duration) { this.logger.warn('[PackageSearchService._parseDuration] invalid duration format: %s, expected format: 1h, 1d, 1w', duration); } return 0; } const value = parseInt(match[1], 10); const unit = match[2]; switch (unit) { case 'h': return value * 60 * 60 * 1000; case 'd': return value * 24 * 60 * 60 * 1000; case 'w': return value * 7 * 24 * 60 * 60 * 1000; default: return 0; } } // https://github.com/npms-io/queries/blob/master/lib/search.js#L8C1-L78C2 _buildMatchQueries(text) { if (!text) { return []; } return [ // Standard match using cross_fields { multi_match: { query: text, operator: 'and', fields: ['package.name.standard^4', 'package.description.standard', 'package.keywords.standard^2'], type: 'cross_fields', boost: 6, tie_breaker: 0.5, }, }, // Partial match using edge-ngram { multi_match: { query: text, operator: 'and', fields: ['package.name.edge_ngram^4', 'package.description.edge_ngram', 'package.keywords.edge_ngram^2'], type: 'phrase', slop: 3, boost: 3, tie_breaker: 0.5, }, }, // Normal term match with an english stemmer { multi_match: { query: text, operator: 'and', fields: [ 'package.name.english_docs^4', 'package.description.english_docs', 'package.keywords.english_docs^2', ], type: 'cross_fields', boost: 3, tie_breaker: 0.5, }, }, // Normal term match with a more aggressive english stemmer (not so important) { multi_match: { query: text, operator: 'and', fields: [ 'package.name.english_aggressive_docs^4', 'package.description.english_aggressive_docs', 'package.keywords.english_aggressive_docs^2', ], type: 'cross_fields', tie_breaker: 0.5, }, }, ]; } _buildScriptScore(params) { // keep search simple, only download(popularity) const downloads = 'doc["downloads.all"].value'; const source = `doc["package.name.raw"].value.equals(params.text) ? 100000 + ${downloads} : _score * Math.pow(${downloads}, params.scoreEffect)`; return { script: { source, params: { text: params.text || '', scoreEffect: params.scoreEffect, }, }, }; } }; __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "packageManagerService", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "searchRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "packageVersionDownloadRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "packageRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "packageVersionBlockRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "packageVersionRepository", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSearchService.prototype, "distRepository", void 0); PackageSearchService = __decorate([ SingletonProto({ accessLevel: AccessLevel.PUBLIC, }) ], PackageSearchService); export { PackageSearchService }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFja2FnZVNlYXJjaFNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hcHAvY29yZS9zZXJ2aWNlL1BhY2thZ2VTZWFyY2hTZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFDOUQsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUUxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFlBQVksRUFBRSxlQUFlLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQVlyRSxJQUFNLG9CQUFvQixHQUExQixNQUFNLG9CQUFxQixTQUFRLGVBQWU7SUFnQnZELEtBQUssQ0FBQyxXQUFXLENBQUMsUUFBZ0IsRUFBRSxNQUFNLEdBQUcsSUFBSTtRQUMvQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNoRCxNQUFNLEVBQ0osV0FBVyxFQUNYLFFBQVEsRUFBRSxjQUFjLEVBQ3hCLEdBQUcsR0FDSixHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLDBCQUEwQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyRyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsNkRBQTZELEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDMUYsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxD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