@camstack/server 1.1.20 → 1.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,38 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createEventBusProxyRouter = createEventBusProxyRouter;
4
2
  /**
5
- * EventBus proxy router — allows forked workers to emit events to the
6
- * hub's EventBus via tRPC.
3
+ * EventBus proxy router — allows forked workers to emit events to, and
4
+ * read the recent-events registry of, the hub's EventBus via tRPC.
7
5
  *
8
6
  * Workers call `trpc.eventBusProxy.emit.mutate(event)` from their
9
7
  * `context.eventBus.emit()` implementation. The hub-side router
10
8
  * deserializes the event and emits it on the real EventBus.
11
9
  *
12
- * Subscribe/getRecent are routed through the existing `live.onEvent`
13
- * subscription and `events` query routers no duplication needed here.
10
+ * `getRecent` exposes the hub's retained recent-events registry to forked
11
+ * addon runners. Post the `retainRecent` change (f5a93332) ONLY the hub
12
+ * main process keeps the `recent[]` buffer — a child runner's own
13
+ * `ctx.eventBus.getRecent()` now returns `[]`. Addons that need event
14
+ * HISTORY (e.g. advanced-notifier's `testRule`) must read it from the hub
15
+ * over this proxy instead of their local, non-retaining bus. This router
16
+ * is in `CORE_NAMESPACES` (`core-cap-bridge.ts`), so the call reaches the
17
+ * hub's `services.eventBus` from any hub-local child over the UDS/core-cap
18
+ * path — exactly like `capabilities.*` / `system.*`.
19
+ *
20
+ * `subscribe` is routed through the existing `live.onEvent` subscription
21
+ * and `systemEvents.subscribe` routers — no duplication needed here.
14
22
  *
15
23
  * Introduced in session 7 (EventBus wiring for forked addons).
16
24
  */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.createEventBusProxyRouter = createEventBusProxyRouter;
17
27
  const zod_1 = require("zod");
18
28
  const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
29
+ /**
30
+ * Upper bound on the `getRecent` limit — kept in step with the hub's
31
+ * `recent[]` ring-buffer size (`MAX_RECENT_EVENTS` in `event-bus-core.ts`).
32
+ * Duplicated as a local literal rather than imported so this router does
33
+ * not depend on the event-bus core internals.
34
+ */
35
+ const MAX_RECENT_EVENTS = 1000;
19
36
  const SystemEventInputSchema = zod_1.z.object({
20
37
  id: zod_1.z.string(),
21
38
  timestamp: zod_1.z.string(), // ISO 8601 — converted to Date on emit
@@ -26,6 +43,50 @@ const SystemEventInputSchema = zod_1.z.object({
26
43
  category: zod_1.z.string(),
27
44
  data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
28
45
  });
46
+ /**
47
+ * `getRecent` input — mirrors `systemEvents.getRecent`'s category/limit
48
+ * semantics. `category` accepts a single string or an array so a caller
49
+ * can whitelist the categories it cares about server-side; `limit` is
50
+ * capped at the hub's `recent[]` buffer size (`MAX_RECENT_EVENTS`).
51
+ */
52
+ const GetRecentInputSchema = zod_1.z.object({
53
+ category: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]).optional(),
54
+ limit: zod_1.z.number().int().min(1).max(MAX_RECENT_EVENTS).optional(),
55
+ });
56
+ /**
57
+ * Serialized recent event — `timestamp` is an ISO-8601 string so the
58
+ * shape survives every transport (UDS/MsgPack, Moleculer) unchanged.
59
+ * Callers reconstruct the `Date` on receipt. Mirrors the serialization
60
+ * used by `systemEvents.getRecent`.
61
+ */
62
+ const RecentEventOutputSchema = zod_1.z.object({
63
+ id: zod_1.z.string(),
64
+ timestamp: zod_1.z.string(),
65
+ source: zod_1.z.object({
66
+ type: zod_1.z.string(),
67
+ id: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]),
68
+ nodeId: zod_1.z.string().optional(),
69
+ addonId: zod_1.z.string().optional(),
70
+ deviceId: zod_1.z.number().optional(),
71
+ }),
72
+ category: zod_1.z.string(),
73
+ data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
74
+ });
75
+ function serializeRecentEvent(e) {
76
+ return {
77
+ id: e.id,
78
+ timestamp: new Date(e.timestamp).toISOString(),
79
+ source: {
80
+ type: e.source.type,
81
+ id: e.source.id,
82
+ ...(e.source.nodeId ? { nodeId: e.source.nodeId } : {}),
83
+ ...(e.source.addonId ? { addonId: e.source.addonId } : {}),
84
+ ...(e.source.deviceId !== undefined ? { deviceId: e.source.deviceId } : {}),
85
+ },
86
+ category: e.category,
87
+ data: e.data,
88
+ };
89
+ }
29
90
  function createEventBusProxyRouter(eventBus) {
30
91
  return (0, trpc_middleware_js_1.trpcRouter)({
31
92
  emit: trpc_middleware_js_1.protectedProcedure
@@ -41,5 +102,13 @@ function createEventBusProxyRouter(eventBus) {
41
102
  });
42
103
  return { ok: true };
43
104
  }),
105
+ getRecent: trpc_middleware_js_1.protectedProcedure
106
+ .input(GetRecentInputSchema)
107
+ .output(zod_1.z.array(RecentEventOutputSchema))
108
+ .query(({ input }) => {
109
+ return eventBus
110
+ .getRecent(input.category !== undefined ? { category: input.category } : undefined, input.limit)
111
+ .map(serializeRecentEvent);
112
+ }),
44
113
  });
45
114
  }
@@ -36,7 +36,12 @@ class EventBusService {
36
36
  if (this.broker === broker)
37
37
  return;
38
38
  this.broker = broker;
39
- const inner = (0, system_1.getBrokerEventBus)(broker);
39
+ // The hub main process is the ONLY process that serves `getRecent` — so it
40
+ // is the only bus that opts into retaining the recent[] registry. Child
41
+ // addon runners + remote agents leave `retainRecent` false: their events
42
+ // are one-shot (fire-and-forget), fanned out to local subscribers but never
43
+ // accumulated, so their heap can't grow an unbounded recent[] backlog.
44
+ const inner = (0, system_1.getBrokerEventBus)(broker, { retainRecent: true });
40
45
  this.inner = inner;
41
46
  // Replay deferred subscriptions onto the real bus.
42
47
  for (const sub of this.deferredSubs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",