MCPcopy Create free account
hub / github.com/cloudflare/computer / createWorkspaceClient

Function createWorkspaceClient

packages/rpc/src/client.ts:136–178  ·  view source on GitHub ↗
(options: {
  url: string;
  WebSocketImpl?: typeof WebSocket;
})

Source from the content-addressed store, hash-verified

134// shim from createSyncClient doesn't compose cleanly. Add when a
135// caller actually needs it.
136export function createWorkspaceClient(options: {
137 url: string;
138 WebSocketImpl?: typeof WebSocket;
139}): WorkspaceClient {
140 const WS = options.WebSocketImpl ?? WebSocket;
141 const ws = new WS(options.url);
142 // Same WebSocket / RpcStub cast pattern as createSyncClient —
143 // see comment there. WorkspaceRPC adds the composite shape so
144 // callers can pipeline `.sync.push(...)` and `.shell.exec(...)`.
145 const stub = newWebSocketRpcSession(
146 ws as unknown as globalThis.WebSocket,
147 ) as RpcStub<WorkspaceRPC>;
148 return new Proxy(stub, {
149 get(target, prop, receiver) {
150 if (prop === "close") {
151 return async () => {
152 // Same dispose-before-close pattern as createSyncClient.
153 try {
154 (target as unknown as Disposable)[Symbol.dispose]?.();
155 } catch {
156 // already disposed; idempotent
157 }
158 await new Promise<void>((resolve) => {
159 const w = ws as unknown as { readyState: number; close: () => void };
160 if (w.readyState >= 2) {
161 resolve();
162 return;
163 }
164 (ws as unknown as EventTarget).addEventListener("close", () => resolve(), {
165 once: true,
166 });
167 w.close();
168 setTimeout(resolve, 200);
169 });
170 };
171 }
172 return Reflect.get(target, prop, receiver);
173 },
174 // As in createSyncClient, the Proxy is structurally a
175 // WorkspaceRPC stub + close(); route through unknown so TS
176 // accepts the WorkspaceClient landing type.
177 }) as unknown as WorkspaceClient;
178}

Callers 6

mainFunction · 0.90
connectMethod · 0.90
computerd.test.tsFile · 0.85
mainFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected