UNPKG

cnpmcore

Version:

Private NPM Registry for Enterprise

250 lines 21.5 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); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; import { HTTPContext, BackgroundTaskHelper, Context, HTTPBody, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPParam, HTTPQuery, Inject, } from 'egg'; import { ForbiddenError, NotFoundError } from 'egg/errors'; import { SyncMode } from "../../common/constants.js"; import { TaskState } from "../../common/enum/Task.js"; import { FULLNAME_REG_STRING, getScopeAndName } from "../../common/PackageUtil.js"; import { SyncPackageTaskRule } from "../typebox.js"; import { AbstractController } from "./AbstractController.js"; let PackageSyncController = class PackageSyncController extends AbstractController { async _executeTaskAsync(task) { const startTime = Date.now(); this.logger.info('[PackageSyncController:executeTask:start] taskId: %s, targetName: %s, attempts: %s, params: %j, updatedAt: %s, delay %sms', task.taskId, task.targetName, task.attempts, task.data, task.updatedAt, startTime - task.updatedAt.getTime()); let result = 'success'; try { await this.packageSyncerService.executeTask(task); } catch (err) { result = 'error'; this.logger.error(err); } finally { const use = Date.now() - startTime; this.logger.info('[PackageSyncController:executeTask:%s] taskId: %s, targetName: %s, use %sms', result, task.taskId, task.targetName, use); } } async createSyncTask(ctx, fullname, data) { if (!this.enableSync) { throw new ForbiddenError('Not allow to sync package'); } const tips = data.tips || `Sync cause by "${ctx.href}", parent traceId: ${ctx.tracer.traceId}`; const isAdmin = await this.userRoleManager.isAdmin(ctx); if (this.config.cnpmcore.syncMode === SyncMode.admin && !isAdmin) { throw new ForbiddenError('Only admin allow to sync package'); } const params = { fullname, tips, skipDependencies: !!data.skipDependencies, syncDownloadData: !!data.syncDownloadData, force: !!data.force, // only admin allow to sync history version forceSyncHistory: !!data.forceSyncHistory && isAdmin, specificVersions: data.specificVersions, }; ctx.tValidate(SyncPackageTaskRule, params); const [scope, name] = getScopeAndName(params.fullname); const packageEntity = await this.packageRepository.findPackage(scope, name); const registry = await this.registryManagerService.findByRegistryName(data?.registryName); if (!registry && data.registryName) { throw new ForbiddenError(`Can't find target registry "${data.registryName}"`); } if (packageEntity?.isPrivate && !registry) { throw new ForbiddenError(`Can't sync private package "${params.fullname}"`); } if (params.syncDownloadData && !this.packageSyncerService.allowSyncDownloadData) { throw new ForbiddenError('Not allow to sync package download data'); } if (registry && packageEntity?.registryId && packageEntity.registryId !== registry.registryId) { throw new ForbiddenError(`The package is synced from ${packageEntity.registryId}`); } const authorized = await this.userRoleManager.getAuthorizedUserAndToken(ctx); const task = await this.packageSyncerService.createTask(params.fullname, { authorIp: ctx.ip, authorId: authorized?.user.userId, tips: params.tips, skipDependencies: params.skipDependencies, syncDownloadData: params.syncDownloadData, forceSyncHistory: params.forceSyncHistory, force: isAdmin ? params.force : undefined, registryId: registry?.registryId, specificVersions: params.specificVersions && JSON.parse(params.specificVersions), }); ctx.logger.info('[PackageSyncController.createSyncTask:success] taskId: %s, fullname: %s', task.taskId, fullname); if (data.force && isAdmin) { // set background task timeout to 5min this.backgroundTaskHelper.timeout = 1000 * 60 * 5; this.backgroundTaskHelper.run(async () => { ctx.logger.info('[PackageSyncController.createSyncTask:execute-immediately] taskId: %s', task.taskId); // execute task in background await this._executeTaskAsync(task); }); } ctx.status = 201; return { ok: true, id: task.taskId, type: task.type, state: task.state, }; } // TODO: no-cache for CDN if task state is processing or timeout async showSyncTask(fullname, taskId) { const task = await this.packageSyncerService.findTask(taskId); if (!task) throw new NotFoundError(`Package "${fullname}" sync task "${taskId}" not found`); let logUrl; if (task.state !== TaskState.Waiting) { logUrl = `${this.config.cnpmcore.registry}/-/package/${fullname}/syncs/${taskId}/log`; } const error = task.error || undefined; return { ok: true, id: task.taskId, type: task.type, state: task.state, logUrl, error, }; } // TODO: no-cache for CDN if task state is processing or timeout async showSyncTaskLog(ctx, fullname, taskId) { const task = await this.packageSyncerService.findTask(taskId); if (!task) throw new NotFoundError(`Package "${fullname}" sync task "${taskId}" not found`); if (task.state === TaskState.Waiting) throw new NotFoundError(`Package "${fullname}" sync task "${taskId}" log not found`); const logUrlOrStream = await this.packageSyncerService.findTaskLog(task); if (!logUrlOrStream) throw new NotFoundError(`Package "${fullname}" sync task "${taskId}" log not found`); if (typeof logUrlOrStream === 'string') { ctx.redirect(logUrlOrStream); return; } ctx.type = 'log'; return logUrlOrStream; } // deprecate create sync task api for cnpmjs.org // https://github.com/cnpm/cnpmjs.org/blob/master/controllers/sync.js async deprecatedCreateSyncTask(ctx, fullname, nodeps) { const options = { fullname, tips: `Sync cause by "${ctx.href}", parent traceId: ${ctx.tracer.traceId}`, skipDependencies: nodeps === 'true', syncDownloadData: false, force: false, forceSyncHistory: false, }; const task = await this.createSyncTask(ctx, fullname, options); return { ok: true, logId: task.id, }; } // https://github.com/cnpm/cnpmjs.org/blob/master/controllers/sync.js#L55 async deprecatedShowSyncTask(fullname, taskId) { const task = await this.showSyncTask(fullname, taskId); const syncDone = task.state !== TaskState.Waiting && task.state !== TaskState.Processing; const stateMessage = syncDone ? '[done]' : '[processing]'; // https://github.com/cnpm/cnpm/blob/cadd3cd54c22b1a157810a43ab10febdb2410ca6/bin/cnpm-sync#L82 const log = `[${new Date().toISOString()}] ${stateMessage} Sync ${fullname} data: ${JSON.stringify(task)}`; return { ok: true, syncDone, log, logUrl: task.logUrl, error: task.error, }; } }; __decorate([ Inject(), __metadata("design:type", Function) ], PackageSyncController.prototype, "packageSyncerService", void 0); __decorate([ Inject(), __metadata("design:type", BackgroundTaskHelper) ], PackageSyncController.prototype, "backgroundTaskHelper", void 0); __decorate([ Inject(), __metadata("design:type", Function) ], PackageSyncController.prototype, "registryManagerService", void 0); __decorate([ HTTPMethod({ // PUT /-/package/:fullname/syncs path: `/-/package/:fullname(${FULLNAME_REG_STRING})/syncs`, method: HTTPMethodEnum.PUT, }), __param(0, HTTPContext()), __param(1, HTTPParam()), __param(2, HTTPBody()), __metadata("design:type", Function), __metadata("design:paramtypes", [Context, String, Object]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "createSyncTask", null); __decorate([ HTTPMethod({ // GET /-/package/:fullname/syncs/:syncId path: `/-/package/:fullname(${FULLNAME_REG_STRING})/syncs/:taskId`, method: HTTPMethodEnum.GET, }), __param(0, HTTPParam()), __param(1, HTTPParam()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "showSyncTask", null); __decorate([ HTTPMethod({ // GET /-/package/:fullname/syncs/:syncId/log path: `/-/package/:fullname(${FULLNAME_REG_STRING})/syncs/:taskId/log`, method: HTTPMethodEnum.GET, }), __param(0, HTTPContext()), __param(1, HTTPParam()), __param(2, HTTPParam()), __metadata("design:type", Function), __metadata("design:paramtypes", [Context, String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "showSyncTaskLog", null); __decorate([ HTTPMethod({ // PUT /:fullname/sync path: `/:fullname(${FULLNAME_REG_STRING})/sync`, method: HTTPMethodEnum.PUT, }), __param(0, HTTPContext()), __param(1, HTTPParam()), __param(2, HTTPQuery()), __metadata("design:type", Function), __metadata("design:paramtypes", [Context, String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "deprecatedCreateSyncTask", null); __decorate([ HTTPMethod({ // GET /:fullname/sync/log/:taskId path: `/:fullname(${FULLNAME_REG_STRING})/sync/log/:taskId`, method: HTTPMethodEnum.GET, }), __param(0, HTTPParam()), __param(1, HTTPParam()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "deprecatedShowSyncTask", null); PackageSyncController = __decorate([ HTTPController() ], PackageSyncController); export { PackageSyncController }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFja2FnZVN5bmNDb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXBwL3BvcnQvY29udHJvbGxlci9QYWNrYWdlU3luY0NvbnRyb2xsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUNMLFdBQVcsRUFDWCxvQkFBb0IsRUFDcEIsT0FBTyxFQUNQLFFBQVEsRUFDUixjQUFjLEVBQ2QsVUFBVSxFQUNWLGNBQWMsRUFDZCxTQUFTLEVBQ1QsU0FBUyxFQUNULE1BQU0sR0FDUCxNQUFNLEtBQUssQ0FBQztBQUNiLE9BQU8sRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTNELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGVBQWUsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBSW5GLE9BQU8sRUFBRSxtQkFBbUIsRUFBNEIsTUFBTSxlQUFlLENBQUM7QUFDOUUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHdEQsSUFBTSxxQkFBcUIsR0FBM0IsTUFBTSxxQkFBc0IsU0FBUSxrQkFBa0I7SUFVbkQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQVU7UUFDeEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUNkLDJIQUEySCxFQUMzSCxJQUFJLENBQUMsTUFBTSxFQUNYLElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLFFBQVEsRUFDYixJQUFJLENBQUMsSUFBSSxFQUNULElBQUksQ0FBQyxTQUFTLEVBQ2QsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENB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