masto
Version:
Mastodon API client for JavaScript, TypeScript, Node.js, browsers
95 lines (94 loc) • 3.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketSubscription = void 0;
const index_js_1 = require("../errors/index.js");
const async_iterable_js_1 = require("./async-iterable.js");
class WebSocketSubscription {
connector;
counter;
serializer;
stream;
logger;
params;
connection;
constructor(connector, counter, serializer, stream, logger, params) {
this.connector = connector;
this.counter = counter;
this.serializer = serializer;
this.stream = stream;
this.logger = logger;
this.params = params;
}
async *values() {
try {
this.logger?.log("info", "Subscribing to stream", this.stream);
for await (this.connection of this.connector) {
const data = this.serializer.serialize("json", {
type: "subscribe",
stream: this.stream,
...this.params,
});
this.logger?.log("debug", "↑ WEBSOCKET", data);
this.connection.send(data);
this.counter.increment(this.stream, this.params);
const messages = (0, async_iterable_js_1.toAsyncIterable)(this.connection);
for await (const message of messages) {
const event = this.parseMessage(message.data);
if (!this.test(event)) {
continue;
}
this.logger?.log("debug", "↓ WEBSOCKET", event);
yield event;
}
/* c8 ignore next */
}
}
finally {
this.unsubscribe();
}
}
unsubscribe() {
if (!this.connection) {
return;
}
this.counter.decrement(this.stream, this.params);
if (this.counter.count(this.stream, this.params) <= 0) {
const data = this.serializer.serialize("json", {
type: "unsubscribe",
stream: this.stream,
...this.params,
});
this.connection.send(data);
}
this.connection = undefined;
}
[Symbol.asyncIterator]() {
return this.values();
}
[Symbol.dispose]() {
this.unsubscribe();
}
test(event) {
// subscribe("hashtag", { tag: "foo" }) -> ["hashtag", "foo"]
// subscribe("list", { list: "foo" }) -> ["list", "foo"]
const params = this.params ?? {};
const extra = Object.values(params);
const stream = [this.stream, ...extra];
return stream.every((s) => event.stream.includes(s));
}
parseMessage(rawEvent) {
const data = this.serializer.deserialize("json", rawEvent);
if ("error" in data) {
throw new index_js_1.MastoUnexpectedError(data.error);
}
const payload = data.event === "delete" || data.payload == undefined
? data.payload
: this.serializer.deserialize("json", data.payload);
return {
stream: data.stream,
event: data.event,
payload: payload,
};
}
}
exports.WebSocketSubscription = WebSocketSubscription;