summaryrefslogtreecommitdiffhomepage
path: root/js/src/bus
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-05-18 14:13:04 -0400
committerDax Raad <[email protected]>2025-05-26 12:40:17 -0400
commit0e303e6508edb4374213d1f98ec383b266339774 (patch)
treef7dc146eb58126f55f470ef135b66c678bf16898 /js/src/bus
parentbcd2fd68b7fa00af055f558049994c2975d9515d (diff)
downloadopencode-0e303e6508edb4374213d1f98ec383b266339774.tar.gz
opencode-0e303e6508edb4374213d1f98ec383b266339774.zip
sync
Diffstat (limited to 'js/src/bus')
-rw-r--r--js/src/bus/index.ts79
1 files changed, 79 insertions, 0 deletions
diff --git a/js/src/bus/index.ts b/js/src/bus/index.ts
new file mode 100644
index 000000000..5359debd9
--- /dev/null
+++ b/js/src/bus/index.ts
@@ -0,0 +1,79 @@
+import type { z, ZodSchema } from "zod/v4";
+import { App } from "../app";
+import { Log } from "../util/log";
+
+export namespace Bus {
+ const log = Log.create({ service: "bus" });
+ type Subscription = (event: any) => void;
+
+ const state = App.state("bus", () => {
+ const subscriptions = new Map<any, Subscription[]>();
+
+ return {
+ subscriptions,
+ };
+ });
+
+ export type EventDefinition = ReturnType<typeof event>;
+
+ export function event<Type extends string, Properties extends ZodSchema>(
+ type: Type,
+ properties: Properties,
+ ) {
+ return {
+ type,
+ properties,
+ };
+ }
+
+ export function publish<Definition extends EventDefinition>(
+ def: Definition,
+ properties: z.output<Definition["properties"]>,
+ ) {
+ const payload = {
+ type: def.type,
+ properties,
+ };
+ log.info("publishing", {
+ type: def.type,
+ ...properties,
+ });
+ for (const key of [def.type, "*"]) {
+ const match = state().subscriptions.get(key);
+ for (const sub of match ?? []) {
+ sub(payload);
+ }
+ }
+ }
+
+ export function subscribe<Definition extends EventDefinition>(
+ def: Definition,
+ callback: (event: {
+ type: Definition["type"];
+ properties: z.infer<Definition["properties"]>;
+ }) => void,
+ ) {
+ return raw(def.type, callback);
+ }
+
+ export function subscribeAll(callback: (event: any) => void) {
+ return raw("*", callback);
+ }
+
+ function raw(type: string, callback: (event: any) => void) {
+ log.info("subscribing", { type });
+ const subscriptions = state().subscriptions;
+ let match = subscriptions.get(type) ?? [];
+ match.push(callback);
+ subscriptions.set(type, match);
+
+ return () => {
+ log.info("unsubscribing", { type });
+ const match = subscriptions.get(type);
+ if (!match) return;
+ const index = match.indexOf(callback);
+ if (index === -1) return;
+ match.splice(index, 1);
+ };
+ }
+}