Skip to content

Commit

Permalink
feat: local mock service (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
buqiyuan committed Jun 5, 2022
1 parent a9b61b7 commit ef81576
Show file tree
Hide file tree
Showing 28 changed files with 3,058 additions and 2,245 deletions.
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@
"test:workbench": "cd src/workbench/browser && yarn test",
"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",
"electron:dev": "npm run electron:tsc && npm run copyfile:out && electron . --development",
"build": "npm-run-all -s build:workbench electron:tsc && electron-builder build",
"build:static": "npm run electron:tsc && electron-builder build",
"release": "npm-run-all -s build:workbench electron:tsc && electron-builder --publish=always",
"test": "npm-run-all --serial test:*",
"electron:tsc": "tsc -p tsconfig.json"
"electron:tsc": "tsc -p tsconfig.json",
"copyfile:out": "copyfiles -u 1 src/**/*.json src/app/common/images/** out"
},
"dependencies": {
"@bqy/node-module-alias": "^1.0.1",
"@electron/remote": "2.0.8",
"@koa/cors": "3.3.0",
"@koa/router": "10.1.1",
"content-disposition": "^0.5.4",
"copyfiles": "2.4.1",
"cross-spawn": "^7.0.3",
"crypto-js": "^4.1.1",
"dexie": "3.2.2",
Expand All @@ -38,13 +42,19 @@
"fix-path": "3.0.0",
"form-data": "^4.0.0",
"iconv-lite": "^0.6.3",
"koa": "2.13.4",
"koa-bodyparser": "4.3.0",
"mockjs": "1.1.0",
"npm": "6.14.17",
"portfinder": "1.0.28",
"resolve": "^1.22.0",
"rxjs": "7.5.5",
"xml2js": "^0.4.23"
},
"devDependencies": {
"@types/cross-spawn": "6.0.2",
"@types/koa": "2.13.4",
"@types/koa__router": "8.0.11",
"@types/node": "17.0.32",
"@typescript-eslint/eslint-plugin": "5.23.0",
"@typescript-eslint/parser": "5.23.0",
Expand Down
24 changes: 22 additions & 2 deletions src/app/electron-main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import { deleteFile, readJson } from 'eo/shared/node/file';
import { STORAGE_TEMP as storageTemp } from 'eo/shared/common/constant';
import { UnitWorkerModule } from 'eo/workbench/node/unitWorker';
import Configuration from 'eo/platform/node/configuration/lib';
import { ConfigurationInterface } from 'eo/platform/node/configuration';
import { ConfigurationInterface } from 'src/platform/node/configuration';
import { MockServer } from 'eo/platform/node/mock-server';

let win: BrowserWindow = null;
export const subView = {
appView: null,
mainView: null,
};
const eoUpdater = new EoUpdater();
const mockServer = new MockServer();
const moduleManager: ModuleManagerInterface = ModuleManager();
const configuration: ConfigurationInterface = Configuration();
// Remote
Expand Down Expand Up @@ -85,9 +88,11 @@ try {
// initialization and is ready to create browser windows.
// 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', () => {
app.on('ready', async () => {
setTimeout(createWindow, 400);
eoUpdater.check();
// 启动mock服务
await mockServer.start();
});
//!TODO only api manage app need this
// setupUnit(subView.appView);
Expand All @@ -99,6 +104,7 @@ try {
if (process.platform !== 'darwin') {
app.quit();
}
mockServer.stop();
});

app.on('activate', () => {
Expand Down Expand Up @@ -204,6 +210,20 @@ try {
returnValue = configuration.getModuleSettings(arg.data.moduleID);
} else if (arg.action === 'getSidePosition') {
returnValue = subView.appView?.sidePosition;
// 注册单个mock路由
} else if (arg.action === 'registerMockRoute') {
const { method, path, data } = arg.data;
returnValue = mockServer.registerRoute(method, path, data);
// 注销mock路由
} else if (arg.action === 'unRegisterMockRoute') {
const { method, path } = arg.data;
returnValue = mockServer.unRegisterRoute(method, path);
// 获取mock服务地址
} else if (arg.action === 'getMockUrl') {
returnValue = mockServer.getMockUrl();
// 重置并初始化mock路由
} else if (arg.action === 'resetAndInitRoutes') {
returnValue = mockServer.resetAndInitRoutes();
} else if (arg.action === 'hook') {
returnValue = 'hook返回';
} else {
Expand Down
98 changes: 58 additions & 40 deletions src/platform/browser/IndexedDB/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface StorageModel {
* 主键UUID,字符串UUID或数值型
* @type {string|number}
*/
uuid?: string|number;
uuid?: string | number;

/**
* 名称
Expand Down Expand Up @@ -49,7 +49,7 @@ export interface Environment extends StorageModel {
* 项目主键ID
* @type {string|number}
*/
projectID: string|number;
projectID: string | number;

/**
* 前置url
Expand All @@ -64,7 +64,6 @@ export interface Environment extends StorageModel {
parameters?: object;
}


/**
* 分组对象接口
*/
Expand All @@ -79,13 +78,13 @@ export interface Group extends StorageModel {
* 项目主键ID
* @type {string|number}
*/
projectID: string|number;
projectID: string | number;

/**
* 上级分组主键,最顶层是0
* @type {string|number}
*/
parentID?: string|number;
parentID?: string | number;

/**
* 分组排序号
Expand Down Expand Up @@ -391,6 +390,10 @@ export interface ApiData extends StorageModel {
* @type {JsonRootType|string}
*/
responseBodyJsonType?: JsonRootType | string;
/**
* mock列表
*/
mockList?: ApiEditMock[];
}

/**
Expand Down Expand Up @@ -450,6 +453,18 @@ export interface ParamsEnum {
*/
description: string;
}

export type ApiEditMock = {
/** mock名称 */
name: string;
/** mock地址 */
url: string;
/** mock返回值 */
response: string;
/** 是否系统默认mock */
isDefault?: boolean;
};

export interface BasiApiEditParams {
/**
* 参数名
Expand Down Expand Up @@ -512,56 +527,59 @@ export interface ApiEditBody extends BasiApiEditParams {
export interface StorageInterface {
// Project
projectCreate: (item: Project) => Observable<object>;
projectUpdate: (item: Project, uuid: number|string) => Observable<object>;
projectUpdate: (item: Project, uuid: number | string) => Observable<object>;
projectBulkUpdate: (items: Array<Project>) => Observable<object>;
projectRemove: (uuid: number|string) => Observable<boolean>;
projectBulkRemove: (uuids: Array<number|string>) => Observable<boolean>;
projectLoad: (uuid: number|string) => Observable<object>;
projectBulkLoad: (uuids: Array<number|string>) => Observable<Array<object>>;
projectRemove: (uuid: number | string) => Observable<boolean>;
projectBulkRemove: (uuids: Array<number | string>) => Observable<boolean>;
projectLoad: (uuid: number | string) => Observable<object>;
projectBulkLoad: (uuids: Array<number | string>) => Observable<Array<object>>;
projectExport: () => Observable<object>;
// Environment
environmentCreate: (item: Environment) => Observable<object>;
environmentUpdate: (item: Environment, uuid: number|string) => Observable<object>;
environmentUpdate: (item: Environment, uuid: number | string) => Observable<object>;
environmentBulkCreate: (items: Array<Environment>) => Observable<object>;
environmentBulkUpdate: (items: Array<Environment>) => Observable<object>;
environmentRemove: (uuid: number|string) => Observable<boolean>;
environmentBulkRemove: (uuids: Array<number|string>) => Observable<boolean>;
environmentLoad: (uuid: number|string) => Observable<object>;
environmentBulkLoad: (uuids: Array<number|string>) => Observable<Array<object>>;
environmentLoadAllByProjectID: (projectID: number|string) => Observable<Array<object>>;
environmentRemove: (uuid: number | string) => Observable<boolean>;
environmentBulkRemove: (uuids: Array<number | string>) => Observable<boolean>;
environmentLoad: (uuid: number | string) => Observable<object>;
environmentBulkLoad: (uuids: Array<number | string>) => Observable<Array<object>>;
environmentLoadAllByProjectID: (projectID: number | string) => Observable<Array<object>>;
// Group
groupCreate: (item: Group) => Observable<object>;
groupUpdate: (item: Group, uuid: number|string) => Observable<object>;
groupUpdate: (item: Group, uuid: number | string) => Observable<object>;
groupBulkCreate: (items: Array<Group>) => Observable<object>;
groupBulkUpdate: (items: Array<Group>) => Observable<object>;
groupRemove: (uuid: number|string) => Observable<boolean>;
groupBulkRemove: (uuids: Array<number|string>) => Observable<boolean>;
groupLoad: (uuid: number|string) => Observable<object>;
groupBulkLoad: (uuids: Array<number|string>) => Observable<Array<object>>;
groupLoadAllByProjectID: (projectID: number|string) => Observable<Array<object>>;
groupRemove: (uuid: number | string) => Observable<boolean>;
groupBulkRemove: (uuids: Array<number | string>) => Observable<boolean>;
groupLoad: (uuid: number | string) => Observable<object>;
groupBulkLoad: (uuids: Array<number | string>) => Observable<Array<object>>;
groupLoadAllByProjectID: (projectID: number | string) => Observable<Array<object>>;
// Api Data
apiDataCreate: (item: ApiData) => Observable<object>;
apiDataUpdate: (item: ApiData, uuid: number|string) => Observable<object>;
apiDataUpdate: (item: ApiData, uuid: number | string) => Observable<object>;
apiDataBulkCreate: (items: Array<ApiData>) => Observable<object>;
apiDataBulkUpdate: (items: Array<ApiData>) => Observable<object>;
apiDataRemove: (uuid: number|string) => Observable<boolean>;
apiDataBulkRemove: (uuids: Array<number|string>) => Observable<boolean>;
apiDataLoad: (uuid: number|string) => Observable<object>;
apiDataBulkLoad: (uuids: Array<number|string>) => Observable<Array<object>>;
apiDataLoadAllByProjectID: (projectID: number|string) => Observable<Array<object>>;
apiDataLoadAllByGroupID: (groupID: number|string) => Observable<Array<object>>;
apiDataLoadAllByProjectIDAndGroupID: (projectID: number|string, groupID: number|string) => Observable<Array<object>>;
apiDataRemove: (uuid: number | string) => Observable<boolean>;
apiDataBulkRemove: (uuids: Array<number | string>) => Observable<boolean>;
apiDataLoad: (uuid: number | string) => Observable<object>;
apiDataBulkLoad: (uuids: Array<number | string>) => Observable<Array<object>>;
apiDataLoadAllByProjectID: (projectID: number | string) => Observable<Array<object>>;
apiDataLoadAllByGroupID: (groupID: number | string) => Observable<Array<object>>;
apiDataLoadAllByProjectIDAndGroupID: (
projectID: number | string,
groupID: number | string
) => Observable<Array<object>>;
// Api Test History
apiTestHistoryCreate: (item: ApiTestHistory) => Observable<object>;
apiTestHistoryUpdate: (item: ApiTestHistory, uuid: number|string) => Observable<object>;
apiTestHistoryUpdate: (item: ApiTestHistory, uuid: number | string) => Observable<object>;
apiTestHistoryBulkCreate: (items: Array<ApiTestHistory>) => Observable<object>;
apiTestHistoryBulkUpdate: (items: Array<ApiTestHistory>) => Observable<object>;
apiTestHistoryRemove: (uuid: number|string) => Observable<boolean>;
apiTestHistoryBulkRemove: (uuids: Array<number|string>) => Observable<boolean>;
apiTestHistoryLoad: (uuid: number|string) => Observable<object>;
apiTestHistoryBulkLoad: (uuids: Array<number|string>) => Observable<Array<object>>;
apiTestHistoryLoadAllByProjectID: (projectID: number|string) => Observable<Array<object>>;
apiTestHistoryLoadAllByApiDataID: (apiDataID: number|string) => Observable<Array<object>>;
apiTestHistoryRemove: (uuid: number | string) => Observable<boolean>;
apiTestHistoryBulkRemove: (uuids: Array<number | string>) => Observable<boolean>;
apiTestHistoryLoad: (uuid: number | string) => Observable<object>;
apiTestHistoryBulkLoad: (uuids: Array<number | string>) => Observable<Array<object>>;
apiTestHistoryLoadAllByProjectID: (projectID: number | string) => Observable<Array<object>>;
apiTestHistoryLoadAllByApiDataID: (apiDataID: number | string) => Observable<Array<object>>;
}

export type StorageItem = Project | Environment | Group | ApiData | ApiTestHistory;
Expand All @@ -583,11 +601,11 @@ export enum StorageHandleStatus {
success = 'success',
empty = 'empty',
error = 'error',
invalid = 'invalid'
invalid = 'invalid',
}

export enum StorageProcessType {
default = 'default',
remote = 'remote',
sync = 'sync'
}
sync = 'sync',
}
19 changes: 19 additions & 0 deletions src/platform/electron-browser/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,22 @@ window.eo.getSettings = (settings) => {
window.eo.getModuleSettings = (moduleID) => {
return ipcRenderer.sendSync('eo-sync', { action: 'getModuleSettings', data: { moduleID: moduleID } });
};

// 注册单个mock路由
window.eo.registerMockRoute = ({ method, path, data }) => {
return ipcRenderer.sendSync('eo-sync', { action: 'registerMockRoute', data: { method, path, data } });
};

// 注销mock路由
window.eo.unRegisterMockRoute = ({ method, path }) => {
return ipcRenderer.sendSync('eo-sync', { action: 'unRegisterMockRoute', data: { method, path } });
};
// 获取mock服务地址
window.eo.getMockUrl = () => {
return ipcRenderer.sendSync('eo-sync', { action: 'getMockUrl' });
};

// 重置并初始化路由
window.eo.resetAndInitRoutes = () => {
return ipcRenderer.sendSync('eo-sync', { action: 'resetAndInitRoutes' });
};
2 changes: 1 addition & 1 deletion src/platform/node/configuration/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Configuration implements ConfigurationInterface {
data.nestedSettings ??= {};
data.settings[moduleID] = settings;
const propArr = moduleID.split('.');
const target = propArr.slice(0, -1).reduce((p, k) => p[k], data.nestedSettings);
const target = propArr.slice(0, -1).reduce((p, k) => p?.[k], data.nestedSettings);
target[propArr.at(-1)] = settings;
return this.saveConfig(data);
}
Expand Down
53 changes: 53 additions & 0 deletions src/platform/node/mock-server/index copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const Koa = require('koa');
const Router = require('koa-router');
const glob = require('glob');
const logger = require('koa-logger');
const { resolve } = require('path');
const fs = require('fs');

const app = new Koa();
const router = new Router({ prefix: '/api' });
const routerMap = {}; // 存放路由映射

app.use(logger());

// 注册路由
glob.sync(resolve('./api', '**/*.json')).forEach((item, i) => {
let apiJsonPath = item && item.split('/api')[1];
let apiPath = apiJsonPath.replace('.json', '');

router.get(apiPath, (ctx, next) => {
try {
let jsonStr = fs.readFileSync(item).toString();
ctx.body = {
data: JSON.parse(jsonStr),
state: 200,
type: 'success', // 自定义响应体
};
} catch (err) {
ctx.throw('服务器错误', 500);
}
});

// 记录路由
routerMap[apiJsonPath] = apiPath;
});

fs.writeFile('./routerMap.json', JSON.stringify(routerMap, null, 4), (err) => {
if (!err) {
console.log('路由地图生成成功!');
}
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3040);
// const Koa = require('koa');
// const app = new Koa();

// app.use(async (ctx) => {
// ctx.body = 'hello koa2';
// });

// app.listen(3000);
// console.log('[demo] start-quick is starting at port 3000');
Loading

0 comments on commit ef81576

Please sign in to comment.