UNPKG

@sealevel-dev/sdk

Version:

TypeScript SDK for Sealevel.

271 lines (261 loc) 7.53 kB
// src/api/v1/client.ts import createClient from "openapi-fetch"; // src/api/const.ts var API_DEFAULT_BASE_URL = "https://api.sealevel.dev"; // src/api/v1/client.ts function createV1ApiClient(options) { const baseUrl = `${options?.baseUrl ?? API_DEFAULT_BASE_URL}/v1`; const client = createClient({ baseUrl, headers: { Authorization: `Bearer ${options.accessToken}` } }); return client; } // src/realtime/v1/client.ts import EventEmitter from "eventemitter3"; import { WebSocket } from "ws"; import { z } from "zod"; // src/realtime/v1/const.ts var REALTIME_V1_DEFAULT_URL = "wss://realtime.sealevel.dev/v1"; // src/realtime/v1/client.ts var realtimeClientOptionsSchema = z.object({ url: z.string().default(REALTIME_V1_DEFAULT_URL), accessToken: z.string(), reconnect: z.boolean().default(true), reconnectInterval: z.number().default(1e3) }); var RealtimeV1Client = class extends EventEmitter { #options; #userDisconnected = false; #ws = null; constructor(options) { super(); this.#options = realtimeClientOptionsSchema.parse(options ?? {}); } connect = () => { if (this.#ws) { throw new Error("connect: websocket already intialized"); } const url = new URL(this.#options.url); url.searchParams.set("access_token", this.#options.accessToken); this.#userDisconnected = false; this.#ws = new WebSocket(url); this.#ws.addEventListener("message", this.#handleMessage); this.#ws.addEventListener("error", this.#handleError); this.#ws.addEventListener("close", this.#handleClose); this.#ws.addEventListener("open", this.#handleOpen); }; send = (message) => { if (!this.#ws) { throw new Error( "send: websocket not initialized, please connect before trying to send a message" ); } this.#ws.send(JSON.stringify(message)); }; subscribe = (topics) => { this.send({ type: "subscribe", topics }); }; unsubscribe = (topics) => { this.send({ type: "unsubscribe", topics }); }; disconnect = () => { if (!this.#ws) { throw new Error( "disconnect: websocket not initialized, please connect before trying to disconnect" ); } this.#userDisconnected = true; this.#removeListeners(); this.#ws.close(); this.#ws = null; this.emit("disconnect"); }; #reconnect = () => { if (!this.#userDisconnected) { this.connect(); } }; #removeListeners = () => { if (!this.#ws) { throw new Error("disconnect: websocket not initialized"); } this.#ws.removeEventListener("message", this.#handleMessage); this.#ws.removeEventListener("error", this.#handleError); this.#ws.removeEventListener("close", this.#handleClose); this.#ws.removeEventListener("open", this.#handleOpen); }; #handleOpen = () => { this.emit("connect"); }; #handleClose = (event) => { this.#removeListeners(); this.#ws = null; this.emit("disconnect", { ...event, code: event.code }); if (this.#options.reconnect) { setTimeout(this.#reconnect, this.#options.reconnectInterval); } }; #handleError = (event) => { this.emit("error", new Error(event.message, { cause: event })); }; #handleMessage = (event) => { if (typeof event.data !== "string") { this.emit("error", new Error("Invalid message format")); return; } let data; try { data = JSON.parse(event.data); } catch (error) { this.emit("error", new Error("Invalid message format", { cause: error })); return; } this.emit("message", data); }; }; function createRealtimeV1Client(options) { return new RealtimeV1Client(options); } // src/realtime/v1/close-code.ts var RealtimeV1CloseCode = { InvalidMessage: 4e3, UnknownOperation: 4001, InvalidParams: 4002, InternalError: 5e3 }; // src/realtime/v2/client.ts import EventEmitter2 from "eventemitter3"; import { WebSocket as WebSocket2 } from "ws"; import { z as z2 } from "zod"; // src/realtime/v2/const.ts var REALTIME_V2_DEFAULT_URL = "wss://realtime.sealevel.dev/v2"; // src/realtime/v2/client.ts var realtimeClientOptionsSchema2 = z2.object({ url: z2.string().default(REALTIME_V2_DEFAULT_URL), accessToken: z2.string(), reconnect: z2.boolean().default(true), reconnectInterval: z2.number().default(1e3) }); var RealtimeV2Client = class extends EventEmitter2 { #options; #userDisconnected = false; #ws = null; constructor(options) { super(); this.#options = realtimeClientOptionsSchema2.parse(options ?? {}); } connect = () => { if (this.#ws) { throw new Error("connect: websocket already intialized"); } const url = new URL(this.#options.url); url.searchParams.set("access_token", this.#options.accessToken); this.#userDisconnected = false; this.#ws = new WebSocket2(url); this.#ws.addEventListener("message", this.#handleMessage); this.#ws.addEventListener("error", this.#handleError); this.#ws.addEventListener("close", this.#handleClose); this.#ws.addEventListener("open", this.#handleOpen); }; send = (message) => { if (!this.#ws) { throw new Error( "send: websocket not initialized, please connect before trying to send a message" ); } this.#ws.send(JSON.stringify(message)); }; subscribe = (topics) => { this.send({ type: "subscribe", topics }); }; unsubscribe = (topics) => { this.send({ type: "unsubscribe", topics }); }; disconnect = () => { if (!this.#ws) { throw new Error( "disconnect: websocket not initialized, please connect before trying to disconnect" ); } this.#userDisconnected = true; this.#removeListeners(); this.#ws.close(); this.#ws = null; this.emit("disconnect"); }; #reconnect = () => { if (!this.#userDisconnected) { this.connect(); } }; #removeListeners = () => { if (!this.#ws) { throw new Error("disconnect: websocket not initialized"); } this.#ws.removeEventListener("message", this.#handleMessage); this.#ws.removeEventListener("error", this.#handleError); this.#ws.removeEventListener("close", this.#handleClose); this.#ws.removeEventListener("open", this.#handleOpen); }; #handleOpen = () => { this.emit("connect"); }; #handleClose = (event) => { this.#removeListeners(); this.#ws = null; this.emit("disconnect", { ...event, code: event.code }); if (this.#options.reconnect) { setTimeout(this.#reconnect, this.#options.reconnectInterval); } }; #handleError = (event) => { this.emit("error", new Error(event.message, { cause: event })); }; #handleMessage = (event) => { if (typeof event.data !== "string") { this.emit("error", new Error("Invalid message format")); return; } let data; try { data = JSON.parse(event.data); } catch (error) { this.emit("error", new Error("Invalid message format", { cause: error })); return; } this.emit("message", data); }; }; function createRealtimeV2Client(options) { return new RealtimeV2Client(options); } // src/realtime/v2/close-code.ts var RealtimeV2CloseCode = { InvalidMessage: 4e3, UnknownOperation: 4001, InvalidParams: 4002, InternalError: 5e3 }; export { RealtimeV1Client, RealtimeV1CloseCode, RealtimeV2Client, RealtimeV2CloseCode, createRealtimeV1Client, createRealtimeV2Client, createV1ApiClient }; //# sourceMappingURL=index.js.map