@unbrained/pm-web 2026.8.10 → 2026.8.14
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.
- package/CHANGELOG.md +16 -0
- package/dist/app.d.ts +16 -0
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts +5 -0
- package/dist/auth.js.map +1 -1
- package/dist/board.d.ts +53 -0
- package/dist/board.js +48 -0
- package/dist/board.js.map +1 -1
- package/dist/crypto.d.ts +23 -0
- package/dist/crypto.js +32 -0
- package/dist/crypto.js.map +1 -1
- package/dist/db.d.ts +19 -0
- package/dist/db.js +19 -0
- package/dist/db.js.map +1 -1
- package/dist/ical.d.ts +72 -0
- package/dist/ical.js +73 -0
- package/dist/ical.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +52 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts +8 -0
- package/dist/middleware/auth.js.map +1 -1
- package/dist/oidc.d.ts +87 -0
- package/dist/oidc.js +113 -0
- package/dist/oidc.js.map +1 -1
- package/dist/routes/admin.js +15 -0
- package/dist/routes/admin.js.map +1 -1
- package/dist/routes/github.js +13 -0
- package/dist/routes/github.js.map +1 -1
- package/dist/routes/oidc.d.ts +10 -0
- package/dist/routes/oidc.js +51 -0
- package/dist/routes/oidc.js.map +1 -1
- package/dist/routes/pm.js +132 -1
- package/dist/routes/pm.js.map +1 -1
- package/dist/routes/sharing.js +8 -0
- package/dist/routes/sharing.js.map +1 -1
- package/dist/services/mutation-event-watcher.js +13 -0
- package/dist/services/mutation-event-watcher.js.map +1 -1
- package/dist/services/pm-runner.d.ts +82 -0
- package/dist/services/pm-runner.js +121 -0
- package/dist/services/pm-runner.js.map +1 -1
- package/dist/services/project-watcher.d.ts +22 -0
- package/dist/services/project-watcher.js +51 -0
- package/dist/services/project-watcher.js.map +1 -1
- package/dist/services/realtime-bus.d.ts +46 -0
- package/dist/services/realtime-bus.js +59 -0
- package/dist/services/realtime-bus.js.map +1 -1
- package/dist/services/sse.d.ts +134 -0
- package/dist/services/sse.js +145 -0
- package/dist/services/sse.js.map +1 -1
- package/manifest.json +1 -1
- package/package.json +5 -3
- package/public/src/app.js +44 -1
- package/public/src/app.js.map +1 -1
- package/public/src/app.ts +44 -1
- package/public/src/components/modals.js +11 -0
- package/public/src/components/modals.js.map +1 -1
- package/public/src/components/modals.ts +11 -0
- package/public/src/components/toast.js +2 -0
- package/public/src/components/toast.js.map +1 -1
- package/public/src/components/toast.ts +2 -0
- package/public/src/constants.js +21 -4
- package/public/src/constants.js.map +1 -1
- package/public/src/constants.ts +21 -4
- package/public/src/filters.js +10 -7
- package/public/src/filters.js.map +1 -1
- package/public/src/filters.ts +10 -7
- package/public/src/i18n.js +11 -1
- package/public/src/i18n.js.map +1 -1
- package/public/src/i18n.ts +13 -1
- package/public/src/state.js +3 -0
- package/public/src/state.js.map +1 -1
- package/public/src/state.ts +3 -0
- package/public/src/sw.ts +71 -7
- package/public/src/theme.js +13 -1
- package/public/src/theme.js.map +1 -1
- package/public/src/theme.ts +15 -1
- package/public/src/types.ts +2 -0
- package/public/src/utils.js +26 -1
- package/public/src/utils.js.map +1 -1
- package/public/src/utils.ts +26 -1
- package/public/src/views/activity.js +1 -0
- package/public/src/views/activity.js.map +1 -1
- package/public/src/views/activity.ts +1 -0
- package/public/src/views/admin.js +134 -0
- package/public/src/views/admin.js.map +1 -1
- package/public/src/views/admin.ts +134 -0
- package/public/src/views/auth.js +31 -0
- package/public/src/views/auth.js.map +1 -1
- package/public/src/views/auth.ts +31 -0
- package/public/src/views/calendar.js +3 -0
- package/public/src/views/calendar.js.map +1 -1
- package/public/src/views/calendar.ts +3 -0
- package/public/src/views/comments-audit.js +1 -0
- package/public/src/views/comments-audit.js.map +1 -1
- package/public/src/views/comments-audit.ts +1 -0
- package/public/src/views/config.js +67 -0
- package/public/src/views/config.js.map +1 -1
- package/public/src/views/config.ts +67 -0
- package/public/src/views/context.js +2 -0
- package/public/src/views/context.js.map +1 -1
- package/public/src/views/context.ts +2 -0
- package/public/src/views/create.js +3 -0
- package/public/src/views/create.js.map +1 -1
- package/public/src/views/create.ts +3 -0
- package/public/src/views/dedupe.js +1 -0
- package/public/src/views/dedupe.js.map +1 -1
- package/public/src/views/dedupe.ts +1 -0
- package/public/src/views/export.js +6 -0
- package/public/src/views/export.js.map +1 -1
- package/public/src/views/export.ts +6 -0
- package/public/src/views/github.js +58 -0
- package/public/src/views/github.js.map +1 -1
- package/public/src/views/github.ts +58 -0
- package/public/src/views/graph-canvas.js +18 -0
- package/public/src/views/graph-canvas.js.map +1 -1
- package/public/src/views/graph-canvas.ts +20 -0
- package/public/src/views/graph.js +41 -0
- package/public/src/views/graph.js.map +1 -1
- package/public/src/views/graph.ts +42 -1
- package/public/src/views/groups.js +45 -0
- package/public/src/views/groups.js.map +1 -1
- package/public/src/views/groups.ts +45 -0
- package/public/src/views/guide.js +3 -0
- package/public/src/views/guide.js.map +1 -1
- package/public/src/views/guide.ts +3 -0
- package/public/src/views/health.js +3 -0
- package/public/src/views/health.js.map +1 -1
- package/public/src/views/health.ts +3 -0
- package/public/src/views/items.js +196 -6
- package/public/src/views/items.js.map +1 -1
- package/public/src/views/items.ts +196 -6
- package/public/src/views/normalize.js +2 -0
- package/public/src/views/normalize.js.map +1 -1
- package/public/src/views/normalize.ts +2 -0
- package/public/src/views/packages.js +41 -0
- package/public/src/views/packages.js.map +1 -1
- package/public/src/views/packages.ts +41 -0
- package/public/src/views/plan-execution.js +6 -0
- package/public/src/views/plan-execution.js.map +1 -1
- package/public/src/views/plan-execution.ts +8 -0
- package/public/src/views/plan.js +145 -0
- package/public/src/views/plan.js.map +1 -1
- package/public/src/views/plan.ts +146 -1
- package/public/src/views/projects.js +60 -0
- package/public/src/views/projects.js.map +1 -1
- package/public/src/views/projects.ts +60 -0
- package/public/src/views/router.js +43 -0
- package/public/src/views/router.js.map +1 -1
- package/public/src/views/router.ts +43 -0
- package/public/src/views/search.js +5 -0
- package/public/src/views/search.js.map +1 -1
- package/public/src/views/search.ts +5 -0
- package/public/src/views/settings.js +36 -0
- package/public/src/views/settings.js.map +1 -1
- package/public/src/views/settings.ts +36 -0
- package/public/src/views/shared.js +1 -0
- package/public/src/views/shared.js.map +1 -1
- package/public/src/views/shared.ts +1 -0
- package/public/src/views/sharing.js +32 -0
- package/public/src/views/sharing.js.map +1 -1
- package/public/src/views/sharing.ts +32 -0
- package/public/src/views/stats.js +1 -0
- package/public/src/views/stats.js.map +1 -1
- package/public/src/views/stats.ts +1 -0
- package/public/src/views/templates.js +4 -0
- package/public/src/views/templates.js.map +1 -1
- package/public/src/views/templates.ts +4 -0
- package/public/src/views/validate.js +1 -0
- package/public/src/views/validate.js.map +1 -1
- package/public/src/views/validate.ts +1 -0
- package/public/sw.js +60 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-watcher.js","sourceRoot":"","sources":["../../src/services/project-watcher.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"project-watcher.js","sourceRoot":"","sources":["../../src/services/project-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,54 @@ interface RealtimeEnvelope {
|
|
|
5
5
|
data: unknown;
|
|
6
6
|
sourceId?: string;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse and validate a realtime NOTIFY payload into an envelope.
|
|
10
|
+
*
|
|
11
|
+
* Returns `null` when the payload is missing or exceeds 7,500 bytes, or when
|
|
12
|
+
* JSON parsing, the project-id (UUID) check, or the event-type check fails. The
|
|
13
|
+
* envelope's data is passed through {@link safeSharedData}; a `sourceId` is kept
|
|
14
|
+
* only when present, so receivers can ignore their own broadcasts.
|
|
15
|
+
*
|
|
16
|
+
* @param raw - The raw NOTIFY payload string, or `undefined`.
|
|
17
|
+
* @returns The validated envelope, or `null`.
|
|
18
|
+
*/
|
|
8
19
|
export declare function parseEnvelope(raw: string | undefined): RealtimeEnvelope | null;
|
|
20
|
+
/**
|
|
21
|
+
* Serialize a project event into a realtime NOTIFY payload.
|
|
22
|
+
*
|
|
23
|
+
* Returns `null` without throwing when the project id is not a UUID or the event
|
|
24
|
+
* type is malformed, or when the JSON payload (after {@link safeSharedData}) would
|
|
25
|
+
* exceed 7,500 bytes — so an over-large event is dropped rather than corrupting
|
|
26
|
+
* the channel.
|
|
27
|
+
*
|
|
28
|
+
* @param projectId - The project the event belongs to.
|
|
29
|
+
* @param event - The SSE event to encode.
|
|
30
|
+
* @param sourceId - This instance's id, embedded so other instances can skip it.
|
|
31
|
+
* @returns The JSON payload string, or `null` when invalid or too large.
|
|
32
|
+
*/
|
|
9
33
|
export declare function buildEnvelope(projectId: string, event: SSEEvent, sourceId: string): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Deliver one NOTIFY payload to local clients, ignoring this instance's own.
|
|
36
|
+
*
|
|
37
|
+
* Parses the payload (no-op when invalid); if it carries a `sourceId` matching
|
|
38
|
+
* this instance the event is dropped to avoid echoing it back, otherwise the
|
|
39
|
+
* event is handed to `deliver` for local SSE fan-out.
|
|
40
|
+
*
|
|
41
|
+
* @param raw - The raw NOTIFY payload.
|
|
42
|
+
* @param instanceId - This instance's id, to suppress self-echo.
|
|
43
|
+
* @param deliver - Sink that fans the event out to local clients.
|
|
44
|
+
*/
|
|
10
45
|
export declare function handleIncomingEnvelope(raw: string | undefined, instanceId: string, deliver: (projectId: string, event: SSEEvent) => void): void;
|
|
46
|
+
/**
|
|
47
|
+
* Start the Postgres LISTEN/NOTIFY realtime bus and return a stop function.
|
|
48
|
+
*
|
|
49
|
+
* A no-op (returning a resolver that does nothing) when `PM_REALTIME_ENABLED`
|
|
50
|
+
* is `"false"`. Otherwise reserves a pool client on the `pm_workspace_events`
|
|
51
|
+
* channel, fans incoming envelopes out to local SSE clients (skipping this
|
|
52
|
+
* instance's own), publishes local events via `pg_notify`, and reconnects with
|
|
53
|
+
* exponential backoff on disconnect. The returned function undoes all of it.
|
|
54
|
+
*
|
|
55
|
+
* @returns A function that stops the bus and releases the listener.
|
|
56
|
+
*/
|
|
11
57
|
export declare function startRealtimeBus(): Promise<() => Promise<void>>;
|
|
12
58
|
export {};
|
|
@@ -5,6 +5,19 @@ const CHANNEL = "pm_workspace_events";
|
|
|
5
5
|
const INSTANCE_ID = randomUUID();
|
|
6
6
|
const PROJECT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
7
7
|
const EVENT_TYPE = /^[a-z][a-z0-9-]{0,63}$/;
|
|
8
|
+
/**
|
|
9
|
+
* Project a raw event payload down to a small, safe object for cross-instance
|
|
10
|
+
* transport.
|
|
11
|
+
*
|
|
12
|
+
* Only a fixed whitelist of keys (`itemId`, `userId`, `change`, `target`,
|
|
13
|
+
* `rel`, `reason`, `count`, `source`, `operation`) is copied, and only when the
|
|
14
|
+
* value is a string of at most 256 characters or a finite number. Non-objects
|
|
15
|
+
* and arrays yield an empty object, so the NOTIFY payload stays small and free
|
|
16
|
+
* of arbitrary user data.
|
|
17
|
+
*
|
|
18
|
+
* @param data - The raw event data.
|
|
19
|
+
* @returns The filtered, transport-safe data object.
|
|
20
|
+
*/
|
|
8
21
|
function safeSharedData(data) {
|
|
9
22
|
if (!data || typeof data !== "object" || Array.isArray(data))
|
|
10
23
|
return {};
|
|
@@ -19,6 +32,17 @@ function safeSharedData(data) {
|
|
|
19
32
|
}
|
|
20
33
|
return safe;
|
|
21
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse and validate a realtime NOTIFY payload into an envelope.
|
|
37
|
+
*
|
|
38
|
+
* Returns `null` when the payload is missing or exceeds 7,500 bytes, or when
|
|
39
|
+
* JSON parsing, the project-id (UUID) check, or the event-type check fails. The
|
|
40
|
+
* envelope's data is passed through {@link safeSharedData}; a `sourceId` is kept
|
|
41
|
+
* only when present, so receivers can ignore their own broadcasts.
|
|
42
|
+
*
|
|
43
|
+
* @param raw - The raw NOTIFY payload string, or `undefined`.
|
|
44
|
+
* @returns The validated envelope, or `null`.
|
|
45
|
+
*/
|
|
22
46
|
export function parseEnvelope(raw) {
|
|
23
47
|
if (!raw || Buffer.byteLength(raw, "utf8") > 7_500)
|
|
24
48
|
return null;
|
|
@@ -32,18 +56,53 @@ export function parseEnvelope(raw) {
|
|
|
32
56
|
return null;
|
|
33
57
|
}
|
|
34
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Serialize a project event into a realtime NOTIFY payload.
|
|
61
|
+
*
|
|
62
|
+
* Returns `null` without throwing when the project id is not a UUID or the event
|
|
63
|
+
* type is malformed, or when the JSON payload (after {@link safeSharedData}) would
|
|
64
|
+
* exceed 7,500 bytes — so an over-large event is dropped rather than corrupting
|
|
65
|
+
* the channel.
|
|
66
|
+
*
|
|
67
|
+
* @param projectId - The project the event belongs to.
|
|
68
|
+
* @param event - The SSE event to encode.
|
|
69
|
+
* @param sourceId - This instance's id, embedded so other instances can skip it.
|
|
70
|
+
* @returns The JSON payload string, or `null` when invalid or too large.
|
|
71
|
+
*/
|
|
35
72
|
export function buildEnvelope(projectId, event, sourceId) {
|
|
36
73
|
if (!PROJECT_ID.test(projectId) || !EVENT_TYPE.test(event.type))
|
|
37
74
|
return null;
|
|
38
75
|
const payload = JSON.stringify({ projectId, type: event.type, data: safeSharedData(event.data), sourceId });
|
|
39
76
|
return Buffer.byteLength(payload, "utf8") <= 7_500 ? payload : null;
|
|
40
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Deliver one NOTIFY payload to local clients, ignoring this instance's own.
|
|
80
|
+
*
|
|
81
|
+
* Parses the payload (no-op when invalid); if it carries a `sourceId` matching
|
|
82
|
+
* this instance the event is dropped to avoid echoing it back, otherwise the
|
|
83
|
+
* event is handed to `deliver` for local SSE fan-out.
|
|
84
|
+
*
|
|
85
|
+
* @param raw - The raw NOTIFY payload.
|
|
86
|
+
* @param instanceId - This instance's id, to suppress self-echo.
|
|
87
|
+
* @param deliver - Sink that fans the event out to local clients.
|
|
88
|
+
*/
|
|
41
89
|
export function handleIncomingEnvelope(raw, instanceId, deliver) {
|
|
42
90
|
const event = parseEnvelope(raw);
|
|
43
91
|
if (!event || event.sourceId === instanceId)
|
|
44
92
|
return;
|
|
45
93
|
deliver(event.projectId, { type: event.type, data: event.data });
|
|
46
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Start the Postgres LISTEN/NOTIFY realtime bus and return a stop function.
|
|
97
|
+
*
|
|
98
|
+
* A no-op (returning a resolver that does nothing) when `PM_REALTIME_ENABLED`
|
|
99
|
+
* is `"false"`. Otherwise reserves a pool client on the `pm_workspace_events`
|
|
100
|
+
* channel, fans incoming envelopes out to local SSE clients (skipping this
|
|
101
|
+
* instance's own), publishes local events via `pg_notify`, and reconnects with
|
|
102
|
+
* exponential backoff on disconnect. The returned function undoes all of it.
|
|
103
|
+
*
|
|
104
|
+
* @returns A function that stops the bus and releases the listener.
|
|
105
|
+
*/
|
|
47
106
|
export async function startRealtimeBus() {
|
|
48
107
|
if (process.env.PM_REALTIME_ENABLED === "false")
|
|
49
108
|
return async () => undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-bus.js","sourceRoot":"","sources":["../../src/services/realtime-bus.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"realtime-bus.js","sourceRoot":"","sources":["../../src/services/realtime-bus.ts"],"names":[],"mappings":"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"}
|
package/dist/services/sse.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { Response } from "express";
|
|
2
|
+
/**
|
|
3
|
+
* One connected SSE viewer, indexed both by client id and by project so that
|
|
4
|
+
* per-event work scales with the clients on the affected project rather than
|
|
5
|
+
* the total number of connected clients.
|
|
6
|
+
*/
|
|
2
7
|
export interface SSEClient {
|
|
3
8
|
id: string;
|
|
4
9
|
projectId: string;
|
|
@@ -14,22 +19,151 @@ export interface PresenceUser {
|
|
|
14
19
|
currentView: string;
|
|
15
20
|
connectedAt: string;
|
|
16
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Record that a mutation in this project was just announced to clients, so the
|
|
24
|
+
* filesystem change-detector can suppress re-announcing the same change.
|
|
25
|
+
*
|
|
26
|
+
* @param projectId - The project whose workspace changed.
|
|
27
|
+
*/
|
|
17
28
|
export declare function noteSignaledMutation(projectId: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Record that a mutation of one specific item was just announced to clients.
|
|
31
|
+
*
|
|
32
|
+
* The mutation-event watcher consults {@link consumeSignaledItemMutation} to
|
|
33
|
+
* skip the matching committed-mutation event, giving per-item dedupe so a
|
|
34
|
+
* concurrent change to a different item by another agent is still delivered.
|
|
35
|
+
*
|
|
36
|
+
* @param projectId - The project containing the item.
|
|
37
|
+
* @param itemId - The item that was announced.
|
|
38
|
+
*/
|
|
18
39
|
export declare function noteSignaledItemMutation(projectId: string, itemId: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Consume one per-item signal, returning whether one was present.
|
|
42
|
+
*
|
|
43
|
+
* Returns `true` and deletes the entry when this instance already announced the
|
|
44
|
+
* given project+item (so the mutation-event watcher skips its own write);
|
|
45
|
+
* otherwise returns `false`. Consumption is one-shot: at most one event per
|
|
46
|
+
* recorded signal is ever suppressed.
|
|
47
|
+
*
|
|
48
|
+
* @param projectId - The project containing the item.
|
|
49
|
+
* @param itemId - The item to check.
|
|
50
|
+
* @returns True when a signal was present and has been consumed.
|
|
51
|
+
*/
|
|
19
52
|
export declare function consumeSignaledItemMutation(projectId: string, itemId: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Report whether a project was signaled within the given time window.
|
|
55
|
+
*
|
|
56
|
+
* @param projectId - The project to check.
|
|
57
|
+
* @param windowMs - How recently a signal must have been recorded.
|
|
58
|
+
* @param now - Current time in ms; defaults to `Date.now()` (injectable for tests).
|
|
59
|
+
* @returns True when a signal exists and is within the window.
|
|
60
|
+
*/
|
|
20
61
|
export declare function wasSignaledWithin(projectId: string, windowMs: number, now?: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Consume a project-level signal after the change-detector has attributed one
|
|
64
|
+
* filesystem delta to it, so suppression correlates 1:1 with a signaled write
|
|
65
|
+
* rather than swallowing every later delta in the window.
|
|
66
|
+
*
|
|
67
|
+
* @param projectId - The project whose signal to clear.
|
|
68
|
+
*/
|
|
21
69
|
export declare function consumeSignaledMutation(projectId: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Return the ids of projects that currently have at least one connected client,
|
|
72
|
+
* in the order they were first connected.
|
|
73
|
+
*/
|
|
22
74
|
export declare function getActiveProjectIds(): string[];
|
|
75
|
+
/**
|
|
76
|
+
* Install (or clear, with `null`) the cross-instance event publisher.
|
|
77
|
+
*
|
|
78
|
+
* When set, {@link broadcastProjectEvent} forwards each event to it so other
|
|
79
|
+
* pm-web instances receive it over the realtime bus; passing `null` detaches
|
|
80
|
+
* the bus.
|
|
81
|
+
*
|
|
82
|
+
* @param publisher - The async publisher, or `null` to clear.
|
|
83
|
+
*/
|
|
23
84
|
export declare function configureProjectEventPublisher(publisher: ((projectId: string, event: SSEEvent) => Promise<void>) | null): void;
|
|
85
|
+
/**
|
|
86
|
+
* Register a new SSE client and return its unsubscribe function.
|
|
87
|
+
*
|
|
88
|
+
* Indexes the client by id and project, writes an initial `connected` event,
|
|
89
|
+
* and schedules a presence broadcast. The returned function removes the client
|
|
90
|
+
* and schedules a fresh presence broadcast for the project on disconnect.
|
|
91
|
+
*
|
|
92
|
+
* @param client - The client to register.
|
|
93
|
+
* @returns A function that unregisters the client.
|
|
94
|
+
*/
|
|
24
95
|
export declare function addSSEClient(client: SSEClient): () => void;
|
|
96
|
+
/**
|
|
97
|
+
* Broadcast an event to a project's viewers locally and across instances.
|
|
98
|
+
*
|
|
99
|
+
* When the event data carries a plausible string `itemId`, records a per-item
|
|
100
|
+
* signal so the mutation-event watcher can skip the matching committed fact,
|
|
101
|
+
* then delivers the event to local clients and forwards it to the cross-instance
|
|
102
|
+
* publisher when one is configured.
|
|
103
|
+
*
|
|
104
|
+
* @param projectId - The project to broadcast to.
|
|
105
|
+
* @param event - The SSE event.
|
|
106
|
+
*/
|
|
25
107
|
export declare function broadcastProjectEvent(projectId: string, event: SSEEvent): void;
|
|
108
|
+
/**
|
|
109
|
+
* Deliver an event to the local SSE clients of one project.
|
|
110
|
+
*
|
|
111
|
+
* Records a project-level signal, then writes the SSE-formatted payload to every
|
|
112
|
+
* client in the project's set; a write to a disconnected client is swallowed
|
|
113
|
+
* (cleanup happens on the next heartbeat). The project-level signal is recorded
|
|
114
|
+
* even when the project has no clients, so a no-client call is not a complete
|
|
115
|
+
* no-op.
|
|
116
|
+
*
|
|
117
|
+
* @param projectId - The project to deliver to.
|
|
118
|
+
* @param event - The SSE event.
|
|
119
|
+
*/
|
|
26
120
|
export declare function deliverProjectEvent(projectId: string, event: SSEEvent): void;
|
|
121
|
+
/**
|
|
122
|
+
* Broadcast the current presence list to a project's viewers.
|
|
123
|
+
*
|
|
124
|
+
* A no-op when the project has no clients; otherwise writes an SSE `presence`
|
|
125
|
+
* event carrying the deduplicated user list to each connected client.
|
|
126
|
+
*
|
|
127
|
+
* @param projectId - The project whose presence to broadcast.
|
|
128
|
+
*/
|
|
27
129
|
export declare function broadcastPresence(projectId: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Update a client's current view when caller and client agree.
|
|
132
|
+
*
|
|
133
|
+
* Sets the view only when a client with the given id belongs to the given user
|
|
134
|
+
* and project, then schedules a presence broadcast. Returns whether the update
|
|
135
|
+
* applied, so a mismatched/stale client id is reported rather than silently
|
|
136
|
+
* mutating another user's view.
|
|
137
|
+
*/
|
|
28
138
|
export declare function updateClientView(clientId: string, userId: string, projectId: string, currentView: string): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Return the presence list for a project.
|
|
141
|
+
*
|
|
142
|
+
* @param projectId - The project to read.
|
|
143
|
+
* @returns The deduplicated presence users (empty when none connected).
|
|
144
|
+
*/
|
|
29
145
|
export declare function getProjectPresence(projectId: string): PresenceUser[];
|
|
146
|
+
/**
|
|
147
|
+
* Write the SSE response headers for a streaming connection.
|
|
148
|
+
*
|
|
149
|
+
* Sets `text/event-stream`, no-cache, keep-alive, and `X-Accel-Buffering: no`
|
|
150
|
+
* (so nginx/proxies do not buffer the stream), with status 200.
|
|
151
|
+
*/
|
|
30
152
|
export declare function setupSSEHeaders(res: Response): void;
|
|
153
|
+
/** Return the total number of currently connected SSE clients. */
|
|
31
154
|
export declare function getSSEClientCount(): number;
|
|
155
|
+
/**
|
|
156
|
+
* Close long-lived clients and prune stale signal entries.
|
|
157
|
+
*
|
|
158
|
+
* Ends and removes any client connected for more than 12 hours, schedules a
|
|
159
|
+
* presence broadcast for each affected project, and drops project/item signal
|
|
160
|
+
* timestamps older than {@link SIGNAL_ENTRY_TTL_MS} (60 s).
|
|
161
|
+
*/
|
|
32
162
|
export declare function cleanupStaleClients(): void;
|
|
163
|
+
/**
|
|
164
|
+
* One Server-Sent Events message: a client-facing event `type` and an opaque
|
|
165
|
+
* `data` payload serialized to JSON on the wire.
|
|
166
|
+
*/
|
|
33
167
|
export interface SSEEvent {
|
|
34
168
|
type: string;
|
|
35
169
|
data: unknown;
|
package/dist/services/sse.js
CHANGED
|
@@ -17,6 +17,12 @@ const SIGNAL_ENTRY_TTL_MS = 60_000;
|
|
|
17
17
|
// Record that an item mutation for this project was just delivered to clients
|
|
18
18
|
// (via API broadcast or a received cross-process NOTIFY). The filesystem
|
|
19
19
|
// change-detector uses this to suppress re-announcing changes already signaled.
|
|
20
|
+
/**
|
|
21
|
+
* Record that a mutation in this project was just announced to clients, so the
|
|
22
|
+
* filesystem change-detector can suppress re-announcing the same change.
|
|
23
|
+
*
|
|
24
|
+
* @param projectId - The project whose workspace changed.
|
|
25
|
+
*/
|
|
20
26
|
export function noteSignaledMutation(projectId) {
|
|
21
27
|
lastSignaledAt.set(projectId, Date.now());
|
|
22
28
|
}
|
|
@@ -31,6 +37,16 @@ export function noteSignaledMutation(projectId) {
|
|
|
31
37
|
// commits, so if the watcher's poll lands between commit and broadcast one
|
|
32
38
|
// duplicate workspace-changed can still reach clients. That is harmless because
|
|
33
39
|
// the client handler is an idempotent refetch — noted rather than pretended away.
|
|
40
|
+
/**
|
|
41
|
+
* Record that a mutation of one specific item was just announced to clients.
|
|
42
|
+
*
|
|
43
|
+
* The mutation-event watcher consults {@link consumeSignaledItemMutation} to
|
|
44
|
+
* skip the matching committed-mutation event, giving per-item dedupe so a
|
|
45
|
+
* concurrent change to a different item by another agent is still delivered.
|
|
46
|
+
*
|
|
47
|
+
* @param projectId - The project containing the item.
|
|
48
|
+
* @param itemId - The item that was announced.
|
|
49
|
+
*/
|
|
34
50
|
export function noteSignaledItemMutation(projectId, itemId) {
|
|
35
51
|
signaledItemAt.set(`${projectId}\u0000${itemId}`, Date.now());
|
|
36
52
|
}
|
|
@@ -61,6 +77,18 @@ export function noteSignaledItemMutation(projectId, itemId) {
|
|
|
61
77
|
// mis-pair can do is attribute the surviving event's `operation`/`author`
|
|
62
78
|
// metadata to the wrong mutation — that metadata drives only a cosmetic toast,
|
|
63
79
|
// never state.
|
|
80
|
+
/**
|
|
81
|
+
* Consume one per-item signal, returning whether one was present.
|
|
82
|
+
*
|
|
83
|
+
* Returns `true` and deletes the entry when this instance already announced the
|
|
84
|
+
* given project+item (so the mutation-event watcher skips its own write);
|
|
85
|
+
* otherwise returns `false`. Consumption is one-shot: at most one event per
|
|
86
|
+
* recorded signal is ever suppressed.
|
|
87
|
+
*
|
|
88
|
+
* @param projectId - The project containing the item.
|
|
89
|
+
* @param itemId - The item to check.
|
|
90
|
+
* @returns True when a signal was present and has been consumed.
|
|
91
|
+
*/
|
|
64
92
|
export function consumeSignaledItemMutation(projectId, itemId) {
|
|
65
93
|
const key = `${projectId}\u0000${itemId}`;
|
|
66
94
|
if (signaledItemAt.has(key)) {
|
|
@@ -69,6 +97,14 @@ export function consumeSignaledItemMutation(projectId, itemId) {
|
|
|
69
97
|
}
|
|
70
98
|
return false;
|
|
71
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Report whether a project was signaled within the given time window.
|
|
102
|
+
*
|
|
103
|
+
* @param projectId - The project to check.
|
|
104
|
+
* @param windowMs - How recently a signal must have been recorded.
|
|
105
|
+
* @param now - Current time in ms; defaults to `Date.now()` (injectable for tests).
|
|
106
|
+
* @returns True when a signal exists and is within the window.
|
|
107
|
+
*/
|
|
72
108
|
export function wasSignaledWithin(projectId, windowMs, now = Date.now()) {
|
|
73
109
|
const at = lastSignaledAt.get(projectId);
|
|
74
110
|
return at !== undefined && now - at <= windowMs;
|
|
@@ -78,15 +114,42 @@ export function wasSignaledWithin(projectId, windowMs, now = Date.now()) {
|
|
|
78
114
|
// write instead of swallowing every delta for the whole window — so a later,
|
|
79
115
|
// *unrelated* direct write on the shared volume is still surfaced rather than
|
|
80
116
|
// being silently absorbed by a recent API/NOTIFY event's window.
|
|
117
|
+
/**
|
|
118
|
+
* Consume a project-level signal after the change-detector has attributed one
|
|
119
|
+
* filesystem delta to it, so suppression correlates 1:1 with a signaled write
|
|
120
|
+
* rather than swallowing every later delta in the window.
|
|
121
|
+
*
|
|
122
|
+
* @param projectId - The project whose signal to clear.
|
|
123
|
+
*/
|
|
81
124
|
export function consumeSignaledMutation(projectId) {
|
|
82
125
|
lastSignaledAt.delete(projectId);
|
|
83
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Return the ids of projects that currently have at least one connected client,
|
|
129
|
+
* in the order they were first connected.
|
|
130
|
+
*/
|
|
84
131
|
export function getActiveProjectIds() {
|
|
85
132
|
return [...byProject.keys()];
|
|
86
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Install (or clear, with `null`) the cross-instance event publisher.
|
|
136
|
+
*
|
|
137
|
+
* When set, {@link broadcastProjectEvent} forwards each event to it so other
|
|
138
|
+
* pm-web instances receive it over the realtime bus; passing `null` detaches
|
|
139
|
+
* the bus.
|
|
140
|
+
*
|
|
141
|
+
* @param publisher - The async publisher, or `null` to clear.
|
|
142
|
+
*/
|
|
87
143
|
export function configureProjectEventPublisher(publisher) {
|
|
88
144
|
projectEventPublisher = publisher;
|
|
89
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Remove a client from both indexes.
|
|
148
|
+
*
|
|
149
|
+
* Deletes it from the by-id map and from its project's client set, dropping the
|
|
150
|
+
* project set entirely when it becomes empty so {@link getActiveProjectIds}
|
|
151
|
+
* stops reporting a project with no viewers.
|
|
152
|
+
*/
|
|
90
153
|
function removeClient(client) {
|
|
91
154
|
if (byId.get(client.id) === client)
|
|
92
155
|
byId.delete(client.id);
|
|
@@ -97,6 +160,12 @@ function removeClient(client) {
|
|
|
97
160
|
byProject.delete(client.projectId);
|
|
98
161
|
}
|
|
99
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Build the presence list for one project's clients, one entry per user.
|
|
165
|
+
*
|
|
166
|
+
* Deduplicates by `userId`, keeping the most-recently-connected client per user,
|
|
167
|
+
* and maps each to a {@link PresenceUser}. An empty or absent set yields `[]`.
|
|
168
|
+
*/
|
|
100
169
|
function presenceUsers(set) {
|
|
101
170
|
if (!set || set.size === 0)
|
|
102
171
|
return [];
|
|
@@ -114,6 +183,13 @@ function presenceUsers(set) {
|
|
|
114
183
|
connectedAt: c.connectedAt.toISOString(),
|
|
115
184
|
}));
|
|
116
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Debounce a presence broadcast for a project by 75 ms.
|
|
188
|
+
*
|
|
189
|
+
* Replaces any pending presence timer for the project, so a burst of
|
|
190
|
+
* joins/leaves/view changes triggers a single {@link broadcastPresence} rather
|
|
191
|
+
* than one per event.
|
|
192
|
+
*/
|
|
117
193
|
function schedulePresence(projectId) {
|
|
118
194
|
const active = presenceTimers.get(projectId);
|
|
119
195
|
if (active)
|
|
@@ -123,6 +199,16 @@ function schedulePresence(projectId) {
|
|
|
123
199
|
broadcastPresence(projectId);
|
|
124
200
|
}, 75));
|
|
125
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Register a new SSE client and return its unsubscribe function.
|
|
204
|
+
*
|
|
205
|
+
* Indexes the client by id and project, writes an initial `connected` event,
|
|
206
|
+
* and schedules a presence broadcast. The returned function removes the client
|
|
207
|
+
* and schedules a fresh presence broadcast for the project on disconnect.
|
|
208
|
+
*
|
|
209
|
+
* @param client - The client to register.
|
|
210
|
+
* @returns A function that unregisters the client.
|
|
211
|
+
*/
|
|
126
212
|
export function addSSEClient(client) {
|
|
127
213
|
byId.set(client.id, client);
|
|
128
214
|
let set = byProject.get(client.projectId);
|
|
@@ -142,6 +228,17 @@ export function addSSEClient(client) {
|
|
|
142
228
|
schedulePresence(client.projectId);
|
|
143
229
|
};
|
|
144
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Broadcast an event to a project's viewers locally and across instances.
|
|
233
|
+
*
|
|
234
|
+
* When the event data carries a plausible string `itemId`, records a per-item
|
|
235
|
+
* signal so the mutation-event watcher can skip the matching committed fact,
|
|
236
|
+
* then delivers the event to local clients and forwards it to the cross-instance
|
|
237
|
+
* publisher when one is configured.
|
|
238
|
+
*
|
|
239
|
+
* @param projectId - The project to broadcast to.
|
|
240
|
+
* @param event - The SSE event.
|
|
241
|
+
*/
|
|
145
242
|
export function broadcastProjectEvent(projectId, event) {
|
|
146
243
|
// When a route broadcasts an item-scoped event, note it per-item so the
|
|
147
244
|
// mutation-event watcher can skip the corresponding committed-mutation fact.
|
|
@@ -161,6 +258,18 @@ export function broadcastProjectEvent(projectId, event) {
|
|
|
161
258
|
void projectEventPublisher(projectId, event).catch(() => undefined);
|
|
162
259
|
}
|
|
163
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Deliver an event to the local SSE clients of one project.
|
|
263
|
+
*
|
|
264
|
+
* Records a project-level signal, then writes the SSE-formatted payload to every
|
|
265
|
+
* client in the project's set; a write to a disconnected client is swallowed
|
|
266
|
+
* (cleanup happens on the next heartbeat). The project-level signal is recorded
|
|
267
|
+
* even when the project has no clients, so a no-client call is not a complete
|
|
268
|
+
* no-op.
|
|
269
|
+
*
|
|
270
|
+
* @param projectId - The project to deliver to.
|
|
271
|
+
* @param event - The SSE event.
|
|
272
|
+
*/
|
|
164
273
|
export function deliverProjectEvent(projectId, event) {
|
|
165
274
|
noteSignaledMutation(projectId);
|
|
166
275
|
const set = byProject.get(projectId);
|
|
@@ -176,6 +285,14 @@ export function deliverProjectEvent(projectId, event) {
|
|
|
176
285
|
}
|
|
177
286
|
}
|
|
178
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Broadcast the current presence list to a project's viewers.
|
|
290
|
+
*
|
|
291
|
+
* A no-op when the project has no clients; otherwise writes an SSE `presence`
|
|
292
|
+
* event carrying the deduplicated user list to each connected client.
|
|
293
|
+
*
|
|
294
|
+
* @param projectId - The project whose presence to broadcast.
|
|
295
|
+
*/
|
|
179
296
|
export function broadcastPresence(projectId) {
|
|
180
297
|
const set = byProject.get(projectId);
|
|
181
298
|
if (!set || set.size === 0)
|
|
@@ -191,6 +308,14 @@ export function broadcastPresence(projectId) {
|
|
|
191
308
|
}
|
|
192
309
|
}
|
|
193
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* Update a client's current view when caller and client agree.
|
|
313
|
+
*
|
|
314
|
+
* Sets the view only when a client with the given id belongs to the given user
|
|
315
|
+
* and project, then schedules a presence broadcast. Returns whether the update
|
|
316
|
+
* applied, so a mismatched/stale client id is reported rather than silently
|
|
317
|
+
* mutating another user's view.
|
|
318
|
+
*/
|
|
194
319
|
export function updateClientView(clientId, userId, projectId, currentView) {
|
|
195
320
|
const client = byId.get(clientId);
|
|
196
321
|
if (client && client.userId === userId && client.projectId === projectId) {
|
|
@@ -200,9 +325,21 @@ export function updateClientView(clientId, userId, projectId, currentView) {
|
|
|
200
325
|
}
|
|
201
326
|
return false;
|
|
202
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Return the presence list for a project.
|
|
330
|
+
*
|
|
331
|
+
* @param projectId - The project to read.
|
|
332
|
+
* @returns The deduplicated presence users (empty when none connected).
|
|
333
|
+
*/
|
|
203
334
|
export function getProjectPresence(projectId) {
|
|
204
335
|
return presenceUsers(byProject.get(projectId));
|
|
205
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Write the SSE response headers for a streaming connection.
|
|
339
|
+
*
|
|
340
|
+
* Sets `text/event-stream`, no-cache, keep-alive, and `X-Accel-Buffering: no`
|
|
341
|
+
* (so nginx/proxies do not buffer the stream), with status 200.
|
|
342
|
+
*/
|
|
206
343
|
export function setupSSEHeaders(res) {
|
|
207
344
|
res.writeHead(200, {
|
|
208
345
|
"Content-Type": "text/event-stream",
|
|
@@ -211,9 +348,17 @@ export function setupSSEHeaders(res) {
|
|
|
211
348
|
"X-Accel-Buffering": "no", // Disable nginx buffering
|
|
212
349
|
});
|
|
213
350
|
}
|
|
351
|
+
/** Return the total number of currently connected SSE clients. */
|
|
214
352
|
export function getSSEClientCount() {
|
|
215
353
|
return byId.size;
|
|
216
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Close long-lived clients and prune stale signal entries.
|
|
357
|
+
*
|
|
358
|
+
* Ends and removes any client connected for more than 12 hours, schedules a
|
|
359
|
+
* presence broadcast for each affected project, and drops project/item signal
|
|
360
|
+
* timestamps older than {@link SIGNAL_ENTRY_TTL_MS} (60 s).
|
|
361
|
+
*/
|
|
217
362
|
export function cleanupStaleClients() {
|
|
218
363
|
const now = Date.now();
|
|
219
364
|
const staleProjectIds = new Set();
|