import * as api from './apiServer.js'; import * as md from './markdown.js'; class PostToChannel { constructor(channel, body) { this.channel = channel; this.body = body; this.renderedBody = md.render(body); } async send() { return await api.retry(() => api.postToChannel(this.channel, this.body)); } } class DeleteMessage { constructor(messageId) { this.messageId = messageId; } async send() { return await api.retry(() => api.deleteMessage(this.messageId)); } } class CreateChannel { constructor(name) { this.name = name; } async send() { return await api.retry(() => api.createChannel(this.name)); } } export class Outbox { pending = $state([]); static empty() { return new Outbox([]); } constructor(pending) { this.pending = pending; } enqueue(operation) { this.pending.push(operation); this.start(); } createChannel(name) { this.enqueue(new CreateChannel(name)); } postToChannel(channel, body) { this.enqueue(new PostToChannel(channel, body)); } deleteMessage(messageId) { this.enqueue(new DeleteMessage(messageId)); } start() { if (this.sending) { return; } // This is a promise transform primarily to keep the management of `this.sending` in one place, // rather than spreading it across multiple methods. this.sending = this.drain().finally(() => { this.sending = null; }); } async drain() { while (this.pending.length > 0) { const operation = this.pending[0]; await operation.send(); this.pending.shift(); } } }