cnpmcore
Version:
Private NPM Registry for Enterprise
216 lines • 16.9 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 path from 'node:path';
import { HTTPContext, Context, HTTPController, HTTPMethod, HTTPMethodEnum, HTTPParam, HTTPQuery, Inject, Middleware, HTTPBody, } from 'egg';
import { NotFoundError } from 'egg/errors';
import binaries from "../../../config/binaries.js";
import { AdminAccess } from "../middleware/AdminAccess.js";
import { BinaryNameRule, BinarySubpathRule } from "../typebox.js";
import { AbstractController } from "./AbstractController.js";
let BinarySyncController = class BinarySyncController extends AbstractController {
async showBinaryHTML(ctx) {
ctx.type = 'html';
return ctx.app.binaryHTML;
}
async listBinaries() {
return Object.entries(binaries).map(([binaryName, binaryConfig]) => {
return {
name: `${binaryName}/`,
category: `${binaryConfig.category}/`,
description: binaryConfig.description,
distUrl: binaryConfig.distUrl,
repoUrl: /^https?:\/\//.test(binaryConfig.repo) ? binaryConfig.repo : `https://github.com/${binaryConfig.repo}`,
type: 'dir',
url: `${this.config.cnpmcore.registry}/-/binary/${binaryConfig.category}/`,
};
});
}
async showBinary(ctx, binaryName, subpath, since, limit) {
// check binaryName valid
try {
ctx.tValidate(BinaryNameRule, binaryName);
}
catch {
throw new NotFoundError(`Binary "${binaryName}" not found`);
}
let limitCount;
if (limit) {
limitCount = Number(limit);
if (Number.isNaN(limitCount)) {
throw new NotFoundError(`invalidate limit "${limit}"`);
}
if (limitCount > 1000) {
throw new NotFoundError(`limit should less than 1000, query is "${limit}"`);
}
}
subpath = subpath || '/';
if (subpath === '/') {
const items = await this.binarySyncerService.listRootBinaries(binaryName);
return this.formatItems(items);
}
try {
ctx.tValidate(BinarySubpathRule, subpath);
}
catch {
throw new NotFoundError(`Binary "${binaryName}/${subpath}" not found`);
}
subpath = `/${subpath}`;
const parsed = path.parse(subpath);
const parent = parsed.dir === '/' ? '/' : `${parsed.dir}/`;
const name = subpath.endsWith('/') ? `${parsed.base}/` : parsed.base;
// 首先查询 binary === category 的情况
let binary = await this.binarySyncerService.findBinary(binaryName, parent, name);
if (!binary) {
// 查询不到再去查询 mergeCategory 的情况
const category = binaries?.[binaryName]?.category;
if (category) {
// canvas/v2.6.1/canvas-v2.6.1-node-v57-linux-glibc-x64.tar.gz
// -> node-canvas-prebuilt/v2.6.1/node-canvas-prebuilt-v2.6.1-node-v57-linux-glibc-x64.tar.gz
binary = await this.binarySyncerService.findBinary(category, parent, name.replace(new RegExp(`^${binaryName}-`), `${category}-`));
}
}
if (!binary) {
throw new NotFoundError(`Binary "${binaryName}${subpath}" not found`);
}
if (binary.isDir) {
let options;
if (limitCount && since) {
options = {
limit: limitCount,
since,
};
}
const items = await this.binarySyncerService.listDirBinaries(binary, options);
return this.formatItems(items);
}
// download file
const urlOrStream = await this.binarySyncerService.downloadBinary(binary);
if (!urlOrStream) {
throw new NotFoundError(`Binary "${binaryName}${subpath}" not found`);
}
if (typeof urlOrStream === 'string') {
ctx.redirect(urlOrStream);
return;
}
ctx.attachment(name);
return urlOrStream;
}
async syncBinary(ctx, binaryName, lastData) {
// check binaryName valid
try {
ctx.tValidate(BinaryNameRule, binaryName);
}
catch {
throw new NotFoundError(`Binary "${binaryName}" not found`);
}
this.logger.info('SyncBinary: %s, lastData: %j', binaryName, lastData);
const task = await this.binarySyncerService.createTask(binaryName, lastData);
return {
ok: true,
taskId: task?.taskId,
logPath: task?.logPath,
};
}
async showBinaryIndex(ctx, binaryName, since, limit) {
// check binaryName valid
try {
ctx.tValidate(BinaryNameRule, binaryName);
}
catch {
throw new NotFoundError(`Binary "${binaryName}" not found`);
}
return await this.showBinary(ctx, binaryName, '/', since, limit);
}
formatItems(items) {
return items.map((item) => {
return {
id: item.binaryId,
category: item.category,
name: item.name,
date: item.date,
type: item.isDir ? 'dir' : 'file',
size: item.isDir ? undefined : item.size,
url: `${this.config.cnpmcore.registry}/-/binary/${item.category}${item.parent}${item.name}`,
modified: item.updatedAt,
};
});
}
};
__decorate([
Inject(),
__metadata("design:type", Function)
], BinarySyncController.prototype, "binarySyncerService", void 0);
__decorate([
HTTPMethod({
path: '/binary.html',
method: HTTPMethodEnum.GET,
}),
__param(0, HTTPContext()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Context]),
__metadata("design:returntype", Promise)
], BinarySyncController.prototype, "showBinaryHTML", null);
__decorate([
HTTPMethod({
path: '/-/binary/',
method: HTTPMethodEnum.GET,
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], BinarySyncController.prototype, "listBinaries", null);
__decorate([
HTTPMethod({
path: '/-/binary/:binaryName(@[^/]{1,220}/[^/]{1,220}|[^@/]{1,220})/:subpath(.*)',
method: HTTPMethodEnum.GET,
}),
__param(0, HTTPContext()),
__param(1, HTTPParam()),
__param(2, HTTPParam()),
__param(3, HTTPQuery()),
__param(4, HTTPQuery()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Context, String, String, String, String]),
__metadata("design:returntype", Promise)
], BinarySyncController.prototype, "showBinary", null);
__decorate([
HTTPMethod({
path: '/-/binary/:binaryName/sync',
method: HTTPMethodEnum.POST,
}),
Middleware(AdminAccess),
__param(0, HTTPContext()),
__param(1, HTTPParam()),
__param(2, HTTPBody()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Context, String, Object]),
__metadata("design:returntype", Promise)
], BinarySyncController.prototype, "syncBinary", null);
__decorate([
HTTPMethod({
path: '/-/binary/:binaryName(@[^/]{1,220}/[^/]{1,220}|[^@/]{1,220})',
method: HTTPMethodEnum.GET,
}),
__param(0, HTTPContext()),
__param(1, HTTPParam()),
__param(2, HTTPQuery()),
__param(3, HTTPQuery()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Context, String, String, String]),
__metadata("design:returntype", Promise)
], BinarySyncController.prototype, "showBinaryIndex", null);
BinarySyncController = __decorate([
HTTPController()
], BinarySyncController);
export { BinarySyncController };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmluYXJ5U3luY0NvbnRyb2xsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hcHAvcG9ydC9jb250cm9sbGVyL0JpbmFyeVN5bmNDb250cm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUU3QixPQUFPLEVBQ0wsV0FBVyxFQUNYLE9BQU8sRUFDUCxjQUFjLEVBQ2QsVUFBVSxFQUNWLGNBQWMsRUFDZCxTQUFTLEVBQ1QsU0FBUyxFQUNULE1BQU0sRUFDTixVQUFVLEVBQ1YsUUFBUSxHQUNULE1BQU0sS0FBSyxDQUFDO0FBQ2IsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUUzQyxPQUFPLFFBQTZCLE1BQU0sNkJBQTZCLENBQUM7QUFHeEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxjQUFjLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHdEQsSUFBTSxvQkFBb0IsR0FBMUIsTUFBTSxvQkFBcUIsU0FBUSxrQkFBa0I7SUFRcEQsQUFBTixLQUFLLENBQUMsY0FBYyxDQUFnQixHQUFZO1FBQzlDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDO1FBQ2xCLE9BQU8sR0FBRyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQU1LLEFBQU4sS0FBSyxDQUFDLFlBQVk7UUFDaEIsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxFQUFFLEVBQUU7WUFDakUsT0FBTztnQkFDTCxJQUFJLEVBQUUsR0FBRyxVQUFVLEdBQUc7Z0JBQ3RCLFFBQVEsRUFBRSxHQUFH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