This commit is contained in:
buqiyuan 2022-07-19 18:05:45 +08:00
commit b679a5834f
14 changed files with 75 additions and 13869 deletions

1
.gitignore vendored
View File

@ -52,4 +52,5 @@ testem.log
.DS_Store
Thumbs.db
# *-lock.json
-error.log
.vercel

View File

@ -33,6 +33,7 @@
"dependencies": {
"@bqy/node-module-alias": "^1.0.1",
"@electron/remote": "2.0.8",
"axios": "0.27.2",
"content-disposition": "^0.5.4",
"copyfiles": "2.4.1",
"crypto-js": "^4.1.1",

View File

@ -206,7 +206,7 @@ try {
} else if (arg.action === 'getAppModuleList') {
returnValue = moduleManager.getAppModuleList();
} else if (arg.action === 'installModule') {
const data = await moduleManager.install(arg.data);
const data = await moduleManager.installExt(arg.data);
if (data.code === 0) {
//subView.mainView.view.webContents.send('moduleUpdate');
}

View File

@ -59,15 +59,15 @@ export class ModuleHandler extends CoreHandler {
* @param modules
* @param isLocal link
*/
async install(modules: string[], isLocal: boolean): Promise<ModuleHandlerResult> {
async install(modules: any[], isLocal: boolean): Promise<ModuleHandlerResult> {
return await this.execCommand(isLocal ? 'link' : 'install', modules);
}
/**
*
* @param {...string[]} modules
* @param [{ name:string, version:string }]
*/
async update(...modules: string[]): Promise<ModuleHandlerResult> {
return await this.execCommand('update', modules);
async update(modules: any[]): Promise<ModuleHandlerResult> {
return await this.execCommand('install', modules);
}
/**
@ -75,7 +75,7 @@ export class ModuleHandler extends CoreHandler {
* @param {string[]} modules
* @param isLocal unlink
*/
async uninstall(modules: string[], isLocal: boolean): Promise<ModuleHandlerResult> {
async uninstall(modules: any[], isLocal: boolean): Promise<ModuleHandlerResult> {
return await this.execCommand(isLocal ? 'unlink' : 'uninstall', modules);
}
@ -106,14 +106,16 @@ export class ModuleHandler extends CoreHandler {
});
}
}
private executeByAppNpm(command: string, modules: string[], resolve, reject) {
private executeByAppNpm(command: string, modules: any[], resolve, reject) {
// https://www.npmjs.com/package/bin-links
npmCli.load({ 'bin-links': false, verbose: true, prefix: this.baseDir }, (loaderr) => {
const moduleList = modules.map((it) => it + '@latest');
console.log('moduleList', command, moduleList);
const moduleList = modules.map(({ name, version }) => (version ? `${name}@${version}` : name));
let executeCommand = ['update', 'install', 'uninstall'];
if (!executeCommand.includes(command)) return;
if (!executeCommand.includes(command)) {
return;
}
npmCli.commands[command](moduleList, (err, data) => {
console.log('command', command);
process.chdir(this.baseDir);
if (err) {
return reject(err);
@ -160,7 +162,7 @@ export class ModuleHandler extends CoreHandler {
* @param command
* @param modules
*/
private async execCommand(command: string, modules: string[]): Promise<ModuleHandlerResult> {
private async execCommand(command: string, modules: any[]): Promise<ModuleHandlerResult> {
return await new Promise((resolve: any, reject: any): void => {
// this.executeBySystemNpm(command, modules, resolve)
this.executeByAppNpm(command, modules, resolve, reject);

View File

@ -3,9 +3,17 @@ import { ModuleHandler } from './handler';
import { ModuleHandlerResult, ModuleInfo, ModuleManagerInfo, ModuleManagerInterface, ModuleType } from '../types';
import { isNotEmpty } from 'eo/shared/common/common';
import { processEnv } from '../../constant';
import http from 'axios';
import { DATA_DIR } from '../../../../shared/electron-main/constant';
import { promises, readFileSync } from 'fs';
// * npm pkg name
const installExtension = [{ name: 'eoapi-export-openapi' }, { name: 'eoapi-import-openapi' }];
const defaultExtension = [{ name: 'eoapi-export-openapi' }, { name: 'eoapi-import-openapi' }];
const isExists = async (filePath) =>
await promises
.access(filePath)
.then(() => true)
.catch((_) => false);
export class ModuleManager implements ModuleManagerInterface {
/**
*
@ -15,7 +23,7 @@ export class ModuleManager implements ModuleManagerInterface {
/**
* extension list
*/
private readonly installExtension = installExtension;
private installExtension = [];
/**
*
@ -35,12 +43,22 @@ export class ModuleManager implements ModuleManagerInterface {
this.updateAll();
}
async getRemoteExtension() {
const { data } = await http.get(process.env.EXTENSION_URL + '/list');
return data.data.map(({ name, version }) => ({ name, version }));
}
async installExt({ name }) {
const remoteExtension = await this.getRemoteExtension();
return await this.install(remoteExtension.find((it) => it.name === name));
}
/**
* npm install | link
* @param module
*/
async install(module: ModuleManagerInfo): Promise<ModuleHandlerResult> {
const result = await this.moduleHandler.install([module.name], module.isLocal || false);
const result = await this.moduleHandler.install([{ name: module.name }], module.isLocal || false);
if (result.code === 0) {
const moduleInfo: ModuleInfo = this.moduleHandler.info(module.name);
this.set(moduleInfo);
@ -48,46 +66,42 @@ export class ModuleManager implements ModuleManagerInterface {
return result;
}
/**
* npm update
* @param module
*/
async update(module: ModuleManagerInfo): Promise<ModuleHandlerResult> {
const result = await this.moduleHandler.update(module.name);
if (result.code === 0) {
this.refresh(module);
}
return result;
}
updateAll() {
// * ModuleManager will be new only one while app run start, so it should be here upgrade & install extension
// * Upgrade
const list = Array.from(this.getModules().values()).map((val) => val.name);
list.forEach((item) => {
//!Warn this is bug,it did't work @kungfuboy
this.update({ name: item });
});
// * Install default extension
this.installExtension.forEach((item) => {
// * If the extension already in local extension list, then do not repeat installation
if (list.includes(item.name)) return;
//!TODO this will reinstall all package, npm link(debug) package will be remove after npm install command,
this.install(item);
});
}
/**
* npm uninstall | unlink
* @param module
*/
async uninstall(module: ModuleManagerInfo): Promise<ModuleHandlerResult> {
const moduleInfo: ModuleInfo = this.moduleHandler.info(module.name);
const result = await this.moduleHandler.uninstall([module.name], module.isLocal || false);
const result = await this.moduleHandler.uninstall([{ name: module.name }], module.isLocal || false);
if (result.code === 0) {
this.delete(moduleInfo);
}
return result;
}
async updateAll() {
// * ModuleManager will be new only one while app run start, so it should be here upgrade & install extension
// * Upgrade
const list = Array.from(this.getModules().values()).map((val) => ({ name: val.name, version: val.version }));
// * get version in remote
const remoteExtension = await this.getRemoteExtension();
const isOK = await isExists(`${DATA_DIR}/debugger.json`);
let debugExtension = [];
if (isOK) {
const debuggerExtension = readFileSync(`${DATA_DIR}/debugger.json`, 'utf-8');
const { extensions } = JSON.parse(debuggerExtension);
debugExtension = extensions;
}
const localExtensionName = [...new Set(list.map((it) => it.name).concat(defaultExtension.map((it) => it.name)))];
this.installExtension = remoteExtension
.filter((it) => localExtensionName.includes(it.name))
.filter((it) => !debugExtension.includes(it.name));
this.moduleHandler.update(this.installExtension);
this.installExtension.forEach((it) => {
this.install(it);
});
}
/**
* package.json更新模块信息
* @param module

View File

@ -13,8 +13,9 @@ export enum ModuleType {
app = 'app',
feature = 'feature',
}
export interface I18nLocale{
locale: string; package: any
export interface I18nLocale {
locale: string;
package: any;
}
/**
*
@ -68,7 +69,7 @@ export interface ModuleInfo {
features?: {
[index: string]: any;
};
i18n?:I18nLocale[]
i18n?: I18nLocale[];
}
/**
*
@ -117,11 +118,11 @@ export interface ModuleManagerInfo {
* getModules
*/
export interface ModuleManagerInterface {
installExt: any;
install: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
update: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
uninstall: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
refresh: (module: ModuleManagerInfo) => void;
refreshAll:()=>void;
refreshAll: () => void;
getModule: (moduleID: string, belongs?: boolean) => ModuleInfo;
getModules: (belongs?: boolean) => Map<string, ModuleInfo>;
getAppModuleList: () => Array<ModuleInfo>;

View File

@ -1,22 +0,0 @@
{
"private": true,
"name": "Eoapi-about",
"version": "0.0.1",
"moduleName": "关于",
"moduleID": "eoapi-about",
"author": "eoapi",
"publisher": "eoapi",
"contributes": {
"configuration": {
"type": "object",
"order": 1,
"properties": {
"app.about": {
"type": "component",
"label": "",
"default": "eo-about"
}
}
}
}
}

View File

@ -1,47 +0,0 @@
{
"private": true,
"name": "eoapi-common",
"version": "0.0.1",
"moduleName": "通用",
"moduleID": "eoapi-common",
"author": "eoapi",
"publisher": "eoapi",
"features": {
"configuration": {
"type": "object",
"title": "通用",
"order": 1,
"properties": {
"common.app.autoUpdate": {
"type": "boolean",
"default": true,
"label": "自动升级",
"disabled": true,
"description": "检测到应用升级后,后台将下载最新的安装包在下次启动时更新"
},
"common.dataSource": {
"type": "component",
"default": "swtich-dataSource-btn",
"label": "数据源切换",
"description": ""
},
"remoteServer.url": {
"type": "string",
"label": "远程服务器地址",
"required": true,
"default": "http://localhost:3000",
"placeholder": "数据源地址",
"description": "从远程服务器存取数据,配置后支持多人合作,配置文档请见:[远程数据源](https://eoapi.io/docs/storage.html)"
},
"remoteServer.token": {
"type": "string",
"label": "Token",
"required": true,
"default": "1ab2c3d4e5f61ab2c3d4e5f6",
"placeholder": "Token 凭证",
"description": "远程服务器 Token配置后才可访问"
}
}
}
}
}

View File

@ -1,52 +0,0 @@
{
"private": true,
"name": "eoapi-features",
"version": "0.0.1",
"moduleName": "功能",
"moduleID": "eoapi-features",
"author": "eoapi",
"publisher": "eoapi",
"features": {
"configuration": [
{
"type": "object",
"title": "API 测试",
"order": 1,
"properties": {
"api.test": {
"type": "boolean",
"default": true,
"label": "自动重定向",
"description": "勾选后自动跟随请求重定向"
}
}
},
{
"type": "object",
"title": "Mock",
"order": 2,
"properties": {
"mock.matchType": {
"type": "boolean",
"default": true,
"label": "匹配请求方式",
"description": "开启后系统会匹配和API文档请求方式GET、POST...)一致的 Mock"
}
}
},
{
"type": "object",
"title": "插件",
"order": 2,
"properties": {
"extension.autoupdate": {
"type": "boolean",
"default": true,
"label": "自动更新",
"description": "检测到最新的安装包后自动更新"
}
}
}
]
}
}

View File

@ -1,22 +1,10 @@
import commonSettings from './common-settings.json';
import extenstionSettings from './extenstion-settings.json';
import featureSettings from './feature-settings.json';
import themeSettings from './theme-settings.json';
import about from './about.json';
export type eoapiSettingsKey = keyof typeof eoapiSettings;
export const eoapiSettings = {
/** 通用设置 */
'eoapi-common': commonSettings,
/** 功能设置 */
'eoapi-extensions': extenstionSettings,
/** 插件配置 */
'eoapi-features': featureSettings,
/** 主题配置 */
'eoapi-theme': themeSettings,
/** 关于 */
'eoapi-about': about,
} as const;
export default eoapiSettings;

View File

@ -1,22 +0,0 @@
{
"private": true,
"name": "eoapi-theme",
"version": "0.0.1",
"moduleName": "主题",
"moduleID": "eoapi-theme",
"author": "eoapi",
"publisher": "eoapi",
"features": {
"configuration": {
"type": "object",
"order": 1,
"properties": {
"select.theme": {
"type": "component",
"label": "主题列表",
"default": "eo-select-theme"
}
}
}
}
}

View File

@ -1,20 +0,0 @@
export type TOCEntry<T> = {
id: string;
label: string;
order?: number;
children?: TOCEntry<T>[];
settings?: Array<T>;
};
export const tocData: TOCEntry<string>[] = [
{
id: 'common',
label: '通用',
settings: ['common.*'],
},
{
id: 'extension',
label: '插件',
settings: ['extension.*'],
},
];

File diff suppressed because it is too large Load Diff

View File

@ -3092,6 +3092,14 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axios@0.27.2:
version "0.27.2"
resolved "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
dependencies:
follow-redirects "^1.14.9"
form-data "^4.0.0"
axios@^0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a"
@ -6120,7 +6128,7 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@^1.0.0, follow-redirects@^1.14.7:
follow-redirects@^1.0.0, follow-redirects@^1.14.7, follow-redirects@^1.14.9:
version "1.15.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==