aboutsummaryrefslogtreecommitdiff
path: root/source/utility/pubsub.ts
diff options
context:
space:
mode:
authornetop://ウィビ <paul@webb.page>2026-10-21 16:47:38 -0700
committernetop://ウィビ <paul@webb.page>2026-10-21 16:47:38 -0700
commit389ad1349c4ff245a3466a2e361c1cd1dd11d2ba (patch)
tree0ad0638f60ab0a77c7a095e96b472312ab39f83b /source/utility/pubsub.ts
parentbbcbb02ef64d094f0f13de22ae135eeba1ff4c5d (diff)
downloadgq-primary.tar.gz
gq-primary.zip
MAJOR RELEASEHEADprimary
- inlined vendored dependencies from npm - makes this module work in Ende
Diffstat (limited to '')
-rw-r--r--source/utility/pubsub.ts64
1 files changed, 64 insertions, 0 deletions
diff --git a/source/utility/pubsub.ts b/source/utility/pubsub.ts
new file mode 100644
index 0000000..bb8679a
--- /dev/null
+++ b/source/utility/pubsub.ts
@@ -0,0 +1,64 @@
+export class PubSub {
+ #target = new EventTarget();
+
+ publish(trigger: string, payload: unknown): Promise<void> {
+ this.#target.dispatchEvent(new CustomEvent(trigger, { detail: payload }));
+ return Promise.resolve();
+ }
+
+ asyncIterator<T>(triggers: string | string[]): AsyncIterableIterator<T> {
+ const names = Array.isArray(triggers) ? triggers : [triggers];
+ const pulls: Array<(result: IteratorResult<T>) => void> = [];
+ const pushes: T[] = [];
+ let done = false;
+
+ const listener = (event: Event) => {
+ const value = (event as CustomEvent<T>).detail;
+ const pull = pulls.shift();
+
+ if (pull)
+ pull({ done: false, value });
+ else
+ pushes.push(value);
+ };
+
+ for (const name of names)
+ this.#target.addEventListener(name, listener);
+
+ const close = (): Promise<IteratorResult<T>> => {
+ if (!done) {
+ done = true;
+
+ for (const name of names)
+ this.#target.removeEventListener(name, listener);
+
+ for (const pull of pulls.splice(0))
+ pull({ done: true, value: undefined });
+
+ pushes.length = 0;
+ }
+
+ return Promise.resolve({ done: true, value: undefined });
+ };
+
+ return {
+ next: () => {
+ if (done)
+ return Promise.resolve({ done: true, value: undefined });
+
+ if (pushes.length > 0)
+ return Promise.resolve({ done: false, value: pushes.shift() as T });
+
+ return new Promise((resolve) => pulls.push(resolve));
+ },
+ return: close,
+ throw: (error: unknown) => {
+ close();
+ return Promise.reject(error);
+ },
+ [Symbol.asyncIterator]() {
+ return this;
+ }
+ };
+ }
+}