diff --git a/.gitignore b/.gitignore index 2d9f84c2..153e2e0b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ out/ *.js.map *.webpack.js !src/workbench/node/request/**/*.js +!src/workbench/node/server/**/*.js !/api/*.js !/build/*.js !*.config.js diff --git a/.vscode/settings.json b/.vscode/settings.json index 040de70e..b4634a5d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,7 +13,8 @@ // } "search.exclude": { "**/node_modules": true, - "**/bower_components": true, + "**/dist":true, + "**/.angular":true, "**/*.code-search": true, "**/*.lock": true, } diff --git a/api/unit.js b/api/unit.js index 03eaf928..a74c3091 100644 --- a/api/unit.js +++ b/api/unit.js @@ -4,20 +4,19 @@ let _LibsCommon = require('../src/workbench/node/request/libs/common.js'); module.exports = (req, res) => { console.log('unit.js', req.body); try { - let data = req.body.data; - data.env = _LibsCommon.parseEnv(data.env); - new _LibsFlowCommon.core().main(data, (tmpInputReport, tmpInputHistory) => { + let reqJSON = req.body.data; + reqJSON.env = _LibsCommon.parseEnv(reqJSON.env); + new _LibsFlowCommon.core().main(reqJSON).then(({ report, history }) => { ['general', 'requestInfo', 'resultInfo'].forEach((keyName) => { - if (typeof tmpInputHistory[keyName] === 'string') - tmpInputHistory[keyName] = JSON.parse(tmpInputHistory[keyName]); + if (typeof history[keyName] === 'string') history[keyName] = JSON.parse(history[keyName]); }); res.send( JSON.stringify({ action: 'finish', data: { - id: req.body.id, - report: tmpInputReport, - history: tmpInputHistory, + id: ctx.request.body.id, + report: report, + history: history, }, }) ); @@ -25,4 +24,4 @@ module.exports = (req, res) => { } catch (e) { console.error('unit.js', e, req.body); } -}; \ No newline at end of file +}; diff --git a/electron-builder.json b/electron-builder.json index 0b7ab86b..5187c4e5 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -10,7 +10,8 @@ "out/shared/**/*.js*", "**/*/browser/dist/**/*", "**/*/node/dist/**/*", - "out/workbench/node/", + "out/workbench/browser/src/**/*.js*", + "out/workbench/node/**/*.js*", "out/core/**/package.json", "out/app/common/**/*", "!**/*.ts" diff --git a/package.json b/package.json index 602b3ffc..a26a9a94 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,14 @@ { "name": "eoapi", "souceLocale": "zh-Hans", - "version": "1.2.4", + "version": "1.3.0", "main": "out/app/electron-main/main.js", "description": "A lightweight, extensible API tool", "homepage": "https://github.com/eolinker/eoapi.git", "author": "eoapi", "private": true, "workspaces": [ - "src/workbench/browser", - "src/app/electron-browser/IndexedDB" + "src/workbench/browser" ], "scripts": { "postinstall": "electron-builder install-app-deps", @@ -21,11 +20,12 @@ "electron:serve": "wait-on tcp:4200 && npm run electron:dev", "electron:dev:static": "npm run electron:tsc && electron .", "electron:dev": "npm run electron:tsc && electron . --development", - "build": "npm-run-all -s build:workbench electron:tsc && electron-builder build", - "build:static": "npm-run-all -s build:workbench electron:tsc && electron-builder build", - "release": "npm-run-all -s build:workbench electron:tsc && electron-builder --publish=always && node upload.js", + "build": "npm-run-all -s build:workbench clear:electron:tsc electron:tsc && electron-builder build", + "build:static": "npm run clear:electron:tsc&&npm run electron:tsc && electron-builder build", + "release": "npm-run-all -s build:workbench electron:tsc && electron-builder --publish=always", "release:m1": "npm-run-all -s build:workbench electron:tsc && electron-builder -m=dmg --arm64 -p onTagOrDraft", "test": "npm-run-all --serial test:*", + "clear:electron:tsc": "tsc --build --clean", "electron:tsc": "tsc -p tsconfig.json", "copyfile:out": "copyfiles -u 1 src/**/*.json src/app/common/images/** out" }, @@ -36,6 +36,7 @@ "copyfiles": "2.4.1", "crypto-js": "^4.1.1", "electron-log": "^4.4.8", + "electron-store": "8.0.2", "electron-updater": "^5.0.5", "express": "4.18.1", "fix-path": "3.0.0", @@ -44,7 +45,6 @@ "iconv-lite": "^0.6.3", "npm": "6.14.17", "portfinder": "1.0.28", - "qiniu": "^6.1.13", "resolve": "^1.22.1", "rxjs": "7.5.5", "xml2js": "^0.4.23" @@ -65,8 +65,7 @@ "npm-run-all": "4.1.5", "ts-node": "10.8.1", "typescript": "~4.7.4", - "wait-on": "6.0.1", - "yaml": "2.1.1" + "wait-on": "6.0.1" }, "__npminstall_done": false, "node-module-alias": { diff --git a/src/app/electron-browser/IndexedDB/index.html b/src/app/electron-browser/IndexedDB/index.html deleted file mode 100644 index 26ebb0a2..00000000 --- a/src/app/electron-browser/IndexedDB/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/app/electron-browser/IndexedDB/package.json b/src/app/electron-browser/IndexedDB/package.json deleted file mode 100644 index a48bf452..00000000 --- a/src/app/electron-browser/IndexedDB/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "eoapi", - "version": "1.0.0", - "description": "A storage load service.", - "scripts": { - "build": "rimraf ./dist && rollup -c rollup.config", - "dev": "rollup -c rollup.config.js -w" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^21.0.0", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-replace": "^3.0.0", - "@types/rimraf": "^3.0.0", - "rimraf": "^3.0.2", - "rollup": "^2.58.0", - "rollup-plugin-node-polyfills": "^0.2.1", - "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-string": "^3.0.0", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-typescript2": "^0.30.0" - }, - "engines": { - "node": ">= 12.0.0" - } -} diff --git a/src/app/electron-browser/IndexedDB/rollup.config b/src/app/electron-browser/IndexedDB/rollup.config deleted file mode 100644 index 180a6894..00000000 --- a/src/app/electron-browser/IndexedDB/rollup.config +++ /dev/null @@ -1,47 +0,0 @@ -import { terser } from 'rollup-plugin-terser'; -import typescript from 'rollup-plugin-typescript2'; -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import replace from '@rollup/plugin-replace'; -import resolve from 'rollup-plugin-node-resolve'; -import nodePolyfills from 'rollup-plugin-node-polyfills'; - -const sourcemap = 'inline'; -const input = './src/index.ts'; - -const commonOptions = { - external: ['dexie', 'rxjs'], - plugins: [ - typescript({ - tsconfigOverride: { - compilerOptions: { - target: 'ES2017', - module: 'ES2015' - } - } - }), - terser(), - resolve(), - nodePolyfills(), - commonjs(), - json(), - replace({ - preventAssignment: true - }) - ], - input -}; - -/** @type import('rollup').RollupOptions */ -const nodeCjs = { - output: [{ - file: 'dist/index.js', - format: 'cjs', - sourcemap - }], - ...commonOptions -}; - -const bundles = [nodeCjs]; - -export default bundles; diff --git a/src/app/electron-main/coreView.ts b/src/app/electron-main/coreView.ts deleted file mode 100644 index f42564cb..00000000 --- a/src/app/electron-main/coreView.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { BrowserView, BrowserWindow, ipcMain } from 'electron'; -import { BrowserViewInstance } from 'eo/platform/electron-main/browserView/browserView'; -import * as path from 'path'; -import { processEnv } from 'eo/platform/node/constant'; -export class CoreViews { - moduleID: string; - view: BrowserView; - constructor(private win: BrowserWindow) { - this.triggleEvent = this.triggleEvent.bind(this); - } - - rebuildBounds() { - if (!this.view) { - return; - } - const _bounds = this.win.getContentBounds(); - _bounds.x = 0; - _bounds.y = 0; - this.view.setBounds(_bounds); - } - - /** - * create core module browserview with sidebar/navbar/toolbar - */ - create() { - const _bounds = this.win.getContentBounds(); - _bounds.x = 0; - _bounds.y = 0; - this.view = new BrowserViewInstance({ - bounds: _bounds, - partition: '', - preloadPath: path.join(__dirname, '../../', 'platform', 'electron-browser', 'preload.js'), - viewPath: - processEnv === 'development' - ? 'http://localhost:4201' - : `file://${path.join(__dirname, '../../', 'workbench', 'browser', 'dist', 'index.html')}`, - }).init(this.win); - this.view.webContents.openDevTools(); - this.view.webContents.once('dom-ready', () => { - require('@electron/remote/main').enable(this.view.webContents); - }); - this.watch(); - } - watch() { - // ipcMain.on('message', this.triggleEvent); - } - triggleEvent(event, arg) { - console.log(`core view ${event.frameId}: recieve render msg=>`, arg, arg.action); - if (event.frameId !== 1) return; - switch (arg.action) { - case 'setBounds': { - //sidebar shrink or expand - break; - } - } - } - /** - * 删除视图 - * @param view - * @param window - */ - remove() { - if (!this.view) return; - this.win.removeBrowserView(this.view); - this.view.webContents.closeDevTools(); - ipcMain.removeListener('message', this.triggleEvent); - this.view = undefined; - } -} diff --git a/src/app/electron-main/language.service.ts b/src/app/electron-main/language.service.ts new file mode 100644 index 00000000..f373d7bd --- /dev/null +++ b/src/app/electron-main/language.service.ts @@ -0,0 +1,23 @@ +import { app } from 'electron'; +import { LANGUAGES } from '../../workbench/browser/src/app/core/services/language/language.model'; +import Store from 'electron-store'; +const store = new Store(); +class LanguageInstance { + private static _instance: LanguageInstance; + constructor() {} + public static get Instance(): LanguageInstance { + return this._instance || (this._instance = new this()); + } + get(): string { + let lang = store.get('language') || (app.getLocale().includes('zh') ? 'zh-Hans' : 'en-US'); + return lang as string; + } + getPath() { + const systemLanguage = this.get(); + return LANGUAGES.find((val) => val.value === systemLanguage).path; + } + set(localeID) { + store.set('language', localeID); + } +} +export const LanguageService = LanguageInstance.Instance; diff --git a/src/app/electron-main/main.ts b/src/app/electron-main/main.ts index 3b1ff3f0..6a42d2f9 100644 --- a/src/app/electron-main/main.ts +++ b/src/app/electron-main/main.ts @@ -3,97 +3,100 @@ import { app, BrowserWindow, ipcMain, screen } from 'electron'; import { EoUpdater } from './updater'; import * as path from 'path'; import * as os from 'os'; -import ModuleManager from '../../platform/node/extension-manager/lib/manager'; +import {ModuleManager} from '../../platform/node/extension-manager/lib/manager'; import { ModuleManagerInterface } from '../../platform/node/extension-manager'; -// TODO 引入问题 -// import { -// StorageResStatus, -// StorageProcessType, -// } from '../../workbench/browser/src/app/shared/services/storage/index.model'; import { processEnv } from '../../platform/node/constant'; import { proxyOpenExternal } from '../../shared/common/browserView'; import { deleteFile, readJson } from '../../shared/node/file'; -import { STORAGE_TEMP as storageTemp } from '../../shared/common/constant'; -import { UnitWorkerModule } from '../../workbench/node/unitWorker'; +import { STORAGE_TEMP as storageTemp } from '../../shared/electron-main/constant'; +import { UnitWorkerModule } from '../../workbench/node/electron/main'; import Configuration from '../../platform/node/configuration/lib'; import { ConfigurationInterface } from 'src/platform/node/configuration'; import { MockServer } from 'eo/platform/node/mock-server'; +import { LanguageService } from 'eo/app/electron-main/language.service'; -let win: BrowserWindow = null; export const subView = { appView: null, mainView: null, }; const eoUpdater = new EoUpdater(); const mockServer = new MockServer(); -const moduleManager: ModuleManagerInterface = ModuleManager(); +const moduleManager: ModuleManagerInterface = new ModuleManager(); const configuration: ConfigurationInterface = Configuration(); -// Remote -const mainRemote = require('@electron/remote/main'); -mainRemote.initialize(); global.shareObject = { storageResult: null, }; - -function createWindow(): BrowserWindow { - const electronScreen = screen; - const size = electronScreen.getPrimaryDisplay().workAreaSize; - // Create the browser window. - win = new BrowserWindow({ - width: Math.round(size.width * 0.85), - height: Math.round(size.height * 0.85), - minWidth: 1280, - minHeight: 720, - useContentSize: true, // 这个要设置,不然计算显示区域尺寸不准 - frame: os.type() === 'Darwin' ? true : false, //mac use default frame - webPreferences: { - webSecurity: false, - preload: path.join(__dirname, '../../', 'platform', 'electron-browser', 'preload.js'), - nodeIntegration: true, - allowRunningInsecureContent: processEnv === 'development' ? true : false, - contextIsolation: false, // false if you want to run e2e test with Spectron - }, - }); - // 启动mock服务 - mockServer.start(win as any); - proxyOpenExternal(win); - let loadPage = async () => { - let currentUrl = win.webContents.getURL(); - let locale = ['zh', 'en'].find((val) => currentUrl.includes(val)); +let eoBrowserWindow: EoBrowserWindow = null; +class EoBrowserWindow { + // Start mock server when app inital + win: BrowserWindow; + constructor() { + this.create(); + } + private startMock() { + mockServer.start(this.win as any); + } + // Start unit test function + private startUnitTest() { + UnitWorkerModule.setup({ + view: this.win, + }); + } + //Watch win event + private watch() { + // Reload page when load page url error + this.win.webContents.on('did-fail-load', (event, errorCode) => { + console.error('did-fail-load', errorCode); + this.loadURL(); + }); + this.win.on('closed', () => { + // Dereference the window object, usually you would store window + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + this.win = null; + }); + } + public loadURL() { + console.log('loadURL') const file: string = processEnv === 'development' ? 'http://localhost:4200' : `file://${path.join( __dirname, - `../../../src/workbench/browser/dist/${locale || app.getLocale()}/index.html` + `../../../src/workbench/browser/dist/${LanguageService.getPath()}/index.html` )}`; - win.loadURL(file); + this.win.loadURL(file); if (['development'].includes(processEnv)) { - win.webContents.openDevTools({ + this.win.webContents.openDevTools({ mode: 'undocked', }); } - UnitWorkerModule.setup({ - view: win, + } + public create(): BrowserWindow { + const size = screen.getPrimaryDisplay().workAreaSize; + // Create the browser window. + this.win = new BrowserWindow({ + width: Math.round(size.width * 0.85), + height: Math.round(size.height * 0.85), + minWidth: 1280, + minHeight: 720, + useContentSize: true, // 这个要设置,不然计算显示区域尺寸不准 + frame: os.type() === 'Darwin' ? true : false, //mac use default frame + webPreferences: { + webSecurity: false, + preload: path.join(__dirname, '../../', 'platform', 'electron-browser', 'preload.js'), + nodeIntegration: true, + allowRunningInsecureContent: processEnv === 'development' ? true : false, + contextIsolation: false, // false if you want to run e2e test with Spectron + }, }); - }; - win.webContents.on('did-fail-load', (event, errorCode) => { - console.error('did-fail-load', errorCode); - loadPage(); - }); - win.webContents.on('did-finish-load', () => { - mainRemote.enable(win.webContents); - }); - loadPage(); - - // Emitted when the window is closed. - win.on('closed', () => { - // Dereference the window object, usually you would store window - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - win = null; - }); - return win; + proxyOpenExternal(this.win); + this.loadURL(); + this.startMock(); + this.startUnitTest(); + this.watch(); + return this.win; + } } try { @@ -102,7 +105,9 @@ try { // Some APIs can only be used after this event occurs. // Added 400 ms to fix the black background issue while using transparent window. More detais at https://github.com/electron/electron/issues/15947 app.on('ready', async () => { - setTimeout(createWindow, 400); + setTimeout(() => { + eoBrowserWindow = new EoBrowserWindow(); + }, 400); eoUpdater.check(); }); //!TODO only api manage app need this @@ -121,8 +126,8 @@ try { app.on('activate', () => { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. - if (win === null) { - createWindow(); + if (eoBrowserWindow.win === null) { + eoBrowserWindow.create(); } }); ipcMain.on('message', function (event, arg) { @@ -131,32 +136,37 @@ try { // if (event.frameId !== 1) return; switch (arg.action) { case 'minimize': { - win.minimize(); + eoBrowserWindow.win.minimize(); break; } case 'restore': { - win.restore(); + eoBrowserWindow.win.restore(); break; } case 'maximize': { - win.maximize(); + eoBrowserWindow.win.maximize(); break; } case 'close': { - win.close(); + eoBrowserWindow.win.close(); + break; + } + case 'changeLanguage': { + LanguageService.set(arg.data); + eoBrowserWindow.loadURL(); + moduleManager.refreshAll(); break; } } }); - ipcMain.on('eo-storage', (event, args) => { let returnValue: any; if (args.type === 'default' || args.type === 'remote') { - win.webContents.send('eo-storage', args); + eoBrowserWindow.win.webContents.send('eo-storage', args); returnValue = null; } else if (args.type === 'sync') { deleteFile(storageTemp); - win.webContents.send('eo-storage', args); + eoBrowserWindow.win.webContents.send('eo-storage', args); let data = readJson(storageTemp); let count: number = 0; while (data === null) { @@ -174,7 +184,7 @@ try { deleteFile(storageTemp); returnValue = data; } else if (args.type === 'result') { - let view = subView.appView ? subView.appView?.view.webContents : win.webContents; + let view = subView.appView ? subView.appView?.view.webContents : eoBrowserWindow.win.webContents; view.send('storageCallback', args.result); } }); diff --git a/src/platform/common/i18n.ts b/src/platform/common/i18n.ts new file mode 100644 index 00000000..470a4fdd --- /dev/null +++ b/src/platform/common/i18n.ts @@ -0,0 +1,40 @@ +import { ModuleInfo } from 'eo/platform/node/extension-manager'; +/** + * Single extension i18 service,chain call + */ +export class TranslateService { + // Default key in package.json translate replace directly + defaultKeys = ['moduleName', 'description', 'author', 'logo']; + constructor(private module: ModuleInfo, private locale) {} + translate() { + return this.translateDefaultKey().translateVariableKey().get(); + } + get() { + return this.module; + } + translateDefaultKey() { + this.defaultKeys.forEach((defaultKey) => { + if (!this.module[defaultKey] || !this.locale[defaultKey]) return; + this.module[defaultKey] = this.locale[defaultKey]; + }); + return this; + } + /** + * Transalte package.json variable ${} to locale text + */ + translateVariableKey() { + let that = this; + Object.keys(this.module.features).forEach((name) => { + let feature = that.module.features[name]; + Object.keys(feature).forEach((childName) => { + if (typeof feature[childName] !== 'string') return; + that.module.features[name][childName] = feature[childName].replace(/\$\{(.+)\}/g, (match, rest) => { + let replacement = match; + replacement = that.locale[rest] || replacement; + return replacement; + }); + }); + }); + return this; + } +} diff --git a/src/platform/electron-browser/i18n.ts b/src/platform/electron-browser/i18n.ts new file mode 100644 index 00000000..85572311 --- /dev/null +++ b/src/platform/electron-browser/i18n.ts @@ -0,0 +1,30 @@ +import { getLocaleData } from '../node/i18n'; +import { LANGUAGES } from '../../workbench/browser/src/app/core/services/language/language.model'; +export class I18N { + constructor() { + } + getSystemLanguage() { + let deafultLanguage = + LANGUAGES.find((val) => window.location.href.includes(`/${val.path}`))?.value || + (navigator.language.includes('zh') ? 'zh-Hans' : 'en-US'); + return window.eo.getSettings()['eoapi-language'] || deafultLanguage; + } + localize(id: string, originText: string, ...args) { + let result = originText; + const locale: Object = getLocaleData(window.eo.getModule(window.eo._currentExtensionID), this.getSystemLanguage()); + if (!locale) return result; + result ??= locale[id]; + result = result.replace(/\{(\d+)\}/g, (match, rest) => { + let index = rest[0]; + let arg = args[index]; + let replacement = match; + if (typeof arg === 'string') { + replacement = arg; + } else if (typeof arg === 'number' || typeof arg === 'boolean' || arg === void 0 || arg === null) { + replacement = String(arg); + } + return replacement; + }); + return result; + } +} diff --git a/src/platform/electron-browser/preload.ts b/src/platform/electron-browser/preload.ts index 4eb23989..9994c080 100644 --- a/src/platform/electron-browser/preload.ts +++ b/src/platform/electron-browser/preload.ts @@ -1,5 +1,5 @@ +import { I18N } from './i18n'; const { ipcRenderer } = require('electron'); -console.log('eoapi public api load'); // 可以加上条件判断,根据不同模块id哪些允许放出 const apiAccessRules = ipcRenderer.sendSync('eo-sync', { action: 'getApiAccessRules' }) || []; @@ -53,6 +53,7 @@ window.eo.loadFeatureModule = (moduleID) => { if (!featureModules.has(moduleID)) { try { const module = window.eo.getModule(moduleID); + window.eo._currentExtensionID=moduleID; const _module = window.require(module.baseDir); featureModules.set(moduleID, _module); } catch (e) { @@ -102,28 +103,28 @@ window.eo.storageSync = (args) => { args.type = 'sync'; return ipcRenderer.sendSync('eo-storage', args); }; -window.eo.storageRemote = (args) => { - console.log('run preload storageRemote'); - args.type = 'remote'; - const shareObject = window.require('@electron/remote').getGlobal('shareObject'); - shareObject.storageResult = null; - ipcRenderer.send('eo-storage', args); - let output: any = shareObject.storageResult; - let count: number = 0; - while (output === null) { - if (count > 1500) { - output = { - status: 'error', - data: 'storage remote load error', - }; - break; - } - output = shareObject.storageResult; - ++count; - } - shareObject.storageResult = null; - return output; -}; +// window.eo.storageRemote = (args) => { +// console.log('run preload storageRemote'); +// args.type = 'remote'; +// const shareObject = window.require('@electron/remote').getGlobal('shareObject'); +// shareObject.storageResult = null; +// ipcRenderer.send('eo-storage', args); +// let output: any = shareObject.storageResult; +// let count: number = 0; +// while (output === null) { +// if (count > 1500) { +// output = { +// status: 'error', +// data: 'storage remote load error', +// }; +// break; +// } +// output = shareObject.storageResult; +// ++count; +// } +// shareObject.storageResult = null; +// return output; +// }; window.eo.saveSettings = (settings) => { // console.log('window.eo.saveSettings', settings); @@ -141,14 +142,18 @@ window.eo.deleteModuleSettings = (moduleID) => { return ipcRenderer.sendSync('eo-sync', { action: 'deleteModuleSettings', data: { moduleID: moduleID } }); }; -window.eo.getSettings = (settings) => { - return ipcRenderer.sendSync('eo-sync', { action: 'getSettings' }); +window.eo.getSettings = () => { + try { + return JSON.parse(localStorage.getItem('localSettings') || '{}'); + } catch (error) { + return {}; + } }; +window.eo.i18n = new I18N(); window.eo.getModuleSettings = (moduleID) => { return ipcRenderer.sendSync('eo-sync', { action: 'getModuleSettings', data: { moduleID: moduleID } }); }; - // 注册单个mock路由 window.eo.registerMockRoute = ({ method, path, data }) => { return ipcRenderer.send('eo-sync', { action: 'registerMockRoute', data: { method, path, data } }); diff --git a/src/platform/node/configuration/lib/index.ts b/src/platform/node/configuration/lib/index.ts index 554ef45f..7cbbf85c 100644 --- a/src/platform/node/configuration/lib/index.ts +++ b/src/platform/node/configuration/lib/index.ts @@ -1,4 +1,4 @@ -import { DATA_DIR as dataDir } from 'eo/shared/common/constant'; +import { DATA_DIR as dataDir } from 'eo/shared/electron-main/constant'; import { ConfigurationInterface, ConfigurationValueInterface } from '../types'; import * as path from 'path'; import { fileExists, readJson, writeJson } from 'eo/shared/node/file'; diff --git a/src/platform/node/extension-manager/lib/core.ts b/src/platform/node/extension-manager/lib/core.ts index 8d64cb2a..9a7b68ad 100644 --- a/src/platform/node/extension-manager/lib/core.ts +++ b/src/platform/node/extension-manager/lib/core.ts @@ -1,8 +1,10 @@ import * as path from 'path'; import { ModuleHandlerOptions, ModuleInfo } from '../types'; -import { fileExists, readJson } from 'eo/shared/node/file'; +import { fileExists, readFile, readJson } from 'eo/shared/node/file'; import { isNotEmpty } from 'eo/shared/common/common'; -import { readFileSync } from 'node:fs'; +import { getLocaleData } from 'eo/platform/node/i18n'; +import { LanguageService } from 'eo/app/electron-main/language.service'; +import { TranslateService } from 'eo/platform/common/i18n'; /** * 核心模块管理器 * @class CoreHandler @@ -37,8 +39,20 @@ export class CoreHandler { try { const baseDir: string = this.getModuleDir(name); moduleInfo = readJson(path.join(baseDir, 'package.json')) as ModuleInfo; - moduleInfo.introduction = readFileSync(path.join(baseDir, 'README.md')).toString(); moduleInfo.baseDir = baseDir; + // Get language locale + //!Warn:baseDir must be set before get locale file + const lang = LanguageService.get(); + if (moduleInfo.features?.i18n) { + const locale = getLocaleData(moduleInfo, lang); + if (locale) { + let translateService = new TranslateService(moduleInfo, locale); + moduleInfo = translateService.translate(); + } + } + // Check that the file exists locally + moduleInfo.introduction = + readFile(path.join(baseDir, `README.${lang}.md`)) || readFile(path.join(baseDir, `README.md`)); moduleInfo.main = 'file://' + path.join(moduleInfo.baseDir, moduleInfo.main); if (moduleInfo.preload?.length > 0) { moduleInfo.preload = path.join(moduleInfo.baseDir, moduleInfo.preload); @@ -56,9 +70,9 @@ export class CoreHandler { moduleInfo.author = moduleInfo.author['name'] || ''; } } catch (e) { + console.log(`get module ${moduleInfo.moduleID} error:${e}`); moduleInfo = {} as ModuleInfo; } - return moduleInfo; } diff --git a/src/platform/node/extension-manager/lib/handler.ts b/src/platform/node/extension-manager/lib/handler.ts index 76155cda..b93e7ef6 100644 --- a/src/platform/node/extension-manager/lib/handler.ts +++ b/src/platform/node/extension-manager/lib/handler.ts @@ -4,6 +4,8 @@ import { ModuleHandlerOptions, ModuleHandlerResult } from '../types'; import { fileExists, writeJson } from 'eo/shared/node/file'; import { CoreHandler } from './core'; import * as fs from 'fs'; +import { spawn } from 'child_process'; +type Action = 'uninstall' | 'install' | 'update'; // import npmCli from 'npm'; const npmCli = require('npm'); /** @@ -60,7 +62,6 @@ export class ModuleHandler extends CoreHandler { async install(modules: string[], isLocal: boolean): Promise { return await this.execCommand(isLocal ? 'link' : 'install', modules); } - /** * 更新模块 * @param {...string[]} modules 模块名称数组 @@ -83,7 +84,7 @@ export class ModuleHandler extends CoreHandler { * @param result npm install安装成功回调的结果 * @param moduleList 所有的模块列表 */ - private operatePackage(result: any[], moduleList: string[], action: 'uninstall' | 'install' | 'update') { + private operatePackage(result: any[], moduleList: string[], action: Action) { if (Array.isArray(result)) { const moduleNames = moduleList.map((n) => n.split('@')[0]); const packagePath = path.join(this.baseDir, 'package.json'); @@ -105,7 +106,55 @@ export class ModuleHandler extends CoreHandler { }); } } - + private executeByAppNpm(command: string, modules: string[], 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); + let executeCommand = ['update', 'install', 'uninstall']; + if (!executeCommand.includes(command)) return; + npmCli.commands[command](moduleList, (err, data) => { + process.chdir(this.baseDir); + if (err) { + return reject(err); + } + this.operatePackage(data, moduleList, command as Action); + return resolve({ code: 0, data }); + }); + }); + } + private executeBySystemNpm(command: string, modules: string[], resolve) { + let args = [command].concat(modules).concat('--color=always', '--save'); + if (!['link', 'unlink', 'uninstall', 'update'].includes(command)) { + if (this.registry) { + args = args.concat(`--registry=${this.registry}`); + } + if (this.proxy) { + args = args.concat(`--proxy=${this.proxy}`); + } + } + console.log(args) + const npm = spawn('npm', args, { cwd: this.baseDir }); + // console.log('2==>', npm); + let output = ''; + npm.stdout + .on('data', (data: string) => { + output += data; + }) + .pipe(process.stdout); + npm.stderr + .on('data', (data: string) => { + output += data; + }) + .pipe(process.stderr); + npm.on('close', (code: number) => { + if (!code) { + resolve({ code: 0, data: output }); + } else { + resolve({ code: code, data: output }); + } + }); + } /** * 运行模块管理器 * @param command @@ -113,71 +162,8 @@ export class ModuleHandler extends CoreHandler { */ private async execCommand(command: string, modules: string[]): Promise { return await new Promise((resolve: any, reject: any): void => { - let args = [command].concat(modules).concat('--color=always', '--save'); - if (!['link', 'unlink', 'uninstall', 'update'].includes(command)) { - if (this.registry) { - args = args.concat(`--registry=${this.registry}`); - } - if (this.proxy) { - args = args.concat(`--proxy=${this.proxy}`); - } - } - // console.log(npmCli.commands.run('version')); - // console.log('command', [command].concat(modules), this.baseDir); - npmCli.load({ 'bin-links': false, verbose: true, prefix: this.baseDir }, (loaderr) => { - const moduleList = modules.map((it) => it + '@latest'); - if (command === 'update') { - npmCli.commands.update(moduleList, (err, data) => { - process.chdir(this.baseDir); - if (err) { - return reject(err); - } - this.operatePackage(data, moduleList, 'update'); - return resolve({ code: 0, data }); - }); - } - if (command === 'install') { - npmCli.commands.install(moduleList, (err, data) => { - process.chdir(this.baseDir); - if (err) { - return reject(err); - } - this.operatePackage(data, moduleList, 'install'); - return resolve({ code: 0, data }); - }); - } - if (command === 'uninstall') { - npmCli.commands.uninstall(moduleList, (err, data) => { - process.chdir(this.baseDir); - if (err) { - return reject(err); - } - this.operatePackage(data, moduleList, 'uninstall'); - return resolve({ code: 0, data }); - }); - } - }); - - // const npm = spawn('npm', args, { cwd: this.baseDir }); - // // console.log('2==>', npm); - // let output = ''; - // npm.stdout - // .on('data', (data: string) => { - // output += data; - // }) - // .pipe(process.stdout); - // npm.stderr - // .on('data', (data: string) => { - // output += data; - // }) - // .pipe(process.stderr); - // npm.on('close', (code: number) => { - // if (!code) { - // resolve({ code: 0, data: output }); - // } else { - // resolve({ code: code, data: output }); - // } - // }); + // this.executeBySystemNpm(command, modules, resolve) + this.executeByAppNpm(command, modules, resolve, reject); }); } } diff --git a/src/platform/node/extension-manager/lib/loader.ts b/src/platform/node/extension-manager/lib/loader.ts index 0c5a808e..0296a4cb 100644 --- a/src/platform/node/extension-manager/lib/loader.ts +++ b/src/platform/node/extension-manager/lib/loader.ts @@ -39,7 +39,6 @@ export class ModuleLoader implements ModuleLoaderInterface { * @param module ModuleInfo */ loadModule(module: ModuleInfo): void { - console.log(module); if ((this.runtime === ModuleRuntime.main && ![ModuleType.system, ModuleType.app].indexOf(module.moduleType)) || (this.runtime === ModuleRuntime.render && ![ModuleType.feature].indexOf(module.moduleType)) || (this.runtime === ModuleRuntime.web && !module.web)) { diff --git a/src/platform/node/extension-manager/lib/manager.ts b/src/platform/node/extension-manager/lib/manager.ts index f220579c..7d631dbc 100644 --- a/src/platform/node/extension-manager/lib/manager.ts +++ b/src/platform/node/extension-manager/lib/manager.ts @@ -1,4 +1,4 @@ -import { MODULE_DIR as baseDir } from 'eo/shared/common/constant'; +import { MODULE_DIR as baseDir } from 'eo/shared/electron-main/constant'; import { ModuleHandler } from './handler'; import { ModuleHandlerResult, ModuleInfo, ModuleManagerInfo, ModuleManagerInterface, ModuleType } from '../types'; import { isNotEmpty } from 'eo/shared/common/common'; @@ -6,7 +6,6 @@ import { processEnv } from '../../constant'; // * npm pkg name const installExtension = [{ name: 'eoapi-export-openapi' }, { name: 'eoapi-import-openapi' }]; - export class ModuleManager implements ModuleManagerInterface { /** * 模块管理器 @@ -33,20 +32,7 @@ export class ModuleManager implements ModuleManagerInterface { this.modules = new Map(); this.features = new Map(); this.init(); - // * 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().keys()); - list.forEach((item) => { - this.update({ name: item }); - }); - // * install - // console.log('install'); - this.installExtension.forEach((item) => { - // * If the extension already in local extension list, then do not repeat installation - if (!list.includes(item.name)) { - this.install(item); - } - }); + this.updateAll(); } /** @@ -73,7 +59,22 @@ export class ModuleManager implements ModuleManagerInterface { } 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 @@ -95,7 +96,16 @@ export class ModuleManager implements ModuleManagerInterface { const moduleInfo: ModuleInfo = this.moduleHandler.info(module.name); this.set(moduleInfo); } - + /** + * 读取本地package.json更新模块信息 + * @param module + */ + refreshAll(): void { + const list = Array.from(this.getModules().values()); + list.forEach((module) => { + this.refresh(module); + }); + } /** * 获取应用级app列表 */ @@ -281,5 +291,3 @@ export class ModuleManager implements ModuleManagerInterface { return newModules; } } - -export default () => new ModuleManager(); diff --git a/src/platform/node/extension-manager/types/manager.ts b/src/platform/node/extension-manager/types/manager.ts index 02ec1f2e..a142a9e4 100644 --- a/src/platform/node/extension-manager/types/manager.ts +++ b/src/platform/node/extension-manager/types/manager.ts @@ -13,36 +13,38 @@ export enum ModuleType { app = 'app', feature = 'feature', } - +export interface I18nLocale{ + locale: string; package: any +} /** * 模块信息接口 */ export interface ModuleInfo { - // 模块名称, npm包名 + // npm package name name: string; - // 作者 + // author author: string; - // 版本 + // extension version version: string; - // 模块描述 + // extension description description: string; - // 详细说明 + // extension intro,from README.md introduction: string; - // 模块ID,用于关联 + // extension ID moduleID: string; - // 模块名称,用于显示 + // extension name moduleName: string; - // 模块类型 + // extension type moduleType: ModuleType; - // 模块Logo + // extension logo logo: string; - // 入口文件 + // manifest code file main: string; - // main端运行脚本 + // main node script main_node?: string; // 入口开发调试 main_debug?: string; - // 预加载js文件 + // inject script before start app preload?: string; // 判断是不是顶层App isApp?: boolean; @@ -64,8 +66,9 @@ export interface ModuleInfo { contributes: ModuleContributes; // 功能点配置 features?: { - [index: string]: object; + [index: string]: any; }; + i18n?:I18nLocale[] } /** * 贡献点 @@ -118,6 +121,7 @@ export interface ModuleManagerInterface { update: (module: ModuleManagerInfo) => Promise; uninstall: (module: ModuleManagerInfo) => Promise; refresh: (module: ModuleManagerInfo) => void; + refreshAll:()=>void; getModule: (moduleID: string, belongs?: boolean) => ModuleInfo; getModules: (belongs?: boolean) => Map; getAppModuleList: () => Array; diff --git a/src/platform/node/i18n.ts b/src/platform/node/i18n.ts new file mode 100644 index 00000000..881058fe --- /dev/null +++ b/src/platform/node/i18n.ts @@ -0,0 +1,37 @@ +import { I18nLocale, ModuleInfo } from 'eo/platform/node/extension-manager'; + +interface LooseObject { + [key: string]: any; +} +const localeStorage: LooseObject = {}; +/** + * Get locale file from extension i18 file dir + * @param moduleID + * @returns json + */ +function getLocaleFile(module: ModuleInfo, lang): Object { + let result = {}; + try { + result = require(`${module.baseDir}/i18n/${lang}.json`); + } catch (e) {} + return result; +} +function getSupportLang(module: ModuleInfo) { + return [module.features.i18n.sourceLocale, ...module.features.i18n.locales].filter((val) => val); +} +/** + * Get locale data from storage or file + * @returns json + */ +export function getLocaleData(module: ModuleInfo, lang): Object | null { + let supportLang = getSupportLang(module); + if (!supportLang.includes(lang)) { + console.log(`Error: extenaion ${module.moduleID} can't find the i18n package ${lang}`); + return null; + } + localeStorage[module.moduleID] = localeStorage[module.moduleID] || {}; + if (!localeStorage[module.moduleID][lang]) { + localeStorage[module.moduleID][lang] = getLocaleFile(module, lang); + } + return localeStorage[module.moduleID][lang]; +} diff --git a/src/shared/common/browserView.ts b/src/shared/common/browserView.ts index c0eab710..02d52a25 100644 --- a/src/shared/common/browserView.ts +++ b/src/shared/common/browserView.ts @@ -1,5 +1,5 @@ import { shell } from 'electron'; -//open link through default browser not electron +//Open link through system default browser not Electron browserwin export function proxyOpenExternal(view) { view.webContents.setWindowOpenHandler(({ url }) => { setImmediate(() => { diff --git a/src/shared/common/common.ts b/src/shared/common/common.ts index 7fb63809..5ec29a14 100644 --- a/src/shared/common/common.ts +++ b/src/shared/common/common.ts @@ -17,6 +17,3 @@ export const isNotEmpty = (value: any) => { } }; -export const isElectron = () => { - return !!(window && window.process && window.process.type); -}; diff --git a/src/shared/common/constant.ts b/src/shared/electron-main/constant.ts similarity index 79% rename from src/shared/common/constant.ts rename to src/shared/electron-main/constant.ts index b2c79b52..f45d3375 100644 --- a/src/shared/common/constant.ts +++ b/src/shared/electron-main/constant.ts @@ -5,4 +5,4 @@ export const home: string = app.getPath('home'); export const HOME_DIR = path.join(home, '.eo'); export const DATA_DIR = path.join(HOME_DIR, 'data'); export const MODULE_DIR = HOME_DIR; -export const STORAGE_TEMP = path.join(HOME_DIR, 'tmp.storage'); +export const STORAGE_TEMP = path.join(HOME_DIR, 'tmp.storage'); \ No newline at end of file diff --git a/src/workbench/browser/build/build.js b/src/workbench/browser/build/build.js index 703b6e90..abda48af 100644 --- a/src/workbench/browser/build/build.js +++ b/src/workbench/browser/build/build.js @@ -1,7 +1,5 @@ -//change angular.json const fs = require('fs'); const { execSync } = require('child_process'); - class webPlatformBuilder { resetBuildConfig(json) { delete json.projects.eoapi.i18n.sourceLocale.baseHref; @@ -23,7 +21,7 @@ class appPlatformBuilder { return json; } executeBuild() { - execSync('ng build --base-href ./', { stdio: 'inherit' }); + execSync('ng build -c production --base-href ./', { stdio: 'inherit' }); } } class PlatformBuilder { @@ -40,9 +38,10 @@ class PlatformBuilder { } } build() { - let buildConfigJson = require( '../angular.json'); + //Because of i18n,we should change angular.json for generate different base-href html tag + let buildConfigJson = require('../angular.json'); buildConfigJson = this.instance.resetBuildConfig(buildConfigJson); - let that=this; + let that = this; fs.writeFile('./angular.json', JSON.stringify(buildConfigJson), function (err) { if (err) { console.error('build/beforeBuild.js:', err); @@ -51,6 +50,7 @@ class PlatformBuilder { }); } } + let platform = process.argv[2] || 'app'; let platformBuilder = new PlatformBuilder(platform); platformBuilder.build(); diff --git a/src/workbench/browser/src/app/app.module.ts b/src/workbench/browser/src/app/app.module.ts index cbbaeb83..710b9d1a 100644 --- a/src/workbench/browser/src/app/app.module.ts +++ b/src/workbench/browser/src/app/app.module.ts @@ -24,6 +24,8 @@ import { NzMessageService } from 'ng-zorro-antd/message'; import { NzModalService } from 'ng-zorro-antd/modal'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { BaseUrlInterceptor } from 'eo/workbench/browser/src/app/shared/services/storage/http/lib/baseUrl.service'; +import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; +import { APP_CONFIG } from 'eo/workbench/browser/src/environments/environment'; @NgModule({ declarations: [AppComponent], @@ -58,7 +60,10 @@ import { BaseUrlInterceptor } from 'eo/workbench/browser/src/app/shared/services bootstrap: [AppComponent], }) export class AppModule { - constructor(private upgrade: UpgradeModule) { + constructor(private upgrade: UpgradeModule, private lang: LanguageService) { + if (APP_CONFIG.production) { + this.lang.init(); + } this.upgrade.bootstrap(document.body, ['eolinker']); } } diff --git a/src/workbench/browser/src/app/core/services/language/language.model.ts b/src/workbench/browser/src/app/core/services/language/language.model.ts new file mode 100644 index 00000000..638a1f31 --- /dev/null +++ b/src/workbench/browser/src/app/core/services/language/language.model.ts @@ -0,0 +1,12 @@ +export const LANGUAGES = [ + { + name: 'English', + value: 'en-US', + path: 'en', + }, + { + name: '简体中文', + value: 'zh-Hans', + path: 'zh', + }, +]; diff --git a/src/workbench/browser/src/app/core/services/language/language.service.spec.ts b/src/workbench/browser/src/app/core/services/language/language.service.spec.ts new file mode 100644 index 00000000..299455ee --- /dev/null +++ b/src/workbench/browser/src/app/core/services/language/language.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LanguageService } from './language.service'; + +describe('LanguageService', () => { + let service: LanguageService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LanguageService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/workbench/browser/src/app/core/services/language/language.service.ts b/src/workbench/browser/src/app/core/services/language/language.service.ts new file mode 100644 index 00000000..5fb3f3f1 --- /dev/null +++ b/src/workbench/browser/src/app/core/services/language/language.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@angular/core'; +import { ElectronService } from 'eo/workbench/browser/src/app/core/services/electron/electron.service'; +import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service'; +import { LANGUAGES } from 'eo/workbench/browser/src/app/core/services/language/language.model'; +import { SettingService } from 'eo/workbench/browser/src/app/core/services/settings/settings.service'; + +@Injectable({ + providedIn: 'root', +}) +export class LanguageService { + languages = LANGUAGES; + //If the user does not set it, the system default language is used + // Web from nginx setting and App from computer system setting + systemLanguage = + this.languages.find((val) => window.location.href.includes(`/${val.path}`))?.value || + (navigator.language.includes('zh') ? 'zh-Hans' : 'en-US'); + + constructor(private remote: RemoteService, private electron: ElectronService,private setting:SettingService) {} + + init() { + this.changeLanguage(this.setting.getSettings()?.['eoapi-language']); + } + changeLanguage(localeID) { + if (!localeID || localeID === this.systemLanguage) { + console.warn(`current language has already ${localeID}`); + return; + } + this.systemLanguage = localeID; + const localePath = (this.languages.find((val) => val.value === localeID) || this.languages[0]).path; + if (this.electron.isElectron) { + this.electron.ipcRenderer.send('message', { + action: 'changeLanguage', + data: this.systemLanguage, + }); + } else { + window.location.href = `/${localePath}`; + } + } +} diff --git a/src/workbench/browser/src/app/pages/api/test/api-test.component.ts b/src/workbench/browser/src/app/pages/api/test/api-test.component.ts index d568586c..c7439976 100644 --- a/src/workbench/browser/src/app/pages/api/test/api-test.component.ts +++ b/src/workbench/browser/src/app/pages/api/test/api-test.component.ts @@ -26,6 +26,7 @@ import { ApiParamsNumPipe } from '../../../shared/pipes/api-param-num.pipe'; import { StorageService } from '../../../shared/services/storage'; import { TestServerLocalNodeService } from '../../../shared/services/api-test/local-node/test-connect.service'; import { TestServerServerlessService } from '../../../shared/services/api-test/serverless-node/test-connect.service'; +import { TestServerRemoteService } from 'eo/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service'; @Component({ selector: 'eo-api-test', @@ -48,7 +49,7 @@ export class ApiTestComponent implements OnInit, OnDestroy { response: {}, request: {}, }; - testServer: TestServerLocalNodeService | TestServerServerlessService; + testServer: TestServerLocalNodeService | TestServerServerlessService | TestServerRemoteService; REQUEST_METHOD = objectToArray(RequestMethod); REQUEST_PROTOCOL = objectToArray(RequestProtocol); diff --git a/src/workbench/browser/src/app/pages/api/test/api-test.module.ts b/src/workbench/browser/src/app/pages/api/test/api-test.module.ts index 8e8e1d9d..459e4a0a 100644 --- a/src/workbench/browser/src/app/pages/api/test/api-test.module.ts +++ b/src/workbench/browser/src/app/pages/api/test/api-test.module.ts @@ -40,6 +40,7 @@ import { ApiTestResultHeaderComponent } from './result-header/api-test-result-he import { ApiTestResultResponseComponent } from './result-response/api-test-result-response.component'; import { ApiTestHistoryComponent } from './history/api-test-history.component'; import { ApiTestResultRequestBodyComponent } from './result-request-body/api-test-result-request-body.component'; +import { TestServerRemoteService } from 'eo/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service'; const NZ_COMPONETS = [ NzDropDownModule, NzModalModule, @@ -81,6 +82,6 @@ const COMPONENTS = [ SharedModule, ParamsImportModule ], - providers: [ApiTestService, TestServerService, TestServerLocalNodeService,TestServerServerlessService], + providers: [ApiTestService, TestServerService, TestServerLocalNodeService,TestServerServerlessService,TestServerRemoteService], }) export class ApiTestModule {} diff --git a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html index 0c8ed21f..b5697ab4 100644 --- a/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html +++ b/src/workbench/browser/src/app/pages/extension/detail/extension-detail.component.html @@ -63,7 +63,7 @@

Support

- {{ extensionDetail?.author }} + {{ extensionDetail?.author}} {{ extensionDetail?.version }} diff --git a/src/workbench/browser/src/app/pages/extension/extension.model.ts b/src/workbench/browser/src/app/pages/extension/extension.model.ts index 904884b6..c3a7b698 100644 --- a/src/workbench/browser/src/app/pages/extension/extension.model.ts +++ b/src/workbench/browser/src/app/pages/extension/extension.model.ts @@ -1,4 +1,4 @@ -import { ModuleInfo } from "../../utils/module-loader"; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types/index'; export enum ExtensionGroupType { all = 'all', diff --git a/src/workbench/browser/src/app/pages/extension/extension.service.ts b/src/workbench/browser/src/app/pages/extension/extension.service.ts index 892613b4..7de77397 100644 --- a/src/workbench/browser/src/app/pages/extension/extension.service.ts +++ b/src/workbench/browser/src/app/pages/extension/extension.service.ts @@ -1,30 +1,54 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { isElectron } from 'eo/shared/common/common'; +import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; import { lastValueFrom } from 'rxjs'; -import { ModuleInfo } from '../../utils/module-loader'; -import { EoExtensionInfo } from './extension.model'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types/index'; +import { TranslateService } from 'eo/platform/common/i18n'; +import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; -const HOST = 'http://106.12.149.147'; @Injectable() export class ExtensionService { ignoreList = ['default']; extensionIDs: Array = []; - localModules: Map; - constructor(private http: HttpClient) { - this.getInstalledList(); + HOST = ''; + localExtensions: Map; + constructor(private http: HttpClient, private electron: ElectronService, private language: LanguageService) { + this.localExtensions = this.getExtensions(); + this.extensionIDs = this.updateExtensionIDs(); + this.HOST = this.electron.isElectron + ? 'http://106.12.149.147' + : 'https://mockapi.eolink.com/ztBFKai20ee60c12871881565b5a6ddd718337df0e30979'; + } + private getExtensions() { + // Local extension + return window.eo?.getModules() || new Map(); } getInstalledList() { - this.localModules = window.eo?.getModules() || new Map(); - this.updateExtensionIDs(); + // Local extension exception for ignore list + return Array.from(this.localExtensions.values()).filter((it) => this.extensionIDs.includes(it.moduleID)); + } + private translateModule(module: ModuleInfo) { + const lang = this.language.systemLanguage; + const locale = module.i18n?.find((val) => val.locale === lang)?.package; + console.log(locale, module); + if (!locale) return module; + module = new TranslateService(module, locale).translate(); + return module; } public async requestList() { - return await lastValueFrom(this.http.get(`${HOST}/list`)); + let result: any = await lastValueFrom(this.http.get(`${this.HOST}/list?locale=${this.language.systemLanguage}`)); + result.data = [ + ...result.data, + //Local debug package + ...this.getInstalledList().filter((val) => result.data.every((childVal) => childVal.name !== val.name)), + ]; + result.data = result.data.map((module) => this.translateModule(module)); + return result; } async getDetail(id, name): Promise { let result = {}; - if (this.localModules.has(id)) { - Object.assign(result, this.localModules.get(id), { installed: true }); + if (this.localExtensions.has(id)) { + Object.assign(result, this.localExtensions.get(id), { installed: true }); } let { code, data }: any = await this.requestDetail(name); Object.assign(result, data); @@ -39,7 +63,7 @@ export class ExtensionService { console.log('Install module:', id); const { code, data, modules } = window.eo.installModule(id); if (code === 0) { - this.localModules = modules; + this.localExtensions = modules; this.updateExtensionIDs(); return true; } @@ -50,7 +74,7 @@ export class ExtensionService { console.log('Install module:', id); const { code, data, modules } = window.eo.uninstallModule(id); if (code === 0) { - this.localModules = modules; + this.localExtensions = modules; this.updateExtensionIDs(); return true; } @@ -58,10 +82,12 @@ export class ExtensionService { return false; } private async requestDetail(id) { - return await lastValueFrom(this.http.get(`${HOST}/detail/${id}`)); + return await lastValueFrom(this.http.get(`${this.HOST}/detail/${id}?locale=${this.language.systemLanguage}`)).catch( + (err) => [0, err] + ); } private updateExtensionIDs() { - this.extensionIDs = Array.from(this.localModules.keys()) + return Array.from(this.localExtensions.keys()) .filter((it) => it) .filter((it) => !this.ignoreList.includes(it)); } diff --git a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html index 1db01216..18466c95 100644 --- a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html +++ b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.html @@ -15,8 +15,8 @@ {{ it.description }}
- Installed + Installed
diff --git a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts index a7bb4946..d150b366 100644 --- a/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts +++ b/src/workbench/browser/src/app/pages/extension/list/extension-list.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { isElectron } from 'eo/shared/common/common'; +import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; import { Message, MessageService } from 'eo/workbench/browser/src/app/shared/services/message'; import { debounceTime, distinctUntilChanged, takeUntil, Subject } from 'rxjs'; import { ExtensionGroupType } from '../extension.model'; @@ -25,12 +25,12 @@ export class ExtensionListComponent implements OnInit { type: ExtensionGroupType = ExtensionGroupType.all; keyword = ''; renderList = []; - isElectron = isElectron(); seachChanged$: Subject = new Subject(); private destroy$: Subject = new Subject(); constructor( public extensionService: ExtensionService, + public electron:ElectronService, private route: ActivatedRoute, private router: Router, private messageService: MessageService @@ -46,11 +46,7 @@ export class ExtensionListComponent implements OnInit { } async searchPlugin(keyword = '') { if (this.type === 'installed') { - const installedList = new ExtensionList( - [...window.eo.getModules()] - .map((it) => it[1]) - .filter((it) => this.extensionService.extensionIDs.includes(it.moduleID)) - ); + const installedList = new ExtensionList(this.extensionService.getInstalledList()); return installedList.search(keyword); } const res: any = await this.extensionService.requestList(); diff --git a/src/workbench/browser/src/app/pages/pages.component.html b/src/workbench/browser/src/app/pages/pages.component.html index 1fe2b581..d966e2ec 100644 --- a/src/workbench/browser/src/app/pages/pages.component.html +++ b/src/workbench/browser/src/app/pages/pages.component.html @@ -1,6 +1,6 @@ -
-
+
+
Current data storage exists{{ dataSourceText }},please switch if you want to collaborate {{ isRemote ? 'Remote Server' : 'Localhost' }} Data Storage diff --git a/src/workbench/browser/src/app/pages/pages.component.ts b/src/workbench/browser/src/app/pages/pages.component.ts index e217d975..44e105e9 100644 --- a/src/workbench/browser/src/app/pages/pages.component.ts +++ b/src/workbench/browser/src/app/pages/pages.component.ts @@ -4,9 +4,9 @@ import { SidebarService } from 'eo/workbench/browser/src/app/shared/components/s import { Message } from 'eo/workbench/browser/src/app/shared/services/message/message.model'; import { MessageService } from 'eo/workbench/browser/src/app/shared/services/message/message.service'; import { Subject, takeUntil, debounceTime } from 'rxjs'; -import { isElectron } from 'eo/shared/common/common'; import { RemoteService } from 'eo/workbench/browser/src/app/shared/services/remote/remote.service'; import { IS_SHOW_REMOTE_SERVER_NOTIFICATION } from 'eo/workbench/browser/src/app/shared/services/storage/storage.service'; +import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; @Component({ selector: 'eo-pages', @@ -19,7 +19,6 @@ export class PagesComponent implements OnInit { get isRemote() { return this.remoteService.isRemote; } - isElectron = isElectron(); isShow = localStorage.getItem(IS_SHOW_REMOTE_SERVER_NOTIFICATION) === 'true'; get dataSourceText() { return this.remoteService.dataSourceText; @@ -34,7 +33,8 @@ export class PagesComponent implements OnInit { private cdRef: ChangeDetectorRef, public sidebar: SidebarService, private messageService: MessageService, - private remoteService: RemoteService + private remoteService: RemoteService, + public electron:ElectronService ) { this.rawChange$.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => { this.updateState(); diff --git a/src/workbench/browser/src/app/shared/components/export-api/export-api.component.ts b/src/workbench/browser/src/app/shared/components/export-api/export-api.component.ts index 9a2f080a..6cc9ac8c 100644 --- a/src/workbench/browser/src/app/shared/components/export-api/export-api.component.ts +++ b/src/workbench/browser/src/app/shared/components/export-api/export-api.component.ts @@ -3,6 +3,7 @@ import { StorageService } from '../../../shared/services/storage'; import { StorageRes, StorageResStatus } from '../../services/storage/index.model'; import packageJson from '../../../../../../../../package.json'; import { FeatureType } from '../../types'; +import { ModuleInfo } from 'eo/platform/node/extension-manager'; @Component({ selector: 'eo-export-api', @@ -67,19 +68,14 @@ export class ExportApiComponent implements OnInit { const feature = this.featureMap.get(this.currentExtension); const action = feature.action || null; const filename = feature.filename || null; - const module = window.eo.loadFeatureModule(this.currentExtension); + const module: ModuleInfo = window.eo.loadFeatureModule(this.currentExtension); if (action && filename && module && module[action] && typeof module[action] === 'function') { this.storage.run('projectExport', [], (result: StorageRes) => { if (result.status === StorageResStatus.success) { result.data.version = packageJson.version; - try { - const output = module[action](result || {}); - this.transferTextToFile(filename, output); - callback(true); - } catch (e) { - console.log(e); - callback(false); - } + const output = module[action](result || {}); + this.transferTextToFile(filename, output); + callback(true); } else { callback(false); } diff --git a/src/workbench/browser/src/app/shared/components/setting/common/language-swtcher.component.ts b/src/workbench/browser/src/app/shared/components/setting/common/language-swtcher.component.ts index eaeba4bb..e151ccfb 100644 --- a/src/workbench/browser/src/app/shared/components/setting/common/language-swtcher.component.ts +++ b/src/workbench/browser/src/app/shared/components/setting/common/language-swtcher.component.ts @@ -1,6 +1,5 @@ import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core'; -import { ElectronService } from 'eo/workbench/browser/src/app/core/services'; -import { NzModalService } from 'ng-zorro-antd/modal'; +import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service'; @Component({ selector: 'eo-language-switcher', @@ -13,7 +12,12 @@ import { NzModalService } from 'ng-zorro-antd/modal'; (ngModelChange)="handleChange($event)" [nzCustomTemplate]="defaultTemplate" > - + {{ item.name }} @@ -34,40 +38,15 @@ import { NzModalService } from 'ng-zorro-antd/modal'; export class LanguageSwticherComponent implements OnInit { @Input() model: object = {}; @Output() modelChange: EventEmitter = new EventEmitter(); - languages = [ - { - name: 'English', - value: 'en-US', - path: 'en', - }, - { - name: '简体中文', - value: 'zh-Hans', - path: 'zh', - }, - ]; - constructor(private modal: NzModalService, private electron: ElectronService) {} + constructor(public languageService: LanguageService) {} ngOnInit(): void { - this.model['eoapi-language'] ??= navigator.language.includes('zh') ? 'zh-Hans' : 'en-US'; + this.model['eoapi-language'] = this.languageService.systemLanguage; } - handleChange(inputLocaleID) { - let changeCallback = (localeID) => { - this.model['eoapi-language'] = localeID; - this.modelChange.emit(this.model); - window.location.href = `/${(this.languages.find((val) => val.value === localeID) || this.languages[0]).path}`; - }; - // if (this.electron.isElectron) { - // this.modal.warning({ - // nzTitle: ``, - // nzContent:`Eoapi will need to restart after you switch the app language to ${this.languages.find(val=>val.value===inputLocaleID).name}`, - // nzOnOk: () => { - // changeCallback(inputLocaleID); - // }, - // }); - // } else { - changeCallback(inputLocaleID); - // } + handleChange(localeID) { + this.model['eoapi-language'] = localeID; + this.modelChange.emit(this.model); + this.languageService.changeLanguage(localeID); } } diff --git a/src/workbench/browser/src/app/shared/components/sidebar/sidebar.service.ts b/src/workbench/browser/src/app/shared/components/sidebar/sidebar.service.ts index 10b6f169..c504a80d 100644 --- a/src/workbench/browser/src/app/shared/components/sidebar/sidebar.service.ts +++ b/src/workbench/browser/src/app/shared/components/sidebar/sidebar.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; -import { ModuleInfo } from '../../../utils/module-loader'; +import { ModuleInfo } from 'eo/platform/node/extension-manager/types/index'; import { SidebarModuleInfo } from './sidebar.model'; @Injectable({ diff --git a/src/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service.ts b/src/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service.ts new file mode 100644 index 00000000..e9d83f98 --- /dev/null +++ b/src/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service.ts @@ -0,0 +1,90 @@ +import { Injectable, Inject, LOCALE_ID } from '@angular/core'; + +import { TestServer } from '../test-server.model'; +import { eoFormatRequestData, eoFormatResponseData } from '../api-test.utils'; +@Injectable() +export class TestServerRemoteService implements TestServer { + receiveMessage: (message) => void; + xhrByTabID = {}; + constructor(@Inject(LOCALE_ID) private locale: string) {} + init(receiveMessage: (message) => void) { + this.receiveMessage = receiveMessage; + } + send(module, message) { + switch (message.action) { + case 'ajax': { + this.xhrByTabID[message.id] = this.ajax(message); + break; + } + default: { + this.xhrByTabID[message.id].abort(); + } + } + if (message.action !== 'ajax') return; + } + ajax(message) { + const xhr = new XMLHttpRequest(); + const url = `${window.location.protocol}//${window.location.hostname}:4201/api/unit`; + console.log(url) + xhr.open('POST', url); + xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); + xhr.onreadystatechange = (e) => { + if (xhr.readyState === XMLHttpRequest.DONE) { + if (xhr.status === 200) { + this.receiveMessage(this.formatResponseData(JSON.parse(xhr.responseText).data)); + } else { + this.receiveMessage({ + id: message.id, + general: { redirectTimes: 0, downloadSize: 0, downloadRate: 0, time: '0.00ms' }, + response: { + statusCode: 0, + headers: [], + testDeny: '0.00', + responseLength: 0, + responseType: 'text', + reportList: [], + body: $localize`Test service connection failed, please submit Issue contact community`, + }, + report: { + request: { + requestHeaders: [{ name: 'Content-Type', value: 'application/json' }], + requestBodyType: 'raw', + requestBody: '{}', + }, + }, + history: { + request: { + uri: 'http:///', + method: 'POST', + protocol: 'http', + requestHeaders: [{ name: 'Content-Type', value: 'application/json' }], + requestBodyJsonType: 'object', + requestBodyType: 'raw', + requestBody: '{}', + }, + }, + }); + } + } + }; + xhr.send(JSON.stringify(message)); + return xhr; + } + close() {} + /** + * Format UI Request Data To Server Request Data + * + * @param input + */ + formatRequestData(data, opts = { env: {} }) { + return eoFormatRequestData(data, opts, this.locale); + } + /** + * Format TestResult to TestData + * @param {object} report test result after test finish + * @param {object} history storage test history + */ + formatResponseData(data) { + return eoFormatResponseData(data); + } +} diff --git a/src/workbench/browser/src/app/shared/services/api-test/serverless-node/test-connect.service.ts b/src/workbench/browser/src/app/shared/services/api-test/serverless-node/test-connect.service.ts index 1bfd1c61..d2598f2c 100644 --- a/src/workbench/browser/src/app/shared/services/api-test/serverless-node/test-connect.service.ts +++ b/src/workbench/browser/src/app/shared/services/api-test/serverless-node/test-connect.service.ts @@ -3,6 +3,9 @@ import { Injectable, Inject, LOCALE_ID } from '@angular/core'; import { TestServer } from '../test-server.model'; import { eoFormatRequestData, eoFormatResponseData } from '../api-test.utils'; @Injectable() +/** + * Vercel serverless api + */ export class TestServerServerlessService implements TestServer { receiveMessage: (message) => void; xhrByTabID = {}; diff --git a/src/workbench/browser/src/app/shared/services/api-test/test-server.service.ts b/src/workbench/browser/src/app/shared/services/api-test/test-server.service.ts index d7d2de9c..255c6e35 100644 --- a/src/workbench/browser/src/app/shared/services/api-test/test-server.service.ts +++ b/src/workbench/browser/src/app/shared/services/api-test/test-server.service.ts @@ -2,17 +2,26 @@ import { Injectable } from '@angular/core'; import { TestServerLocalNodeService } from './local-node/test-connect.service'; import { TestServerServerlessService } from './serverless-node/test-connect.service'; import { ElectronService } from '../../../core/services'; +import { TestServerRemoteService } from 'eo/workbench/browser/src/app/shared/services/api-test/remote-node/test-connect.service'; @Injectable() export class TestServerService { isElectron = true; - constructor(private electron: ElectronService, private localNode: TestServerLocalNodeService,private sassNode:TestServerServerlessService) { + constructor( + private electron: ElectronService, + private remoteNode: TestServerRemoteService, + private localNode: TestServerLocalNodeService, + private serverlessNode: TestServerServerlessService + ) { this.isElectron = this.electron.isElectron; } get instance() { + let isVercel = window.location.href.includes('vercel'); if (this.isElectron) { return this.localNode; + } else if (!isVercel) { + return this.remoteNode; } else { - return this.sassNode; + return this.serverlessNode; } } } diff --git a/src/workbench/browser/src/app/shared/services/remote/remote.service.ts b/src/workbench/browser/src/app/shared/services/remote/remote.service.ts index d1a9169a..bafd63ea 100644 --- a/src/workbench/browser/src/app/shared/services/remote/remote.service.ts +++ b/src/workbench/browser/src/app/shared/services/remote/remote.service.ts @@ -120,6 +120,43 @@ export class RemoteService { this.storageService.toggleDataSource({ dataSourceType: 'http' }); } + getSettings() { + try { + return JSON.parse(localStorage.getItem('localSettings') || '{}'); + } catch (error) { + return {}; + } + } + + /** + * Get the value of the corresponding configuration according to the key path + * + * @param key + * @returns + */ + getConfiguration = (keyPath: string) => { + const localSettings = this.getSettings(); + if (Reflect.has(localSettings, keyPath)) { + return Reflect.get(localSettings, keyPath); + } + + const keys = Object.keys(localSettings); + const filterKeys = keys.filter((n) => n.startsWith(keyPath)); + if (filterKeys.length) { + return filterKeys.reduce((pb, ck) => { + const keyArr = ck.replace(`${keyPath}.`, '').split('.'); + const targetKey = keyArr.pop(); + const target = keyArr.reduce((p, v) => { + p[v] ??= {}; + return p[v]; + }, pb); + target[targetKey] = localSettings[ck]; + return pb; + }, {}); + } + return undefined; + }; + /** * switch data */ diff --git a/src/workbench/browser/src/app/shared/services/storage/IndexedDB/lib/index.ts b/src/workbench/browser/src/app/shared/services/storage/IndexedDB/lib/index.ts index 5edffe09..34779f13 100644 --- a/src/workbench/browser/src/app/shared/services/storage/IndexedDB/lib/index.ts +++ b/src/workbench/browser/src/app/shared/services/storage/IndexedDB/lib/index.ts @@ -23,7 +23,6 @@ export type ResultType = { }; let isFirstLoad = true; - const getApiUrl = (apiData: ApiData) => { const dataSourceType: DataSourceType = getSettings()?.['eoapi-common.dataStorage'] ?? 'local'; diff --git a/src/workbench/browser/src/app/utils/module-loader/index.ts b/src/workbench/browser/src/app/utils/module-loader/index.ts deleted file mode 100644 index 1eb4aa70..00000000 --- a/src/workbench/browser/src/app/utils/module-loader/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './loader'; -export * from './type'; diff --git a/src/workbench/browser/src/app/utils/module-loader/loader.ts b/src/workbench/browser/src/app/utils/module-loader/loader.ts deleted file mode 100644 index b1d78883..00000000 --- a/src/workbench/browser/src/app/utils/module-loader/loader.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { ModuleRuntime, ModuleType, ModuleInfo, ModuleLoaderInterface } from './type'; - -/** - * 模块加载类 - * 根据运行环境加载模块 - */ -export class ModuleLoader implements ModuleLoaderInterface { - /** - * 模块运行时环境 - */ - private readonly runtime: ModuleRuntime; - - /** - * 模块加载方法 - */ - private readonly moduleRequire: any; - - constructor(_runtime: ModuleRuntime, _moduleRequire?: any) { - this.runtime = _runtime; - this.moduleRequire = _moduleRequire || require; - } - - /** - * 批量加载模块 - * @param modules - */ - loadModules(modules: Array): void { - modules.forEach((module: ModuleInfo) => { - this.loadModule(module); - }) - } - - /** - * 实际加载模块并运行 - * 需要检查模块的类型与运行环境匹配 - * main运行环境只能加载system和app模块 - * render运行环境只能加载ui和feature模块 - * web运行环境只能加载web支持的模块 - * @param module ModuleInfo - */ - loadModule(module: ModuleInfo): void { - console.log(module); - if ((this.runtime === ModuleRuntime.main && ![ModuleType.system, ModuleType.app].indexOf(module.type)) - || (this.runtime === ModuleRuntime.render && ![ModuleType.ui, ModuleType.feature].indexOf(module.type)) - || (this.runtime === ModuleRuntime.web && !module.web)) { - console.log(`The [${module.type}] module [${module.name}] can not run in runtime [${this.runtime}].`); - return; - } - if (this.runtime === ModuleRuntime.main) { - console.log('load from main'); - const _module = this.moduleRequire(module.baseDir)(); - console.log(_module); - } else if (this.runtime === ModuleRuntime.render) { - console.log('load from render'); - const _module = this.moduleRequire(module.baseDir)(); - console.log(_module); - } else if (this.runtime === ModuleRuntime.web) { - console.log('load from web'); - // todo with script src - } - // 加入hooks列表 - } -} diff --git a/src/workbench/browser/src/locale/messages.zh.xlf b/src/workbench/browser/src/locale/messages.zh.xlf index b2aee85b..bad1e93b 100644 --- a/src/workbench/browser/src/locale/messages.zh.xlf +++ b/src/workbench/browser/src/locale/messages.zh.xlf @@ -1365,7 +1365,7 @@ src/app/pages/extension/detail/extension-detail.component.html 64 - 帮助 + 支持 Author diff --git a/src/workbench/browser/src/main.ts b/src/workbench/browser/src/main.ts index f65f6c82..bc877113 100644 --- a/src/workbench/browser/src/main.ts +++ b/src/workbench/browser/src/main.ts @@ -7,7 +7,6 @@ import { APP_CONFIG } from './environments/environment'; if (APP_CONFIG.production) { enableProdMode(); } - platformBrowserDynamic() .bootstrapModule(AppModule, {}) .catch((err) => console.error(err)); diff --git a/src/workbench/node/README.md b/src/workbench/node/README.md new file mode 100644 index 00000000..c91ccb59 --- /dev/null +++ b/src/workbench/node/README.md @@ -0,0 +1 @@ +# Node Test server \ No newline at end of file diff --git a/src/workbench/node/electron/main.ts b/src/workbench/node/electron/main.ts new file mode 100644 index 00000000..2ac02100 --- /dev/null +++ b/src/workbench/node/electron/main.ts @@ -0,0 +1,27 @@ +import { ipcMain } from 'electron'; +import { UnitWorker } from 'eo/workbench/node/electron/unitWorker'; +/** + * Electron Test use Ipc to communicate + */ +export const UnitWorkerModule = { + works: {}, + setup(eo: any) { + ipcMain.removeAllListeners('unitTest'); + ipcMain.on('unitTest', function (event, message) { + const id = message.id; + switch (message.action) { + case 'ajax': { + UnitWorkerModule.works[id] = new UnitWorker(eo.view); + UnitWorkerModule.works[id].start(message); + break; + } + case 'abort': { + UnitWorkerModule.works[id].kill(); + break; + } + } + }); + }, +}; + + diff --git a/src/workbench/node/electron/unitWorker.ts b/src/workbench/node/electron/unitWorker.ts new file mode 100644 index 00000000..d8732662 --- /dev/null +++ b/src/workbench/node/electron/unitWorker.ts @@ -0,0 +1,25 @@ +import { BrowserView } from 'electron'; +import _LibsFlowCommon from '../request/unit'; +import _LibsCommon from '../request/libs/common'; +export class UnitWorker { + view: BrowserView; + constructor(view: BrowserView) { + this.view = view; + } + async start(message: any) { + message.data.env = _LibsCommon.parseEnv(message.data.env); + await new _LibsFlowCommon.core().main(message.data).then(({ report, history }) => { + ['general', 'requestInfo', 'resultInfo'].forEach((keyName) => { + if (typeof history[keyName] === 'string') history[keyName] = JSON.parse(history[keyName]); + }); + this.finish({ + id: message.id, + report: report, + history: history, + }); + }); + } + finish(message: any) { + this.view.webContents.send('unitTest', message); + } +} diff --git a/src/workbench/node/request/main.js b/src/workbench/node/request/main.js deleted file mode 100644 index ac976eab..00000000 --- a/src/workbench/node/request/main.js +++ /dev/null @@ -1,24 +0,0 @@ -let _LibsFlowCommon = require('./unit.js'); -let _LibsCommon = require('./libs/common.js'); -process.on('message', (message) => { - switch (message.action) { - case 'ajax': { - message.data.env = _LibsCommon.parseEnv(message.data.env); - new _LibsFlowCommon.core().main(message.data, (tmpInputReport, tmpInputHistory) => { - ['general', 'requestInfo', 'resultInfo'].forEach((keyName) => { - if (typeof tmpInputHistory[keyName] === 'string') - tmpInputHistory[keyName] = JSON.parse(tmpInputHistory[keyName]); - }); - process.send({ - action: 'finish', - data: { - id: message.id, - report: tmpInputReport, - history: tmpInputHistory, - }, - }); - }); - break; - } - } -}); diff --git a/src/workbench/node/request/unit.js b/src/workbench/node/request/unit.js index 42712c41..751cd6d6 100644 --- a/src/workbench/node/request/unit.js +++ b/src/workbench/node/request/unit.js @@ -1,3 +1,5 @@ +const { resolve } = require('path'); + (function () { 'use strict'; var url = require('url'), @@ -680,146 +682,150 @@ } }); } - main(inputTestData, callback) { + main(inputTestData) { let unitCommonClass = this; - async function main() { - let template = { - ajax: {}, - status: 'finish', - }, - tmpDecorateObj, - tmpReportData = { - afterInject: inputTestData.afterInject, - beforeInject: inputTestData.beforeInject, - }; - try { - inputTestData.globalHeader = inputTestData.globalHeader || {}; - await privateFun.parseTestData(inputTestData, inputTestData.env || {}).then((tmpInputData) => { - tmpDecorateObj = tmpInputData; - }); - switch (tmpDecorateObj.status) { - case 'preCode error': { - template.ajax = { - status: 'error', - errorReason: tmpDecorateObj.content, - reportList: tmpDecorateObj.reportList, - general: { - time: '0.00ms', - }, - }; - break; - } - default: { - tmpReportData.requestInfo = { - messageSeparatorSetting: inputTestData.messageSeparatorSetting, - params: [], - apiProtocol: '0', - URL: tmpDecorateObj.history.uri, - headers: [], - methodType: inputTestData.methodType, - method: inputTestData.method, - }; - if (tmpDecorateObj.requestType === '4') { - tmpReportData.requestInfo.requestType = '2'; - delete tmpReportData.requestInfo.params; - } else { - switch (typeof tmpDecorateObj.history.body) { - case 'object': { - tmpReportData.requestInfo.requestType = '0'; - for (let key in tmpDecorateObj.history.body) { - switch (typeof tmpDecorateObj.history.body[key]) { - case 'object': { - for (let childKey in tmpDecorateObj.history.body[key]) { + return new Promise((resolve, reject) => { + async function main() { + let template = { + ajax: {}, + status: 'finish', + }, + tmpDecorateObj, + tmpReportData = { + afterInject: inputTestData.afterInject, + beforeInject: inputTestData.beforeInject, + }; + try { + inputTestData.globalHeader = inputTestData.globalHeader || {}; + await privateFun.parseTestData(inputTestData, inputTestData.env || {}).then((tmpInputData) => { + tmpDecorateObj = tmpInputData; + }); + switch (tmpDecorateObj.status) { + case 'preCode error': { + template.ajax = { + status: 'error', + errorReason: tmpDecorateObj.content, + reportList: tmpDecorateObj.reportList, + general: { + time: '0.00ms', + }, + }; + break; + } + default: { + tmpReportData.requestInfo = { + messageSeparatorSetting: inputTestData.messageSeparatorSetting, + params: [], + apiProtocol: '0', + URL: tmpDecorateObj.history.uri, + headers: [], + methodType: inputTestData.methodType, + method: inputTestData.method, + }; + if (tmpDecorateObj.requestType === '4') { + tmpReportData.requestInfo.requestType = '2'; + delete tmpReportData.requestInfo.params; + } else { + switch (typeof tmpDecorateObj.history.body) { + case 'object': { + tmpReportData.requestInfo.requestType = '0'; + for (let key in tmpDecorateObj.history.body) { + switch (typeof tmpDecorateObj.history.body[key]) { + case 'object': { + for (let childKey in tmpDecorateObj.history.body[key]) { + tmpReportData.requestInfo.params.push({ + key: key, + value: + typeof tmpDecorateObj.history.body[key][childKey] == 'string' + ? tmpDecorateObj.history.body[key][childKey] + : '[file]', + }); + if (typeof tmpDecorateObj.history.body[key][childKey] != 'string') break; + } + break; + } + default: { tmpReportData.requestInfo.params.push({ key: key, - value: - typeof tmpDecorateObj.history.body[key][childKey] == 'string' - ? tmpDecorateObj.history.body[key][childKey] - : '[file]', + value: tmpDecorateObj.history.body[key], }); - if (typeof tmpDecorateObj.history.body[key][childKey] != 'string') break; + break; } - break; - } - default: { - tmpReportData.requestInfo.params.push({ - key: key, - value: tmpDecorateObj.history.body[key], - }); - break; } } + break; } - break; - } - default: { - tmpReportData.requestInfo.requestType = '1'; - tmpReportData.requestInfo.params = tmpDecorateObj.history.body; - break; - } - } - } - for (let key in tmpDecorateObj.history.headers) { - tmpReportData.requestInfo.headers.push({ - name: key, - value: tmpDecorateObj.history.headers[key], - }); - } - let tmpIsOversized, - tmpRequestBodyStr = - typeof tmpReportData.requestInfo.params === 'object' - ? JSON.stringify(tmpReportData.requestInfo.params) - : tmpReportData.requestInfo.params; - if ((tmpRequestBodyStr || '').length > CONFIG.REQUEST_BODY_LIMIT_STORAGE_LENGTH) { - tmpReportData.requestInfo.requestType = 'oversized'; - tmpReportData.requestInfo.params = ''; - tmpIsOversized = true; - } - tmpReportData.requestInfo = JSON.stringify(tmpReportData.requestInfo); - await unitCommonClass.ajax( - tmpDecorateObj, - { - requestData: _LibsCommon.parseRequestDataToObj(tmpDecorateObj), - globalHeader: inputTestData.globalHeader, - pckSplitByHeader: inputTestData.messageSeparatorSetting === 'spliceLength', - messageEncoding: inputTestData.messageEncoding, - }, - function (res) { - template.ajax = res; - if (res.status != 'abort') { - let tmpHistoryResponse = Object.assign({}, res.response); - tmpHistoryResponse.reportList = res.reportList; - // if (tmpHistoryResponse.responseType !== 'text') delete tmpHistoryResponse.body; - tmpReportData.general = JSON.stringify(res.general); - tmpReportData.resultInfo = JSON.stringify(tmpHistoryResponse); - template.ajax.request.body = tmpDecorateObj.binaryFileName || tmpDecorateObj.requestBody.body; - if (tmpIsOversized) { - template.ajax.request.requestType = 'oversized'; - } else { - template.ajax.request.requestType = - tmpDecorateObj.requestType === '4' - ? '1' - : typeof tmpDecorateObj.requestBody.body == 'object' - ? '0' - : '1'; + default: { + tmpReportData.requestInfo.requestType = '1'; + tmpReportData.requestInfo.params = tmpDecorateObj.history.body; + break; } } } - ); - break; + for (let key in tmpDecorateObj.history.headers) { + tmpReportData.requestInfo.headers.push({ + name: key, + value: tmpDecorateObj.history.headers[key], + }); + } + let tmpIsOversized, + tmpRequestBodyStr = + typeof tmpReportData.requestInfo.params === 'object' + ? JSON.stringify(tmpReportData.requestInfo.params) + : tmpReportData.requestInfo.params; + if ((tmpRequestBodyStr || '').length > CONFIG.REQUEST_BODY_LIMIT_STORAGE_LENGTH) { + tmpReportData.requestInfo.requestType = 'oversized'; + tmpReportData.requestInfo.params = ''; + tmpIsOversized = true; + } + tmpReportData.requestInfo = JSON.stringify(tmpReportData.requestInfo); + await unitCommonClass.ajax( + tmpDecorateObj, + { + requestData: _LibsCommon.parseRequestDataToObj(tmpDecorateObj), + globalHeader: inputTestData.globalHeader, + pckSplitByHeader: inputTestData.messageSeparatorSetting === 'spliceLength', + messageEncoding: inputTestData.messageEncoding, + }, + function (res) { + template.ajax = res; + if (res.status != 'abort') { + let tmpHistoryResponse = Object.assign({}, res.response); + tmpHistoryResponse.reportList = res.reportList; + // if (tmpHistoryResponse.responseType !== 'text') delete tmpHistoryResponse.body; + tmpReportData.general = JSON.stringify(res.general); + tmpReportData.resultInfo = JSON.stringify(tmpHistoryResponse); + template.ajax.request.body = tmpDecorateObj.binaryFileName || tmpDecorateObj.requestBody.body; + if (tmpIsOversized) { + template.ajax.request.requestType = 'oversized'; + } else { + template.ajax.request.requestType = + tmpDecorateObj.requestType === '4' + ? '1' + : typeof tmpDecorateObj.requestBody.body == 'object' + ? '0' + : '1'; + } + } + } + ); + break; + } } + resolve({ + report: template.ajax, + history: tmpReportData, + }); + } catch (e) { + resolve({ + report: template.ajax, + history: tmpReportData, + }); + console.error(new Date() + ':unit/common.js 336:', e); } - if (callback) { - callback(template.ajax, tmpReportData); - } - } catch (e) { - if (callback) { - callback(template.ajax, tmpReportData); - } - console.error(new Date() + ':unit/common.js 336:', e); } - } - main(); + main(); + }); } abort() { this.areadyAbortXhr = true; diff --git a/src/workbench/node/server/README.md b/src/workbench/node/server/README.md new file mode 100644 index 00000000..a8b6438c --- /dev/null +++ b/src/workbench/node/server/README.md @@ -0,0 +1,12 @@ +# eo-test-server + +Recieve eoapi tes config and response http result + +> This service does not automatically install dependencies,please install it manually + +# Command + +dev/star +``` +yarn start +``` \ No newline at end of file diff --git a/src/workbench/node/server/main.js b/src/workbench/node/server/main.js new file mode 100644 index 00000000..ea907469 --- /dev/null +++ b/src/workbench/node/server/main.js @@ -0,0 +1,46 @@ +/** + * Web Test use Ipc to communicate + */ + +const _LibsFlowCommon = require('../request/unit.js'); +const _LibsCommon = require('../request/libs/common.js'); +// Koa reliance +const koaBody = require('koa-body'); +const Koa = require('koa'); +const cors = require('@koa/cors'); + +const app = new Koa(); +const port = 4201; + +app.use(cors()); +app.use(koaBody()); + +app.use(async (ctx, next) => { + if (ctx.method !== 'POST') { + ctx.body = 'Hello World'; + return; + } + switch (ctx.url) { + case '/api/unit': { + let reqJSON = ctx.request.body.data; + reqJSON.env = _LibsCommon.parseEnv(reqJSON.env); + await new _LibsFlowCommon.core().main(reqJSON).then(({ report, history }) => { + ['general', 'requestInfo', 'resultInfo'].forEach((keyName) => { + if (typeof history[keyName] === 'string') history[keyName] = JSON.parse(history[keyName]); + }); + ctx.body = JSON.stringify({ + action: 'finish', + data: { + id: ctx.request.body.id, + report: report, + history: history, + }, + }); + }); + break; + } + } + next(); +}); + +app.listen(port); diff --git a/src/workbench/node/server/package.json b/src/workbench/node/server/package.json new file mode 100644 index 00000000..a856d573 --- /dev/null +++ b/src/workbench/node/server/package.json @@ -0,0 +1,17 @@ +{ + "name": "eo-test-server", + "version": "1.0.0", + "description": "Recieve eoapi tes config and response http result", + "main": "main.js", + "scripts": { + "start": "node main", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "eoapi", + "license": "ISC", + "dependencies": { + "@koa/cors": "3.3.0", + "koa": "2.13.4", + "koa-body": "5.0.0" + } +} diff --git a/src/workbench/node/server/yarn.lock b/src/workbench/node/server/yarn.lock new file mode 100644 index 00000000..e386ec6c --- /dev/null +++ b/src/workbench/node/server/yarn.lock @@ -0,0 +1,461 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@koa/cors@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.3.0.tgz#b4c1c7ee303b7c968c8727f2a638a74675b50bb2" + integrity sha512-lzlkqLlL5Ond8jb6JLnVVDmD2OPym0r5kvZlMgAWiS9xle+Q5ulw1T358oW+RVguxUkANquZQz82i/STIRmsqQ== + dependencies: + vary "^1.1.2" + +"@types/formidable@^2.0.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/formidable/-/formidable-2.0.5.tgz#e54e31d242ef750ac2d05aa163fa0274c8e6ef9c" + integrity sha512-uvMcdn/KK3maPOaVUAc3HEYbCEhjaGFwww4EsX6IJfWIJ1tzHtDHczuImH3GKdusPnAAmzB07St90uabZeCKPA== + dependencies: + "@types/node" "*" + +"@types/node@*": + version "18.0.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.3.tgz#463fc47f13ec0688a33aec75d078a0541a447199" + integrity sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ== + +accepts@^1.3.5: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cache-content-type@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" + integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA== + dependencies: + mime-types "^2.1.18" + ylru "^1.2.0" + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +co-body@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124" + integrity sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ== + dependencies: + inflation "^2.0.0" + qs "^6.4.0" + raw-body "^2.2.0" + type-is "^1.6.14" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +content-disposition@~0.5.2: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookies@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" + integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + +debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0, depd@^2.0.0, depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +dezalgo@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha512-K7i4zNfT2kgQz3GylDw40ot9GAE47sFZ9EXHFSPP6zONLgH6kWXE0KWJchkbQJLBkRazq4APwZ4OwiFFlT95OQ== + dependencies: + asap "^2.0.0" + wrappy "1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +encodeurl@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +formidable@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff" + integrity sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ== + dependencies: + dezalgo "1.0.3" + hexoid "1.0.0" + once "1.4.0" + qs "6.9.3" + +fresh@~0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-intrinsic@^1.0.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hexoid@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" + integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== + +http-assert@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.5.0.tgz#c389ccd87ac16ed2dfa6246fd73b926aa00e6b8f" + integrity sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w== + dependencies: + deep-equal "~1.0.1" + http-errors "~1.8.0" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@^1.6.3, http-errors@~1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inflation@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" + integrity sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw== + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +keygrip@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" + integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== + dependencies: + tsscmp "1.0.6" + +koa-body@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-5.0.0.tgz#d310372bea09a24ccc450c76ca142ee55395dda6" + integrity sha512-nHwEODrQGiyKBILCWO8QSS40C87cKr2cp3y/Cw8u9Z8w5t0CdSkGm3+y9WK5BIAlPpo9tTw5RtSbxpVyG79vmw== + dependencies: + "@types/formidable" "^2.0.4" + co-body "^5.1.1" + formidable "^2.0.1" + +koa-compose@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" + integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw== + +koa-convert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-2.0.0.tgz#86a0c44d81d40551bae22fee6709904573eea4f5" + integrity sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA== + dependencies: + co "^4.6.0" + koa-compose "^4.1.0" + +koa@2.13.4: + version "2.13.4" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e" + integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.8.0" + debug "^4.3.2" + delegates "^1.0.0" + depd "^2.0.0" + destroy "^1.0.4" + encodeurl "^1.0.2" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^2.0.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.18, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +on-finished@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +only@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" + integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ== + +parseurl@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +qs@6.9.3: + version "6.9.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" + integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== + +qs@^6.4.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +raw-body@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.5.0 < 2", statuses@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tsscmp@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + +type-is@^1.6.14, type-is@^1.6.16: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +vary@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ylru@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.3.2.tgz#0de48017473275a4cbdfc83a1eaf67c01af8a785" + integrity sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA== diff --git a/src/workbench/node/unitWorker.ts b/src/workbench/node/unitWorker.ts deleted file mode 100644 index c8386f68..00000000 --- a/src/workbench/node/unitWorker.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as child_process from 'child_process'; -import { BrowserView, ipcMain } from 'electron'; - -class UnitWorker { - instance: child_process.ChildProcess; - view: BrowserView; - constructor(view: BrowserView) { - this.view = view; - } - start(message: any) { - this.instance = child_process.fork(`${__dirname}/request/main.js`); - this.watch(); - this.instance.send(message); - } - finish(message: any) { - this.view.webContents.send('unitTest', message); - this.kill(); - } - kill() { - this.instance.kill(); - } - private watch() { - this.instance.on('message', (message: any) => { - switch (message.action) { - case 'finish': { - this.finish(message.data); - break; - } - } - }); - } -} - -export const UnitWorkerModule = { - works: {}, - setup(eo: any) { - ipcMain.removeAllListeners('unitTest'); - ipcMain.on('unitTest', function (event, message) { - const id = message.id; - switch (message.action) { - case 'ajax': { - UnitWorkerModule.works[id] = new UnitWorker(eo.view); - UnitWorkerModule.works[id].start(message); - break; - } - case 'abort': { - UnitWorkerModule.works[id].kill(); - break; - } - } - }); - } -}; diff --git a/upload.js b/upload.js deleted file mode 100644 index b8feda97..00000000 --- a/upload.js +++ /dev/null @@ -1,99 +0,0 @@ -const qiniu = require('qiniu'); -const YAML = require('yaml'); -const fs = require('fs'); -const { AK, SK, bucket } = require('./qiniu_env.js'); -const package = require('./package.json'); - -qiniu.conf.ACCESS_KEY = AK; -qiniu.conf.SECRET_KEY = SK; - -// * 构建上传策略函数 -const uptoken = (bucket, key) => new qiniu.rs.PutPolicy(bucket + ':' + key).token(); - -const toLatest = (name) => name.replace(/\d+\.\d+\.\d+/, 'latest'); -const onlyName = (name) => name.replace(/release\//, ''); - -// * 构建客户端实例 -const client = new qiniu.rs.Client(); - -// * 上传单个文件 -const uploadFile = (token, file, localFile) => - new Promise((resolve) => { - const extra = new qiniu.io.PutExtra(); - qiniu.io.putFile(token, file, localFile, extra, (err) => { - console.log(err ? err : 'success'); - return err ? resolve(false) : resolve(true); - }); - }); - -// * 删除单个文件 -const removeFile = (spaceName, file) => - new Promise((resolve) => { - client.remove(spaceName, file, (err, ret) => { - return err ? resolve(false) : resolve(true); - }); - }); - -// * 拷贝单个文件 -const cpFile = (fromFile, toFile) => - new Promise((resolve) => { - client.copy(bucket, fromFile, bucket, toFile, (err) => { - return err ? resolve(false) : resolve(true); - }); - }); - -const version = package.version; -const fileList = [ - 'release/eoapi Setup ?.exe', - 'release/eoapi-?.dmg', - 'release/eoapi-?-arm64.dmg', - 'release/eoapi-?-mac.zip', - 'release/latest.yml', - 'release/latest-mac.yml', -].map((it) => it.replace(/\?/, `${version}`)); -// const fileList = ['releass/eoapi-Setup-?.png', 'releass/eoapi-?.png', 'releass/eoapi-?-arm64.png'].map((it) => -// it.replace(/\?/, `${version}`) -// ); - -const app = async () => { - const uploadResult = await Promise.all( - fileList.map(async (it) => { - let isOK; - // * 生成上传 Token - try { - if (it.endsWith('.yml')) { - const ymlObj = YAML.parse(fs.readFileSync(it, 'utf8')); - ymlObj.files.forEach((n) => (n.url = `${ymlObj.version}/${n.url}`)); - ymlObj.path = `${ymlObj.version}/${ymlObj.path}`; - fs.writeFileSync(it, YAML.stringify(ymlObj)); - await removeFile(bucket, onlyName(it)); - const token = uptoken(bucket, onlyName(it)); - isOK = await uploadFile(token, onlyName(it), it); - } else { - const token = uptoken(bucket, `${version}/${it.replace(/release\//, '')}`); - isOK = await uploadFile(token, `${version}/${it.replace(/release\//, '')}`, it); - } - } catch (error) { - console.log('error', error); - } - return Promise.resolve(isOK || false); - }) - ); - console.log('上传结果:', uploadResult); - const deleteResult = await Promise.all( - fileList.map(async (it) => { - const isOK = await removeFile(bucket, `latest/${toLatest(onlyName(it))}`); - Promise.resolve(isOK || false); - }) - ); - console.log('删除结果:', deleteResult); - const copyResult = await Promise.all( - fileList.map(async (it) => { - const isOK = await cpFile(`${version}/${onlyName(it)}`, `latest/${toLatest(onlyName(it))}`); - Promise.resolve(isOK || false); - }) - ); - console.log('拷贝结果', copyResult); -}; - -app(); diff --git a/vercel.json b/vercel.json index 7dbf0f9c..3090a147 100644 --- a/vercel.json +++ b/vercel.json @@ -1,12 +1,13 @@ { - "rewrites": [ - { - "source": "/:path((?!en/).*)", - "destination": "/en/:path*" - }, - { - "source": "/:path((?!zh/).*)", - "destination": "/zh/:path*" - } - ] -} + "rewrites": [ + { + "source": "/:path((?!en/).*)", + "destination": "/en/:path*" + }, + { + "source": "/:path((?!zh/).*)", + "destination": "/zh/:path*" + } + ] + } + diff --git a/yarn.lock b/yarn.lock index e19f28c3..37487cd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2275,6 +2275,7 @@ version "5.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082" integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A== +<<<<<<< HEAD dependencies: "@types/json-schema" "^7.0.9" "@typescript-eslint/scope-manager" "5.29.0" @@ -2288,6 +2289,21 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" integrity sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ== dependencies: +======= + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.29.0" + "@typescript-eslint/types" "5.29.0" + "@typescript-eslint/typescript-estree" "5.29.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.29.0": + version "5.29.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" + integrity sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ== + dependencies: +>>>>>>> main "@typescript-eslint/types" "5.29.0" eslint-visitor-keys "^3.3.0" @@ -2581,7 +2597,11 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" +<<<<<<< HEAD +ajv@8.11.0, ajv@^8.0.0, ajv@^8.6.3, ajv@^8.8.0: +======= ajv@8.11.0, ajv@^8.0.0, ajv@^8.8.0: +>>>>>>> main version "8.11.0" resolved "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== @@ -2969,6 +2989,14 @@ atob@^2.1.2: resolved "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +<<<<<<< HEAD +atomically@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe" + integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w== + +======= +>>>>>>> main autoprefixer@10.4.7, autoprefixer@^10.4.6: version "10.4.7" resolved "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf" @@ -3989,6 +4017,22 @@ concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@ readable-stream "^2.2.2" typedarray "^0.0.6" +conf@^10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/conf/-/conf-10.1.2.tgz#50132158f388756fa9dea3048f6b47935315c14e" + integrity sha512-o9Fv1Mv+6A0JpoayQ8JleNp3hhkbOJP/Re/Q+QqxMPHPkABVsRjQGWZn9A5GcqLiTNC6d89p2PB5ZhHVDSMwyg== + dependencies: + ajv "^8.6.3" + ajv-formats "^2.1.1" + atomically "^1.7.0" + debounce-fn "^4.0.0" + dot-prop "^6.0.1" + env-paths "^2.2.1" + json-schema-typed "^7.0.3" + onetime "^5.1.2" + pkg-up "^3.1.0" + semver "^7.3.5" + config-chain@^1.1.11, config-chain@^1.1.12, config-chain@^1.1.13: version "1.1.13" resolved "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" @@ -4570,10 +4614,19 @@ dateformat@^3.0.0: resolved "https://registry.npmmirror.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +<<<<<<< HEAD +debounce-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7" + integrity sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ== + dependencies: + mimic-fn "^3.0.0" +======= debug@0.7.2: version "0.7.2" resolved "https://registry.npmjs.org/debug/-/debug-0.7.2.tgz#056692c86670977f115de82917918b8e8b9a10f0" integrity sha512-Ch0X6QrHzrNiWwLsBJj9KgXL5IK67pfDyTsXXVPyrdObVyKuj/rPdCtZg761nHZM1GQ7wW/o9cAZf5JeTN/vRg== +>>>>>>> main debug@2.6.9, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -4933,6 +4986,13 @@ dot-prop@^5.1.0, dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" +dot-prop@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" + integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== + dependencies: + is-obj "^2.0.0" + dotenv-expand@^5.1.0: version "5.1.0" resolved "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" @@ -5066,6 +5126,14 @@ electron-reload@1.5.0: dependencies: chokidar "^3.0.2" +electron-store@8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-8.0.2.tgz#95c8cf81c1e1cf48b24f3ceeea24b921c1ff62d7" + integrity sha512-9GwUMv51w8ydbkaG7X0HrPlElXLApg63zYy1/VZ/a08ndl0gfm4iCoD3f0E1JvP3V16a+7KxqriCI0c122stiA== + dependencies: + conf "^10.1.2" + type-fest "^2.12.2" + electron-to-chromium@^1.4.147: version "1.4.154" resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.154.tgz#d69c60499fc467a6c59591d29183e520afbc78a1" @@ -5198,7 +5266,7 @@ entities@~3.0.1: resolved "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== -env-paths@^2.2.0: +env-paths@^2.2.0, env-paths@^2.2.1: version "2.2.1" resolved "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== @@ -7600,6 +7668,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema-typed@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9" + integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A== + json-schema@0.4.0: version "0.4.0" resolved "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -8450,6 +8523,11 @@ mimic-fn@^2.1.0: resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== + mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.npmmirror.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -9889,6 +9967,13 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + plist@^3.0.1, plist@^3.0.4: version "3.0.5" resolved "https://registry.npmmirror.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987" @@ -10434,7 +10519,11 @@ qs@6.10.3: dependencies: side-channel "^1.0.4" +<<<<<<< HEAD +qs@6.11.0: +======= qs@6.11.0, qs@^6.1.0: +>>>>>>> main version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== @@ -11980,6 +12069,8 @@ symbol-observable@4.0.0: resolved "https://registry.npmmirror.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== +<<<<<<< HEAD +======= sync-request@3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/sync-request/-/sync-request-3.0.1.tgz#caa1235aaf889ba501076a1834c436830a82fb73" @@ -11989,6 +12080,7 @@ sync-request@3.0.1: http-response-object "^1.0.1" then-request "^2.0.1" +>>>>>>> main tailwindcss@3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.4.tgz#64b09059805505902139fa805d97046080bd90b9" @@ -12375,6 +12467,14 @@ type-fest@^0.8.1: resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +<<<<<<< HEAD +type-fest@^2.12.2: + version "2.16.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.16.0.tgz#1250fbd64dafaf4c8e405e393ef3fb16d9651db2" + integrity sha512-qpaThT2HQkFb83gMOrdKVsfCN7LKxP26Yq+smPzY1FqoHRjqmjqHXA7n5Gkxi8efirtbeEUxzfEdePthQWCuHw== + +======= +>>>>>>> main type-fest@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.14.0.tgz#f990e19169517d689c98e16d128b231022b27e12"