import * as http from 'http' import * as fs from 'fs' import * as path from 'path' import * as vscode from 'vscode' import { Socket } from 'net' import { isConnectToCli } from '../readConfig' import { fm } from '../helpers/FileManage' import { ViewDependencies, ForeignViewInfo, ComponentsInfo, store } from '../Store' interface WingedExtensionActionData { syncData: { viewDependencies: ViewDependencies, foreignViewInfo: ForeignViewInfo, componentsInfo: ComponentsInfo }, heartBeat: string } export interface WingedExtensionEvent { action: K data: WingedExtensionActionData[K] } const WINGED_SERVER = { API_PATH: '/__winged_extension' } class Connector { private path?: string private socket: Socket | null = null private lock: boolean = true constructor() { if (!isConnectToCli) return const dir = fm.getRootPath() if (dir) { const target = path.join(dir, './winged.js') fs.watchFile(target, () => { this.path = undefined }) } } public connect(delay = 5000) { if (!isConnectToCli) return setTimeout(() => { if (!this.path) { try { const res = this.initPath() if (!res) { // 项目初始化错误 return } } catch (error) { // 文件寻找出现错误 , 重新连接 this.connect() } } if (this.path) { http .get(this.path, (res) => { if (!this.socket) { this.socket = res.socket } res.on('data', this.handler.bind(this)) res.on('close', () => { vscode.window.showInformationMessage( 'winged-cli 断开了与插件的连接,确保 dev-server 正常工作后,输入命令: "Winged: Restart Client" 重启插件客户端!' ) this.lock = false this.socket = null }) }) .on('error', () => { // 连接失败 重新连接 this.connect() }) } }, delay) } private handler(message: string) { const event: WingedExtensionEvent = JSON.parse(message) if ((event as WingedExtensionEvent<'heartBeat'>).action === 'heartBeat') { return } if ((event as WingedExtensionEvent<'syncData'>).action === 'syncData') { const data: WingedExtensionEvent<'syncData'>['data'] = event.data store.componentsInfo = data.componentsInfo store.foreignViewInfo = data.foreignViewInfo store.viewDependencies = data.viewDependencies } } private initPath() { const dir = fm.getRootPath() if (dir) { const wingedConfig = require(path.join(dir, './winged.js')) const port = wingedConfig?.devServer?.wingedHmrPort if (port) { this.path = `http://localhost:${port}${WINGED_SERVER.API_PATH}` return true } } return undefined } // 重启客户端 public reStart() { if (this.socket) { this.socket.end() this.socket = null this.lock = false } if (this.lock) return this.path = undefined this.connect(100) } } export const con = new Connector()