cnpmcore
Version:
Private NPM Registry for Enterprise
250 lines • 21.5 kB
JavaScript
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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