* fix: can not navigate to extensions page

* feat: add iconpark

* feat:  sidebar done

* feat: update style

* fix: theme components show in bottom

* feat: homepage almost done

* feat: extension detail readme

* feat: ignore eo-setting

* feat: ignore eo-setting

* feat: extension detail support text

* fix: build error

* feat: mock extension preview in web

* update css style

* feat: extension detail support web preview

* pref: update css style

* feat: update setting component

* feat: update style

* feat: ignore

* remove diver

* feat: add link in github logo

* fix: build ts error

* fix: search extension

* feat: change bind event of click

* fix: setting button can not click

* feat: system setting support web

* fix: flex style issue

* feat: icon button width

* chore: switch data source btn move to setting modal

* feat: i18n

* fix: module inject error

* fix: some css style

* feat: hide cloud icon

* add logo to settingModal

* feat: update settingModal UI

* chore: serve support i18n

* feat: base env

* fix: some error message

* fix: build error

* feat: history done

* feat: done env

* feat: settings logic

* fix: env modal auto open while page load

* pref: api-tabs css style

* fix: api-tabs css style issus

* pref: update settingsModal css style

* fix: set default language

* feat: update env

* feat: add goto env callback

* fix: remote source for web

* fix: remote source for web

* fix: rename API to REST

* feat: fix tips text

* feat: fix icon size

* fix: make api-tabs space evenly

* fix: about component descritions issues

* fix: style of env select position

* fix: settings modal navigate to extension page faile

* feat: modal footer left

* fix: mock some logic

* feat: history icon style

* fix: extension list css style

* update extension css style

* fix: env save failed

* chore: build i18n destop app

* fix: rename event name

* feat: change language

* chore

* test vercel

* test vercel

* delete vercel.json

* fix: lose baseHref

* chore: change angular.json beforeBuild

* fix: 2 bug about env

* perf: extension detail scrollbar style

* feat: add ts.code-snippets

* feat: initial i18n

* fix: open test history

* feat: add uuid in history tab

* fix: custom iconpark component

* test merge

* fix: center plus icon

* fix: setttings should auto save

* translate: en

* feat: change lang

* feat: translate en

* translate en

* translate en

* translate en

* delete package.lock

* fix: root directory run error

* vercel.json

* vercel redirects

* vercel.json

* change

* change

* route by accept-language

* vercel.json

* feat:redirect

* vercel rewrites

* vercel

* chore: translate chinese comment to english

* translate: cn

* push zh.xlf

* fix: manage environment

* translate zh

* fix: some css style issues

* feat: changeLanuage

* delete vercel

* fix: language storage none

* feat: app reload

* fix: initial lanugae

* feat:debug success

* feat: node-server

* feat:web node server

* stash ProxySandbox

* feat: extension i18n

* feat: extension i18n logic

Co-authored-by: buqiyuan <1743369777@qq.com>
Co-authored-by: 夜鹰 <17kungfuboy@gmail.com>
This commit is contained in:
Scarqin 2022-07-13 12:46:00 +08:00 committed by GitHub
parent 84c5d65f94
commit c2757a4487
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 1517 additions and 850 deletions

1
.gitignore vendored
View File

@ -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

View File

@ -13,7 +13,8 @@
// }
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/dist":true,
"**/.angular":true,
"**/*.code-search": true,
"**/*.lock": true,
}

View File

@ -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);
}
};
};

View File

@ -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"

View File

@ -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": {

View File

@ -1,9 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="application/javascript" src="./dist/index.js"></script>
</head>
<body>
</body>
</html>

View File

@ -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"
}
}

View File

@ -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;

View File

@ -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: '<core-module>',
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;
}
}

View File

@ -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;

View File

@ -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);
}
});

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 } });

View File

@ -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';

View File

@ -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;
}

View File

@ -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<ModuleHandlerResult> {
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<ModuleHandlerResult> {
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);
});
}
}

View File

@ -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)) {

View File

@ -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();

View File

@ -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<ModuleHandlerResult>;
uninstall: (module: ModuleManagerInfo) => Promise<ModuleHandlerResult>;
refresh: (module: ModuleManagerInfo) => void;
refreshAll:()=>void;
getModule: (moduleID: string, belongs?: boolean) => ModuleInfo;
getModules: (belongs?: boolean) => Map<string, ModuleInfo>;
getAppModuleList: () => Array<ModuleInfo>;

37
src/platform/node/i18n.ts Normal file
View File

@ -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];
}

View File

@ -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(() => {

View File

@ -17,6 +17,3 @@ export const isNotEmpty = (value: any) => {
}
};
export const isElectron = () => {
return !!(window && window.process && window.process.type);
};

View File

@ -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');

View File

@ -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();

View File

@ -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']);
}
}

View File

@ -0,0 +1,12 @@
export const LANGUAGES = [
{
name: 'English',
value: 'en-US',
path: 'en',
},
{
name: '简体中文',
value: 'zh-Hans',
path: 'zh',
},
];

View File

@ -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();
});
});

View File

@ -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}`;
}
}
}

View File

@ -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);

View File

@ -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 {}

View File

@ -63,7 +63,7 @@
<h2 class="text-lg font-bold mt-[30px]" i18n>Support</h2>
<nz-descriptions [nzColumn]="1" nzTitle="">
<nz-descriptions-item i18n-nzTitle nzTitle="Author">{{ extensionDetail?.author }}</nz-descriptions-item>
<nz-descriptions-item i18n-nzTitle nzTitle="Author">{{ extensionDetail?.author}}</nz-descriptions-item>
<nz-descriptions-item i18n-nzTitle nzTitle="Version">{{ extensionDetail?.version }}
</nz-descriptions-item>
</nz-descriptions>

View File

@ -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',

View File

@ -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<string> = [];
localModules: Map<string, ModuleInfo>;
constructor(private http: HttpClient) {
this.getInstalledList();
HOST = '';
localExtensions: Map<string, ModuleInfo>;
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<any> {
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));
}

View File

@ -15,8 +15,8 @@
<span class="my-1 text-gray-500 desc">{{ it.description }}</span>
</div>
<div>
<span *ngIf="isElectron ? extensionService.localModules.has(it.moduleID) : it.installed"
class="p-1 text-xs text-green-700 border-green-700 rounded-sm bd_all" i18n>Installed</span>
<span *ngIf="electron.isElectron ? extensionService.localExtensions.has(it.moduleID) : it.installed"
class="p-1 text-xs text-green-700 border-green-700 rounded-sm bd_all whitespace-nowrap" i18n>Installed</span>
</div>
</div>
</div>

View File

@ -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<string> = new Subject<string>();
private destroy$: Subject<void> = new Subject<void>();
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();

View File

@ -1,6 +1,6 @@
<eo-navbar></eo-navbar>
<div [style.--remote-notification-height]="isShowNotification && isElectron ? '50px' : '0px'">
<div *ngIf="isShowNotification && isElectron" class="remote-notification">
<div [style.--remote-notification-height]="isShowNotification && electron.isElectron ? '50px' : '0px'">
<div *ngIf="isShowNotification && electron.isElectron" class="remote-notification">
<i nz-icon [nzType]="isRemote ? 'cloud' : 'exclamation-circle'" nzTheme="outline" class="text-[13px] mr-[2px]"></i>
<span i18n>Current data storage exists{{ dataSourceText }},please switch if you want to collaborate</span>
<a class="eo-blod" (click)="switchDataSource()" i18n>{{ isRemote ? 'Remote Server' : 'Localhost' }} Data Storage</a>

View File

@ -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();

View File

@ -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);
}

View File

@ -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"
>
<nz-option *ngFor="let item of languages" nzCustomContent [nzValue]="item.value" [nzLabel]="item.name">
<nz-option
*ngFor="let item of languageService.languages"
nzCustomContent
[nzValue]="item.value"
[nzLabel]="item.name"
>
<eo-iconpark-icon name="language"></eo-iconpark-icon>
{{ item.name }}
</nz-option>
@ -34,40 +38,15 @@ import { NzModalService } from 'ng-zorro-antd/modal';
export class LanguageSwticherComponent implements OnInit {
@Input() model: object = {};
@Output() modelChange: EventEmitter<any> = 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);
}
}

View File

@ -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({

View File

@ -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);
}
}

View File

@ -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 = {};

View File

@ -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;
}
}
}

View File

@ -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
*/

View File

@ -23,7 +23,6 @@ export type ResultType<T = any> = {
};
let isFirstLoad = true;
const getApiUrl = (apiData: ApiData) => {
const dataSourceType: DataSourceType = getSettings()?.['eoapi-common.dataStorage'] ?? 'local';

View File

@ -1,2 +0,0 @@
export * from './loader';
export * from './type';

View File

@ -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<ModuleInfo>): 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列表
}
}

View File

@ -1365,7 +1365,7 @@
<context context-type="sourcefile">src/app/pages/extension/detail/extension-detail.component.html</context>
<context context-type="linenumber">64</context>
</context-group>
<target state="translated">帮助</target>
<target state="translated">支持</target>
</trans-unit>
<trans-unit id="d7293b61e9088c66421df2e367e0ccc00346cf9f" datatype="html">
<source>Author</source>

View File

@ -7,7 +7,6 @@ import { APP_CONFIG } from './environments/environment';
if (APP_CONFIG.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule, {})
.catch((err) => console.error(err));

View File

@ -0,0 +1 @@
# Node Test server

View File

@ -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;
}
}
});
},
};

View File

@ -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);
}
}

View File

@ -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;
}
}
});

View File

@ -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;

View File

@ -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
```

View File

@ -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);

View File

@ -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"
}
}

View File

@ -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==

View File

@ -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;
}
}
});
}
};

View File

@ -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();

View File

@ -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*"
}
]
}

102
yarn.lock
View File

@ -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"