| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #!/usr/bin/env npx tsx
- import * as grpc from "@grpc/grpc-js"
- import { ReflectionService } from "@grpc/reflection"
- import * as health from "grpc-health-check"
- import * as os from "os"
- import { type DiffServiceServer, DiffServiceService } from "../src/generated/grpc-js/host/diff"
- import { type EnvServiceServer, EnvServiceService } from "../src/generated/grpc-js/host/env"
- import { type TestingServiceServer, TestingServiceService } from "../src/generated/grpc-js/host/testing"
- import { type WindowServiceServer, WindowServiceService } from "../src/generated/grpc-js/host/window"
- import { type WorkspaceServiceServer, WorkspaceServiceService } from "../src/generated/grpc-js/host/workspace"
- import { getPackageDefinition } from "./proto-utils.mjs"
- export async function startTestHostBridgeServer() {
- const server = new grpc.Server()
- // Set up health check
- const healthImpl = new health.HealthImplementation({ "": "SERVING" })
- healthImpl.addToServer(server)
- // Add host bridge services using the mock implementations
- server.addService(WorkspaceServiceService, createMockService<WorkspaceServiceServer>("WorkspaceService"))
- server.addService(WindowServiceService, createMockService<WindowServiceServer>("WindowService"))
- server.addService(EnvServiceService, createMockService<EnvServiceServer>("EnvService"))
- server.addService(DiffServiceService, createMockService<DiffServiceServer>("DiffService"))
- server.addService(TestingServiceService, createMockService<TestingServiceServer>("TestingService"))
- // Load package definition for reflection service
- const packageDefinition = await getPackageDefinition()
- // Filter service names to only include host services
- const hostBridgeServiceNames = Object.keys(packageDefinition).filter(
- (name) => name.startsWith("host.") || name.startsWith("grpc.health"),
- )
- const reflection = new ReflectionService(packageDefinition, {
- services: hostBridgeServiceNames,
- })
- reflection.addToServer(server)
- const bindAddress = process.env.HOST_BRIDGE_ADDRESS || `127.0.0.1:26041`
- server.bindAsync(bindAddress, grpc.ServerCredentials.createInsecure(), (err) => {
- if (err) {
- console.error(`Failed to bind test host bridge server to ${bindAddress}:`, err)
- process.exit(1)
- }
- server.start()
- console.log(`Test HostBridge gRPC server listening on ${bindAddress}`)
- })
- }
- /**
- * Creates a mock gRPC service implementation using Proxy
- * @param serviceName Name of the service for logging
- * @returns A proxy that implements the service interface
- */
- function createMockService<T extends grpc.UntypedServiceImplementation>(serviceName: string): T {
- const handler: ProxyHandler<T> = {
- get(_target, prop) {
- // Return a function that handles the gRPC call
- return (call: any, callback: any) => {
- console.log(`Hostbridge: ${serviceName}.${String(prop)} called with:`, call.request)
- // Special cases that need specific return values
- switch (prop) {
- case "getWorkspacePaths":
- const workspaceDir = process.env.TEST_HOSTBRIDGE_WORKSPACE_DIR || "/test-workspace"
- callback(null, {
- paths: [workspaceDir],
- })
- return
- case "getMachineId":
- callback(null, {
- value: "fake-machine-id-" + os.hostname(),
- })
- return
- case "getTelemetrySettings":
- callback(null, {
- isEnabled: 2, // Setting.DISABLED
- errorLevel: "all",
- })
- return
- case "clipboardReadText":
- callback(null, {
- value: "",
- })
- return
- case "getWebviewHtml":
- callback(null, {
- html: "<html><body>Fake Webview</body></html>",
- })
- return
- case "showTextDocument":
- callback(null, {
- document_path: call.request?.path || "",
- view_column: 1,
- is_active: true,
- })
- return
- case "openDiff":
- callback(null, {
- diff_id: "fake-diff-" + Date.now(),
- })
- return
- case "getDocumentText":
- callback(null, {
- content: "",
- })
- return
- case "getOpenTabs":
- case "getVisibleTabs":
- case "showOpenDialogue":
- callback(null, {
- paths: [],
- })
- return
- case "getDiagnostics":
- callback(null, {
- file_diagnostics: [],
- })
- return
- // For streaming methods (like subscribeToTelemetrySettings)
- case "subscribeToTelemetrySettings":
- // Just end the stream immediately
- call.end()
- return
- }
- // Default: return empty object for all other methods
- callback(null, {})
- }
- },
- }
- return new Proxy({} as T, handler)
- }
- if (require.main === module) {
- startTestHostBridgeServer().catch((err) => {
- console.error("Failed to start test host bridge server:", err)
- process.exit(1)
- })
- }
|