index ↓

net

client.net

HTTP, WebSocket, and streaming network access for a webapp, proxied through the connected companion app. fetch returns one response, wsOpen opens a socket, and streamOpen delivers a body as onStreamBegin, onStreamChunk, and onStreamEnd.

requests

you ask, the daemon answers. await the tagged result and check .ok

fetch(NetFetch): Promise<TypedRequestResult<NetFetchReply, NetFetchErrorReply>>

push form: onFetchReply (subscribe instead of awaiting)

Sends one HTTP request through the connected companion app and returns the response.

const res = await client.net.fetch({ request: { /* NetFetchRequest */ } });
if (res.ok) {
  console.log(res.response.response);
} else {
  console.warn(res.kind, res.error);
}

wsOpen(NetWsOpen): Promise<TypedRequestResult<NetWsOpenReply, NetWsErrorReply>>

push form: onWsOpenReply (subscribe instead of awaiting)

const res = await client.net.wsOpen({ connectionId: '...', url: '...' });
if (res.ok) {
  console.log(res.response.acceptedProtocol);
} else {
  console.warn(res.kind, res.error);
}

commands

fire-and-forget. the promise resolves once the daemon has taken the message

wsClose(NetWsClose): Promise<void>

await client.net.wsClose({ connectionId: '...' });

wsSend(NetWsSend): Promise<void>

await client.net.wsSend({ connectionId: '...', frame: { /* WsFrame */ } });

streamOpen(NetStreamOpen): Promise<void>

await client.net.streamOpen({ streamId: '...', request: { /* NetFetchRequest */ } });

streamCancel(NetStreamCancel): Promise<void>

await client.net.streamCancel({ streamId: '...' });

events

the daemon pushes these unprompted. subscribing returns an unsubscribe function

onWsMessage(handler: (NetWsMessage) => void): () => void

const off = client.net.onWsMessage((netWsMessage) => {
  console.log(netWsMessage.connectionId);
});
// call off() to unsubscribe

onWsClosed(handler: (NetWsClosed) => void): () => void

const off = client.net.onWsClosed((netWsClosed) => {
  console.log(netWsClosed.connectionId);
});
// call off() to unsubscribe

onWsErrorEvent(handler: (NetWsErrorEvent) => void): () => void

const off = client.net.onWsErrorEvent((event) => {
  console.log(event.connectionId);
});
// call off() to unsubscribe

onStreamBegin(handler: (StreamBegin) => void): () => void

const off = client.net.onStreamBegin((streamBegin) => {
  console.log(streamBegin.streamId);
});
// call off() to unsubscribe

onStreamChunk(handler: (StreamChunk) => void): () => void

const off = client.net.onStreamChunk((streamChunk) => {
  console.log(streamChunk.streamId);
});
// call off() to unsubscribe

onStreamEnd(handler: (StreamEnd) => void): () => void

const off = client.net.onStreamEnd((streamEnd) => {
  console.log(streamEnd.streamId);
});
// call off() to unsubscribe

onStreamError(handler: (StreamError) => void): () => void

const off = client.net.onStreamError((streamError) => {
  console.log(streamError.streamId);
});
// call off() to unsubscribe

types

shapes referenced above, as the sdk types them

type NetWsMessage = {
  connectionId: string;
  frame: WsFrame;
};
type NetWsClosed = {
  connectionId: string;
  code: number;
  reason: string;
};
type NetWsErrorEvent = {
  connectionId: string;
  error: WsError;
};

First event of a stream. StreamChunk and StreamEnd events with the same streamId follow.

type StreamBegin = {
  streamId: string;
  status: number;
  headers: HttpHeader[];
  totalSize?: number; // Null when the server declares no length.
};
type StreamChunk = {
  streamId: string;
  offset: number; // Byte position of `bytes[0]` in the full body. Chunks arrive in order.
  bytes: Uint8Array;
};

The last event of a stream that finished.

type StreamEnd = {
  streamId: string;
};

The last event of a stream that failed.

type StreamError = {
  streamId: string;
  error: NetError;
};

Sends one HTTP request through the connected companion app and returns the response.

type NetFetch = {
  request: NetFetchRequest;
};
type NetFetchReply = {
  response: NetFetchResponse;
};
type NetFetchErrorReply = {
  error: NetError;
};
type NetWsOpen = {
  connectionId: string;
  url: string;
  protocols?: string[];
  headers?: HttpHeader[];
};
type NetWsOpenReply = {
  acceptedProtocol?: string;
};
type NetWsErrorReply = {
  error: WsError;
};
type NetWsClose = {
  connectionId: string;
  code?: number;
  reason?: string;
};
type NetWsSend = {
  connectionId: string;
  frame: WsFrame;
};
type NetStreamOpen = {
  streamId: string;
  request: NetFetchRequest;
};
type NetStreamCancel = {
  streamId: string;
};
type WsFrame =
  | { type: 'text'; data: string }
  | { type: 'binary'; data: Uint8Array };
type WsError =
  | 'connectFailed'
  | 'frameTooLarge'
  | 'gatewayDisconnected'
  | 'protocolError';
type HttpHeader = {
  name: string;
  value: string;
};
type NetError = 'requestFailed' | 'timeout' | 'unavailable' | 'noGateway';
type NetFetchRequest = {
  url: string;
  method: HttpMethod;
  headers: HttpHeader[];
  body: Uint8Array | null;
  timeoutMs?: number;
  redirect: RedirectPolicy;
};
type NetFetchResponse = {
  status: number;
  headers: HttpHeader[];
  body: Uint8Array;
};
type HttpMethod =
  | 'get'
  | 'head'
  | 'post'
  | 'put'
  | 'patch'
  | 'delete'
  | 'options';
type RedirectPolicy =
  | 'follow'
  | 'manual' // Return the 3xx response to the caller.
  | 'error';