@nocobase/app-server 2.0.0-beta.9 → 3.0.0-beta.1
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/README.md +4 -0
- package/dist/application/index.d.ts +4 -1
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +23 -0
- package/dist/application/index.js.map +1 -1
- package/dist/plugins/types.d.ts +3 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/realtime/config.d.ts +20 -0
- package/dist/realtime/config.d.ts.map +1 -0
- package/dist/realtime/config.js +20 -0
- package/dist/realtime/config.js.map +1 -0
- package/dist/realtime/index.d.ts +1 -0
- package/dist/realtime/index.d.ts.map +1 -1
- package/dist/realtime/index.js +1 -0
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/provider.d.ts +5 -0
- package/dist/realtime/provider.d.ts.map +1 -1
- package/dist/realtime/provider.js +7 -3
- package/dist/realtime/provider.js.map +1 -1
- package/dist/realtime/service.d.ts +1 -8
- package/dist/realtime/service.d.ts.map +1 -1
- package/dist/realtime/service.js +1 -353
- package/dist/realtime/service.js.map +1 -1
- package/dist/realtime/types.d.ts +2 -74
- package/dist/realtime/types.d.ts.map +1 -1
- package/dist/realtime/types.js +1 -0
- package/dist/realtime/types.js.map +1 -1
- package/dist/realtime/websocket.d.ts +1 -1
- package/dist/realtime/websocket.d.ts.map +1 -1
- package/dist/realtime/websocket.js +23 -9
- package/dist/realtime/websocket.js.map +1 -1
- package/dist/websocket.d.ts +1 -60
- package/dist/websocket.d.ts.map +1 -1
- package/dist/websocket.js +2 -370
- package/dist/websocket.js.map +1 -1
- package/package.json +9 -9
package/dist/realtime/service.js
CHANGED
|
@@ -1,354 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { encodeRealtimeServerMessage, parseRealtimeClientMessage, RealtimeProtocolError, validateRealtimeTopic, } from '@nocobase/realtime/protocol';
|
|
3
|
-
const WEB_SOCKET_OPEN = 1;
|
|
4
|
-
const CLOSE_GOING_AWAY = 1001;
|
|
5
|
-
export function createRealtimeService(options = {}) {
|
|
6
|
-
const maxSubscriptionsPerConnection = options.maxSubscriptionsPerConnection ?? 64;
|
|
7
|
-
const connections = new Map();
|
|
8
|
-
const subscriptions = new Map();
|
|
9
|
-
const subscriptionsByTopic = new Map();
|
|
10
|
-
const listenersByTopic = new Map();
|
|
11
|
-
const service = {
|
|
12
|
-
connect(ws, context = {}) {
|
|
13
|
-
const connection = {
|
|
14
|
-
id: randomUUID(),
|
|
15
|
-
ws,
|
|
16
|
-
connectedAt: new Date(),
|
|
17
|
-
request: context.request,
|
|
18
|
-
principal: context.principal,
|
|
19
|
-
subscriptions: new Set(),
|
|
20
|
-
};
|
|
21
|
-
connections.set(connection.id, connection);
|
|
22
|
-
return connection;
|
|
23
|
-
},
|
|
24
|
-
disconnect(connection) {
|
|
25
|
-
const stored = connections.get(connection.id);
|
|
26
|
-
if (!stored) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
removeConnectionSubscriptions(stored);
|
|
30
|
-
connections.delete(stored.id);
|
|
31
|
-
},
|
|
32
|
-
disconnectUser(userId) {
|
|
33
|
-
let disconnected = 0;
|
|
34
|
-
for (const connection of Array.from(connections.values())) {
|
|
35
|
-
if (connection.principal?.userId !== userId)
|
|
36
|
-
continue;
|
|
37
|
-
if (connection.ws.readyState === WEB_SOCKET_OPEN) {
|
|
38
|
-
connection.ws.close(CLOSE_GOING_AWAY, 'account session revoked');
|
|
39
|
-
}
|
|
40
|
-
service.disconnect(connection);
|
|
41
|
-
disconnected += 1;
|
|
42
|
-
}
|
|
43
|
-
return disconnected;
|
|
44
|
-
},
|
|
45
|
-
subscribe(connection, topic) {
|
|
46
|
-
validateRealtimeTopic(topic);
|
|
47
|
-
const existing = findSubscription(connection, { topic });
|
|
48
|
-
if (existing) {
|
|
49
|
-
return existing;
|
|
50
|
-
}
|
|
51
|
-
if (connection.subscriptions.size >= maxSubscriptionsPerConnection) {
|
|
52
|
-
throw new RealtimeProtocolError('TOO_MANY_SUBSCRIPTIONS', 'Realtime connection has too many subscriptions.');
|
|
53
|
-
}
|
|
54
|
-
const subscription = {
|
|
55
|
-
id: randomUUID(),
|
|
56
|
-
connectionId: connection.id,
|
|
57
|
-
topic,
|
|
58
|
-
userId: resolveSubscriptionUserId(connection, topic),
|
|
59
|
-
createdAt: new Date(),
|
|
60
|
-
};
|
|
61
|
-
subscriptions.set(subscription.id, subscription);
|
|
62
|
-
connection.subscriptions.add(subscription.id);
|
|
63
|
-
addTopicSubscription(subscription);
|
|
64
|
-
return subscription;
|
|
65
|
-
},
|
|
66
|
-
unsubscribe(connection, selector) {
|
|
67
|
-
const removed = [];
|
|
68
|
-
for (const subscriptionId of Array.from(connection.subscriptions)) {
|
|
69
|
-
const subscription = subscriptions.get(subscriptionId);
|
|
70
|
-
if (!subscription || !matchesSubscription(subscription, selector)) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
removeSubscription(connection, subscription);
|
|
74
|
-
removed.push(subscription);
|
|
75
|
-
}
|
|
76
|
-
return removed;
|
|
77
|
-
},
|
|
78
|
-
handleClientMessage(connection, data) {
|
|
79
|
-
let message;
|
|
80
|
-
try {
|
|
81
|
-
message = parseRealtimeClientMessage(data);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
sendProtocolError(connection, error);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
try {
|
|
88
|
-
switch (message.type) {
|
|
89
|
-
case 'subscribe': {
|
|
90
|
-
const subscription = service.subscribe(connection, message.topic);
|
|
91
|
-
send(connection, {
|
|
92
|
-
type: 'subscribed',
|
|
93
|
-
id: message.id,
|
|
94
|
-
topic: subscription.topic,
|
|
95
|
-
subscriptionId: subscription.id,
|
|
96
|
-
});
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
case 'unsubscribe': {
|
|
100
|
-
const removed = service.unsubscribe(connection, {
|
|
101
|
-
subscriptionId: message.subscriptionId,
|
|
102
|
-
topic: message.topic,
|
|
103
|
-
});
|
|
104
|
-
const first = removed[0];
|
|
105
|
-
send(connection, {
|
|
106
|
-
type: 'unsubscribed',
|
|
107
|
-
id: message.id,
|
|
108
|
-
subscriptionId: message.subscriptionId ?? first?.id,
|
|
109
|
-
topic: message.topic ?? first?.topic,
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
case 'publish':
|
|
114
|
-
send(connection, {
|
|
115
|
-
type: 'error',
|
|
116
|
-
id: message.id,
|
|
117
|
-
code: 'PUBLISH_FORBIDDEN',
|
|
118
|
-
message: 'Client publish is not allowed.',
|
|
119
|
-
});
|
|
120
|
-
return;
|
|
121
|
-
case 'ping':
|
|
122
|
-
send(connection, {
|
|
123
|
-
type: 'pong',
|
|
124
|
-
id: message.id,
|
|
125
|
-
});
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
sendProtocolError(connection, error);
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
registerTopic(topic, topicDefinition) {
|
|
134
|
-
validateRealtimeTopic(topic);
|
|
135
|
-
if (topicOptions.has(topic)) {
|
|
136
|
-
throw new RealtimeProtocolError('TOPIC_ALREADY_REGISTERED', `Realtime topic "${topic}" is already registered.`);
|
|
137
|
-
}
|
|
138
|
-
topicOptions.set(topic, topicDefinition);
|
|
139
|
-
return () => {
|
|
140
|
-
if (topicOptions.get(topic) !== topicDefinition) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
removeTopicSubscriptions(topic);
|
|
144
|
-
topicOptions.delete(topic);
|
|
145
|
-
};
|
|
146
|
-
},
|
|
147
|
-
defineTopic(topic, topicDefinition) {
|
|
148
|
-
const close = service.registerTopic(topic, topicDefinition);
|
|
149
|
-
const definedTopic = topicDefinition.audience === 'user'
|
|
150
|
-
? {
|
|
151
|
-
name: topic,
|
|
152
|
-
audience: 'user',
|
|
153
|
-
publishFor(userId, payload) {
|
|
154
|
-
return service.publish(topic, payload, { userId });
|
|
155
|
-
},
|
|
156
|
-
close,
|
|
157
|
-
}
|
|
158
|
-
: {
|
|
159
|
-
name: topic,
|
|
160
|
-
audience: 'public',
|
|
161
|
-
publish(payload) {
|
|
162
|
-
return service.publish(topic, payload);
|
|
163
|
-
},
|
|
164
|
-
close,
|
|
165
|
-
};
|
|
166
|
-
return definedTopic;
|
|
167
|
-
},
|
|
168
|
-
publish(topic, payload, options = {}) {
|
|
169
|
-
validateRealtimeTopic(topic);
|
|
170
|
-
const audience = topicOptions.get(topic)?.audience ?? 'public';
|
|
171
|
-
const authenticated = requiresAuthentication(topic);
|
|
172
|
-
if (audience === 'user' && !options.userId) {
|
|
173
|
-
throw new RealtimeProtocolError('USER_AUDIENCE_REQUIRED', `Realtime topic "${topic}" requires a user audience.`);
|
|
174
|
-
}
|
|
175
|
-
if (audience === 'public' && options.userId) {
|
|
176
|
-
throw new RealtimeProtocolError('INVALID_AUDIENCE', `Realtime topic "${topic}" does not accept a user audience.`);
|
|
177
|
-
}
|
|
178
|
-
const subscriptionIds = subscriptionsByTopic.get(topic);
|
|
179
|
-
if (!subscriptionIds?.size) {
|
|
180
|
-
return {
|
|
181
|
-
topic,
|
|
182
|
-
subscriberCount: 0,
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
const message = {
|
|
186
|
-
type: 'event',
|
|
187
|
-
topic,
|
|
188
|
-
payload,
|
|
189
|
-
publishedAt: new Date().toISOString(),
|
|
190
|
-
};
|
|
191
|
-
const sentConnections = new Set();
|
|
192
|
-
for (const subscriptionId of Array.from(subscriptionIds)) {
|
|
193
|
-
const subscription = subscriptions.get(subscriptionId);
|
|
194
|
-
const connection = subscription
|
|
195
|
-
? connections.get(subscription.connectionId)
|
|
196
|
-
: undefined;
|
|
197
|
-
if (!subscription ||
|
|
198
|
-
!connection ||
|
|
199
|
-
(audience === 'user' && subscription.userId !== options.userId) ||
|
|
200
|
-
(authenticated && !connection.principal?.userId) ||
|
|
201
|
-
sentConnections.has(connection.id)) {
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
if (connection.ws.readyState !== WEB_SOCKET_OPEN) {
|
|
205
|
-
service.disconnect(connection);
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
sentConnections.add(connection.id);
|
|
209
|
-
send(connection, message);
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
topic,
|
|
213
|
-
subscriberCount: sentConnections.size,
|
|
214
|
-
};
|
|
215
|
-
},
|
|
216
|
-
subscriptionCount(topic) {
|
|
217
|
-
return subscriptionsByTopic.get(topic)?.size ?? 0;
|
|
218
|
-
},
|
|
219
|
-
onTopicSubscriptionChange(topic, listener) {
|
|
220
|
-
validateRealtimeTopic(topic);
|
|
221
|
-
const listeners = listenersByTopic.get(topic) ?? new Set();
|
|
222
|
-
listeners.add(listener);
|
|
223
|
-
listenersByTopic.set(topic, listeners);
|
|
224
|
-
return () => {
|
|
225
|
-
listeners.delete(listener);
|
|
226
|
-
if (listeners.size === 0) {
|
|
227
|
-
listenersByTopic.delete(topic);
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
},
|
|
231
|
-
close() {
|
|
232
|
-
for (const connection of Array.from(connections.values())) {
|
|
233
|
-
if (connection.ws.readyState === WEB_SOCKET_OPEN) {
|
|
234
|
-
connection.ws.close(CLOSE_GOING_AWAY, 'realtime service closed');
|
|
235
|
-
}
|
|
236
|
-
service.disconnect(connection);
|
|
237
|
-
}
|
|
238
|
-
subscriptions.clear();
|
|
239
|
-
subscriptionsByTopic.clear();
|
|
240
|
-
listenersByTopic.clear();
|
|
241
|
-
topicOptions.clear();
|
|
242
|
-
},
|
|
243
|
-
};
|
|
244
|
-
const topicOptions = new Map();
|
|
245
|
-
function findSubscription(connection, selector) {
|
|
246
|
-
for (const subscriptionId of connection.subscriptions) {
|
|
247
|
-
const subscription = subscriptions.get(subscriptionId);
|
|
248
|
-
if (subscription && matchesSubscription(subscription, selector)) {
|
|
249
|
-
return subscription;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return undefined;
|
|
253
|
-
}
|
|
254
|
-
function matchesSubscription(subscription, selector) {
|
|
255
|
-
return ((selector.subscriptionId === undefined ||
|
|
256
|
-
subscription.id === selector.subscriptionId) &&
|
|
257
|
-
(selector.topic === undefined || subscription.topic === selector.topic));
|
|
258
|
-
}
|
|
259
|
-
function addTopicSubscription(subscription) {
|
|
260
|
-
const previousCount = service.subscriptionCount(subscription.topic);
|
|
261
|
-
const topicSubscriptions = subscriptionsByTopic.get(subscription.topic) ?? new Set();
|
|
262
|
-
topicSubscriptions.add(subscription.id);
|
|
263
|
-
subscriptionsByTopic.set(subscription.topic, topicSubscriptions);
|
|
264
|
-
notifyTopicSubscriptionChange(subscription.topic, previousCount);
|
|
265
|
-
}
|
|
266
|
-
function removeConnectionSubscriptions(connection) {
|
|
267
|
-
for (const subscriptionId of Array.from(connection.subscriptions)) {
|
|
268
|
-
const subscription = subscriptions.get(subscriptionId);
|
|
269
|
-
if (subscription) {
|
|
270
|
-
removeSubscription(connection, subscription);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
function removeTopicSubscriptions(topic) {
|
|
275
|
-
const subscriptionIds = subscriptionsByTopic.get(topic);
|
|
276
|
-
if (!subscriptionIds) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
for (const subscriptionId of Array.from(subscriptionIds)) {
|
|
280
|
-
const subscription = subscriptions.get(subscriptionId);
|
|
281
|
-
const connection = subscription
|
|
282
|
-
? connections.get(subscription.connectionId)
|
|
283
|
-
: undefined;
|
|
284
|
-
if (subscription && connection) {
|
|
285
|
-
removeSubscription(connection, subscription);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
function resolveSubscriptionUserId(connection, topic) {
|
|
290
|
-
if (!requiresAuthentication(topic)) {
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
const userId = connection.principal?.userId;
|
|
294
|
-
if (!userId) {
|
|
295
|
-
throw new RealtimeProtocolError('AUTHENTICATION_REQUIRED', `Realtime topic "${topic}" requires authentication.`);
|
|
296
|
-
}
|
|
297
|
-
return userId;
|
|
298
|
-
}
|
|
299
|
-
/** User topics, and public topics registered with `authenticated`, reach only connections with a principal. */
|
|
300
|
-
function requiresAuthentication(topic) {
|
|
301
|
-
const definition = topicOptions.get(topic);
|
|
302
|
-
return (definition?.audience === 'user' || definition?.authenticated === true);
|
|
303
|
-
}
|
|
304
|
-
function removeSubscription(connection, subscription) {
|
|
305
|
-
const previousCount = service.subscriptionCount(subscription.topic);
|
|
306
|
-
connection.subscriptions.delete(subscription.id);
|
|
307
|
-
subscriptions.delete(subscription.id);
|
|
308
|
-
const topicSubscriptions = subscriptionsByTopic.get(subscription.topic);
|
|
309
|
-
topicSubscriptions?.delete(subscription.id);
|
|
310
|
-
if (topicSubscriptions?.size === 0) {
|
|
311
|
-
subscriptionsByTopic.delete(subscription.topic);
|
|
312
|
-
}
|
|
313
|
-
notifyTopicSubscriptionChange(subscription.topic, previousCount);
|
|
314
|
-
}
|
|
315
|
-
function notifyTopicSubscriptionChange(topic, previousCount) {
|
|
316
|
-
const count = service.subscriptionCount(topic);
|
|
317
|
-
if (count === previousCount) {
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
const listeners = listenersByTopic.get(topic);
|
|
321
|
-
if (!listeners) {
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
for (const listener of Array.from(listeners)) {
|
|
325
|
-
try {
|
|
326
|
-
listener(count);
|
|
327
|
-
}
|
|
328
|
-
catch (error) {
|
|
329
|
-
if (options.logger)
|
|
330
|
-
options.logger.error({ err: error }, 'Realtime subscription listener failed');
|
|
331
|
-
else
|
|
332
|
-
console.error(error);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
function sendProtocolError(connection, error) {
|
|
337
|
-
const code = error instanceof RealtimeProtocolError ? error.code : 'REALTIME_ERROR';
|
|
338
|
-
const message = error instanceof Error ? error.message : 'Realtime message failed.';
|
|
339
|
-
send(connection, {
|
|
340
|
-
type: 'error',
|
|
341
|
-
code,
|
|
342
|
-
message,
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
function send(connection, message) {
|
|
346
|
-
if (connection.ws.readyState !== WEB_SOCKET_OPEN) {
|
|
347
|
-
service.disconnect(connection);
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
connection.ws.send(encodeRealtimeServerMessage(message));
|
|
351
|
-
}
|
|
352
|
-
return service;
|
|
353
|
-
}
|
|
1
|
+
export { createRealtimeService, } from '@nocobase/realtime/server';
|
|
354
2
|
//# sourceMappingURL=service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/realtime/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzC,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GAEtB,MAAM,6BAA6B,CAAC;AAErC,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAe9B,MAAM,UAAU,qBAAqB,CACnC,UAAkC,EAAE;IAEpC,MAAM,6BAA6B,GACjC,OAAO,CAAC,6BAA6B,IAAI,EAAE,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC1D,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC9D,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC5D,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAwC,CAAC;IAEzE,MAAM,OAAO,GAAoB;QAC/B,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE;YACtB,MAAM,UAAU,GAAuB;gBACrC,EAAE,EAAE,UAAU,EAAE;gBAChB,EAAE;gBACF,WAAW,EAAE,IAAI,IAAI,EAAE;gBACvB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,aAAa,EAAE,IAAI,GAAG,EAAE;aACzB,CAAC;YACF,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC3C,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,UAAU,CAAC,UAAU;YACnB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YAED,6BAA6B,CAAC,MAAM,CAAC,CAAC;YACtC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChC,CAAC;QAED,cAAc,CAAC,MAAM;YACnB,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC1D,IAAI,UAAU,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM;oBAAE,SAAS;gBACtD,IAAI,UAAU,CAAC,EAAE,CAAC,UAAU,KAAK,eAAe,EAAE,CAAC;oBACjD,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;gBACnE,CAAC;gBACD,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBAC/B,YAAY,IAAI,CAAC,CAAC;YACpB,CAAC;YACD,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,SAAS,CAAC,UAAU,EAAE,KAAK;YACzB,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAE7B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACzD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC;YAED,IAAI,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,6BAA6B,EAAE,CAAC;gBACnE,MAAM,IAAI,qBAAqB,CAC7B,wBAAwB,EACxB,iDAAiD,CAClD,CAAC;YACJ,CAAC;YAED,MAAM,YAAY,GAAyB;gBACzC,EAAE,EAAE,UAAU,EAAE;gBAChB,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,KAAK;gBACL,MAAM,EAAE,yBAAyB,CAAC,UAAU,EAAE,KAAK,CAAC;gBACpD,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC;YACF,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;YACjD,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC9C,oBAAoB,CAAC,YAAY,CAAC,CAAC;YACnC,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,WAAW,CAAC,UAAU,EAAE,QAAQ;YAC9B,MAAM,OAAO,GAA2B,EAAE,CAAC;YAE3C,KAAK,MAAM,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClE,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACvD,IAAI,CAAC,YAAY,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC;oBAClE,SAAS;gBACX,CAAC;gBAED,kBAAkB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;gBAC7C,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC7B,CAAC;YAED,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,mBAAmB,CAAC,UAAU,EAAE,IAAI;YAClC,IAAI,OAAO,CAAC;YACZ,IAAI,CAAC;gBACH,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBACrC,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;oBACrB,KAAK,WAAW,CAAC,CAAC,CAAC;wBACjB,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;wBAClE,IAAI,CAAC,UAAU,EAAE;4BACf,IAAI,EAAE,YAAY;4BAClB,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,KAAK,EAAE,YAAY,CAAC,KAAK;4BACzB,cAAc,EAAE,YAAY,CAAC,EAAE;yBAChC,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBACD,KAAK,aAAa,CAAC,CAAC,CAAC;wBACnB,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE;4BAC9C,cAAc,EAAE,OAAO,CAAC,cAAc;4BACtC,KAAK,EAAE,OAAO,CAAC,KAAK;yBACrB,CAAC,CAAC;wBACH,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;wBACzB,IAAI,CAAC,UAAU,EAAE;4BACf,IAAI,EAAE,cAAc;4BACpB,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,KAAK,EAAE,EAAE;4BACnD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,KAAK;yBACrC,CAAC,CAAC;wBACH,OAAO;oBACT,CAAC;oBACD,KAAK,SAAS;wBACZ,IAAI,CAAC,UAAU,EAAE;4BACf,IAAI,EAAE,OAAO;4BACb,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,IAAI,EAAE,mBAAmB;4BACzB,OAAO,EAAE,gCAAgC;yBAC1C,CAAC,CAAC;wBACH,OAAO;oBACT,KAAK,MAAM;wBACT,IAAI,CAAC,UAAU,EAAE;4BACf,IAAI,EAAE,MAAM;4BACZ,EAAE,EAAE,OAAO,CAAC,EAAE;yBACf,CAAC,CAAC;wBACH,OAAO;gBACX,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,aAAa,CAAC,KAAK,EAAE,eAAe;YAClC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,qBAAqB,CAC7B,0BAA0B,EAC1B,mBAAmB,KAAK,0BAA0B,CACnD,CAAC;YACJ,CAAC;YAED,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YACzC,OAAO,GAAG,EAAE;gBACV,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,eAAe,EAAE,CAAC;oBAChD,OAAO;gBACT,CAAC;gBAED,wBAAwB,CAAC,KAAK,CAAC,CAAC;gBAChC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC,CAAC;QACJ,CAAC;QAED,WAAW,CACT,KAAa,EACb,eAGC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YAC5D,MAAM,YAAY,GAChB,eAAe,CAAC,QAAQ,KAAK,MAAM;gBACjC,CAAC,CAAC;oBACE,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,MAAe;oBACzB,UAAU,CAAC,MAAc,EAAE,OAAgB;wBACzC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;oBACrD,CAAC;oBACD,KAAK;iBACN;gBACH,CAAC,CAAC;oBACE,IAAI,EAAE,KAAK;oBACX,QAAQ,EAAE,QAAiB;oBAC3B,OAAO,CAAC,OAAgB;wBACtB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;oBACzC,CAAC;oBACD,KAAK;iBACN,CAAC;YAER,OAAO,YAAuD,CAAC;QACjE,CAAC;QAED,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE;YAClC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,IAAI,QAAQ,CAAC;YAC/D,MAAM,aAAa,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;YACpD,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC3C,MAAM,IAAI,qBAAqB,CAC7B,wBAAwB,EACxB,mBAAmB,KAAK,6BAA6B,CACtD,CAAC;YACJ,CAAC;YACD,IAAI,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC5C,MAAM,IAAI,qBAAqB,CAC7B,kBAAkB,EAClB,mBAAmB,KAAK,oCAAoC,CAC7D,CAAC;YACJ,CAAC;YAED,MAAM,eAAe,GAAG,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACxD,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;gBAC3B,OAAO;oBACL,KAAK;oBACL,eAAe,EAAE,CAAC;iBACnB,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAA0B;gBACrC,IAAI,EAAE,OAAO;gBACb,KAAK;gBACL,OAAO;gBACP,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACtC,CAAC;YACF,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;YAE1C,KAAK,MAAM,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;gBACzD,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACvD,MAAM,UAAU,GAAG,YAAY;oBAC7B,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC;oBAC5C,CAAC,CAAC,SAAS,CAAC;gBACd,IACE,CAAC,YAAY;oBACb,CAAC,UAAU;oBACX,CAAC,QAAQ,KAAK,MAAM,IAAI,YAAY,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC;oBAC/D,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;oBAChD,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,EAClC,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,IAAI,UAAU,CAAC,EAAE,CAAC,UAAU,KAAK,eAAe,EAAE,CAAC;oBACjD,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;oBAC/B,SAAS;gBACX,CAAC;gBAED,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBACnC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC5B,CAAC;YAED,OAAO;gBACL,KAAK;gBACL,eAAe,EAAE,eAAe,CAAC,IAAI;aACtC,CAAC;QACJ,CAAC;QAED,iBAAiB,CAAC,KAAK;YACrB,OAAO,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;QACpD,CAAC;QAED,yBAAyB,CAAC,KAAK,EAAE,QAAQ;YACvC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAE7B,MAAM,SAAS,GACb,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,EAA2B,CAAC;YACpE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAEvC,OAAO,GAAG,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC3B,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACzB,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,KAAK;YACH,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC1D,IAAI,UAAU,CAAC,EAAE,CAAC,UAAU,KAAK,eAAe,EAAE,CAAC;oBACjD,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,yBAAyB,CAAC,CAAC;gBACnE,CAAC;gBAED,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YACjC,CAAC;YAED,aAAa,CAAC,KAAK,EAAE,CAAC;YACtB,oBAAoB,CAAC,KAAK,EAAE,CAAC;YAC7B,gBAAgB,CAAC,KAAK,EAAE,CAAC;YACzB,YAAY,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE7D,SAAS,gBAAgB,CACvB,UAA8B,EAC9B,QAAqD;QAErD,KAAK,MAAM,cAAc,IAAI,UAAU,CAAC,aAAa,EAAE,CAAC;YACtD,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YACvD,IAAI,YAAY,IAAI,mBAAmB,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAChE,OAAO,YAAY,CAAC;YACtB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,SAAS,mBAAmB,CAC1B,YAAkC,EAClC,QAAqD;QAErD,OAAO,CACL,CAAC,QAAQ,CAAC,cAAc,KAAK,SAAS;YACpC,YAAY,CAAC,EAAE,KAAK,QAAQ,CAAC,cAAc,CAAC;YAC9C,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,KAAK,KAAK,QAAQ,CAAC,KAAK,CAAC,CACxE,CAAC;IACJ,CAAC;IAED,SAAS,oBAAoB,CAAC,YAAkC;QAC9D,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpE,MAAM,kBAAkB,GACtB,oBAAoB,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QACpE,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACxC,oBAAoB,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;QACjE,6BAA6B,CAAC,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IAED,SAAS,6BAA6B,CAAC,UAA8B;QACnE,KAAK,MAAM,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAClE,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YACvD,IAAI,YAAY,EAAE,CAAC;gBACjB,kBAAkB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,wBAAwB,CAAC,KAAa;QAC7C,MAAM,eAAe,GAAG,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YACzD,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YACvD,MAAM,UAAU,GAAG,YAAY;gBAC7B,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC5C,CAAC,CAAC,SAAS,CAAC;YACd,IAAI,YAAY,IAAI,UAAU,EAAE,CAAC;gBAC/B,kBAAkB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,yBAAyB,CAChC,UAA8B,EAC9B,KAAa;QAEb,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,qBAAqB,CAC7B,yBAAyB,EACzB,mBAAmB,KAAK,4BAA4B,CACrD,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+GAA+G;IAC/G,SAAS,sBAAsB,CAAC,KAAa;QAC3C,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3C,OAAO,CACL,UAAU,EAAE,QAAQ,KAAK,MAAM,IAAI,UAAU,EAAE,aAAa,KAAK,IAAI,CACtE,CAAC;IACJ,CAAC;IAED,SAAS,kBAAkB,CACzB,UAA8B,EAC9B,YAAkC;QAElC,MAAM,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACpE,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACjD,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAEtC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACxE,kBAAkB,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,kBAAkB,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC;YACnC,oBAAoB,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;QACD,6BAA6B,CAAC,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IAED,SAAS,6BAA6B,CACpC,KAAa,EACb,aAAqB;QAErB,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,OAAO,CAAC,MAAM;oBAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,EAAE,GAAG,EAAE,KAAK,EAAE,EACd,uCAAuC,CACxC,CAAC;;oBACC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,iBAAiB,CACxB,UAA8B,EAC9B,KAAc;QAEd,MAAM,IAAI,GACR,KAAK,YAAY,qBAAqB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACzE,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;QACtE,IAAI,CAAC,UAAU,EAAE;YACf,IAAI,EAAE,OAAO;YACb,IAAI;YACJ,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,SAAS,IAAI,CACX,UAA8B,EAC9B,OAA8B;QAE9B,IAAI,UAAU,CAAC,EAAE,CAAC,UAAU,KAAK,eAAe,EAAE,CAAC;YACjD,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/realtime/service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC"}
|
package/dist/realtime/types.d.ts
CHANGED
|
@@ -1,81 +1,9 @@
|
|
|
1
|
-
import type { AppWebSocket, AppWebSocketMessageData } from '@nocobase/app-websocket';
|
|
2
1
|
import { type ServiceToken } from '@nocobase/service-provider';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
principal?: RealtimePrincipal;
|
|
6
|
-
}
|
|
7
|
-
export interface RealtimePrincipal {
|
|
8
|
-
readonly userId: string;
|
|
9
|
-
}
|
|
2
|
+
import type { RealtimePrincipal, RealtimeService } from '@nocobase/realtime/server';
|
|
3
|
+
export * from '@nocobase/realtime/server';
|
|
10
4
|
export interface RealtimePrincipalResolver {
|
|
11
5
|
resolve(request: Request): Promise<RealtimePrincipal | undefined>;
|
|
12
6
|
}
|
|
13
|
-
export interface RealtimeConnection {
|
|
14
|
-
readonly id: string;
|
|
15
|
-
readonly ws: AppWebSocket;
|
|
16
|
-
readonly connectedAt: Date;
|
|
17
|
-
readonly request?: Request;
|
|
18
|
-
readonly principal?: RealtimePrincipal;
|
|
19
|
-
readonly subscriptions: Set<string>;
|
|
20
|
-
}
|
|
21
|
-
export interface RealtimeSubscription {
|
|
22
|
-
readonly id: string;
|
|
23
|
-
readonly connectionId: string;
|
|
24
|
-
readonly topic: string;
|
|
25
|
-
readonly userId?: string;
|
|
26
|
-
readonly createdAt: Date;
|
|
27
|
-
}
|
|
28
|
-
export interface RealtimePublishResult {
|
|
29
|
-
readonly topic: string;
|
|
30
|
-
readonly subscriberCount: number;
|
|
31
|
-
}
|
|
32
|
-
export type RealtimeTopicAudience = 'public' | 'user';
|
|
33
|
-
export interface RealtimeTopicOptions {
|
|
34
|
-
readonly audience: RealtimeTopicAudience;
|
|
35
|
-
/**
|
|
36
|
-
* A public topic delivered only to authenticated connections: subscribing without a principal is refused
|
|
37
|
-
* (`AUTHENTICATION_REQUIRED`) and publishing skips such connections. For payloads that name records, such as ids,
|
|
38
|
-
* which anonymous visitors should not learn of. User topics always require authentication.
|
|
39
|
-
*/
|
|
40
|
-
readonly authenticated?: boolean;
|
|
41
|
-
}
|
|
42
|
-
export interface RealtimePublishOptions {
|
|
43
|
-
readonly userId?: string;
|
|
44
|
-
}
|
|
45
|
-
export interface RealtimeTopicBase {
|
|
46
|
-
readonly name: string;
|
|
47
|
-
close(): void;
|
|
48
|
-
}
|
|
49
|
-
export interface RealtimePublicTopic<Payload> extends RealtimeTopicBase {
|
|
50
|
-
readonly audience: 'public';
|
|
51
|
-
publish(payload: Payload): RealtimePublishResult;
|
|
52
|
-
}
|
|
53
|
-
export interface RealtimeUserTopic<Payload> extends RealtimeTopicBase {
|
|
54
|
-
readonly audience: 'user';
|
|
55
|
-
publishFor(userId: string, payload: Payload): RealtimePublishResult;
|
|
56
|
-
}
|
|
57
|
-
export type DefinedRealtimeTopic<Payload, Audience extends RealtimeTopicAudience> = Audience extends 'user' ? RealtimeUserTopic<Payload> : RealtimePublicTopic<Payload>;
|
|
58
|
-
export interface RealtimeService {
|
|
59
|
-
connect(ws: AppWebSocket, context?: RealtimeConnectionContext): RealtimeConnection;
|
|
60
|
-
disconnect(connection: RealtimeConnection): void;
|
|
61
|
-
/** Closes every active connection authenticated as the given user. */
|
|
62
|
-
disconnectUser(userId: string): number;
|
|
63
|
-
subscribe(connection: RealtimeConnection, topic: string): RealtimeSubscription;
|
|
64
|
-
unsubscribe(connection: RealtimeConnection, selector: {
|
|
65
|
-
subscriptionId?: string;
|
|
66
|
-
topic?: string;
|
|
67
|
-
}): RealtimeSubscription[];
|
|
68
|
-
handleClientMessage(connection: RealtimeConnection, data: AppWebSocketMessageData): void;
|
|
69
|
-
registerTopic(topic: string, options: RealtimeTopicOptions): () => void;
|
|
70
|
-
defineTopic<Payload, Audience extends RealtimeTopicAudience>(topic: string, options: {
|
|
71
|
-
readonly audience: Audience;
|
|
72
|
-
readonly authenticated?: boolean;
|
|
73
|
-
}): DefinedRealtimeTopic<Payload, Audience>;
|
|
74
|
-
publish(topic: string, payload: unknown, options?: RealtimePublishOptions): RealtimePublishResult;
|
|
75
|
-
subscriptionCount(topic: string): number;
|
|
76
|
-
onTopicSubscriptionChange(topic: string, listener: (count: number) => void): () => void;
|
|
77
|
-
close(): void;
|
|
78
|
-
}
|
|
79
7
|
export declare const realtimeServiceToken: ServiceToken<RealtimeService>;
|
|
80
8
|
export declare const realtimePrincipalResolverToken: ServiceToken<RealtimePrincipalResolver>;
|
|
81
9
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EAChB,MAAM,2BAA2B,CAAC;AAEnC,cAAc,2BAA2B,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;CACnE;AAED,eAAO,MAAM,oBAAoB,EAAE,YAAY,CAAC,eAAe,CACQ,CAAC;AAExE,eAAO,MAAM,8BAA8B,EAAE,YAAY,CAAC,yBAAyB,CAGhF,CAAC"}
|
package/dist/realtime/types.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createServiceToken, } from '@nocobase/service-provider';
|
|
2
|
+
export * from '@nocobase/realtime/server';
|
|
2
3
|
export const realtimeServiceToken = createServiceToken('@nocobase/app/realtime-service');
|
|
3
4
|
export const realtimePrincipalResolverToken = createServiceToken('@nocobase/app/realtime-principal-resolver');
|
|
4
5
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/realtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,4BAA4B,CAAC;AAMpC,cAAc,2BAA2B,CAAC;AAM1C,MAAM,CAAC,MAAM,oBAAoB,GAC/B,kBAAkB,CAAkB,gCAAgC,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,8BAA8B,GACzC,kBAAkB,CAChB,2CAA2C,CAC5C,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Hono } from 'hono';
|
|
2
2
|
import type { ServiceResolver } from '@nocobase/service-provider';
|
|
3
|
-
import type { AppWebSocketHandler } from '
|
|
3
|
+
import type { AppWebSocketHandler } from '@nocobase/app-websocket';
|
|
4
4
|
export declare const REALTIME_WEBSOCKET_PATH: string;
|
|
5
5
|
export declare function registerRealtimeWebSocketRoutes(router: Hono): void;
|
|
6
6
|
export declare function createRealtimeWebSocketHandler(container: ServiceResolver): AppWebSocketHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/realtime/websocket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/realtime/websocket.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAOnE,eAAO,MAAM,uBAAuB,EAAE,MAAc,CAAC;AAErD,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAclE;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,eAAe,GACzB,mBAAmB,CAiErB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { REALTIME_MAX_MESSAGE_BYTES } from '@nocobase/realtime/protocol';
|
|
1
2
|
import { realtimePrincipalResolverToken, realtimeServiceToken, } from './types.js';
|
|
2
3
|
export const REALTIME_WEBSOCKET_PATH = '/ws';
|
|
3
4
|
export function registerRealtimeWebSocketRoutes(router) {
|
|
@@ -24,9 +25,21 @@ export function createRealtimeWebSocketHandler(container) {
|
|
|
24
25
|
return Response.json({ error: 'WebSocket origin is not allowed.' }, { status: 403 });
|
|
25
26
|
}
|
|
26
27
|
const realtime = container.resolve(realtimeServiceToken);
|
|
27
|
-
const
|
|
28
|
-
?
|
|
28
|
+
const resolver = container.has(realtimePrincipalResolverToken)
|
|
29
|
+
? container.resolve(realtimePrincipalResolverToken)
|
|
29
30
|
: undefined;
|
|
31
|
+
const principal = await resolver?.resolve(request);
|
|
32
|
+
const context = {
|
|
33
|
+
request,
|
|
34
|
+
principal,
|
|
35
|
+
validatePrincipal: principal && resolver
|
|
36
|
+
? async () => {
|
|
37
|
+
const current = await resolver.resolve(request);
|
|
38
|
+
return (current?.userId === principal.userId &&
|
|
39
|
+
current?.sessionId === principal.sessionId);
|
|
40
|
+
}
|
|
41
|
+
: undefined,
|
|
42
|
+
};
|
|
30
43
|
let connection;
|
|
31
44
|
const disconnect = () => {
|
|
32
45
|
if (!connection) {
|
|
@@ -36,20 +49,21 @@ export function createRealtimeWebSocketHandler(container) {
|
|
|
36
49
|
connection = undefined;
|
|
37
50
|
};
|
|
38
51
|
return {
|
|
52
|
+
maxMessageBytes: REALTIME_MAX_MESSAGE_BYTES,
|
|
39
53
|
onOpen(_event, ws) {
|
|
40
|
-
connection = realtime.connect(ws,
|
|
54
|
+
connection = realtime.connect(ws, context);
|
|
41
55
|
},
|
|
42
|
-
onMessage(event
|
|
43
|
-
if (!connection)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
realtime.handleClientMessage(connection, event.data);
|
|
56
|
+
async onMessage(event) {
|
|
57
|
+
if (!connection)
|
|
58
|
+
return;
|
|
59
|
+
await realtime.handleClientMessage(connection, event.data);
|
|
47
60
|
},
|
|
48
61
|
onClose() {
|
|
49
62
|
disconnect();
|
|
50
63
|
},
|
|
51
|
-
onError() {
|
|
64
|
+
onError(_event, ws) {
|
|
52
65
|
disconnect();
|
|
66
|
+
ws.close(1011, 'realtime transport failed');
|
|
53
67
|
},
|
|
54
68
|
};
|
|
55
69
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/realtime/websocket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/realtime/websocket.ts"],"names":[],"mappings":"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"}
|
package/dist/websocket.d.ts
CHANGED
|
@@ -1,61 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
import { type IncomingMessage } from 'node:http';
|
|
10
|
-
import type { Duplex } from 'node:stream';
|
|
11
|
-
export type AppWebSocketReadyState = 0 | 1 | 2 | 3;
|
|
12
|
-
export type AppWebSocketMessageData = string | ArrayBuffer;
|
|
13
|
-
export interface AppWebSocketSendOptions {
|
|
14
|
-
compress?: boolean;
|
|
15
|
-
}
|
|
16
|
-
export interface AppWebSocket {
|
|
17
|
-
readonly url: URL;
|
|
18
|
-
readonly protocol: string | null;
|
|
19
|
-
readonly readyState: AppWebSocketReadyState;
|
|
20
|
-
send(data: string | ArrayBuffer | Uint8Array, options?: AppWebSocketSendOptions): void;
|
|
21
|
-
close(code?: number, reason?: string): void;
|
|
22
|
-
}
|
|
23
|
-
export interface AppWebSocketOpenEvent {
|
|
24
|
-
readonly type: 'open';
|
|
25
|
-
}
|
|
26
|
-
export interface AppWebSocketMessageEvent {
|
|
27
|
-
readonly type: 'message';
|
|
28
|
-
readonly data: AppWebSocketMessageData;
|
|
29
|
-
}
|
|
30
|
-
export interface AppWebSocketCloseEvent {
|
|
31
|
-
readonly type: 'close';
|
|
32
|
-
readonly code: number;
|
|
33
|
-
readonly reason: string;
|
|
34
|
-
readonly wasClean: boolean;
|
|
35
|
-
}
|
|
36
|
-
export interface AppWebSocketErrorEvent {
|
|
37
|
-
readonly type: 'error';
|
|
38
|
-
readonly error: unknown;
|
|
39
|
-
}
|
|
40
|
-
export interface AppWebSocketEvents {
|
|
41
|
-
onOpen?: (event: AppWebSocketOpenEvent, ws: AppWebSocket) => void | Promise<void>;
|
|
42
|
-
onMessage?: (event: AppWebSocketMessageEvent, ws: AppWebSocket) => void | Promise<void>;
|
|
43
|
-
onClose?: (event: AppWebSocketCloseEvent, ws: AppWebSocket) => void | Promise<void>;
|
|
44
|
-
onError?: (event: AppWebSocketErrorEvent, ws: AppWebSocket) => void | Promise<void>;
|
|
45
|
-
}
|
|
46
|
-
export type AppWebSocketAcceptResult = AppWebSocketEvents | Response | null | undefined;
|
|
47
|
-
export type AppWebSocketHandler = (request: Request, env?: unknown) => AppWebSocketAcceptResult | Promise<AppWebSocketAcceptResult>;
|
|
48
|
-
export interface AcceptWebSocketUpgradeOptions {
|
|
49
|
-
request: Request;
|
|
50
|
-
events: AppWebSocketEvents;
|
|
51
|
-
head?: Buffer;
|
|
52
|
-
signal?: AbortSignal;
|
|
53
|
-
}
|
|
54
|
-
export interface CreateWebSocketUpgradeRequestOptions {
|
|
55
|
-
signal?: AbortSignal;
|
|
56
|
-
}
|
|
57
|
-
export declare function isWebSocketUpgrade(req: IncomingMessage): boolean;
|
|
58
|
-
export declare function createWebSocketUpgradeRequest(req: IncomingMessage, options?: CreateWebSocketUpgradeRequestOptions): Request;
|
|
59
|
-
export declare function rejectWebSocketUpgrade(socket: Duplex, status?: number, headers?: Headers): void;
|
|
60
|
-
export declare function acceptWebSocketUpgrade(req: IncomingMessage, socket: Duplex, options: AcceptWebSocketUpgradeOptions): AppWebSocket | null;
|
|
1
|
+
export * from '@nocobase/app-websocket';
|
|
61
2
|
//# sourceMappingURL=websocket.d.ts.map
|
package/dist/websocket.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AACA,cAAc,yBAAyB,CAAC"}
|