UNPKG

cnpmcore

Version:
256 lines 21.9 kB
"use strict"; 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); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PackageSyncController = void 0; const tegg_1 = require("@eggjs/tegg"); const egg_errors_1 = require("egg-errors"); const AbstractController_1 = require("./AbstractController"); const PackageUtil_1 = require("../../common/PackageUtil"); const PackageSyncerService_1 = require("../../core/service/PackageSyncerService"); const RegistryManagerService_1 = require("../../core/service/RegistryManagerService"); const Task_1 = require("../../common/enum/Task"); const typebox_1 = require("../typebox"); const constants_1 = require("../../common/constants"); let PackageSyncController = class PackageSyncController extends AbstractController_1.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 egg_errors_1.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 === constants_1.SyncMode.admin && !isAdmin) { throw new egg_errors_1.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(typebox_1.SyncPackageTaskRule, params); const [scope, name] = (0, PackageUtil_1.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 egg_errors_1.ForbiddenError(`Can\'t find target registry "${data.registryName}"`); } if (packageEntity?.isPrivate && !registry) { throw new egg_errors_1.ForbiddenError(`Can\'t sync private package "${params.fullname}"`); } if (params.syncDownloadData && !this.packageSyncerService.allowSyncDownloadData) { throw new egg_errors_1.ForbiddenError('Not allow to sync package download data'); } if (registry && packageEntity?.registryId && packageEntity.registryId !== registry.registryId) { throw new egg_errors_1.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, 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) { if (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 egg_errors_1.NotFoundError(`Package "${fullname}" sync task "${taskId}" not found`); let logUrl; if (task.state !== Task_1.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 egg_errors_1.NotFoundError(`Package "${fullname}" sync task "${taskId}" not found`); if (task.state === Task_1.TaskState.Waiting) throw new egg_errors_1.NotFoundError(`Package "${fullname}" sync task "${taskId}" log not found`); const logUrlOrStream = await this.packageSyncerService.findTaskLog(task); if (!logUrlOrStream) throw new egg_errors_1.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 !== Task_1.TaskState.Waiting && task.state !== Task_1.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, }; } }; exports.PackageSyncController = PackageSyncController; __decorate([ (0, tegg_1.Inject)(), __metadata("design:type", PackageSyncerService_1.PackageSyncerService) ], PackageSyncController.prototype, "packageSyncerService", void 0); __decorate([ (0, tegg_1.Inject)(), __metadata("design:type", tegg_1.BackgroundTaskHelper) ], PackageSyncController.prototype, "backgroundTaskHelper", void 0); __decorate([ (0, tegg_1.Inject)(), __metadata("design:type", RegistryManagerService_1.RegistryManagerService) ], PackageSyncController.prototype, "registryManagerService", void 0); __decorate([ (0, tegg_1.HTTPMethod)({ // PUT /-/package/:fullname/syncs path: `/-/package/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})/syncs`, method: tegg_1.HTTPMethodEnum.PUT, }), __param(0, (0, tegg_1.Context)()), __param(1, (0, tegg_1.HTTPParam)()), __param(2, (0, tegg_1.HTTPBody)()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, Object]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "createSyncTask", null); __decorate([ (0, tegg_1.HTTPMethod)({ // GET /-/package/:fullname/syncs/:syncId path: `/-/package/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})/syncs/:taskId`, method: tegg_1.HTTPMethodEnum.GET, }), __param(0, (0, tegg_1.HTTPParam)()), __param(1, (0, tegg_1.HTTPParam)()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "showSyncTask", null); __decorate([ (0, tegg_1.HTTPMethod)({ // GET /-/package/:fullname/syncs/:syncId/log path: `/-/package/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})/syncs/:taskId/log`, method: tegg_1.HTTPMethodEnum.GET, }), __param(0, (0, tegg_1.Context)()), __param(1, (0, tegg_1.HTTPParam)()), __param(2, (0, tegg_1.HTTPParam)()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "showSyncTaskLog", null); __decorate([ (0, tegg_1.HTTPMethod)({ // PUT /:fullname/sync path: `/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})/sync`, method: tegg_1.HTTPMethodEnum.PUT, }), __param(0, (0, tegg_1.Context)()), __param(1, (0, tegg_1.HTTPParam)()), __param(2, (0, tegg_1.HTTPQuery)()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "deprecatedCreateSyncTask", null); __decorate([ (0, tegg_1.HTTPMethod)({ // GET /:fullname/sync/log/:taskId path: `/:fullname(${PackageUtil_1.FULLNAME_REG_STRING})/sync/log/:taskId`, method: tegg_1.HTTPMethodEnum.GET, }), __param(0, (0, tegg_1.HTTPParam)()), __param(1, (0, tegg_1.HTTPParam)()), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", Promise) ], PackageSyncController.prototype, "deprecatedShowSyncTask", null); exports.PackageSyncController = PackageSyncController = __decorate([ (0, tegg_1.HTTPController)() ], PackageSyncController); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFja2FnZVN5bmNDb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXBwL3BvcnQvY29udHJvbGxlci9QYWNrYWdlU3luY0NvbnRyb2xsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsc0NBV3FCO0FBQ3JCLDJDQUEyRDtBQUMzRCw2REFBMEQ7QUFDMUQsMERBQWdGO0FBRWhGLGtGQUErRTtBQUMvRSxzRkFBbUY7QUFDbkYsaURBQW1EO0FBQ25ELHdDQUFzRTtBQUN0RSxzREFBa0Q7QUFHM0MsSUFBTSxxQkFBcUIsR0FBM0IsTUFBTSxxQkFBc0IsU0FBUSx1Q0FBa0I7SUFVbkQsS0FBSyxDQUFDLGlCQUFpQixDQUFDLElBQVU7UUFDeEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDJIQUEySCxFQUMxSSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQ3RFLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDeEMsSUFBSSxNQUFNLEdBQUcsU0FBUyxDQUFDO1FBQ3ZCLElBQUk7WUFDRixNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDbkQ7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLE1BQU0sR0FBRyxPQUFPLENBQUM7WUFDakIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDeEI7Z0JBQVM7WUFDUixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDO1lBQ25DLElBQUksQ0FBQyxN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