-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
63 lines (51 loc) · 1.66 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// file: src/server/pub/index.ts
import { getRequestEvent } from 'solid-js/web';
import { makeChat, makeClientReply, type ChatMessage } from '../chat';
import { PUB_SUB_LINK, type PubBound } from '../pub-sub';
import { epochTimestamp } from '../../lib/shame';
import { MessageCache } from './message-cache';
const messageCache = new MessageCache();
let channel: BroadcastChannel | undefined;
const messageTimestamp = (messages: ChatMessage[]) =>
messages.length > 0 ? messages[0].timestamp : epochTimestamp();
// Note: this module doesn't reply to requests
// until the first `broadcast` call loads the module.
// This makes it necessary for the `src/server/sub`
// to time out with an empty Welcome
// Listen for requests for messages and reply with
// those found in the cache;
function listenForRequests() {
if (channel) return;
channel = new BroadcastChannel(PUB_SUB_LINK);
const receiver = (event: MessageEvent<PubBound>) => {
if (!channel) return;
const message = event.data;
const messages = messageCache.sliceAfter(message.lastTime);
channel.postMessage(
makeClientReply(
messages,
messageTimestamp(messages),
message.id,
message.lastTime
)
);
};
channel.addEventListener('message', receiver);
}
// Cache the message for later
// Set up the channel it necessary.
async function broadcast(body: string) {
if (!channel) listenForRequests();
const event = getRequestEvent();
if (!event) return false;
const message = {
timestamp: epochTimestamp(),
from: event.locals.clientId,
body,
};
messageCache.cache(message);
const chat = makeChat([message], message.timestamp);
channel?.postMessage(chat);
return true;
}
export { broadcast };