Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 1x 1x 1x 1x 1x 1x 1x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 1x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 611x 1x | /** biome-ignore-all lint/complexity/noThisInStatic: In static methods, this refers to the constructor (the subclass that invoked the method) when we want to refer to the subclass serviceName.
*
* NOTE: This file imports PLATFORM_CONFIG directly rather than using the PlatformProvider
* because it contains static utility methods that are called from various contexts,
* including non-React code. The configuration is compile-time constant, so direct
* import is safe and ensures the methods work consistently regardless of React context.
*/
import { v4 as uuidv4 } from "uuid"
import { PLATFORM_CONFIG } from "../config/platform.config"
export interface Callbacks<TResponse> {
onResponse: (response: TResponse) => void
onError: (error: Error) => void
onComplete: () => void
}
export abstract class ProtoBusClient {
static serviceName: string
static async makeUnaryRequest<TRequest, TResponse>(
methodName: string,
request: TRequest,
encodeRequest: (_: TRequest) => unknown,
decodeResponse: (_: { [key: string]: any }) => TResponse,
): Promise<TResponse> {
return new Promise((resolve, reject) => {
const requestId = uuidv4()
// Set up one-time listener for this specific request
const handleResponse = (event: MessageEvent) => {
const message = event.data
if (message.type === "grpc_response" && message.grpc_response?.request_id === requestId) {
// Remove listener once we get our response
window.removeEventListener("message", handleResponse)
if (message.grpc_response.message) {
const response = PLATFORM_CONFIG.decodeMessage(message.grpc_response.message, decodeResponse)
resolve(response)
} else if (message.grpc_response.error) {
reject(new Error(message.grpc_response.error))
} else {
console.error("Received ProtoBus message with no response or error ", JSON.stringify(message))
}
}
}
window.addEventListener("message", handleResponse)
PLATFORM_CONFIG.postMessage({
type: "grpc_request",
grpc_request: {
service: this.serviceName,
method: methodName,
message: PLATFORM_CONFIG.encodeMessage(request, encodeRequest),
request_id: requestId,
is_streaming: false,
},
})
})
}
static makeStreamingRequest<TRequest, TResponse>(
methodName: string,
request: TRequest,
encodeRequest: (_: TRequest) => unknown,
decodeResponse: (_: { [key: string]: any }) => TResponse,
callbacks: Callbacks<TResponse>,
): () => void {
const requestId = uuidv4()
// Set up listener for streaming responses
const handleResponse = (event: MessageEvent) => {
const message = event.data
if (message.type === "grpc_response" && message.grpc_response?.request_id === requestId) {
if (message.grpc_response.message) {
// Process streaming message
const response = PLATFORM_CONFIG.decodeMessage(message.grpc_response.message, decodeResponse)
callbacks.onResponse(response)
} else if (message.grpc_response.error) {
// Handle error
if (callbacks.onError) {
callbacks.onError(new Error(message.grpc_response.error))
}
// Only remove the event listener on error
window.removeEventListener("message", handleResponse)
} else {
console.error("Received ProtoBus message with no response or error ", JSON.stringify(message))
}
if (message.grpc_response.is_streaming === false) {
if (callbacks.onComplete) {
callbacks.onComplete()
}
// Only remove the event listener when the stream is explicitly ended
window.removeEventListener("message", handleResponse)
}
}
}
window.addEventListener("message", handleResponse)
PLATFORM_CONFIG.postMessage({
type: "grpc_request",
grpc_request: {
service: this.serviceName,
method: methodName,
message: PLATFORM_CONFIG.encodeMessage(request, encodeRequest),
request_id: requestId,
is_streaming: true,
},
})
// Return a function to cancel the stream
return () => {
window.removeEventListener("message", handleResponse)
PLATFORM_CONFIG.postMessage({
type: "grpc_request_cancel",
grpc_request_cancel: {
request_id: requestId,
},
})
console.log(`[DEBUG] Sent cancellation for request: ${requestId}`)
}
}
}
|