MCPcopy
hub / github.com/MetaCubeX/metacubexd / createHelperClient

Function createHelperClient

apps/desktop/src/main/helper/client.ts:131–303  ·  view source on GitHub ↗
(
  opts: CreateHelperClientOptions,
)

Source from the content-addressed store, hash-verified

129 * helper reports a different protocol version, so B-3 can trigger a re-install.
130 */
131export function createHelperClient(
132 opts: CreateHelperClientOptions,
133): HelperClient {
134 const { socketPath, secret, onDisconnect } = opts
135 const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
136 const closeTimeoutMs = opts.closeTimeoutMs ?? DEFAULT_CLOSE_TIMEOUT_MS
137
138 // FIFO queue of in-flight requests awaiting their response frame.
139 interface Pending {
140 resolve: (res: HelperResponse) => void
141 reject: (err: Error) => void
142 timer: ReturnType<typeof setTimeout>
143 }
144 const pending: Pending[] = []
145 let buffer = ''
146 /** Set once the socket dies so later requests fail fast instead of hanging. */
147 let fatal: Error | undefined
148 /** Set when WE end the socket so the close/error isn't read as a crash. */
149 let closing = false
150 /** Guards onDisconnect to fire at most once (error + close can both arrive). */
151 let disconnected = false
152
153 /**
154 * Notify the owner of an UNEXPECTED drop exactly once. A deliberate `close()`
155 * sets `closing` first, so the resulting close/error is never misreported as a
156 * helper crash. No-op when no callback was supplied (sidecar callers).
157 */
158 function reportDisconnect(err?: Error): void {
159 if (closing || disconnected) return
160 disconnected = true
161 onDisconnect?.(err)
162 }
163
164 const socket: Socket = connect(socketPath)
165 socket.setEncoding('utf8')
166
167 socket.on('data', (chunk: string) => {
168 buffer += chunk
169 const { messages, rest } = parseMessages<HelperResponse>(buffer)
170 buffer = rest
171 for (const res of messages) {
172 const next = pending.shift()
173 if (!next) continue
174 clearTimeout(next.timer)
175 if (res.ok) {
176 next.resolve(res)
177 } else {
178 // Surface the server's failure — never swallow it.
179 next.reject(
180 new HelperRequestError(
181 (res as { error?: string }).error ?? 'helper: request failed',
182 res.type,
183 ),
184 )
185 }
186 }
187 })
188

Callers 2

bootFunction · 0.90

Calls 4

parseMessagesFunction · 0.90
failAllFunction · 0.85
reportDisconnectFunction · 0.85
connectFunction · 0.50

Tested by

no test coverage detected