UNPKG

zan-proxy

Version:
213 lines 8.74 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 __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