修改同步逻辑
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { request, generateRsaKey } from './utils'
|
||||
import { getSyncAuthKey, setSyncAuthKey } from './data'
|
||||
import { SYNC_CODE } from '@common/constants'
|
||||
import log from '../log'
|
||||
import { aesDecrypt, aesEncrypt, getComputerName, rsaDecrypt } from '../utils'
|
||||
import { toMD5 } from '@common/utils/nodejs'
|
||||
import { SYNC_CODE } from '@common/constants_sync'
|
||||
|
||||
|
||||
const hello = async(urlInfo: LX.Sync.Client.UrlInfo) => request(`${urlInfo.httpProtocol}//${urlInfo.hostPath}/hello`)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import WebSocket from 'ws'
|
||||
import { encryptMsg, decryptMsg } from './utils'
|
||||
import { modules, callObj } from './modules'
|
||||
import { callObj } from './sync'
|
||||
// import { action as commonAction } from '@root/store/modules/common'
|
||||
// import { getStore } from '@root/store'
|
||||
// import registerSyncListHandler from './syncList'
|
||||
import log from '../log'
|
||||
import { SYNC_CLOSE_CODE, SYNC_CODE } from '@common/constants'
|
||||
import { dateFormat } from '@common/utils/common'
|
||||
import { aesEncrypt, getAddress } from '../utils'
|
||||
import { sendClientStatus } from '@main/modules/winMain'
|
||||
import { createMsg2call } from 'message2call'
|
||||
import { SYNC_CLOSE_CODE, SYNC_CODE } from '@common/constants_sync'
|
||||
|
||||
let status: LX.Sync.ClientStatus = {
|
||||
status: false,
|
||||
@@ -31,18 +31,6 @@ export const sendSyncMessage = (message: string) => {
|
||||
sendClientStatus(status)
|
||||
}
|
||||
|
||||
const handleConnection = (socket: LX.Sync.Client.Socket) => {
|
||||
for (const { registerEvent } of Object.values(modules)) {
|
||||
registerEvent(socket)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDisconnection = () => {
|
||||
for (const { unregisterEvent } of Object.values(modules)) {
|
||||
unregisterEvent()
|
||||
}
|
||||
}
|
||||
|
||||
const heartbeatTools = {
|
||||
failedNum: 0,
|
||||
maxTryNum: 100000,
|
||||
@@ -139,14 +127,14 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
|
||||
heartbeatTools.connect(client)
|
||||
|
||||
let closeEvents: Array<(err: Error) => (void | Promise<void>)> = []
|
||||
let disconnected = true
|
||||
|
||||
const message2read = createMsg2call({
|
||||
const message2read = createMsg2call<LX.Sync.ServerSyncActions>({
|
||||
funcsObj: {
|
||||
...callObj,
|
||||
list_sync_finished() {
|
||||
finished() {
|
||||
log.info('sync list success')
|
||||
client!.isReady = true
|
||||
handleConnection(client as LX.Sync.Client.Socket)
|
||||
sendSyncStatus({
|
||||
status: true,
|
||||
message: '',
|
||||
@@ -156,6 +144,7 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
|
||||
},
|
||||
timeout: 120 * 1000,
|
||||
sendMessage(data) {
|
||||
if (disconnected) throw new Error('disconnected')
|
||||
void encryptMsg(keyInfo, JSON.stringify(data)).then((data) => {
|
||||
client?.send(data)
|
||||
}).catch((err) => {
|
||||
@@ -178,13 +167,14 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
|
||||
},
|
||||
})
|
||||
|
||||
client.remoteSyncList = message2read.createSyncRemote('list')
|
||||
client.remote = message2read.remote
|
||||
client.remoteQueueList = message2read.createQueueRemote('list')
|
||||
|
||||
client.addEventListener('message', ({ data }) => {
|
||||
if (data == 'ping') return
|
||||
if (typeof data === 'string') {
|
||||
void decryptMsg(keyInfo, data).then((data) => {
|
||||
let syncData: LX.Sync.ServerActions
|
||||
let syncData: LX.Sync.ServerSyncActions
|
||||
try {
|
||||
syncData = JSON.parse(data)
|
||||
} catch (err) {
|
||||
@@ -212,6 +202,10 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
|
||||
// const store = getStore()
|
||||
// global.lx.syncKeyInfo = keyInfo
|
||||
client!.isReady = false
|
||||
client!.moduleReadys = {
|
||||
list: false,
|
||||
}
|
||||
disconnected = false
|
||||
sendSyncStatus({
|
||||
status: false,
|
||||
message: initMessage,
|
||||
@@ -225,7 +219,7 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
|
||||
log.error(err?.message)
|
||||
}
|
||||
closeEvents = []
|
||||
handleDisconnection()
|
||||
disconnected = true
|
||||
message2read.onDestroy()
|
||||
switch (code) {
|
||||
case SYNC_CLOSE_CODE.normal:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { File } from '../constants'
|
||||
import { File } from '../../../../common/constants_sync'
|
||||
|
||||
|
||||
let syncAuthKeys: Record<string, LX.Sync.ClientKeyInfo>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import handleAuth from './auth'
|
||||
import { connect as socketConnect, disconnect as socketDisconnect, sendSyncStatus, sendSyncMessage } from './client'
|
||||
// import { getSyncHost } from '@root/utils/data'
|
||||
import { SYNC_CODE } from '@common/constants'
|
||||
import log from '../log'
|
||||
import { parseUrl } from './utils'
|
||||
import migrateData from '../migrate'
|
||||
import { SYNC_CODE } from '@common/constants_sync'
|
||||
|
||||
let connectId = 0
|
||||
|
||||
|
||||
@@ -8,3 +8,7 @@ export const callObj = Object.assign({}, list.handler)
|
||||
export const modules = {
|
||||
list,
|
||||
}
|
||||
|
||||
export const featureVersion = {
|
||||
list: 1,
|
||||
} as const
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// 这个文件导出的方法将暴露给服务端调用,第一个参数固定为当前 socket 对象
|
||||
import { handleRemoteListAction } from '@main/modules/sync/utils'
|
||||
import { getLocalListData, setLocalListData } from '../../../utils'
|
||||
import { toMD5 } from '@common/utils/nodejs'
|
||||
import { removeSelectModeListener, sendCloseSelectMode, sendSelectMode } from '@main/modules/winMain'
|
||||
import log from '@main/modules/sync/log'
|
||||
import { registerEvent, unregisterEvent } from './localEvent'
|
||||
|
||||
const logInfo = (eventName: string, success = false) => {
|
||||
log.info(`[${eventName}]${eventName.replace('list:sync:list_sync_', '').replaceAll('_', ' ')}${success ? ' success' : ''}`)
|
||||
@@ -11,8 +13,8 @@ const logInfo = (eventName: string, success = false) => {
|
||||
// log.error(`[${eventName}]${eventName.replace('list:sync:list_sync_', '').replaceAll('_', ' ')} error: ${err.message}`)
|
||||
// }
|
||||
|
||||
export const onListSyncAction = async(socket: LX.Sync.Client.Socket, action: LX.Sync.ActionList) => {
|
||||
if (!socket.isReady) return
|
||||
export const onListSyncAction = async(socket: LX.Sync.Client.Socket, action: LX.Sync.List.ActionList) => {
|
||||
if (!socket.moduleReadys?.list) return
|
||||
await handleRemoteListAction(action)
|
||||
}
|
||||
|
||||
@@ -21,7 +23,7 @@ export const list_sync_get_md5 = async(socket: LX.Sync.Client.Socket) => {
|
||||
return toMD5(JSON.stringify(await getLocalListData()))
|
||||
}
|
||||
|
||||
const getSyncMode = async(socket: LX.Sync.Client.Socket): Promise<LX.Sync.ListSyncMode> => new Promise((resolve, reject) => {
|
||||
const getSyncMode = async(socket: LX.Sync.Client.Socket): Promise<LX.Sync.List.SyncMode> => new Promise((resolve, reject) => {
|
||||
const handleDisconnect = (err: Error) => {
|
||||
sendCloseSelectMode()
|
||||
removeSelectModeListener()
|
||||
@@ -47,7 +49,17 @@ export const list_sync_get_list_data = async(socket: LX.Sync.Client.Socket) => {
|
||||
return getLocalListData()
|
||||
}
|
||||
|
||||
export const list_sync_set_list_data = async(socket: LX.Sync.Client.Socket, data: LX.Sync.ListData) => {
|
||||
export const list_sync_set_list_data = async(socket: LX.Sync.Client.Socket, data: LX.Sync.List.ListData) => {
|
||||
logInfo('list:sync:list_sync_set_list_data')
|
||||
await setLocalListData(data)
|
||||
}
|
||||
|
||||
export const list_sync_finished = async(socket: LX.Sync.Client.Socket) => {
|
||||
logInfo('list:sync:finished')
|
||||
socket.moduleReadys.list = true
|
||||
registerEvent(socket)
|
||||
socket.onClose(() => {
|
||||
unregisterEvent()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,10 @@ export const registerEvent = (socket: LX.Sync.Client.Socket) => {
|
||||
// unregisterLocalListAction?.()
|
||||
// unregisterLocalListAction = null
|
||||
// })
|
||||
unregisterEvent()
|
||||
unregisterLocalListAction = registerListActionEvent((action) => {
|
||||
if (!socket?.isReady) return
|
||||
void socket.remoteSyncList.onListSyncAction(action)
|
||||
if (!socket.moduleReadys?.list) return
|
||||
void socket.remoteQueueList.onListSyncAction(action)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// 这个文件导出的方法将暴露给服务端调用,第一个参数固定为当前 socket 对象
|
||||
|
||||
// import { getUserSpace } from '@/user'
|
||||
// import { modules } from '../modules'
|
||||
|
||||
import { featureVersion } from '../modules'
|
||||
|
||||
|
||||
export const getEnabledFeatures = async(socket: LX.Sync.Client.Socket, serverType: LX.Sync.ServerType, supportedFeatures: LX.Sync.SupportedFeatures): Promise<LX.Sync.EnabledFeatures> => {
|
||||
// const userSpace = getUserSpace(socket.userInfo.name)
|
||||
switch (serverType) {
|
||||
case 'server':
|
||||
return {
|
||||
list: featureVersion.list == supportedFeatures.list,
|
||||
}
|
||||
case 'desktop-app':
|
||||
default:
|
||||
return {
|
||||
list: featureVersion.list == supportedFeatures.list,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import * as handler from './handler'
|
||||
import { callObj as _callObj } from '../modules'
|
||||
export { modules } from '../modules'
|
||||
|
||||
export const callObj = {
|
||||
...handler,
|
||||
..._callObj,
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
export const ENV_PARAMS = [
|
||||
'PORT',
|
||||
'BIND_IP',
|
||||
'CONFIG_PATH',
|
||||
'LOG_PATH',
|
||||
'DATA_PATH',
|
||||
'PROXY_HEADER',
|
||||
'MAX_SNAPSHOT_NUM',
|
||||
'LIST_ADD_MUSIC_LOCATION_TYPE',
|
||||
'LX_USER_',
|
||||
] as const
|
||||
|
||||
|
||||
export const LIST_IDS = {
|
||||
DEFAULT: 'default',
|
||||
LOVE: 'love',
|
||||
TEMP: 'temp',
|
||||
DOWNLOAD: 'download',
|
||||
PLAY_LATER: null,
|
||||
} as const
|
||||
|
||||
export const SYNC_CODE = {
|
||||
helloMsg: 'Hello~::^-^::~v4~',
|
||||
idPrefix: 'OjppZDo6',
|
||||
authMsg: 'lx-music auth::',
|
||||
msgAuthFailed: 'Auth failed',
|
||||
msgBlockedIp: 'Blocked IP',
|
||||
msgConnect: 'lx-music connect',
|
||||
|
||||
|
||||
authFailed: 'Auth failed',
|
||||
missingAuthCode: 'Missing auth code',
|
||||
getServiceIdFailed: 'Get service id failed',
|
||||
connectServiceFailed: 'Connect service failed',
|
||||
connecting: 'Connecting...',
|
||||
unknownServiceAddress: 'Unknown service address',
|
||||
} as const
|
||||
|
||||
export const SYNC_CLOSE_CODE = {
|
||||
normal: 1000,
|
||||
failed: 4100,
|
||||
} as const
|
||||
|
||||
export const TRANS_MODE: Readonly<Record<LX.Sync.ListSyncMode, LX.Sync.ListSyncMode>> = {
|
||||
merge_local_remote: 'merge_remote_local',
|
||||
merge_remote_local: 'merge_local_remote',
|
||||
overwrite_local_remote: 'overwrite_remote_local',
|
||||
overwrite_remote_local: 'overwrite_local_remote',
|
||||
overwrite_local_remote_full: 'overwrite_remote_local_full',
|
||||
overwrite_remote_local_full: 'overwrite_local_remote_full',
|
||||
cancel: 'cancel',
|
||||
} as const
|
||||
|
||||
export const File = {
|
||||
serverDataPath: 'sync/server',
|
||||
clientDataPath: 'sync/client',
|
||||
|
||||
serverInfoJSON: 'serverInfo.json',
|
||||
userDir: 'users',
|
||||
userDevicesJSON: 'devices.json',
|
||||
listDir: 'list',
|
||||
listSnapshotDir: 'snapshot',
|
||||
listSnapshotInfoJSON: 'snapshotInfo.json',
|
||||
|
||||
syncAuthKeysJSON: 'syncAuthKey.json',
|
||||
} as const
|
||||
@@ -1,4 +1,4 @@
|
||||
import { File } from './constants'
|
||||
import { File } from '../../../common/constants_sync'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
|
||||
@@ -10,3 +10,7 @@ export const modules = {
|
||||
|
||||
|
||||
export { ListManage } from './list'
|
||||
|
||||
export const featureVersion = {
|
||||
list: 1,
|
||||
} as const
|
||||
|
||||
@@ -44,7 +44,7 @@ export class ListManage {
|
||||
await this.snapshotDataManage.updateDeviceSnapshotKey(clientId, key)
|
||||
}
|
||||
|
||||
getListData = async(): Promise<LX.Sync.ListData> => {
|
||||
getListData = async(): Promise<LX.Sync.List.ListData> => {
|
||||
return getLocalListData()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import syncLog from '../../../log'
|
||||
import { getUserConfig, type UserDataManage } from '../../user/data'
|
||||
import { File } from '../../../constants'
|
||||
import { File } from '../../../../../../common/constants_sync'
|
||||
import { checkAndCreateDirSync } from '../../utils'
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ interface SnapshotInfo {
|
||||
latest: string | null
|
||||
time: number
|
||||
list: string[]
|
||||
clients: Record<string, LX.Sync.ListInfo>
|
||||
clients: Record<string, LX.Sync.List.ListInfo>
|
||||
}
|
||||
export class SnapshotDataManage {
|
||||
userDataManage: UserDataManage
|
||||
@@ -70,7 +70,7 @@ export class SnapshotDataManage {
|
||||
|
||||
getSnapshot = async(name: string) => {
|
||||
const filePath = path.join(this.snapshotDir, `snapshot_${name}`)
|
||||
let listData: LX.Sync.ListData
|
||||
let listData: LX.Sync.List.ListData
|
||||
try {
|
||||
listData = JSON.parse((await fs.promises.readFile(filePath)).toString('utf-8'))
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// 这个文件导出的方法将暴露给客户端调用,第一个参数固定为当前 socket 对象
|
||||
// import { throttle } from '@common/utils/common'
|
||||
// import { sendSyncActionList } from '@main/modules/winMain'
|
||||
// import { SYNC_CLOSE_CODE } from '@/constants'
|
||||
import { SYNC_CLOSE_CODE } from '@main/modules/sync/constants'
|
||||
import { SYNC_CLOSE_CODE } from '@common/constants_sync'
|
||||
import { getUserSpace } from '@main/modules/sync/server/user'
|
||||
import { handleRemoteListAction } from '@main/modules/sync/utils'
|
||||
// import { encryptMsg } from '@/utils/tools'
|
||||
@@ -108,7 +109,7 @@ import { handleRemoteListAction } from '@main/modules/sync/utils'
|
||||
// }
|
||||
// }
|
||||
|
||||
// export const sendListAction = async(action: LX.Sync.ActionList) => {
|
||||
// export const sendListAction = async(action: LX.Sync.List.ActionList) => {
|
||||
// console.log('sendListAction', action.action)
|
||||
// // io.sockets
|
||||
// await broadcast('list:sync:action', action)
|
||||
@@ -144,7 +145,8 @@ import { handleRemoteListAction } from '@main/modules/sync/utils'
|
||||
// // }
|
||||
// }
|
||||
|
||||
export const onListSyncAction = async(socket: LX.Sync.Server.Socket, action: LX.Sync.ActionList) => {
|
||||
export const onListSyncAction = async(socket: LX.Sync.Server.Socket, action: LX.Sync.List.ActionList) => {
|
||||
if (!socket.moduleReadys.list) return
|
||||
const userSpace = getUserSpace(socket.userInfo.name)
|
||||
await handleRemoteListAction(action).then(async updated => {
|
||||
if (!updated) {
|
||||
@@ -156,8 +158,8 @@ export const onListSyncAction = async(socket: LX.Sync.Server.Socket, action: LX.
|
||||
const currentUserName = socket.userInfo.name
|
||||
const currentId = socket.keyInfo.clientId
|
||||
socket.broadcast((client) => {
|
||||
if (client.keyInfo.clientId == currentId || !client.isReady || client.userInfo.name != currentUserName) return
|
||||
void client.remoteSyncList.onListSyncAction(action)
|
||||
if (client.keyInfo.clientId == currentId || !client.moduleReadys?.list || client.userInfo.name != currentUserName) return
|
||||
void client.remoteQueueList.onListSyncAction(action)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * as handler from './handler'
|
||||
export { default as sync } from './sync'
|
||||
export { sync } from './sync'
|
||||
export * from './localEvent'
|
||||
|
||||
@@ -5,13 +5,13 @@ import { getUserSpace } from '../../../user'
|
||||
let unregisterLocalListAction: (() => void) | null
|
||||
|
||||
|
||||
const sendListAction = async(wss: LX.Sync.Server.SocketServer, action: LX.Sync.ActionList) => {
|
||||
const sendListAction = async(wss: LX.Sync.Server.SocketServer, action: LX.Sync.List.ActionList) => {
|
||||
// console.log('sendListAction', action.action)
|
||||
const userSpace = getUserSpace()
|
||||
const key = await userSpace.listManage.createSnapshot()
|
||||
for (const client of wss.clients) {
|
||||
if (!client.isReady) return
|
||||
void client.remoteSyncList.onListSyncAction(action).then(() => {
|
||||
if (!client.moduleReadys?.list) continue
|
||||
void client.remoteQueueList.onListSyncAction(action).then(() => {
|
||||
void userSpace.listManage.updateDeviceSnapshotKey(client.keyInfo.clientId, key)
|
||||
})
|
||||
}
|
||||
@@ -23,6 +23,7 @@ export const registerEvent = (wss: LX.Sync.Server.SocketServer) => {
|
||||
// unregisterLocalListAction?.()
|
||||
// unregisterLocalListAction = null
|
||||
// })
|
||||
unregisterEvent()
|
||||
unregisterLocalListAction = registerListActionEvent((action) => {
|
||||
void sendListAction(wss, action)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SYNC_CLOSE_CODE } from '../../../../constants'
|
||||
// import { SYNC_CLOSE_CODE } from '../../../../constants'
|
||||
import { getUserSpace, getUserConfig } from '../../../user'
|
||||
import { getLocalListData, setLocalListData } from '@main/modules/sync/utils'
|
||||
// import { LIST_IDS } from '@common/constants'
|
||||
@@ -9,7 +9,7 @@ import { getLocalListData, setLocalListData } from '@main/modules/sync/utils'
|
||||
let syncingId: string | null = null
|
||||
const wait = async(time = 1000) => await new Promise((resolve, reject) => setTimeout(resolve, time))
|
||||
|
||||
const patchListData = (listData: Partial<LX.Sync.ListData>): LX.Sync.ListData => {
|
||||
const patchListData = (listData: Partial<LX.Sync.List.ListData>): LX.Sync.List.ListData => {
|
||||
return Object.assign({
|
||||
defaultList: [],
|
||||
loveList: [],
|
||||
@@ -17,39 +17,39 @@ const patchListData = (listData: Partial<LX.Sync.ListData>): LX.Sync.ListData =>
|
||||
}, listData)
|
||||
}
|
||||
|
||||
const getRemoteListData = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.ListData> => {
|
||||
const getRemoteListData = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.List.ListData> => {
|
||||
console.log('getRemoteListData')
|
||||
return patchListData(await socket.remoteSyncList.list_sync_get_list_data())
|
||||
return patchListData(await socket.remoteQueueList.list_sync_get_list_data())
|
||||
}
|
||||
|
||||
const getRemoteListMD5 = async(socket: LX.Sync.Server.Socket): Promise<string> => {
|
||||
return socket.remoteSyncList.list_sync_get_md5()
|
||||
return socket.remoteQueueList.list_sync_get_md5()
|
||||
}
|
||||
|
||||
// const getLocalListData = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.ListData> => {
|
||||
// const getLocalListData = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.List.ListData> => {
|
||||
// return getUserSpace(socket.userInfo.name).listManage.getListData()
|
||||
// }
|
||||
const getSyncMode = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.ListSyncMode> => {
|
||||
return socket.remoteSyncList.list_sync_get_sync_mode()
|
||||
const getSyncMode = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.List.SyncMode> => {
|
||||
return socket.remoteQueueList.list_sync_get_sync_mode()
|
||||
}
|
||||
|
||||
const finishedSync = async(socket: LX.Sync.Server.Socket) => {
|
||||
await socket.remoteSyncList.list_sync_finished()
|
||||
await socket.remoteQueueList.list_sync_finished()
|
||||
}
|
||||
|
||||
|
||||
const setLocalList = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.ListData) => {
|
||||
const setLocalList = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.List.ListData) => {
|
||||
await setLocalListData(listData)
|
||||
const userSpace = getUserSpace(socket.userInfo.name)
|
||||
return userSpace.listManage.createSnapshot()
|
||||
}
|
||||
|
||||
const overwriteRemoteListData = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.ListData, key: string, excludeIds: string[] = []) => {
|
||||
const overwriteRemoteListData = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.List.ListData, key: string, excludeIds: string[] = []) => {
|
||||
const action = { action: 'list_data_overwrite', data: listData } as const
|
||||
const tasks: Array<Promise<void>> = []
|
||||
socket.broadcast((client) => {
|
||||
if (excludeIds.includes(client.keyInfo.clientId) || client.userInfo.name != socket.userInfo.name || !client.isReady) return
|
||||
tasks.push(client.remoteSyncList.onListSyncAction(action).then(async() => {
|
||||
if (excludeIds.includes(client.keyInfo.clientId) || client.userInfo.name != socket.userInfo.name || !client.moduleReadys?.list) return
|
||||
tasks.push(client.remoteQueueList.onListSyncAction(action).then(async() => {
|
||||
const userSpace = getUserSpace(socket.userInfo.name)
|
||||
return userSpace.listManage.updateDeviceSnapshotKey(socket.keyInfo.clientId, key)
|
||||
}).catch(err => {
|
||||
@@ -59,14 +59,14 @@ const overwriteRemoteListData = async(socket: LX.Sync.Server.Socket, listData: L
|
||||
if (!tasks.length) return
|
||||
await Promise.all(tasks)
|
||||
}
|
||||
const setRemotelList = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.ListData, key: string): Promise<void> => {
|
||||
await socket.remoteSyncList.list_sync_set_list_data(listData)
|
||||
const setRemotelList = async(socket: LX.Sync.Server.Socket, listData: LX.Sync.List.ListData, key: string): Promise<void> => {
|
||||
await socket.remoteQueueList.list_sync_set_list_data(listData)
|
||||
const userSpace = getUserSpace(socket.userInfo.name)
|
||||
await userSpace.listManage.updateDeviceSnapshotKey(socket.keyInfo.clientId, key)
|
||||
}
|
||||
|
||||
type UserDataObj = Map<string, LX.List.UserListInfoFull>
|
||||
const createUserListDataObj = (listData: LX.Sync.ListData): UserDataObj => {
|
||||
const createUserListDataObj = (listData: LX.Sync.List.ListData): UserDataObj => {
|
||||
const userListDataObj: UserDataObj = new Map()
|
||||
for (const list of listData.userList) userListDataObj.set(list.id, list)
|
||||
return userListDataObj
|
||||
@@ -111,9 +111,9 @@ const handleMergeList = (
|
||||
}
|
||||
return ids.map(id => map.get(id)) as LX.Music.MusicInfo[]
|
||||
}
|
||||
const mergeList = (socket: LX.Sync.Server.Socket, sourceListData: LX.Sync.ListData, targetListData: LX.Sync.ListData): LX.Sync.ListData => {
|
||||
const mergeList = (socket: LX.Sync.Server.Socket, sourceListData: LX.Sync.List.ListData, targetListData: LX.Sync.List.ListData): LX.Sync.List.ListData => {
|
||||
const addMusicLocationType = getUserConfig(socket.userInfo.name)['list.addMusicLocationType']
|
||||
const newListData: LX.Sync.ListData = {
|
||||
const newListData: LX.Sync.List.ListData = {
|
||||
defaultList: [],
|
||||
loveList: [],
|
||||
userList: [],
|
||||
@@ -147,8 +147,8 @@ const mergeList = (socket: LX.Sync.Server.Socket, sourceListData: LX.Sync.ListDa
|
||||
|
||||
return newListData
|
||||
}
|
||||
const overwriteList = (sourceListData: LX.Sync.ListData, targetListData: LX.Sync.ListData): LX.Sync.ListData => {
|
||||
const newListData: LX.Sync.ListData = {
|
||||
const overwriteList = (sourceListData: LX.Sync.List.ListData, targetListData: LX.Sync.List.ListData): LX.Sync.List.ListData => {
|
||||
const newListData: LX.Sync.List.ListData = {
|
||||
defaultList: [],
|
||||
loveList: [],
|
||||
userList: [],
|
||||
@@ -171,16 +171,13 @@ const overwriteList = (sourceListData: LX.Sync.ListData, targetListData: LX.Sync
|
||||
return newListData
|
||||
}
|
||||
|
||||
const handleMergeListData = async(socket: LX.Sync.Server.Socket): Promise<[LX.Sync.ListData, boolean, boolean]> => {
|
||||
const mode: LX.Sync.ListSyncMode = await getSyncMode(socket)
|
||||
const handleMergeListData = async(socket: LX.Sync.Server.Socket): Promise<[LX.Sync.List.ListData, boolean, boolean]> => {
|
||||
const mode: LX.Sync.List.SyncMode = await getSyncMode(socket)
|
||||
|
||||
if (mode == 'cancel') {
|
||||
socket.close(SYNC_CLOSE_CODE.normal)
|
||||
throw new Error('cancel')
|
||||
}
|
||||
if (mode == 'cancel') throw new Error('cancel')
|
||||
const [remoteListData, localListData] = await Promise.all([getRemoteListData(socket), getLocalListData()])
|
||||
console.log('handleMergeListData', 'remoteListData, localListData')
|
||||
let listData: LX.Sync.ListData
|
||||
let listData: LX.Sync.List.ListData
|
||||
let requiredUpdateLocalListData = true
|
||||
let requiredUpdateRemoteListData = true
|
||||
switch (mode) {
|
||||
@@ -206,9 +203,7 @@ const handleMergeListData = async(socket: LX.Sync.Server.Socket): Promise<[LX.Sy
|
||||
break
|
||||
// case 'none': return null
|
||||
// case 'cancel':
|
||||
default:
|
||||
socket.close(SYNC_CLOSE_CODE.normal)
|
||||
throw new Error('cancel')
|
||||
default: throw new Error('cancel')
|
||||
}
|
||||
return [listData, requiredUpdateLocalListData, requiredUpdateRemoteListData]
|
||||
}
|
||||
@@ -299,12 +294,12 @@ const checkListLatest = async(socket: LX.Sync.Server.Socket) => {
|
||||
if (latest && userCurrentListInfoKey != currentListInfoKey) await userSpace.listManage.updateDeviceSnapshotKey(socket.keyInfo.clientId, currentListInfoKey)
|
||||
return latest
|
||||
}
|
||||
const handleMergeListDataFromSnapshot = async(socket: LX.Sync.Server.Socket, snapshot: LX.Sync.ListData) => {
|
||||
const handleMergeListDataFromSnapshot = async(socket: LX.Sync.Server.Socket, snapshot: LX.Sync.List.ListData) => {
|
||||
if (await checkListLatest(socket)) return
|
||||
|
||||
const addMusicLocationType = getUserConfig(socket.userInfo.name)['list.addMusicLocationType']
|
||||
const [remoteListData, localListData] = await Promise.all([getRemoteListData(socket), getLocalListData()])
|
||||
const newListData: LX.Sync.ListData = {
|
||||
const newListData: LX.Sync.List.ListData = {
|
||||
defaultList: [],
|
||||
loveList: [],
|
||||
userList: [],
|
||||
@@ -413,7 +408,7 @@ const syncList = async(socket: LX.Sync.Server.Socket) => {
|
||||
// await fsPromises.unlink(filePath)
|
||||
// }
|
||||
|
||||
export default async(socket: LX.Sync.Server.Socket) => {
|
||||
export const sync = async(socket: LX.Sync.Server.Socket) => {
|
||||
let disconnected = false
|
||||
socket.onClose(() => {
|
||||
disconnected = true
|
||||
@@ -428,7 +423,8 @@ export default async(socket: LX.Sync.Server.Socket) => {
|
||||
|
||||
syncingId = socket.keyInfo.clientId
|
||||
await syncList(socket).then(async() => {
|
||||
return finishedSync(socket)
|
||||
await finishedSync(socket)
|
||||
socket.moduleReadys.list = true
|
||||
}).finally(() => {
|
||||
syncingId = null
|
||||
})
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type http from 'http'
|
||||
import { SYNC_CODE } from '@common/constants'
|
||||
import {
|
||||
aesEncrypt,
|
||||
aesDecrypt,
|
||||
@@ -10,6 +9,7 @@ import querystring from 'node:querystring'
|
||||
import { getUserSpace, createClientKeyInfo } from '../user'
|
||||
import { toMD5 } from '../utils'
|
||||
import { getComputerName } from '../../utils'
|
||||
import { SYNC_CODE } from '@common/constants_sync'
|
||||
|
||||
const requestIps = new Map<string, number>()
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import http, { type IncomingMessage } from 'node:http'
|
||||
import url from 'node:url'
|
||||
import { WebSocketServer } from 'ws'
|
||||
import { modules, callObj } from '../modules'
|
||||
import { registerLocalSyncEvent, callObj, sync, unregisterLocalSyncEvent } from './sync'
|
||||
import { authCode, authConnect } from './auth'
|
||||
import { getAddress } from '../../utils'
|
||||
import { SYNC_CLOSE_CODE, SYNC_CODE } from '../../constants'
|
||||
import { SYNC_CLOSE_CODE, SYNC_CODE } from '@common/constants_sync'
|
||||
import { getUserSpace, releaseUserSpace, getServerId, initServerInfo } from '../user'
|
||||
import { createMsg2call } from 'message2call'
|
||||
import log from '../../log'
|
||||
@@ -23,6 +22,8 @@ let status: LX.Sync.ServerStatus = {
|
||||
|
||||
let stopingServer = false
|
||||
|
||||
let host = 'http://localhost'
|
||||
|
||||
const codeTools: {
|
||||
timeout: NodeJS.Timer | null
|
||||
start: () => void
|
||||
@@ -42,46 +43,25 @@ const codeTools: {
|
||||
},
|
||||
}
|
||||
|
||||
const syncData = async(socket: LX.Sync.Server.Socket) => {
|
||||
let disconnected = false
|
||||
socket.onClose(() => {
|
||||
disconnected = true
|
||||
})
|
||||
for (const module of Object.values(modules)) {
|
||||
await module.sync(socket)
|
||||
if (disconnected) throw new Error('disconnected')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const registerLocalSyncEvent = async(wss: LX.Sync.Server.SocketServer) => {
|
||||
for (const module of Object.values(modules)) {
|
||||
module.registerEvent(wss)
|
||||
}
|
||||
}
|
||||
|
||||
const unregisterLocalSyncEvent = () => {
|
||||
for (const module of Object.values(modules)) {
|
||||
module.unregisterEvent()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const checkDuplicateClient = (newSocket: LX.Sync.Server.Socket) => {
|
||||
for (const client of [...wss!.clients]) {
|
||||
if (client === newSocket || client.keyInfo.clientId != newSocket.keyInfo.clientId) continue
|
||||
log.info('duplicate client', client.userInfo.name, client.keyInfo.deviceName)
|
||||
client.isReady = false
|
||||
for (const name of Object.keys(client.moduleReadys) as Array<keyof LX.Sync.Server.Socket['moduleReadys']>) {
|
||||
client.moduleReadys[name] = false
|
||||
}
|
||||
client.close(SYNC_CLOSE_CODE.normal)
|
||||
}
|
||||
}
|
||||
|
||||
const handleConnection = async(socket: LX.Sync.Server.Socket, request: IncomingMessage) => {
|
||||
const queryData = url.parse(request.url as string, true).query as Record<string, string>
|
||||
const queryData = new URL(request.url as string, host).searchParams
|
||||
const clientId = queryData.get('i')
|
||||
|
||||
// // if (typeof socket.handshake.query.i != 'string') return socket.disconnect(true)
|
||||
const userSpace = getUserSpace()
|
||||
const keyInfo = userSpace.dataManage.getClientKeyInfo(queryData.i)
|
||||
const keyInfo = userSpace.dataManage.getClientKeyInfo(clientId)
|
||||
if (!keyInfo) {
|
||||
socket.close(SYNC_CLOSE_CODE.failed)
|
||||
return
|
||||
@@ -95,7 +75,7 @@ const handleConnection = async(socket: LX.Sync.Server.Socket, request: IncomingM
|
||||
checkDuplicateClient(socket)
|
||||
|
||||
try {
|
||||
await syncData(socket)
|
||||
await sync(socket)
|
||||
} catch (err) {
|
||||
// console.log(err)
|
||||
log.warn(err)
|
||||
@@ -174,6 +154,12 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
|
||||
|
||||
wss.on('connection', function(socket, request) {
|
||||
socket.isReady = false
|
||||
socket.moduleReadys = {
|
||||
list: false,
|
||||
}
|
||||
socket.feature = {
|
||||
list: false,
|
||||
}
|
||||
socket.on('pong', () => {
|
||||
socket.isAlive = true
|
||||
})
|
||||
@@ -182,10 +168,12 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
|
||||
// const events = new Map<keyof LX.Sync.ActionSyncType, Array<(err: Error | null, data: LX.Sync.ActionSyncType[keyof LX.Sync.ActionSyncType]) => void>>()
|
||||
// let events: Partial<{ [K in keyof LX.Sync.ActionSyncType]: Array<(data: LX.Sync.ActionSyncType[K]) => void> }> = {}
|
||||
let closeEvents: Array<(err: Error) => (void | Promise<void>)> = []
|
||||
const msg2call = createMsg2call<LX.Sync.ClientActions>({
|
||||
let disconnected = false
|
||||
const msg2call = createMsg2call<LX.Sync.ClientSyncActions>({
|
||||
funcsObj: callObj,
|
||||
timeout: 120 * 1000,
|
||||
sendMessage(data) {
|
||||
if (disconnected) throw new Error('disconnected')
|
||||
void encryptMsg(socket.keyInfo, JSON.stringify(data)).then((data) => {
|
||||
// console.log('sendData', eventName)
|
||||
socket.send(data)
|
||||
@@ -200,13 +188,14 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
|
||||
},
|
||||
onError(error, path, groupName) {
|
||||
const name = groupName ?? ''
|
||||
log.error(`sync call ${name} ${path.join('.')} error:`, error)
|
||||
const deviceName = socket.keyInfo?.deviceName ?? ''
|
||||
log.error(`sync call ${deviceName} ${name} ${path.join('.')} error:`, error)
|
||||
if (groupName == null) return
|
||||
socket.close(SYNC_CLOSE_CODE.failed)
|
||||
},
|
||||
})
|
||||
socket.remote = msg2call.remote
|
||||
socket.remoteSyncList = msg2call.createSyncRemote('list')
|
||||
socket.remoteQueueList = msg2call.createQueueRemote('list')
|
||||
socket.addEventListener('message', ({ data }) => {
|
||||
if (typeof data != 'string') return
|
||||
void decryptMsg(socket.keyInfo, data).then((data) => {
|
||||
@@ -233,14 +222,15 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
|
||||
log.error(err?.message)
|
||||
}
|
||||
closeEvents = []
|
||||
disconnected = true
|
||||
msg2call.onDestroy()
|
||||
if (socket.isReady) {
|
||||
log.info('deconnection', socket.userInfo.name, socket.keyInfo.deviceName)
|
||||
// events = {}
|
||||
if (!status.devices.length) handleUnconnection()
|
||||
} else {
|
||||
const queryData = url.parse(request.url as string, true).query as Record<string, string>
|
||||
log.info('deconnection', queryData.i)
|
||||
const queryData = new URL(request.url as string, host).searchParams
|
||||
log.info('deconnection', queryData.get('i'))
|
||||
}
|
||||
})
|
||||
socket.onClose = function(handler: typeof closeEvents[number]) {
|
||||
@@ -311,6 +301,7 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
|
||||
void registerLocalSyncEvent(wss as LX.Sync.Server.SocketServer)
|
||||
})
|
||||
|
||||
host = `http://${ip}:${port}`
|
||||
httpServer.listen(port, ip)
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { modules } from '../../modules'
|
||||
|
||||
export const registerLocalSyncEvent = async(wss: LX.Sync.Server.SocketServer) => {
|
||||
unregisterLocalSyncEvent()
|
||||
for (const module of Object.values(modules)) {
|
||||
module.registerEvent(wss)
|
||||
}
|
||||
}
|
||||
|
||||
export const unregisterLocalSyncEvent = () => {
|
||||
for (const module of Object.values(modules)) {
|
||||
module.unregisterEvent()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 这个文件导出的方法将暴露给客户端调用,第一个参数固定为当前 socket 对象
|
||||
// import { getUserSpace } from '@/user'
|
||||
import { FeaturesList } from '../../../../../../common/constants_sync'
|
||||
import { modules } from '../../modules'
|
||||
|
||||
|
||||
export const onFeatureChanged = async(socket: LX.Sync.Server.Socket, feature: LX.Sync.EnabledFeatures) => {
|
||||
// const userSpace = getUserSpace(socket.userInfo.name)
|
||||
const beforeFeature = socket.feature
|
||||
|
||||
for (const name of FeaturesList) {
|
||||
if (feature[name] == beforeFeature[name]) continue
|
||||
if (feature[name]) {
|
||||
await modules[name].sync(socket).then(() => {
|
||||
beforeFeature[name] = true
|
||||
}).catch(_ => _)
|
||||
} else {
|
||||
socket.moduleReadys[name] = false
|
||||
beforeFeature[name] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as handler from './handler'
|
||||
import { callObj as _callObj } from '../../modules'
|
||||
export { sync } from './sync'
|
||||
export { modules } from '../../modules'
|
||||
export * from './event'
|
||||
|
||||
export const callObj = {
|
||||
...handler,
|
||||
..._callObj,
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { FeaturesList } from '../../../../../../common/constants_sync'
|
||||
import { featureVersion, modules } from '../../modules'
|
||||
|
||||
|
||||
export const sync = async(socket: LX.Sync.Server.Socket) => {
|
||||
let disconnected = false
|
||||
socket.onClose(() => {
|
||||
disconnected = true
|
||||
})
|
||||
const enabledFeatures = await socket.remote.getEnabledFeatures('desktop-app', featureVersion)
|
||||
|
||||
if (disconnected) throw new Error('disconnected')
|
||||
for (const moduleName of FeaturesList) {
|
||||
if (enabledFeatures[moduleName]) {
|
||||
await modules[moduleName].sync(socket).then(() => {
|
||||
socket.feature[moduleName] = true
|
||||
}).catch(_ => _)
|
||||
}
|
||||
if (disconnected) throw new Error('disconnected')
|
||||
}
|
||||
await socket.remote.finished()
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import path from 'node:path'
|
||||
import { randomBytes } from 'node:crypto'
|
||||
import { throttle } from '@common/utils/common'
|
||||
import { filterFileName, toMD5 } from '../utils'
|
||||
import { File } from '../../constants'
|
||||
import { File } from '../../../../../common/constants_sync'
|
||||
|
||||
|
||||
interface ServerInfo {
|
||||
@@ -111,7 +111,7 @@ export class UserDataManage {
|
||||
this.saveDevicesInfoThrottle()
|
||||
}
|
||||
|
||||
getClientKeyInfo = (clientId?: string): LX.Sync.ServerKeyInfo | null => {
|
||||
getClientKeyInfo = (clientId?: string | null): LX.Sync.ServerKeyInfo | null => {
|
||||
if (!clientId) return null
|
||||
return this.devicesInfo.clients[clientId] ?? null
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ export const rsaDecrypt = (buffer: Buffer, key: string): Buffer => {
|
||||
return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer)
|
||||
}
|
||||
|
||||
export const getLocalListData = async(): Promise<LX.Sync.ListData> => {
|
||||
const lists: LX.Sync.ListData = {
|
||||
export const getLocalListData = async(): Promise<LX.Sync.List.ListData> => {
|
||||
const lists: LX.Sync.List.ListData = {
|
||||
defaultList: await global.lx.worker.dbService.getListMusics(LIST_IDS.DEFAULT),
|
||||
loveList: await global.lx.worker.dbService.getListMusics(LIST_IDS.LOVE),
|
||||
userList: [],
|
||||
@@ -106,12 +106,12 @@ export const getLocalListData = async(): Promise<LX.Sync.ListData> => {
|
||||
return lists
|
||||
}
|
||||
|
||||
export const setLocalListData = async(listData: LX.Sync.ListData) => {
|
||||
export const setLocalListData = async(listData: LX.Sync.List.ListData) => {
|
||||
await global.lx.event_list.list_data_overwrite(listData, true)
|
||||
}
|
||||
|
||||
|
||||
export const registerListActionEvent = (sendListAction: (action: LX.Sync.ActionList) => (void | Promise<void>)) => {
|
||||
export const registerListActionEvent = (sendListAction: (action: LX.Sync.List.ActionList) => (void | Promise<void>)) => {
|
||||
const list_data_overwrite = async(listData: MakeOptional<LX.List.ListDataFull, 'tempList'>, isRemote: boolean = false) => {
|
||||
if (isRemote) return
|
||||
await sendListAction({ action: 'list_data_overwrite', data: listData })
|
||||
@@ -188,7 +188,7 @@ export const registerListActionEvent = (sendListAction: (action: LX.Sync.ActionL
|
||||
}
|
||||
}
|
||||
|
||||
export const handleRemoteListAction = async({ action, data }: LX.Sync.ActionList) => {
|
||||
export const handleRemoteListAction = async({ action, data }: LX.Sync.List.ActionList) => {
|
||||
// console.log('handleRemoteListAction', action)
|
||||
|
||||
switch (action) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { WIN_MAIN_RENDERER_EVENT_NAME } from '@common/ipcNames'
|
||||
import { startServer, stopServer, getServerStatus, generateCode, connectServer, disconnectServer, getClientStatus } from '@main/modules/sync'
|
||||
import { sendEvent } from '../main'
|
||||
|
||||
let selectModeListenr: ((mode: LX.Sync.ListSyncMode | null) => void) | null = null
|
||||
let selectModeListenr: ((mode: LX.Sync.List.SyncMode | null) => void) | null = null
|
||||
|
||||
export default () => {
|
||||
mainHandle<LX.Sync.SyncServiceActions, any>(WIN_MAIN_RENDERER_EVENT_NAME.sync_action, async({ params: data }) => {
|
||||
@@ -46,7 +46,7 @@ export const sendServerStatus = (status: LX.Sync.ServerStatus) => {
|
||||
data: status,
|
||||
})
|
||||
}
|
||||
export const sendSelectMode = (deviceName: string, listener: (mode: LX.Sync.ListSyncMode | null) => void) => {
|
||||
export const sendSelectMode = (deviceName: string, listener: (mode: LX.Sync.List.SyncMode | null) => void) => {
|
||||
selectModeListenr = listener
|
||||
sendSyncAction({ action: 'select_mode', data: deviceName })
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -3,8 +3,8 @@ import '@common/types/app_setting'
|
||||
import '@common/types/common'
|
||||
import '@common/types/user_api'
|
||||
import '@common/types/sync'
|
||||
import '@common/types/sync_common'
|
||||
import '@common/types/list'
|
||||
import '@common/types/list_sync'
|
||||
import '@common/types/download_list'
|
||||
import '@common/types/music'
|
||||
import '@common/types/player'
|
||||
|
||||
Vendored
+12
-3
@@ -13,9 +13,13 @@ declare global {
|
||||
keyInfo: ClientKeyInfo
|
||||
urlInfo: UrlInfo
|
||||
}
|
||||
moduleReadys: {
|
||||
list: boolean
|
||||
}
|
||||
|
||||
onClose: (handler: (err: Error) => (void | Promise<void>)) => () => void
|
||||
remoteSyncList: LX.Sync.ServerActions
|
||||
remote: LX.Sync.ServerSyncActions
|
||||
remoteQueueList: LX.Sync.ServerSyncListActions
|
||||
}
|
||||
|
||||
interface UrlInfo {
|
||||
@@ -31,11 +35,16 @@ declare global {
|
||||
isReady: boolean
|
||||
userInfo: { name: 'default' }
|
||||
keyInfo: ServerKeyInfo
|
||||
feature: LX.Sync.EnabledFeatures
|
||||
moduleReadys: {
|
||||
list: boolean
|
||||
}
|
||||
|
||||
onClose: (handler: (err: Error) => (void | Promise<void>)) => () => void
|
||||
broadcast: (handler: (client: Socket) => void) => void
|
||||
|
||||
remote: LX.Sync.ClientActions
|
||||
remoteSyncList: LX.Sync.ClientActions
|
||||
remote: LX.Sync.ClientSyncActions
|
||||
remoteQueueList: LX.Sync.ClientSyncListActions
|
||||
}
|
||||
type SocketServer = WS.Server<Socket>
|
||||
}
|
||||
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
declare namespace LX {
|
||||
namespace Sync {
|
||||
type ServerSyncActions = WarpPromiseRecord<{
|
||||
onFeatureChanged: (feature: EnabledFeatures) => void
|
||||
}>
|
||||
type ServerSyncListActions = WarpPromiseRecord<{
|
||||
onListSyncAction: (action: LX.Sync.List.ActionList) => void
|
||||
}>
|
||||
|
||||
type ClientSyncActions = WarpPromiseRecord<{
|
||||
getEnabledFeatures: (serverType: ServerType, supportedFeatures: SupportedFeatures) => EnabledFeatures
|
||||
finished: () => void
|
||||
}>
|
||||
type ClientSyncListActions = WarpPromiseRecord<{
|
||||
onListSyncAction: (action: LX.Sync.List.ActionList) => void
|
||||
list_sync_get_md5: () => string
|
||||
list_sync_get_sync_mode: () => LX.Sync.List.SyncMode
|
||||
list_sync_get_list_data: () => LX.Sync.List.ListData
|
||||
list_sync_set_list_data: (data: LX.Sync.List.ListData) => void
|
||||
list_sync_finished: () => void
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user