@sealevel-dev/sdk
Version:
TypeScript SDK for Sealevel.
271 lines (261 loc) • 7.53 kB
JavaScript
// 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