Skip to content

Commit 26ba277

Browse files
committed
优化:更新接口对接类
1 parent e8b44af commit 26ba277

26 files changed

+567
-234
lines changed

electron/mapi/app/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,18 @@ const spawnShell = async (command: string | string[], option: {
130130
*/
131131
const availablePort = async (start: number): Promise<number> => {
132132
for (let i = start; i < 65535; i++) {
133-
const available = await isPortAvailable('0.0.0.0', i)
134-
// console.log('isPortAvailable', i, available)
135-
if (available) {
133+
const available = await isPortAvailable(i, '0.0.0.0')
134+
const availableLocal = await isPortAvailable(i, '127.0.0.1')
135+
// console.log('isPortAvailable', i, available, availableLocal)
136+
if (available && availableLocal) {
136137
return i
137138
}
138139
}
139140
throw new Error('no available port')
140141
}
141142

142-
const isPortAvailable = async (host: string, port: number): Promise<boolean> => {
143143

144+
const isPortAvailable = async (port: number, host?: string): Promise<boolean> => {
144145
return new Promise((resolve) => {
145146
const server = net.createServer()
146147
server.listen(port, host)
@@ -164,6 +165,8 @@ const fixExecutable = async (executable: string) => {
164165
export const Apps = {
165166
shell,
166167
spawnShell,
168+
availablePort,
169+
isPortAvailable,
167170
}
168171

169172
export default {

electron/mapi/event/main.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import {AppRuntime} from "../env";
22
import {ipcMain} from "electron";
33
import {StrUtil} from "../../lib/util";
44

5+
56
const init = () => {
67

78
}
89

910
type NameType = 'main' | string
10-
type EventType = 'APP_READY' | 'CALL_THIRD_PARTY' | 'CALL_PAGE'
11+
type EventType = 'APP_READY' | 'CALL_THIRD_PARTY' | 'CALL_PAGE' | 'CHANNEL'
1112

1213
const send = (name: NameType, type: EventType, data: any = {}, id?: string): boolean => {
1314
id = id || StrUtil.randomString(32)
@@ -16,6 +17,7 @@ const send = (name: NameType, type: EventType, data: any = {}, id?: string): boo
1617
if (!AppRuntime.mainWindow) {
1718
return false
1819
}
20+
// console.log('send', payload)
1921
AppRuntime.mainWindow?.webContents.send('MAIN_PROCESS_MESSAGE', payload)
2022
} else {
2123
if (!AppRuntime.windows[name]) {
@@ -76,11 +78,49 @@ ipcMain.handle('event:callPage', async (_, name: string, type: string, data: any
7678
})
7779
})
7880

81+
const sendChannel = (channel: string, data: any) => {
82+
send('main', 'CHANNEL', {channel, data})
83+
}
84+
85+
let onChannelIsListen = false
86+
let channelOnCallback = {}
87+
88+
const onChannel = (channel: string, callback: (data: any) => void) => {
89+
if (!channelOnCallback[channel]) {
90+
channelOnCallback[channel] = []
91+
}
92+
channelOnCallback[channel].push(callback)
93+
if (!onChannelIsListen) {
94+
onChannelIsListen = true
95+
ipcMain.handle('event:channelSend', (event, channel_, data) => {
96+
if (channelOnCallback[channel_]) {
97+
channelOnCallback[channel_].forEach((callback: (data: any) => void) => {
98+
callback(data)
99+
})
100+
}
101+
})
102+
}
103+
}
104+
105+
const offChannel = (channel: string, callback: (data: any) => void) => {
106+
if (channelOnCallback[channel]) {
107+
channelOnCallback[channel] = channelOnCallback[channel].filter((item: (data: any) => void) => {
108+
return item !== callback
109+
})
110+
}
111+
if (channelOnCallback[channel].length === 0) {
112+
delete channelOnCallback[channel]
113+
}
114+
}
115+
79116
export default {
80117
init,
81118
send
82119
}
83120

84121
export const Events = {
85-
send
122+
send,
123+
sendChannel,
124+
onChannel,
125+
offChannel,
86126
}

electron/mapi/event/render.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const init = () => {
55
}
66

77
const send = (name: string, type: string, data: any = {}) => {
8-
ipcRenderer.invoke('event:send', name, type, data).then()
8+
return ipcRenderer.invoke('event:send', name, type, data).then()
99
}
1010

1111
const callThirdParty = async (name: string, type: string, data: any, option: any) => {
@@ -16,9 +16,28 @@ const callPage = async (name: string, type: string, data: any, option: any) => {
1616
return ipcRenderer.invoke('event:callPage', name, type, data, option)
1717
}
1818

19+
20+
const channelCreate = async (callback: (data: any) => void) => {
21+
const channel = Math.random().toString(36).substring(2)
22+
window['__channel'] = window['__channel'] || {}
23+
window['__channel'][channel] = callback
24+
return channel
25+
}
26+
27+
const channelDestroy = async (channel: string) => {
28+
delete window['__channel'][channel]
29+
}
30+
31+
const channelSend = async (channel: string, data: any) => {
32+
return ipcRenderer.invoke('event:channelSend', channel, data)
33+
}
34+
1935
export default {
2036
init,
2137
send,
2238
callThirdParty,
23-
callPage
39+
callPage,
40+
channelCreate,
41+
channelDestroy,
42+
channelSend,
2443
}

electron/mapi/main.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import page from "./page/main";
1111
import user from "./user/main";
1212
import misc from "./misc/main";
1313

14+
import server from "./server/main";
15+
1416
const $mapi = {
1517
app,
1618
log,
@@ -23,7 +25,8 @@ const $mapi = {
2325
keys,
2426
page,
2527
user,
26-
misc
28+
misc,
29+
server
2730
}
2831

2932
export const MAPI = {

electron/mapi/misc/main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ ipcMain.handle('misc:unzip', async (_, zipPath: string, dest: string) => {
99
return await index.unzip(zipPath, dest)
1010
})
1111

12-
export default {}
12+
export default {
13+
...index,
14+
}

electron/mapi/render.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import user from "./user/render";
1717
import misc from "./misc/render";
1818

1919
import ffmpeg from "./ffmpeg/render";
20+
import server from "./server/render";
2021

2122
export const MAPI = {
2223
init(env: typeof AppEnv = null) {
@@ -39,6 +40,7 @@ export const MAPI = {
3940
misc,
4041

4142
ffmpeg,
43+
server,
4244
})
4345
db.init()
4446
event.init()

electron/mapi/server/api.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {net} from 'electron'
2+
import {Client, handle_file} from "@gradio/client";
3+
import {platformArch, platformName} from "../../lib/env";
4+
import {Events} from "../event/main";
5+
import {Apps} from "../app";
6+
import {Files} from "../file/main";
7+
import fs from 'node:fs'
8+
9+
const request = async (url, data?: {}, option?: {}) => {
10+
option = Object.assign({
11+
method: 'GET',
12+
timeout: 60 * 1000,
13+
headers: {
14+
'Content-Type': 'application/json'
15+
},
16+
responseType: 'json' as 'json'
17+
})
18+
if (option['method'] === 'GET') {
19+
url += '?'
20+
for (let key in data) {
21+
url += `${key}=${data[key]}&`
22+
}
23+
}
24+
return new Promise((resolve, reject) => {
25+
const req = net.request({
26+
url,
27+
method: option['method'],
28+
headers: option['headers'],
29+
})
30+
req.on('response', (response) => {
31+
let body = ''
32+
response.on('data', (chunk) => {
33+
body += chunk.toString()
34+
})
35+
response.on('end', () => {
36+
if ('json' === option['responseType']) {
37+
try {
38+
resolve(JSON.parse(body))
39+
} catch (e) {
40+
resolve({code: -1, msg: `ResponseError: ${body}`})
41+
}
42+
} else {
43+
resolve(body)
44+
}
45+
})
46+
})
47+
req.on('error', (err) => {
48+
reject(err)
49+
})
50+
req.end()
51+
})
52+
}
53+
54+
const requestPost = async (url, data?: {}, option?: {}) => {
55+
option = Object.assign({
56+
method: 'POST',
57+
})
58+
return request(url, data, option)
59+
}
60+
61+
const requestGet = async (url, data?: {}, option?: {}) => {
62+
option = Object.assign({
63+
method: 'GET',
64+
})
65+
return request(url, data, option)
66+
}
67+
68+
const requestPostSuccess = async (url, data?: {}, option?: {}) => {
69+
const res = await requestPost(url, data, option)
70+
if (res['code'] === 0) {
71+
return res
72+
}
73+
throw new Error(res['msg'])
74+
}
75+
76+
const requestUrlFileToLocal = async (url, path) => {
77+
return new Promise((resolve, reject) => {
78+
const req = net.request(url)
79+
req.on('response', (response) => {
80+
const file = fs.createWriteStream(path)
81+
// @ts-ignore
82+
response.pipe(file)
83+
file.on('finish', () => {
84+
file.close()
85+
resolve('x')
86+
})
87+
})
88+
req.on('error', (err) => {
89+
reject(err)
90+
})
91+
req.end()
92+
})
93+
}
94+
95+
export default {
96+
GradioClient: Client,
97+
GradioHandleFile: handle_file,
98+
event: Events,
99+
file: Files,
100+
app: Apps,
101+
request,
102+
requestPost,
103+
requestGet,
104+
requestPostSuccess,
105+
requestUrlFileToLocal,
106+
platformName: platformName(),
107+
platformArch: platformArch(),
108+
}

electron/mapi/server/main.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import ServerApi from './api'
2+
import {ipcMain} from "electron";
3+
import file from "../file";
4+
5+
const serverModule = {}
6+
7+
const init = () => {
8+
9+
}
10+
11+
const getModule = async (serverInfo: ServerInfo) => {
12+
// console.log('getModule', serverInfo)
13+
if (!serverModule[serverInfo.localPath]) {
14+
try {
15+
const serverPath = `${serverInfo.localPath}/server.js`
16+
const module = await import(`file://${serverPath}`)
17+
// console.log('module', module)
18+
await module.default.init(ServerApi)
19+
serverModule[serverInfo.localPath] = module.default
20+
} catch (e) {
21+
console.error('getModule.error', e)
22+
throw new Error(e)
23+
}
24+
}
25+
return serverModule[serverInfo.localPath]
26+
}
27+
28+
ipcMain.handle('server:start', async (event, serverInfo: ServerInfo) => {
29+
const module = await getModule(serverInfo)
30+
return await module.start(serverInfo)
31+
})
32+
33+
ipcMain.handle('server:ping', async (event, serverInfo: ServerInfo) => {
34+
const module = await getModule(serverInfo)
35+
return await module.ping()
36+
})
37+
38+
ipcMain.handle('server:stop', async (event, serverInfo: ServerInfo) => {
39+
const module = await getModule(serverInfo)
40+
return await module.stop(serverInfo)
41+
})
42+
43+
ipcMain.handle('server:config', async (event, serverInfo: ServerInfo) => {
44+
const module = await getModule(serverInfo)
45+
return await module.config()
46+
})
47+
48+
ipcMain.handle('server:callFunction', async (event, serverInfo: ServerInfo, method: string, data: any) => {
49+
// console.log('getModule.before', serverInfo, method)
50+
const module = await getModule(serverInfo)
51+
// console.log('getModule.end', serverInfo, method, module)
52+
const func = module[method]
53+
if (!func) {
54+
throw new Error(`MethodNotFound : ${method}`)
55+
}
56+
return await func.bind(module)(serverInfo, data)
57+
})
58+
59+
export default {
60+
init
61+
}

electron/mapi/server/render.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {ipcRenderer} from 'electron'
2+
3+
const start = async (serverInfo: ServerInfo) => {
4+
return ipcRenderer.invoke('server:start', serverInfo)
5+
}
6+
7+
const ping = async (serverInfo: ServerInfo) => {
8+
return ipcRenderer.invoke('server:ping', serverInfo)
9+
}
10+
11+
const stop = async (serverInfo: ServerInfo) => {
12+
return ipcRenderer.invoke('server:stop', serverInfo)
13+
}
14+
15+
const config = async (serverInfo: ServerInfo) => {
16+
return ipcRenderer.invoke('server:config', serverInfo)
17+
}
18+
19+
const callFunction = async (serverInfo: ServerInfo, method: string, data: any) => {
20+
return ipcRenderer.invoke('server:callFunction', serverInfo, method, data)
21+
}
22+
23+
export default {
24+
start,
25+
ping,
26+
stop,
27+
config,
28+
callFunction,
29+
}

electron/mapi/server/type.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
interface ServerInfo {
2+
localPath: string,
3+
name: string,
4+
version: string,
5+
setting: {
6+
[key: string]: any,
7+
},
8+
logFile: string,
9+
}

0 commit comments

Comments
 (0)