@actuate-media/cms-core 0.23.0 → 0.24.0
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/dist/__tests__/api/notifications-routes.test.js +45 -0
- package/dist/__tests__/api/notifications-routes.test.js.map +1 -1
- package/dist/__tests__/realtime/notification-bus.test.d.ts +2 -0
- package/dist/__tests__/realtime/notification-bus.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/notification-bus.test.js +79 -0
- package/dist/__tests__/realtime/notification-bus.test.js.map +1 -0
- package/dist/__tests__/realtime/notification-stream.test.d.ts +2 -0
- package/dist/__tests__/realtime/notification-stream.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/notification-stream.test.js +157 -0
- package/dist/__tests__/realtime/notification-stream.test.js.map +1 -0
- package/dist/api/handlers.d.ts.map +1 -1
- package/dist/api/handlers.js +41 -3
- package/dist/api/handlers.js.map +1 -1
- package/dist/preview/sse-stream.d.ts +2 -5
- package/dist/preview/sse-stream.d.ts.map +1 -1
- package/dist/preview/sse-stream.js +7 -16
- package/dist/preview/sse-stream.js.map +1 -1
- package/dist/realtime/index.d.ts +3 -0
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +9 -0
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/notification-bus.d.ts +60 -0
- package/dist/realtime/notification-bus.d.ts.map +1 -0
- package/dist/realtime/notification-bus.js +77 -0
- package/dist/realtime/notification-bus.js.map +1 -0
- package/dist/realtime/notification-stream.d.ts +50 -0
- package/dist/realtime/notification-stream.d.ts.map +1 -0
- package/dist/realtime/notification-stream.js +148 -0
- package/dist/realtime/notification-stream.js.map +1 -0
- package/dist/realtime/sse.d.ts +20 -0
- package/dist/realtime/sse.d.ts.map +1 -0
- package/dist/realtime/sse.js +31 -0
- package/dist/realtime/sse.js.map +1 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { handleActuateAPI } from '../../api/index.js';
|
|
|
3
3
|
import { createSession } from '../../auth/session.js';
|
|
4
4
|
import { initDB } from '../../db.js';
|
|
5
5
|
import { generateToken as generateCsrfToken } from '../../security/csrf.js';
|
|
6
|
+
import { __resetNotificationBus, notificationSubscriberCount, } from '../../realtime/notification-bus.js';
|
|
6
7
|
/**
|
|
7
8
|
* Integration tests for the notifications REST endpoints introduced in
|
|
8
9
|
* slice 6 of Phase 3. The pure service is covered by
|
|
@@ -202,6 +203,50 @@ describe('notifications REST endpoints (Phase 3 slice 6)', () => {
|
|
|
202
203
|
}));
|
|
203
204
|
expect((await after.json()).data.count).toBe(0);
|
|
204
205
|
});
|
|
206
|
+
describe('GET /notifications/stream (SSE push channel)', () => {
|
|
207
|
+
beforeEach(() => {
|
|
208
|
+
__resetNotificationBus();
|
|
209
|
+
});
|
|
210
|
+
it('rejects unauthenticated stream requests with 401', async () => {
|
|
211
|
+
const res = await handler(new Request('https://example.com/api/cms/notifications/stream'));
|
|
212
|
+
expect(res.status).toBe(401);
|
|
213
|
+
});
|
|
214
|
+
it('returns 200 + text/event-stream + a ready frame for the session user', async () => {
|
|
215
|
+
const headers = await sessionHeaders('EDITOR', 'user-1');
|
|
216
|
+
const res = await handler(new Request('https://example.com/api/cms/notifications/stream', {
|
|
217
|
+
headers: { cookie: headers.cookie },
|
|
218
|
+
}));
|
|
219
|
+
expect(res.status).toBe(200);
|
|
220
|
+
expect(res.headers.get('content-type')).toMatch(/text\/event-stream/);
|
|
221
|
+
expect(res.headers.get('cache-control')).toBe('no-cache, no-transform');
|
|
222
|
+
// SSE buffering guard — without this proxies hold events back.
|
|
223
|
+
expect(res.headers.get('x-accel-buffering')).toBe('no');
|
|
224
|
+
const reader = res.body.getReader();
|
|
225
|
+
try {
|
|
226
|
+
// Subscription is attached synchronously in the stream's
|
|
227
|
+
// start() — by the time we get a reader, the bus should
|
|
228
|
+
// already have the listener registered. That contract matters
|
|
229
|
+
// because the comment-write path publishes immediately after
|
|
230
|
+
// the DB insert; a lazy subscribe would race.
|
|
231
|
+
expect(notificationSubscriberCount('user-1')).toBe(1);
|
|
232
|
+
const decoder = new TextDecoder();
|
|
233
|
+
const first = await reader.read();
|
|
234
|
+
expect(first.done).toBe(false);
|
|
235
|
+
const text = decoder.decode(first.value);
|
|
236
|
+
expect(text).toContain('event: ready');
|
|
237
|
+
expect(text).toContain('"userId":"user-1"');
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
// Cancel triggers the stream's cleanup hook — verifies the
|
|
241
|
+
// bus subscription is dropped on hang-up.
|
|
242
|
+
await reader.cancel().catch(() => undefined);
|
|
243
|
+
}
|
|
244
|
+
// Yield once so the cancel() callback has a chance to run
|
|
245
|
+
// before we sample the subscriber count again.
|
|
246
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
247
|
+
expect(notificationSubscriberCount('user-1')).toBe(0);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
205
250
|
it('honours includeRead=true', async () => {
|
|
206
251
|
await seedNotification(db, 'user-1', {
|
|
207
252
|
payload: { actorId: 'a', actorName: 'A', excerpt: 'unread' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications-routes.test.js","sourceRoot":"","sources":["../../../src/__tests__/api/notifications-routes.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"notifications-routes.test.js","sourceRoot":"","sources":["../../../src/__tests__/api/notifications-routes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-bus.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/realtime/notification-bus.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { __resetNotificationBus, notificationSubscriberCount, publishNotification, subscribeUserNotifications, } from '../../realtime/notification-bus.js';
|
|
3
|
+
beforeEach(() => {
|
|
4
|
+
__resetNotificationBus();
|
|
5
|
+
});
|
|
6
|
+
function makeDto(overrides = {}) {
|
|
7
|
+
return {
|
|
8
|
+
id: 'n-1',
|
|
9
|
+
userId: 'user-a',
|
|
10
|
+
kind: 'comment_reply',
|
|
11
|
+
documentId: 'doc-1',
|
|
12
|
+
commentId: 'c-1',
|
|
13
|
+
payload: {
|
|
14
|
+
kind: 'comment_reply',
|
|
15
|
+
actorId: 'user-b',
|
|
16
|
+
actorName: 'B',
|
|
17
|
+
excerpt: 'hi',
|
|
18
|
+
},
|
|
19
|
+
readAt: null,
|
|
20
|
+
createdAt: new Date().toISOString(),
|
|
21
|
+
...overrides,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
describe('notification-bus', () => {
|
|
25
|
+
it('delivers published notifications to subscribed userIds only', () => {
|
|
26
|
+
const a = [];
|
|
27
|
+
const b = [];
|
|
28
|
+
subscribeUserNotifications('user-a', (n) => a.push(n));
|
|
29
|
+
subscribeUserNotifications('user-b', (n) => b.push(n));
|
|
30
|
+
publishNotification(makeDto({ id: 'a-1', userId: 'user-a' }));
|
|
31
|
+
publishNotification(makeDto({ id: 'b-1', userId: 'user-b' }));
|
|
32
|
+
expect(a.map((n) => n.id)).toEqual(['a-1']);
|
|
33
|
+
expect(b.map((n) => n.id)).toEqual(['b-1']);
|
|
34
|
+
});
|
|
35
|
+
it('returns true only when at least one subscriber received the event', () => {
|
|
36
|
+
expect(publishNotification(makeDto({ userId: 'nobody' }))).toBe(false);
|
|
37
|
+
subscribeUserNotifications('user-a', () => undefined);
|
|
38
|
+
expect(publishNotification(makeDto({ userId: 'user-a' }))).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it('isolates throwing listeners so siblings still receive the event', () => {
|
|
41
|
+
const seen = [];
|
|
42
|
+
subscribeUserNotifications('user-a', () => {
|
|
43
|
+
throw new Error('boom');
|
|
44
|
+
});
|
|
45
|
+
subscribeUserNotifications('user-a', (n) => seen.push(n.id));
|
|
46
|
+
publishNotification(makeDto({ id: 'iso-1', userId: 'user-a' }));
|
|
47
|
+
expect(seen).toEqual(['iso-1']);
|
|
48
|
+
});
|
|
49
|
+
it('unsubscribe drops the listener and clears empty buckets', () => {
|
|
50
|
+
const seen = [];
|
|
51
|
+
const off = subscribeUserNotifications('user-a', (n) => seen.push(n));
|
|
52
|
+
expect(notificationSubscriberCount('user-a')).toBe(1);
|
|
53
|
+
publishNotification(makeDto({ id: 'pre' }));
|
|
54
|
+
off();
|
|
55
|
+
expect(notificationSubscriberCount('user-a')).toBe(0);
|
|
56
|
+
publishNotification(makeDto({ id: 'post' }));
|
|
57
|
+
expect(seen.map((n) => n.id)).toEqual(['pre']);
|
|
58
|
+
});
|
|
59
|
+
it('snapshots the listener set so synchronous unsubscribes from inside a listener do not skip neighbours', () => {
|
|
60
|
+
const seen = [];
|
|
61
|
+
let off2;
|
|
62
|
+
subscribeUserNotifications('user-a', (n) => {
|
|
63
|
+
seen.push(`first:${n.id}`);
|
|
64
|
+
// Synchronous teardown — exactly the shape the SSE stream uses
|
|
65
|
+
// when its own controller throws. Must not poison the rest of
|
|
66
|
+
// the broadcast pass.
|
|
67
|
+
off2?.();
|
|
68
|
+
});
|
|
69
|
+
off2 = subscribeUserNotifications('user-a', (n) => {
|
|
70
|
+
seen.push(`second:${n.id}`);
|
|
71
|
+
});
|
|
72
|
+
publishNotification(makeDto({ id: 'snap' }));
|
|
73
|
+
expect(seen).toEqual(['first:snap', 'second:snap']);
|
|
74
|
+
});
|
|
75
|
+
it('rejects empty userId at subscribe time to prevent silent cross-user leaks', () => {
|
|
76
|
+
expect(() => subscribeUserNotifications('', () => undefined)).toThrow();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=notification-bus.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-bus.test.js","sourceRoot":"","sources":["../../../src/__tests__/realtime/notification-bus.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-stream.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/realtime/notification-stream.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { createNotificationStream, createNotificationStreamResponse, encodeSseEvent, NOTIFICATION_SSE_HEADERS, } from '../../realtime/notification-stream.js';
|
|
3
|
+
import { __resetNotificationBus, notificationSubscriberCount, publishNotification, } from '../../realtime/notification-bus.js';
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
__resetNotificationBus();
|
|
6
|
+
});
|
|
7
|
+
const decoder = new TextDecoder();
|
|
8
|
+
function makeDto(overrides = {}) {
|
|
9
|
+
return {
|
|
10
|
+
id: 'n-1',
|
|
11
|
+
userId: 'user-a',
|
|
12
|
+
kind: 'comment_mention',
|
|
13
|
+
documentId: 'doc-1',
|
|
14
|
+
commentId: 'c-1',
|
|
15
|
+
payload: {
|
|
16
|
+
kind: 'comment_mention',
|
|
17
|
+
actorId: 'user-b',
|
|
18
|
+
actorName: 'B',
|
|
19
|
+
excerpt: 'ping',
|
|
20
|
+
},
|
|
21
|
+
readAt: null,
|
|
22
|
+
createdAt: '2026-05-27T00:00:00.000Z',
|
|
23
|
+
...overrides,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
async function readNext(reader, timeoutMs = 1000) {
|
|
27
|
+
let timer;
|
|
28
|
+
const timeout = new Promise((_, reject) => {
|
|
29
|
+
timer = setTimeout(() => reject(new Error(`SSE read timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
const result = await Promise.race([reader.read(), timeout]);
|
|
33
|
+
if (result.done)
|
|
34
|
+
throw new Error('Stream closed before a chunk arrived');
|
|
35
|
+
return decoder.decode(result.value);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
if (timer)
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
describe('createNotificationStream', () => {
|
|
43
|
+
let reader;
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
if (reader) {
|
|
46
|
+
// Cancel triggers the stream's cancel() — verifies cleanup.
|
|
47
|
+
await reader.cancel().catch(() => undefined);
|
|
48
|
+
reader = undefined;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
it('emits a ready frame immediately', async () => {
|
|
52
|
+
const stream = createNotificationStream('user-a', {
|
|
53
|
+
heartbeatMs: 60_000,
|
|
54
|
+
maxLifetimeMs: 60_000,
|
|
55
|
+
});
|
|
56
|
+
reader = stream.getReader();
|
|
57
|
+
const first = await readNext(reader);
|
|
58
|
+
expect(first).toContain('event: ready');
|
|
59
|
+
expect(first).toContain('"userId":"user-a"');
|
|
60
|
+
});
|
|
61
|
+
it('forwards published notifications as notification events', async () => {
|
|
62
|
+
const stream = createNotificationStream('user-a', {
|
|
63
|
+
heartbeatMs: 60_000,
|
|
64
|
+
maxLifetimeMs: 60_000,
|
|
65
|
+
});
|
|
66
|
+
reader = stream.getReader();
|
|
67
|
+
// ready frame
|
|
68
|
+
await readNext(reader);
|
|
69
|
+
const dto = makeDto({ id: 'sse-1', userId: 'user-a' });
|
|
70
|
+
publishNotification(dto);
|
|
71
|
+
const chunk = await readNext(reader);
|
|
72
|
+
expect(chunk).toContain('event: notification');
|
|
73
|
+
expect(chunk).toContain('"id":"sse-1"');
|
|
74
|
+
expect(chunk).toContain('"userId":"user-a"');
|
|
75
|
+
});
|
|
76
|
+
it('does not deliver events for other users', async () => {
|
|
77
|
+
const stream = createNotificationStream('user-a', {
|
|
78
|
+
heartbeatMs: 60_000,
|
|
79
|
+
maxLifetimeMs: 60_000,
|
|
80
|
+
});
|
|
81
|
+
reader = stream.getReader();
|
|
82
|
+
await readNext(reader); // ready
|
|
83
|
+
publishNotification(makeDto({ id: 'wrong', userId: 'user-b' }));
|
|
84
|
+
publishNotification(makeDto({ id: 'right', userId: 'user-a' }));
|
|
85
|
+
const chunk = await readNext(reader);
|
|
86
|
+
expect(chunk).toContain('"id":"right"');
|
|
87
|
+
expect(chunk).not.toContain('"id":"wrong"');
|
|
88
|
+
});
|
|
89
|
+
it('emits heartbeats on interval', async () => {
|
|
90
|
+
const stream = createNotificationStream('user-a', {
|
|
91
|
+
heartbeatMs: 20,
|
|
92
|
+
maxLifetimeMs: 60_000,
|
|
93
|
+
});
|
|
94
|
+
reader = stream.getReader();
|
|
95
|
+
await readNext(reader); // ready
|
|
96
|
+
const heartbeat = await readNext(reader, 500);
|
|
97
|
+
expect(heartbeat).toBe(': heartbeat\n\n');
|
|
98
|
+
});
|
|
99
|
+
it('closes the stream after maxLifetimeMs and tears down the bus subscription', async () => {
|
|
100
|
+
const stream = createNotificationStream('user-a', {
|
|
101
|
+
heartbeatMs: 60_000,
|
|
102
|
+
maxLifetimeMs: 20,
|
|
103
|
+
});
|
|
104
|
+
reader = stream.getReader();
|
|
105
|
+
await readNext(reader); // ready
|
|
106
|
+
expect(notificationSubscriberCount('user-a')).toBe(1);
|
|
107
|
+
// Wait for the lifetime timer to fire.
|
|
108
|
+
const result = await reader.read();
|
|
109
|
+
expect(result.done).toBe(true);
|
|
110
|
+
// After the stream closes the cancel() handler must run and
|
|
111
|
+
// drop the subscription — otherwise we leak listener refs over
|
|
112
|
+
// the process lifetime.
|
|
113
|
+
expect(notificationSubscriberCount('user-a')).toBe(0);
|
|
114
|
+
reader = undefined;
|
|
115
|
+
});
|
|
116
|
+
it('removes the bus subscription on cancel() (client disconnect)', async () => {
|
|
117
|
+
const stream = createNotificationStream('user-a', {
|
|
118
|
+
heartbeatMs: 60_000,
|
|
119
|
+
maxLifetimeMs: 60_000,
|
|
120
|
+
});
|
|
121
|
+
reader = stream.getReader();
|
|
122
|
+
await readNext(reader); // ready
|
|
123
|
+
expect(notificationSubscriberCount('user-a')).toBe(1);
|
|
124
|
+
await reader.cancel();
|
|
125
|
+
reader = undefined;
|
|
126
|
+
expect(notificationSubscriberCount('user-a')).toBe(0);
|
|
127
|
+
});
|
|
128
|
+
it('rejects an empty userId at stream creation', () => {
|
|
129
|
+
expect(() => createNotificationStream('')).toThrow();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('createNotificationStreamResponse', () => {
|
|
133
|
+
it('wraps the stream with text/event-stream headers + 200', async () => {
|
|
134
|
+
const res = createNotificationStreamResponse('user-a', {
|
|
135
|
+
heartbeatMs: 60_000,
|
|
136
|
+
maxLifetimeMs: 60_000,
|
|
137
|
+
});
|
|
138
|
+
expect(res.status).toBe(200);
|
|
139
|
+
expect(res.headers.get('content-type')).toBe(NOTIFICATION_SSE_HEADERS['Content-Type']);
|
|
140
|
+
expect(res.headers.get('cache-control')).toBe(NOTIFICATION_SSE_HEADERS['Cache-Control']);
|
|
141
|
+
expect(res.headers.get('x-accel-buffering')).toBe(NOTIFICATION_SSE_HEADERS['X-Accel-Buffering']);
|
|
142
|
+
// Drain the body so the underlying stream tears down cleanly.
|
|
143
|
+
await res.body?.cancel();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe('encodeSseEvent (notification stream copy)', () => {
|
|
147
|
+
// The notification stream re-exports its own encoder so callers
|
|
148
|
+
// don't take a cross-module dep on the preview stream's copy.
|
|
149
|
+
// Verify the contract stays in lock-step.
|
|
150
|
+
it('serializes JSON payloads with an event tag', () => {
|
|
151
|
+
expect(encodeSseEvent({ id: 'x' }, 'notification')).toBe('event: notification\ndata: {"id":"x"}\n\n');
|
|
152
|
+
});
|
|
153
|
+
it('splits multi-line strings across data lines', () => {
|
|
154
|
+
expect(encodeSseEvent('one\ntwo')).toBe('data: one\ndata: two\n\n');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=notification-stream.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-stream.test.js","sourceRoot":"","sources":["../../../src/__tests__/realtime/notification-stream.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/api/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/api/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAunB5C,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS9E;AA2ND,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqwNzD"}
|
package/dist/api/handlers.js
CHANGED
|
@@ -17,6 +17,8 @@ import { createPreviewStreamResponse } from '../preview/sse-stream.js';
|
|
|
17
17
|
import { notifyPreviewUpdate } from '../preview/event-bus.js';
|
|
18
18
|
import { createComment as createCommentService, deleteComment as deleteCommentService, listComments as listCommentsService, reopenComment as reopenCommentService, resolveComment as resolveCommentService, updateComment as updateCommentService, } from '../realtime/comments.js';
|
|
19
19
|
import { createNotification, excerptForNotification, extractMentionedUserIds, listForUser as listNotificationsForUser, markAllRead as markAllNotificationsRead, markRead as markNotificationRead, unreadCount as notificationsUnreadCount, } from '../realtime/notifications.js';
|
|
20
|
+
import { publishNotification } from '../realtime/notification-bus.js';
|
|
21
|
+
import { createNotificationStreamResponse } from '../realtime/notification-stream.js';
|
|
20
22
|
import { schedulingCronHandler } from '../scheduling/index.js';
|
|
21
23
|
import { isAuthorizedCronRequest, processCleanup, processSeoScan } from '../cron/index.js';
|
|
22
24
|
import { verifyCaptcha, getCaptchaConfig } from '../security/captcha.js';
|
|
@@ -4710,7 +4712,7 @@ export function registerCMSRoutes(router) {
|
|
|
4710
4712
|
if (opts.parentId) {
|
|
4711
4713
|
const root = await findCommentRecipient(opts.parentId);
|
|
4712
4714
|
if (root && root.userId && root.userId !== opts.actorId) {
|
|
4713
|
-
await createNotification(ndb, {
|
|
4715
|
+
const result = await createNotification(ndb, {
|
|
4714
4716
|
userId: root.userId,
|
|
4715
4717
|
documentId: opts.documentId,
|
|
4716
4718
|
commentId: opts.commentId,
|
|
@@ -4721,12 +4723,21 @@ export function registerCMSRoutes(router) {
|
|
|
4721
4723
|
excerpt: excerptForNotification(opts.body),
|
|
4722
4724
|
},
|
|
4723
4725
|
});
|
|
4726
|
+
// Push the new DTO to any active SSE subscribers for this user
|
|
4727
|
+
// so the bell badge bumps in real time. We only publish AFTER
|
|
4728
|
+
// the DB insert succeeds — otherwise an SSE client would see a
|
|
4729
|
+
// ghost notification that doesn't exist on a subsequent
|
|
4730
|
+
// refresh. Failure to publish (no subscribers, or bus error)
|
|
4731
|
+
// is non-fatal: the poll fallback in the admin UI still
|
|
4732
|
+
// converges.
|
|
4733
|
+
if (result.ok)
|
|
4734
|
+
publishNotification(result.value);
|
|
4724
4735
|
}
|
|
4725
4736
|
}
|
|
4726
4737
|
for (const userId of extractMentionedUserIds(opts.body)) {
|
|
4727
4738
|
if (userId === opts.actorId)
|
|
4728
4739
|
continue;
|
|
4729
|
-
await createNotification(ndb, {
|
|
4740
|
+
const result = await createNotification(ndb, {
|
|
4730
4741
|
userId,
|
|
4731
4742
|
documentId: opts.documentId,
|
|
4732
4743
|
commentId: opts.commentId,
|
|
@@ -4737,6 +4748,8 @@ export function registerCMSRoutes(router) {
|
|
|
4737
4748
|
excerpt: excerptForNotification(opts.body),
|
|
4738
4749
|
},
|
|
4739
4750
|
});
|
|
4751
|
+
if (result.ok)
|
|
4752
|
+
publishNotification(result.value);
|
|
4740
4753
|
}
|
|
4741
4754
|
}
|
|
4742
4755
|
/** Notify the comment's author when someone else resolves their thread. */
|
|
@@ -4744,7 +4757,7 @@ export function registerCMSRoutes(router) {
|
|
|
4744
4757
|
const comment = await findCommentRecipient(opts.commentId);
|
|
4745
4758
|
if (!comment || !comment.userId || comment.userId === opts.actorId)
|
|
4746
4759
|
return;
|
|
4747
|
-
await createNotification(notificationsDb(), {
|
|
4760
|
+
const result = await createNotification(notificationsDb(), {
|
|
4748
4761
|
userId: comment.userId,
|
|
4749
4762
|
commentId: opts.commentId,
|
|
4750
4763
|
payload: {
|
|
@@ -4754,6 +4767,8 @@ export function registerCMSRoutes(router) {
|
|
|
4754
4767
|
rootExcerpt: excerptForNotification(comment.body),
|
|
4755
4768
|
},
|
|
4756
4769
|
});
|
|
4770
|
+
if (result.ok)
|
|
4771
|
+
publishNotification(result.value);
|
|
4757
4772
|
}
|
|
4758
4773
|
router.post('/documents/:documentId/comments', async (request, params) => {
|
|
4759
4774
|
try {
|
|
@@ -5005,6 +5020,29 @@ export function registerCMSRoutes(router) {
|
|
|
5005
5020
|
return internalError(err, 'mark all notifications read');
|
|
5006
5021
|
}
|
|
5007
5022
|
});
|
|
5023
|
+
// Per-user notification SSE push channel (Phase 7 carry-over). The
|
|
5024
|
+
// admin's NotificationBell subscribes via EventSource for real-time
|
|
5025
|
+
// delivery of comment_reply / comment_mention / comment_resolved
|
|
5026
|
+
// events. The existing GET /notifications and
|
|
5027
|
+
// /notifications/unread-count REST endpoints are kept as a
|
|
5028
|
+
// poll-fallback path for multi-node deployments where a write on
|
|
5029
|
+
// node A doesn't reach SSE subscribers on node B (the in-process
|
|
5030
|
+
// bus is single-instance by design — see notification-bus.ts).
|
|
5031
|
+
//
|
|
5032
|
+
// Auth: same scope as every other /notifications route — the
|
|
5033
|
+
// session userId determines which channel the stream subscribes to;
|
|
5034
|
+
// there is no admin override.
|
|
5035
|
+
router.get('/notifications/stream', async (request) => {
|
|
5036
|
+
try {
|
|
5037
|
+
const auth = await requireAuth(request);
|
|
5038
|
+
if (auth.error)
|
|
5039
|
+
return auth.error;
|
|
5040
|
+
return createNotificationStreamResponse(auth.session.userId);
|
|
5041
|
+
}
|
|
5042
|
+
catch (err) {
|
|
5043
|
+
return internalError(err, 'notifications stream');
|
|
5044
|
+
}
|
|
5045
|
+
});
|
|
5008
5046
|
// ---------------------------------------------------------------------------
|
|
5009
5047
|
// Workflow routes
|
|
5010
5048
|
// ---------------------------------------------------------------------------
|