@eleven-am/pondsocket 0.1.217 → 0.1.219
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 +84 -164
- package/{abstracts → dist/abstracts}/types.d.ts +3 -3
- package/{contexts → dist/contexts}/baseContext.d.ts +3 -1
- package/{contexts → dist/contexts}/baseContext.js +6 -0
- package/{contexts → dist/contexts}/eventContext.d.ts +2 -2
- package/{contexts → dist/contexts}/joinContext.js +8 -2
- package/dist/contexts/outgoingContext.d.ts +36 -0
- package/{contexts → dist/contexts}/outgoingContext.js +12 -6
- package/{engines → dist/engines}/channelEngine.d.ts +3 -1
- package/{engines → dist/engines}/channelEngine.js +103 -13
- package/{engines → dist/engines}/endpointEngine.d.ts +2 -1
- package/{engines → dist/engines}/endpointEngine.js +29 -11
- package/{engines → dist/engines}/lobbyEngine.js +14 -9
- package/{index.d.ts → dist/index.d.ts} +1 -0
- package/dist/matcher/matcher.js +17 -0
- package/{server → dist/server}/server.d.ts +8 -4
- package/{server → dist/server}/server.js +112 -33
- package/{types.d.ts → dist/types.d.ts} +6 -6
- package/{wrappers → dist/wrappers}/channel.d.ts +13 -5
- package/{wrappers → dist/wrappers}/channel.js +22 -6
- package/{wrappers → dist/wrappers}/endpoint.d.ts +4 -2
- package/{wrappers → dist/wrappers}/pondChannel.d.ts +4 -4
- package/{wrappers → dist/wrappers}/pondChannel.js +6 -6
- package/package.json +48 -64
- package/contexts/outgoingContext.d.ts +0 -28
- package/matcher/matcher.js +0 -74
- /package/{abstracts → dist/abstracts}/distributor.d.ts +0 -0
- /package/{abstracts → dist/abstracts}/distributor.js +0 -0
- /package/{abstracts → dist/abstracts}/middleware.d.ts +0 -0
- /package/{abstracts → dist/abstracts}/middleware.js +0 -0
- /package/{abstracts → dist/abstracts}/types.js +0 -0
- /package/{contexts → dist/contexts}/connectionContext.d.ts +0 -0
- /package/{contexts → dist/contexts}/connectionContext.js +0 -0
- /package/{contexts → dist/contexts}/eventContext.js +0 -0
- /package/{contexts → dist/contexts}/joinContext.d.ts +0 -0
- /package/{engines → dist/engines}/lobbyEngine.d.ts +0 -0
- /package/{engines → dist/engines}/presenceEngine.d.ts +0 -0
- /package/{engines → dist/engines}/presenceEngine.js +0 -0
- /package/{errors → dist/errors}/httpError.d.ts +0 -0
- /package/{errors → dist/errors}/httpError.js +0 -0
- /package/{index.js → dist/index.js} +0 -0
- /package/{matcher → dist/matcher}/matcher.d.ts +0 -0
- /package/{types.js → dist/types.js} +0 -0
- /package/{wrappers → dist/wrappers}/endpoint.js +0 -0
package/README.md
CHANGED
|
@@ -1,212 +1,132 @@
|
|
|
1
1
|
# PondSocket
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Typed WebSocket channels for Node.js with presence, private assigns, request/reply events, and Redis-backed distribution.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
To integrate PondSocket into your Node.js project, simply install it via npm:
|
|
5
|
+
## Install
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install @eleven-am/pondsocket
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
PondSocket simplifies the complexity of handling WebSocket connections by abstracting the communication process into individual requests rather than dealing with intricate callbacks within the connection event. It offers a lightweight yet powerful solution for managing bidirectional communication channels, enabling real-time updates and collaboration between server and client components.
|
|
16
|
-
|
|
17
|
-
## Key Features
|
|
18
|
-
|
|
19
|
-
- **Simple and Efficient API**: PondSocket offers an easy-to-use API, making WebSocket communication straightforward and hassle-free.
|
|
20
|
-
- **Organized Channels**: Channels provide a structured approach for grouping users and facilitating efficient communication.
|
|
21
|
-
- **Assigns**: PondSocket allows the storage of private information for users and channels, enhancing data security.
|
|
22
|
-
- **Presence**: The presence feature keeps track of users' current states and notifies other users about any changes.
|
|
23
|
-
- **Broadcasting**: PondSocket enables broadcasting messages to all users or specific groups within a channel, facilitating real-time updates.
|
|
24
|
-
- **Type Safety**: The codebase is thoroughly typed with TypeScript, providing a seamless development experience with improved IDE suggestions.
|
|
25
|
-
- **Middleware Support**: Extensible middleware system for request processing and validation.
|
|
26
|
-
- **Distributed Support**: Built-in support for distributed deployment with state synchronization.
|
|
27
|
-
|
|
28
|
-
## Server-side Usage
|
|
11
|
+
## Server
|
|
29
12
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
import PondSocket from "@eleven-am/pondsocket";
|
|
13
|
+
```ts
|
|
14
|
+
import { PondSocket } from '@eleven-am/pondsocket';
|
|
34
15
|
|
|
35
16
|
const pond = new PondSocket();
|
|
36
17
|
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const role = getRoleFromToken(token);
|
|
44
|
-
ctx.accept({ role }); // Assign the user's role to the socket
|
|
45
|
-
} else {
|
|
46
|
-
ctx.reject('Invalid token', 401);
|
|
18
|
+
const endpoint = pond.createEndpoint('/v1/socket', (ctx) => {
|
|
19
|
+
const token = ctx.query.token;
|
|
20
|
+
|
|
21
|
+
if (!token) {
|
|
22
|
+
ctx.decline('Missing token', 401);
|
|
23
|
+
return;
|
|
47
24
|
}
|
|
25
|
+
|
|
26
|
+
ctx.accept({ role: 'member' });
|
|
48
27
|
});
|
|
49
28
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const { id } = ctx.event.params;
|
|
55
|
-
|
|
56
|
-
if (role === 'admin') {
|
|
57
|
-
ctx.accept({ username })
|
|
58
|
-
.trackPresence({
|
|
59
|
-
username,
|
|
60
|
-
role,
|
|
61
|
-
status: 'online',
|
|
62
|
-
onlineSince: Date.now(),
|
|
63
|
-
});
|
|
64
|
-
} else {
|
|
65
|
-
ctx.decline('Insufficient permissions', 403);
|
|
66
|
-
}
|
|
29
|
+
const chat = endpoint.createChannel('/chat/:roomId', (ctx) => {
|
|
30
|
+
ctx.params.roomId.toUpperCase();
|
|
31
|
+
ctx.accept({ displayName: ctx.joinParams.displayName });
|
|
32
|
+
ctx.trackPresence({ online: true });
|
|
67
33
|
});
|
|
68
34
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// Broadcast to all users in the channel
|
|
74
|
-
ctx.broadcast('message', { text });
|
|
75
|
-
|
|
76
|
-
// Or broadcast to specific users
|
|
77
|
-
ctx.broadcastTo(['user1', 'user2'], 'message', { text });
|
|
78
|
-
|
|
79
|
-
// Or broadcast to all except sender
|
|
80
|
-
ctx.broadcastFrom('message', { text });
|
|
35
|
+
chat.onEvent('message/:messageId', (ctx) => {
|
|
36
|
+
ctx.params.messageId.toUpperCase();
|
|
37
|
+
ctx.broadcast(ctx.event.event, ctx.payload);
|
|
81
38
|
});
|
|
82
39
|
|
|
83
|
-
// Start the server
|
|
84
40
|
pond.listen(3000);
|
|
85
41
|
```
|
|
86
42
|
|
|
87
|
-
|
|
43
|
+
Connection and join handlers must call `accept()`, `decline()`, or delegate with `next()`. A handler that completes without deciding is declined instead of leaving the client pending.
|
|
44
|
+
|
|
45
|
+
## Shared schema
|
|
46
|
+
|
|
47
|
+
Schemas are optional. A definition can be shared by Core, the Nest adapter, and the client without repeating route literals as generic arguments.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import {
|
|
51
|
+
definePondChannel,
|
|
52
|
+
definePondEndpoint,
|
|
53
|
+
definePondSchema,
|
|
54
|
+
PondSocket,
|
|
55
|
+
} from '@eleven-am/pondsocket';
|
|
56
|
+
|
|
57
|
+
interface ChatSchema {
|
|
58
|
+
events: {
|
|
59
|
+
message: { text: string };
|
|
60
|
+
ping: [{ sentAt: number }, { receivedAt: number }];
|
|
61
|
+
};
|
|
62
|
+
presence: {
|
|
63
|
+
online: boolean;
|
|
64
|
+
};
|
|
65
|
+
assigns: {
|
|
66
|
+
role: 'admin' | 'member';
|
|
67
|
+
};
|
|
68
|
+
joinParams: {
|
|
69
|
+
token: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const Socket = definePondEndpoint('/v1/socket');
|
|
74
|
+
export const Chat = definePondChannel(
|
|
75
|
+
definePondSchema<ChatSchema>(),
|
|
76
|
+
'/chat/:roomId',
|
|
77
|
+
);
|
|
88
78
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
import PondClient from "@eleven-am/pondsocket-client";
|
|
93
|
-
|
|
94
|
-
// Create a new client instance
|
|
95
|
-
const socket = new PondClient('ws://your-server/api/socket', {
|
|
96
|
-
token: 'your-auth-token'
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Connect to the server
|
|
100
|
-
socket.connect();
|
|
101
|
-
|
|
102
|
-
// Handle connection state changes
|
|
103
|
-
socket.onConnectionChange((connected) => {
|
|
104
|
-
if (connected) {
|
|
105
|
-
console.log('Connected to the server');
|
|
106
|
-
} else {
|
|
107
|
-
console.log('Disconnected from the server');
|
|
108
|
-
}
|
|
109
|
-
});
|
|
79
|
+
const pond = new PondSocket();
|
|
80
|
+
const endpoint = pond.createEndpoint(Socket, (ctx) => ctx.accept());
|
|
110
81
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
82
|
+
const channel = endpoint.createChannel(Chat, (ctx) => {
|
|
83
|
+
ctx.params.roomId.toUpperCase();
|
|
84
|
+
ctx.joinParams.token.toUpperCase();
|
|
85
|
+
ctx.accept({ role: 'member' }).trackPresence({ online: true });
|
|
114
86
|
});
|
|
115
87
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// Handle channel events
|
|
120
|
-
const subscription = channel.onMessage((event, message) => {
|
|
121
|
-
console.log(`Received message: ${message.text}`);
|
|
88
|
+
channel.onEvent('ping', (ctx) => {
|
|
89
|
+
ctx.payload.sentAt.toFixed();
|
|
90
|
+
ctx.reply('ping', { receivedAt: Date.now() });
|
|
122
91
|
});
|
|
123
|
-
|
|
124
|
-
// Send a message
|
|
125
|
-
channel.broadcast('message', { text: 'Hello, PondSocket!' });
|
|
126
|
-
|
|
127
|
-
// Leave the channel
|
|
128
|
-
channel.leave();
|
|
129
|
-
|
|
130
|
-
// Unsubscribe from events
|
|
131
|
-
subscription();
|
|
132
92
|
```
|
|
133
93
|
|
|
134
|
-
|
|
94
|
+
The schema types event names and payloads, request/response tuples, join params, presence, assigns, channel route params, and event route params.
|
|
135
95
|
|
|
136
|
-
|
|
96
|
+
## Distribution
|
|
137
97
|
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
channel.onEvent('presence', (ctx, next) => {
|
|
141
|
-
ctx.trackPresence({
|
|
142
|
-
username: ctx.user.assigns.username,
|
|
143
|
-
status: 'online',
|
|
144
|
-
lastSeen: Date.now()
|
|
145
|
-
});
|
|
146
|
-
});
|
|
98
|
+
```ts
|
|
99
|
+
import { PondSocket, RedisDistributedBackend } from '@eleven-am/pondsocket';
|
|
147
100
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
101
|
+
const backend = new RedisDistributedBackend({
|
|
102
|
+
url: process.env.REDIS_URL,
|
|
103
|
+
namespace: 'my-app',
|
|
151
104
|
});
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### User Assigns
|
|
155
105
|
|
|
156
|
-
|
|
157
|
-
// Server-side
|
|
158
|
-
channel.onEvent('update-profile', (ctx, next) => {
|
|
159
|
-
ctx.assign({
|
|
160
|
-
...ctx.user.assigns,
|
|
161
|
-
profile: ctx.event.payload
|
|
162
|
-
});
|
|
163
|
-
});
|
|
106
|
+
const pond = new PondSocket({ distributedBackend: backend });
|
|
164
107
|
|
|
165
|
-
|
|
166
|
-
channel.onAssigns((assigns) => {
|
|
167
|
-
console.log('User data updated:', assigns);
|
|
168
|
-
});
|
|
108
|
+
await pond.ready();
|
|
169
109
|
```
|
|
170
110
|
|
|
171
|
-
|
|
111
|
+
Distributed messages use the PondSocket v1 protocol shared by the supported server implementations. Events, presence, assigns, user removal, and cross-node user lookup are propagated through the backend.
|
|
172
112
|
|
|
173
|
-
|
|
174
|
-
// Server-side
|
|
175
|
-
channel.onEvent('message', (ctx, next) => {
|
|
176
|
-
try {
|
|
177
|
-
// Your logic here
|
|
178
|
-
ctx.accept();
|
|
179
|
-
} catch (error) {
|
|
180
|
-
ctx.decline(error.message, 400);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// Client-side
|
|
185
|
-
channel.onError((error) => {
|
|
186
|
-
console.error('Channel error:', error);
|
|
187
|
-
});
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## Distributed Deployment
|
|
113
|
+
## Lifecycle
|
|
191
114
|
|
|
192
|
-
|
|
115
|
+
`ready()` reports distributed-backend initialization failures. `isHealthy()` reports backend/server health. `closeAsync()` stops heartbeat work, closes WebSockets, unsubscribes from the backend, and optionally closes the HTTP server.
|
|
193
116
|
|
|
194
|
-
|
|
195
|
-
import PondSocket from "@eleven-am/pondsocket";
|
|
196
|
-
import { RedisBackend } from "@eleven-am/pondsocket";
|
|
117
|
+
When PondSocket uses a framework-owned HTTP server, pass `closeHttpServerOnShutdown: false`.
|
|
197
118
|
|
|
119
|
+
```ts
|
|
198
120
|
const pond = new PondSocket({
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
port: 6379
|
|
202
|
-
})
|
|
121
|
+
server: existingHttpServer,
|
|
122
|
+
closeHttpServerOnShutdown: false,
|
|
203
123
|
});
|
|
204
|
-
```
|
|
205
124
|
|
|
206
|
-
|
|
125
|
+
await pond.closeAsync();
|
|
126
|
+
```
|
|
207
127
|
|
|
208
|
-
|
|
128
|
+
Channel patterns use path syntax. `/jobs/:id` and a whole `*` segment are supported; `job:*` is invalid and throws during registration. An unmatched join receives `CHANNEL_NOT_FOUND` with the original channel name and request ID.
|
|
209
129
|
|
|
210
130
|
## License
|
|
211
131
|
|
|
212
|
-
|
|
132
|
+
GPL-3.0
|
|
@@ -6,7 +6,7 @@ import { WebSocket, WebSocketServer } from 'ws';
|
|
|
6
6
|
import { ConnectionContext } from '../contexts/connectionContext';
|
|
7
7
|
import { EventContext } from '../contexts/eventContext';
|
|
8
8
|
import { JoinContext } from '../contexts/joinContext';
|
|
9
|
-
import {
|
|
9
|
+
import { OutgoingHandlerContext } from '../contexts/outgoingContext';
|
|
10
10
|
import { EndpointEngine } from '../engines/endpointEngine';
|
|
11
11
|
import { HttpError } from '../errors/httpError';
|
|
12
12
|
import { Channel } from '../wrappers/channel';
|
|
@@ -23,7 +23,7 @@ export type EventKey<Schema extends AnyPondSchema> = Extract<keyof EventsOf<Sche
|
|
|
23
23
|
export type ConnectionHandler<Path extends string> = (ctx: ConnectionContext<Path>, next: NextFunction) => unknown | Promise<unknown>;
|
|
24
24
|
export type AuthorizationHandler<Path extends string, Schema extends AnyPondSchema = AnyPondSchema> = (ctx: JoinContext<Path, Schema>, next: NextFunction) => unknown | Promise<unknown>;
|
|
25
25
|
export type EventHandler<Path extends string, Schema extends AnyPondSchema = AnyPondSchema, Event extends EventKey<Schema> = EventKey<Schema>> = (ctx: EventContext<Path, Schema, Event>, next: NextFunction) => unknown | Promise<unknown>;
|
|
26
|
-
export type OutgoingEventHandler<Path extends string, Schema extends AnyPondSchema = AnyPondSchema, Event extends EventKey<Schema> = EventKey<Schema>> = (event:
|
|
26
|
+
export type OutgoingEventHandler<Path extends string, Schema extends AnyPondSchema = AnyPondSchema, Event extends EventKey<Schema> = EventKey<Schema>> = (event: OutgoingHandlerContext<Path, Schema, Event>) => void | Promise<void>;
|
|
27
27
|
export interface ConnectionParams {
|
|
28
28
|
head: Buffer;
|
|
29
29
|
socket: internal.Duplex;
|
|
@@ -65,4 +65,4 @@ export interface LeaveEvent {
|
|
|
65
65
|
user: UserData<PondPresence, PondAssigns>;
|
|
66
66
|
channel: Channel;
|
|
67
67
|
}
|
|
68
|
-
export type LeaveCallback = (event: LeaveEvent) =>
|
|
68
|
+
export type LeaveCallback = (event: LeaveEvent) => unknown | Promise<unknown>;
|
|
@@ -14,12 +14,14 @@ export declare abstract class BaseContext<Path extends string, Schema extends An
|
|
|
14
14
|
get channel(): Channel<Schema>;
|
|
15
15
|
get presences(): UserPresences<PresenceOf<Schema>>;
|
|
16
16
|
get assigns(): UserAssigns<AssignsOf<Schema>>;
|
|
17
|
-
get user(): import("@eleven-am/pondsocket-common").UserData<PresenceOf<Schema>, AssignsOf<Schema
|
|
17
|
+
get user(): import("@eleven-am/pondsocket-common").UserData<PresenceOf<Schema>, AssignsOf<Schema>>;
|
|
18
18
|
broadcast<Event extends Extract<keyof EventsOf<Schema>, string>>(event: Event, payload: EventPayload<EventsOf<Schema>, Event>): this;
|
|
19
19
|
broadcastFrom<Event extends Extract<keyof EventsOf<Schema>, string>>(event: Event, payload: EventPayload<EventsOf<Schema>, Event>): this;
|
|
20
20
|
broadcastTo<Event extends Extract<keyof EventsOf<Schema>, string>>(event: Event, payload: EventPayload<EventsOf<Schema>, Event>, userIds: string | string[]): this;
|
|
21
21
|
protected abstract _sendMessageToRecipients(recipient: ChannelReceivers, event: string, payload: PondObject): void;
|
|
22
22
|
protected get engine(): ChannelEngine;
|
|
23
23
|
protected get sender(): string;
|
|
24
|
+
protected get currentPayload(): Payload;
|
|
25
|
+
protected updatePayload(payload: Payload): void;
|
|
24
26
|
protected updateParams(params: EventParams<Path>): void;
|
|
25
27
|
}
|
|
@@ -76,6 +76,12 @@ class BaseContext {
|
|
|
76
76
|
get sender() {
|
|
77
77
|
return __classPrivateFieldGet(this, _BaseContext_sender, "f");
|
|
78
78
|
}
|
|
79
|
+
get currentPayload() {
|
|
80
|
+
return __classPrivateFieldGet(this, _BaseContext_payload, "f");
|
|
81
|
+
}
|
|
82
|
+
updatePayload(payload) {
|
|
83
|
+
__classPrivateFieldSet(this, _BaseContext_payload, payload, "f");
|
|
84
|
+
}
|
|
79
85
|
updateParams(params) {
|
|
80
86
|
__classPrivateFieldSet(this, _BaseContext_params, params, "f");
|
|
81
87
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChannelReceivers, AnyPondSchema, AssignsOf, EventParams, EventPayload, EventsOf, PondObject, PresenceOf } from '@eleven-am/pondsocket-common';
|
|
1
|
+
import { ChannelReceivers, AnyPondSchema, AssignsOf, EventParams, EventPayload, EventReplyPayload, EventsOf, PondObject, PresenceOf } from '@eleven-am/pondsocket-common';
|
|
2
2
|
import { BaseContext } from './baseContext';
|
|
3
3
|
import { BroadcastEvent } from '../abstracts/types';
|
|
4
4
|
import { ChannelEngine } from '../engines/channelEngine';
|
|
@@ -7,7 +7,7 @@ export declare class EventContext<Path extends string, Schema extends AnyPondSch
|
|
|
7
7
|
constructor(event: BroadcastEvent, params: EventParams<Path>, engine: ChannelEngine);
|
|
8
8
|
get payload(): EventPayload<EventsOf<Schema>, EventName>;
|
|
9
9
|
assign(assigns: Partial<AssignsOf<Schema>>): EventContext<Path, Schema, EventName>;
|
|
10
|
-
reply<Event extends Extract<keyof EventsOf<Schema>, string>>(event: Event, payload:
|
|
10
|
+
reply<Event extends Extract<keyof EventsOf<Schema>, string>>(event: Event, payload: EventReplyPayload<EventsOf<Schema>, Event>): this;
|
|
11
11
|
trackPresence(presence: PresenceOf<Schema>, userId?: string): EventContext<Path, Schema, EventName>;
|
|
12
12
|
updatePresence(presence: Partial<PresenceOf<Schema>>, userId?: string): EventContext<Path, Schema, EventName>;
|
|
13
13
|
evictUser(reason: string, userId?: string): EventContext<Path, Schema, EventName>;
|
|
@@ -51,7 +51,7 @@ class JoinContext extends baseContext_1.BaseContext {
|
|
|
51
51
|
}
|
|
52
52
|
__classPrivateFieldGet(this, _JoinContext_instances, "m", _JoinContext_performChecks).call(this);
|
|
53
53
|
const onMessage = this.engine.parent.parent.sendMessage.bind(this.engine.parent.parent, __classPrivateFieldGet(this, _JoinContext_user, "f").socket);
|
|
54
|
-
const subscription = this.engine.addUser(__classPrivateFieldGet(this, _JoinContext_user, "f").clientId, __classPrivateFieldGet(this, _JoinContext_newAssigns, "f"), onMessage);
|
|
54
|
+
const subscription = this.engine.addUser(__classPrivateFieldGet(this, _JoinContext_user, "f").clientId, __classPrivateFieldGet(this, _JoinContext_newAssigns, "f"), onMessage, __classPrivateFieldGet(this, _JoinContext_user, "f").requestId);
|
|
55
55
|
const wrappedSubscription = () => {
|
|
56
56
|
var _a;
|
|
57
57
|
subscription();
|
|
@@ -68,8 +68,14 @@ class JoinContext extends baseContext_1.BaseContext {
|
|
|
68
68
|
const errorMessage = {
|
|
69
69
|
event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
|
|
70
70
|
payload: {
|
|
71
|
+
code: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
|
|
71
72
|
message: message || 'Unauthorized connection',
|
|
72
|
-
|
|
73
|
+
status: errorCode || 401,
|
|
74
|
+
statusCode: errorCode || 401,
|
|
75
|
+
error: {
|
|
76
|
+
message: message || 'Unauthorized connection',
|
|
77
|
+
status: errorCode || 401,
|
|
78
|
+
},
|
|
73
79
|
},
|
|
74
80
|
channelName: this.engine.name,
|
|
75
81
|
action: pondsocket_common_1.ServerActions.ERROR,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChannelReceivers, AnyPondSchema, Event, EventParams, EventPayload, EventReplyPayload, EventsOf, PondEvent, PondMessage, PondObject, ServerActions } from '@eleven-am/pondsocket-common';
|
|
2
|
+
import { BaseContext } from './baseContext';
|
|
3
|
+
import { ChannelEngine } from '../engines/channelEngine';
|
|
4
|
+
export declare class OutgoingContext<Path extends string, Schema extends AnyPondSchema = AnyPondSchema, EventName extends Extract<keyof EventsOf<Schema>, string> = Extract<keyof EventsOf<Schema>, string>, Action extends Event['action'] = Event['action']> extends BaseContext<Path, Schema, EventName, OutgoingPayload<Schema, EventName, Action>> {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(event: Event, params: EventParams<Path>, engine: ChannelEngine, userid: string);
|
|
7
|
+
get action(): Action;
|
|
8
|
+
get event(): PondEvent<Path> & {
|
|
9
|
+
action: Action;
|
|
10
|
+
event: EventName;
|
|
11
|
+
payload: OutgoingPayload<Schema, EventName, Action>;
|
|
12
|
+
};
|
|
13
|
+
get payload(): OutgoingPayload<Schema, EventName, Action>;
|
|
14
|
+
/**
|
|
15
|
+
* Blocks the outgoing context, preventing further processing of the event.
|
|
16
|
+
*/
|
|
17
|
+
block(): this;
|
|
18
|
+
/**
|
|
19
|
+
* Checks if the outgoing context is blocked.
|
|
20
|
+
* @returns {boolean} - True if blocked, false otherwise.
|
|
21
|
+
*/
|
|
22
|
+
isBlocked(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Transforms the outgoing context with a new payload.
|
|
25
|
+
* @param payload - The new payload to set for the context.
|
|
26
|
+
*/
|
|
27
|
+
transform(payload: OutgoingPayload<Schema, EventName, Action>): this;
|
|
28
|
+
/**
|
|
29
|
+
* Updates the parameters of the outgoing context.
|
|
30
|
+
* @param params - The new parameters to set for the context.
|
|
31
|
+
*/
|
|
32
|
+
updateParams(params: EventParams<Path>): void;
|
|
33
|
+
protected _sendMessageToRecipients(_recipient: ChannelReceivers, _event: string, _payload: PondObject): void;
|
|
34
|
+
}
|
|
35
|
+
export type OutgoingPayload<Schema extends AnyPondSchema, EventName extends Extract<keyof EventsOf<Schema>, string>, Action extends Event['action']> = Action extends ServerActions.BROADCAST ? EventPayload<EventsOf<Schema>, EventName> : Action extends ServerActions.SYSTEM ? EventReplyPayload<EventsOf<Schema>, EventName> : PondMessage;
|
|
36
|
+
export type OutgoingHandlerContext<Path extends string, Schema extends AnyPondSchema, EventName extends Extract<keyof EventsOf<Schema>, string>> = OutgoingContext<Path, Schema, EventName, ServerActions.BROADCAST> | OutgoingContext<Path, Schema, EventName, ServerActions.SYSTEM>;
|
|
@@ -10,20 +10,26 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var
|
|
13
|
+
var _OutgoingContext_action, _OutgoingContext_isBlocked;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.OutgoingContext = void 0;
|
|
16
16
|
const baseContext_1 = require("./baseContext");
|
|
17
17
|
class OutgoingContext extends baseContext_1.BaseContext {
|
|
18
18
|
constructor(event, params, engine, userid) {
|
|
19
19
|
super(engine, params, event.event, event.payload, userid);
|
|
20
|
-
|
|
20
|
+
_OutgoingContext_action.set(this, void 0);
|
|
21
21
|
_OutgoingContext_isBlocked.set(this, void 0);
|
|
22
|
-
__classPrivateFieldSet(this,
|
|
22
|
+
__classPrivateFieldSet(this, _OutgoingContext_action, event.action, "f");
|
|
23
23
|
__classPrivateFieldSet(this, _OutgoingContext_isBlocked, false, "f");
|
|
24
24
|
}
|
|
25
|
+
get action() {
|
|
26
|
+
return __classPrivateFieldGet(this, _OutgoingContext_action, "f");
|
|
27
|
+
}
|
|
28
|
+
get event() {
|
|
29
|
+
return Object.assign(Object.assign({}, super.event), { action: __classPrivateFieldGet(this, _OutgoingContext_action, "f"), payload: this.currentPayload });
|
|
30
|
+
}
|
|
25
31
|
get payload() {
|
|
26
|
-
return
|
|
32
|
+
return this.currentPayload;
|
|
27
33
|
}
|
|
28
34
|
/**
|
|
29
35
|
* Blocks the outgoing context, preventing further processing of the event.
|
|
@@ -44,7 +50,7 @@ class OutgoingContext extends baseContext_1.BaseContext {
|
|
|
44
50
|
* @param payload - The new payload to set for the context.
|
|
45
51
|
*/
|
|
46
52
|
transform(payload) {
|
|
47
|
-
|
|
53
|
+
this.updatePayload(payload);
|
|
48
54
|
return this;
|
|
49
55
|
}
|
|
50
56
|
/**
|
|
@@ -59,4 +65,4 @@ class OutgoingContext extends baseContext_1.BaseContext {
|
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
67
|
exports.OutgoingContext = OutgoingContext;
|
|
62
|
-
|
|
68
|
+
_OutgoingContext_action = new WeakMap(), _OutgoingContext_isBlocked = new WeakMap();
|
|
@@ -8,7 +8,7 @@ export declare class ChannelEngine {
|
|
|
8
8
|
constructor(parent: LobbyEngine, name: string, backend?: IDistributedBackend | null);
|
|
9
9
|
get name(): string;
|
|
10
10
|
get users(): Set<string>;
|
|
11
|
-
addUser(userId: string, assigns: PondAssigns, onMessage: (event: ChannelEvent) => void): Unsubscribe;
|
|
11
|
+
addUser(userId: string, assigns: PondAssigns, onMessage: (event: ChannelEvent) => void, requestId?: string): Unsubscribe;
|
|
12
12
|
sendMessage(sender: ChannelSenders, recipient: ChannelReceivers, action: ServerActions, event: string, payload: PondMessage, requestId?: string): void;
|
|
13
13
|
broadcastMessage(userId: string, message: ClientMessage): void;
|
|
14
14
|
trackPresence(userId: string, presence: PondPresence): void;
|
|
@@ -17,6 +17,8 @@ export declare class ChannelEngine {
|
|
|
17
17
|
upsertPresence(userId: string, presence: PondPresence): void;
|
|
18
18
|
updateAssigns(userId: string, assigns: PondMessage): void;
|
|
19
19
|
kickUser(userId: string, reason: string): void;
|
|
20
|
+
requestUserRemoval(userId: string): void;
|
|
21
|
+
getUserAcrossNodes(userId: string, timeoutMs?: number): Promise<UserData | null>;
|
|
20
22
|
getAssigns(): UserAssigns;
|
|
21
23
|
getPresence(): UserPresences;
|
|
22
24
|
destroy(reason?: string): void;
|