zan-proxy
Version:
213 lines • 8.74 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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const koa_1 = __importDefault(require("koa"));
const koa_bodyparser_1 = __importDefault(require("koa-bodyparser"));
const koa_mount_1 = __importDefault(require("koa-mount"));
const koa_router_1 = __importDefault(require("koa-router"));
const lodash_1 = require("lodash");
const npm_1 = __importDefault(require("npm"));
const path_1 = __importDefault(require("path"));
const typedi_1 = require("typedi");
const services_1 = require("../services");
const storage_1 = __importDefault(require("./storage"));
let PluginManager = class PluginManager {
constructor(appInfoService) {
this.dir = path_1.default.join(appInfoService.getProxyDataDir(), 'plugins');
this.storage = new storage_1.default(this.getDir());
this.plugins = this.storage
.get()
.filter(p => !p.disabled)
.reduce((prev, curr) => {
try {
const pluginPath = this.getPluginDir(curr.name);
if (!fs_1.default.existsSync(pluginPath)) {
throw Error(`plugin ${curr.name} not found`);
}
const pluginClass = require(pluginPath);
prev[curr.name] = new pluginClass();
}
catch (error) {
console.error(`plugin "${curr.name}" has a runtime error. please check it.\n${error.stack}`);
process.exit(-1);
}
return prev;
}, {});
}
add(pluginName, npmConfig = {}) {
return new Promise((resolve, reject) => {
const install = () => {
npm_1.default.install(pluginName, this.getDir(), err => {
if (err) {
if (err.code === 'E404') {
return reject(Error(`插件不存在 ${err.uri}`));
}
return reject(err);
}
const plugins = lodash_1.uniqWith(this.storage.get().concat([
{
name: pluginName,
},
]), (p1, p2) => {
return p1.name === p2.name;
});
this.storage.set(plugins);
return resolve(plugins);
});
};
npmConfig = Object.assign({}, npmConfig, {
loglevel: 'silent',
prefix: this.getDir(),
});
if (npm_1.default.config.loaded) {
Object.keys(npmConfig).forEach(k => {
npm_1.default.config.set(k, npmConfig[k]);
});
install();
}
else {
npm_1.default.load(npmConfig, () => install());
}
});
}
remove(pluginName) {
return new Promise((resolve, reject) => {
const uninstall = () => {
npm_1.default.uninstall(pluginName, this.getDir(), err => {
if (err) {
return reject(err);
}
const plugins = this.storage.get();
lodash_1.remove(plugins, p => p.name === pluginName);
this.storage.set(plugins);
return resolve(plugins);
});
};
const npmConfig = { loglevel: 'silent', prefix: this.getDir() };
if (npm_1.default.config.loaded) {
Object.keys(npmConfig).forEach(k => {
npm_1.default.config.set(k, npmConfig[k]);
});
uninstall();
}
else {
npm_1.default.load(npmConfig, () => uninstall());
}
});
}
setAttrs(pluginName, attrs) {
let plugins = this.storage.get();
plugins = plugins.map(p => {
if (p.name === pluginName) {
p = Object.assign(p, attrs);
}
return p;
});
this.storage.set(plugins);
}
has(name) {
return !!this.plugins[name];
}
getUIApp() {
const app = new koa_1.default();
app.use(koa_bodyparser_1.default());
Object.keys(this.plugins).forEach(name => {
const plugin = this.plugins[name];
if (plugin.manage) {
const pluginApp = plugin.manage();
if (Object.prototype.toString.call(pluginApp) === '[object Object]' &&
pluginApp.__proto__.constructor.name === 'Application') {
app.use(koa_mount_1.default(`/${name}`, pluginApp));
}
else {
console.error(`"${name}" 插件的 manage() 方法需要返回 koa 实例`);
process.exit(-1);
}
}
});
const router = new koa_router_1.default();
router.post('/remove', (ctx) => __awaiter(this, void 0, void 0, function* () {
const { name } = ctx.request.body;
yield this.remove(name);
ctx.body = {
message: 'ok',
status: 200,
};
}));
router.get('/list', (ctx) => __awaiter(this, void 0, void 0, function* () {
ctx.body = {
data: this.storage.get().map(plugin => {
return Object.assign({}, plugin, require(path_1.default.join(this.getPluginDir(plugin.name), './package.json')));
}),
status: 200,
};
}));
router.post('/add', (ctx) => __awaiter(this, void 0, void 0, function* () {
const { name, registry } = ctx.request.body;
const npmConfig = {};
if (registry) {
npmConfig.registry = registry;
}
try {
yield this.add(name, npmConfig);
}
catch (err) {
ctx.status = 400;
ctx.body = err.message;
return;
}
ctx.body = {
message: 'ok',
status: 200,
};
}));
router.post('/disabled', (ctx) => __awaiter(this, void 0, void 0, function* () {
const { name, disabled } = ctx.request.body;
this.setAttrs(name, { disabled });
ctx.body = {
message: 'ok',
status: 200,
};
}));
app.use(router.routes()).use(router.allowedMethods());
return app;
}
loadProxyMiddleware(server) {
Object.keys(this.plugins).forEach(name => {
const plugin = this.plugins[name];
server.use(plugin.proxy(server));
});
}
getDir() {
return this.dir;
}
getPluginDir(pluginName) {
return path_1.default.resolve(this.getDir(), 'node_modules', pluginName);
}
};
PluginManager = __decorate([
typedi_1.Service(),
__metadata("design:paramtypes", [services_1.AppInfoService])
], PluginManager);
exports.default = PluginManager;
//# sourceMappingURL=index.js.map
;