@eleven-am/pondsocket 0.1.214 → 0.1.215

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.
@@ -0,0 +1,13 @@
1
+ import { Unsubscribe } from '@eleven-am/pondsocket-common';
2
+ import { DistributedChannelMessage, IDistributedBackend, RedisDistributedBackendOptions } from '../types';
3
+ export declare class RedisDistributedBackend implements IDistributedBackend {
4
+ #private;
5
+ get nodeId(): string;
6
+ get heartbeatTimeoutMs(): number;
7
+ constructor(options?: RedisDistributedBackendOptions);
8
+ subscribeToChannel(endpointName: string, channelName: string, handler: (message: DistributedChannelMessage) => void): Promise<Unsubscribe>;
9
+ subscribeToHeartbeats(handler: (nodeId: string) => void): Unsubscribe;
10
+ broadcast(endpointName: string, channelName: string, message: DistributedChannelMessage): Promise<void>;
11
+ cleanup(): Promise<void>;
12
+ initialize(): Promise<void>;
13
+ }
@@ -8,84 +8,113 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
+ 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");
14
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
+ };
11
16
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
12
17
  if (kind === "m") throw new TypeError("Private method is not writable");
13
18
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
14
19
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
15
20
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
16
21
  };
17
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
18
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
19
- 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");
20
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
21
- };
22
- var _RedisDistributedBackend_instances, _RedisDistributedBackend_publishClient, _RedisDistributedBackend_subscribeClient, _RedisDistributedBackend_keyPrefix, _RedisDistributedBackend_subject, _RedisDistributedBackend_nodeId, _RedisDistributedBackend_isConnected, _RedisDistributedBackend_initialize, _RedisDistributedBackend_handleRedisMessage, _RedisDistributedBackend_isValidMessage, _RedisDistributedBackend_buildKey;
22
+ var _RedisDistributedBackend_instances, _RedisDistributedBackend_publishClient, _RedisDistributedBackend_subscribeClient, _RedisDistributedBackend_keyPrefix, _RedisDistributedBackend_heartbeatSubject, _RedisDistributedBackend_nodeId, _RedisDistributedBackend_heartbeatIntervalMs, _RedisDistributedBackend_heartbeatTimeoutMs, _RedisDistributedBackend_onError, _RedisDistributedBackend_isConnected, _RedisDistributedBackend_heartbeatTimer, _RedisDistributedBackend_attachEventHandlers, _RedisDistributedBackend_startHeartbeat, _RedisDistributedBackend_publishHeartbeat, _RedisDistributedBackend_handleHeartbeatMessage, _RedisDistributedBackend_isValidMessage, _RedisDistributedBackend_buildKey;
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.RedisDistributedBackend = void 0;
25
25
  const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
26
26
  const redis_1 = require("redis");
27
- const types_1 = require("./types");
27
+ const types_1 = require("../types");
28
28
  class RedisDistributedBackend {
29
+ get nodeId() {
30
+ return __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f");
31
+ }
32
+ get heartbeatTimeoutMs() {
33
+ return __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimeoutMs, "f");
34
+ }
29
35
  constructor(options = {}) {
30
36
  _RedisDistributedBackend_instances.add(this);
31
37
  _RedisDistributedBackend_publishClient.set(this, void 0);
32
38
  _RedisDistributedBackend_subscribeClient.set(this, void 0);
33
39
  _RedisDistributedBackend_keyPrefix.set(this, void 0);
34
- _RedisDistributedBackend_subject.set(this, void 0);
40
+ _RedisDistributedBackend_heartbeatSubject.set(this, void 0);
35
41
  _RedisDistributedBackend_nodeId.set(this, void 0);
42
+ _RedisDistributedBackend_heartbeatIntervalMs.set(this, void 0);
43
+ _RedisDistributedBackend_heartbeatTimeoutMs.set(this, void 0);
44
+ _RedisDistributedBackend_onError.set(this, void 0);
36
45
  _RedisDistributedBackend_isConnected.set(this, false);
37
- const { host = 'localhost', port = 6379, password, database = 0, url, keyPrefix = 'pondsocket', } = options;
46
+ _RedisDistributedBackend_heartbeatTimer.set(this, null);
47
+ const { host = 'localhost', port = 6379, password, database = 0, url, keyPrefix = 'pondsocket', heartbeatIntervalMs = 30000, heartbeatTimeoutMs = 90000, onError = null, } = options;
38
48
  __classPrivateFieldSet(this, _RedisDistributedBackend_keyPrefix, keyPrefix, "f");
49
+ __classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatIntervalMs, heartbeatIntervalMs, "f");
50
+ __classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimeoutMs, heartbeatTimeoutMs, "f");
51
+ __classPrivateFieldSet(this, _RedisDistributedBackend_onError, onError, "f");
39
52
  __classPrivateFieldSet(this, _RedisDistributedBackend_nodeId, Math.random().toString(36)
40
53
  .substring(2, 15), "f");
41
- __classPrivateFieldSet(this, _RedisDistributedBackend_subject, new pondsocket_common_1.Subject(), "f");
42
- // Create Redis clients
54
+ __classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatSubject, new pondsocket_common_1.Subject(), "f");
55
+ const reconnectStrategy = (retries) => {
56
+ const delay = Math.min(retries * 100, 5000);
57
+ return delay;
58
+ };
43
59
  const clientConfig = url
44
- ? { url }
45
- : { socket: { host,
46
- port },
60
+ ? { url,
61
+ socket: { reconnectStrategy } }
62
+ : {
63
+ socket: { host,
64
+ port,
65
+ reconnectStrategy },
47
66
  password,
48
- database };
67
+ database,
68
+ };
49
69
  __classPrivateFieldSet(this, _RedisDistributedBackend_publishClient, (0, redis_1.createClient)(clientConfig), "f");
50
70
  __classPrivateFieldSet(this, _RedisDistributedBackend_subscribeClient, __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").duplicate(), "f");
51
- void __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_initialize).call(this);
71
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_attachEventHandlers).call(this, __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f"), 'publish');
72
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_attachEventHandlers).call(this, __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f"), 'subscribe');
52
73
  }
53
- /**
54
- * Gets the subject for subscribing to distributed messages
55
- */
56
- get subject() {
57
- return __classPrivateFieldGet(this, _RedisDistributedBackend_subject, "f");
58
- }
59
- /**
60
- * Subscribe to messages for a specific endpoint and channel
61
- */
62
- subscribe(endpointName, channelName, handler) {
63
- return this.subject.subscribe((message) => {
64
- if (message.endpointName === endpointName && message.channelName === channelName && message.nodeId !== __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f")) {
65
- handler(message);
66
- }
74
+ subscribeToChannel(endpointName, channelName, handler) {
75
+ return __awaiter(this, void 0, void 0, function* () {
76
+ const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, endpointName, channelName);
77
+ const listener = (message) => {
78
+ try {
79
+ const parsedMessage = JSON.parse(message);
80
+ if (!__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_isValidMessage).call(this, parsedMessage)) {
81
+ return;
82
+ }
83
+ if (parsedMessage.nodeId !== __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f")) {
84
+ handler(parsedMessage);
85
+ }
86
+ }
87
+ catch (_) {
88
+ void 0;
89
+ }
90
+ };
91
+ yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").subscribe(key, listener);
92
+ return () => {
93
+ __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").unsubscribe(key).catch(() => { });
94
+ };
67
95
  });
68
96
  }
69
- /**
70
- * Broadcasts a message to all nodes for a specific endpoint and channel
71
- */
97
+ subscribeToHeartbeats(handler) {
98
+ return __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").subscribe(handler);
99
+ }
72
100
  broadcast(endpointName, channelName, message) {
73
101
  return __awaiter(this, void 0, void 0, function* () {
74
102
  if (!__classPrivateFieldGet(this, _RedisDistributedBackend_isConnected, "f")) {
75
103
  throw new Error('Redis backend is not connected');
76
104
  }
77
105
  const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, endpointName, channelName);
78
- const distributedMessage = Object.assign(Object.assign({}, message), { nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f") });
106
+ const distributedMessage = Object.assign(Object.assign({}, message), { nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f"), sourceNodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f") });
79
107
  const serializedMessage = JSON.stringify(distributedMessage);
80
108
  yield __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").publish(key, serializedMessage);
81
109
  });
82
110
  }
83
- /**
84
- * Cleanup and close all Redis connections
85
- */
86
111
  cleanup() {
87
112
  return __awaiter(this, void 0, void 0, function* () {
88
- this.subject.close();
113
+ if (__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimer, "f")) {
114
+ clearInterval(__classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatTimer, "f"));
115
+ __classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimer, null, "f");
116
+ }
117
+ __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").close();
89
118
  if (__classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").isOpen) {
90
119
  yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").quit();
91
120
  }
@@ -95,29 +124,67 @@ class RedisDistributedBackend {
95
124
  __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
96
125
  });
97
126
  }
127
+ initialize() {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ yield Promise.all([
130
+ __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").connect(),
131
+ __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").connect(),
132
+ ]);
133
+ const heartbeatKey = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, '__heartbeat__', '__heartbeat__');
134
+ yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").subscribe(heartbeatKey, (message) => {
135
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_handleHeartbeatMessage).call(this, message);
136
+ });
137
+ __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, true, "f");
138
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_startHeartbeat).call(this);
139
+ });
140
+ }
98
141
  }
99
142
  exports.RedisDistributedBackend = RedisDistributedBackend;
100
- _RedisDistributedBackend_publishClient = new WeakMap(), _RedisDistributedBackend_subscribeClient = new WeakMap(), _RedisDistributedBackend_keyPrefix = new WeakMap(), _RedisDistributedBackend_subject = new WeakMap(), _RedisDistributedBackend_nodeId = new WeakMap(), _RedisDistributedBackend_isConnected = new WeakMap(), _RedisDistributedBackend_instances = new WeakSet(), _RedisDistributedBackend_initialize = function _RedisDistributedBackend_initialize() {
101
- return __awaiter(this, void 0, void 0, function* () {
102
- yield Promise.all([
103
- __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").connect(),
104
- __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").connect(),
105
- ]);
106
- const pattern = `${__classPrivateFieldGet(this, _RedisDistributedBackend_keyPrefix, "f")}:*`;
107
- yield __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").pSubscribe(pattern, (message) => {
108
- __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_handleRedisMessage).call(this, message);
109
- });
110
- __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, true, "f");
143
+ _RedisDistributedBackend_publishClient = new WeakMap(), _RedisDistributedBackend_subscribeClient = new WeakMap(), _RedisDistributedBackend_keyPrefix = new WeakMap(), _RedisDistributedBackend_heartbeatSubject = new WeakMap(), _RedisDistributedBackend_nodeId = new WeakMap(), _RedisDistributedBackend_heartbeatIntervalMs = new WeakMap(), _RedisDistributedBackend_heartbeatTimeoutMs = new WeakMap(), _RedisDistributedBackend_onError = new WeakMap(), _RedisDistributedBackend_isConnected = new WeakMap(), _RedisDistributedBackend_heartbeatTimer = new WeakMap(), _RedisDistributedBackend_instances = new WeakSet(), _RedisDistributedBackend_attachEventHandlers = function _RedisDistributedBackend_attachEventHandlers(client, label) {
144
+ client.on('error', (err) => {
145
+ __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
146
+ if (__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f")) {
147
+ __classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f").call(this, new Error(`Redis ${label} client error: ${err.message}`));
148
+ }
149
+ });
150
+ client.on('ready', () => {
151
+ if (__classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").isReady && __classPrivateFieldGet(this, _RedisDistributedBackend_subscribeClient, "f").isReady) {
152
+ __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, true, "f");
153
+ }
154
+ });
155
+ client.on('end', () => {
156
+ __classPrivateFieldSet(this, _RedisDistributedBackend_isConnected, false, "f");
157
+ });
158
+ }, _RedisDistributedBackend_startHeartbeat = function _RedisDistributedBackend_startHeartbeat() {
159
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_publishHeartbeat).call(this);
160
+ __classPrivateFieldSet(this, _RedisDistributedBackend_heartbeatTimer, setInterval(() => {
161
+ __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_publishHeartbeat).call(this);
162
+ }, __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatIntervalMs, "f")), "f");
163
+ }, _RedisDistributedBackend_publishHeartbeat = function _RedisDistributedBackend_publishHeartbeat() {
164
+ if (!__classPrivateFieldGet(this, _RedisDistributedBackend_isConnected, "f")) {
165
+ return;
166
+ }
167
+ const heartbeatMessage = {
168
+ type: types_1.DistributedMessageType.NODE_HEARTBEAT,
169
+ endpointName: '__heartbeat__',
170
+ channelName: '__heartbeat__',
171
+ nodeId: __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f"),
172
+ };
173
+ const key = __classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_buildKey).call(this, '__heartbeat__', '__heartbeat__');
174
+ __classPrivateFieldGet(this, _RedisDistributedBackend_publishClient, "f").publish(key, JSON.stringify(heartbeatMessage)).catch((err) => {
175
+ if (__classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f")) {
176
+ __classPrivateFieldGet(this, _RedisDistributedBackend_onError, "f").call(this, new Error(`Failed to publish heartbeat: ${err.message}`));
177
+ }
111
178
  });
112
- }, _RedisDistributedBackend_handleRedisMessage = function _RedisDistributedBackend_handleRedisMessage(message) {
179
+ }, _RedisDistributedBackend_handleHeartbeatMessage = function _RedisDistributedBackend_handleHeartbeatMessage(message) {
113
180
  try {
114
181
  const parsedMessage = JSON.parse(message);
115
- if (__classPrivateFieldGet(this, _RedisDistributedBackend_instances, "m", _RedisDistributedBackend_isValidMessage).call(this, parsedMessage)) {
116
- this.subject.publish(parsedMessage);
182
+ if (parsedMessage.type === types_1.DistributedMessageType.NODE_HEARTBEAT && parsedMessage.nodeId !== __classPrivateFieldGet(this, _RedisDistributedBackend_nodeId, "f")) {
183
+ __classPrivateFieldGet(this, _RedisDistributedBackend_heartbeatSubject, "f").publish(parsedMessage.nodeId);
117
184
  }
118
185
  }
119
- catch (_a) {
120
- // Silently ignore invalid messages
186
+ catch (_) {
187
+ void 0;
121
188
  }
122
189
  }, _RedisDistributedBackend_isValidMessage = function _RedisDistributedBackend_isValidMessage(message) {
123
190
  return (typeof message === 'object' &&
@@ -0,0 +1,22 @@
1
+ import { MiddlewareFunction, NextFunction } from './types';
2
+ export declare class Middleware<Request, Response> {
3
+ #private;
4
+ constructor(second?: Middleware<Request, Response>);
5
+ /**
6
+ * @desc Returns the middleware stack length
7
+ */
8
+ get length(): number;
9
+ /**
10
+ * @desc Adds a middleware function to the middleware stack
11
+ * @param middleware - the middleware function to add
12
+ */
13
+ use(middleware: MiddlewareFunction<Request, Response> | Middleware<Request, Response>): this;
14
+ /**
15
+ * @desc Runs the middleware stack
16
+ * @param req - the request object
17
+ * @param res - the response object
18
+ * @param final - the final function to call
19
+ */
20
+ run(req: Request, res: Response, final: NextFunction): void;
21
+ runAsync(req: Request, res: Response, final: NextFunction): Promise<void>;
22
+ }
@@ -64,7 +64,14 @@ class Middleware {
64
64
  try {
65
65
  const result = middleware(req, res, next);
66
66
  if (result instanceof Promise) {
67
- result.catch(next);
67
+ result.catch((error) => {
68
+ try {
69
+ final(__classPrivateFieldGet(this, _Middleware_instances, "m", _Middleware_handleError).call(this, error));
70
+ }
71
+ catch (_) {
72
+ void 0;
73
+ }
74
+ });
68
75
  }
69
76
  }
70
77
  catch (error) {
@@ -0,0 +1,64 @@
1
+ import { IncomingHttpHeaders } from 'http';
2
+ import { IncomingMessage } from 'node:http';
3
+ import internal from 'node:stream';
4
+ import { ChannelEvent, EventParams, JoinParams, PondAssigns, PondMessage, ServerActions, SystemSender, Unsubscribe, UserData } from '@eleven-am/pondsocket-common';
5
+ import { WebSocket, WebSocketServer } from 'ws';
6
+ import { ConnectionContext } from '../contexts/connectionContext';
7
+ import { EventContext } from '../contexts/eventContext';
8
+ import { JoinContext } from '../contexts/joinContext';
9
+ import { OutgoingContext } from '../contexts/outgoingContext';
10
+ import { EndpointEngine } from '../engines/endpointEngine';
11
+ import { HttpError } from '../errors/httpError';
12
+ import { Channel } from '../wrappers/channel';
13
+ export type NextFunction<Error extends HttpError = HttpError> = (error?: Error) => void;
14
+ export type MiddlewareFunction<Request, Response> = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
15
+ export interface SocketRequest {
16
+ id: string;
17
+ headers: IncomingHttpHeaders;
18
+ address: string;
19
+ }
20
+ export type ConnectionHandler<Path extends string> = (ctx: ConnectionContext<Path>, next: NextFunction) => void | Promise<void>;
21
+ export type AuthorizationHandler<Path extends string> = (ctx: JoinContext<Path>, next: NextFunction) => void | Promise<void>;
22
+ export type EventHandler<Path extends string> = (ctx: EventContext<Path>, next: NextFunction) => void | Promise<void>;
23
+ export type OutgoingEventHandler<Event extends string> = (event: OutgoingContext<Event>, next: NextFunction) => PondMessage | Promise<PondMessage> | void | Promise<void>;
24
+ export interface ConnectionParams {
25
+ head: Buffer;
26
+ socket: internal.Duplex;
27
+ request: IncomingMessage;
28
+ requestId: string;
29
+ }
30
+ export interface SocketCache {
31
+ clientId: string;
32
+ socket: WebSocket;
33
+ assigns: PondAssigns;
34
+ subscriptions: Set<Unsubscribe>;
35
+ }
36
+ export interface ConnectionResponseOptions {
37
+ engine: EndpointEngine;
38
+ params: ConnectionParams;
39
+ webSocketServer: WebSocketServer;
40
+ }
41
+ export interface JoinRequestOptions<Path extends string> {
42
+ clientId: string;
43
+ assigns: PondAssigns;
44
+ joinParams: JoinParams;
45
+ params: EventParams<Path>;
46
+ }
47
+ export interface RequestCache extends SocketCache {
48
+ channelName: string;
49
+ requestId: string;
50
+ }
51
+ export type InternalChannelEvent = ChannelEvent & {
52
+ recipients: string[];
53
+ };
54
+ export type ChannelSenders = SystemSender.CHANNEL | string;
55
+ export type BroadcastEvent = Omit<InternalChannelEvent, 'action' | 'payload' | 'recipients'> & {
56
+ action: ServerActions.BROADCAST;
57
+ sender: ChannelSenders;
58
+ payload: PondMessage;
59
+ };
60
+ export interface LeaveEvent {
61
+ user: UserData;
62
+ channel: Channel;
63
+ }
64
+ export type LeaveCallback = (event: LeaveEvent) => void;
@@ -1,16 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DistributedMessageType = void 0;
4
- var DistributedMessageType;
5
- (function (DistributedMessageType) {
6
- DistributedMessageType["STATE_REQUEST"] = "STATE_REQUEST";
7
- DistributedMessageType["STATE_RESPONSE"] = "STATE_RESPONSE";
8
- DistributedMessageType["USER_JOINED"] = "USER_JOINED";
9
- DistributedMessageType["USER_LEFT"] = "USER_LEFT";
10
- DistributedMessageType["USER_MESSAGE"] = "USER_MESSAGE";
11
- DistributedMessageType["PRESENCE_UPDATE"] = "PRESENCE_UPDATE";
12
- DistributedMessageType["PRESENCE_REMOVED"] = "PRESENCE_REMOVED";
13
- DistributedMessageType["ASSIGNS_UPDATE"] = "ASSIGNS_UPDATE";
14
- DistributedMessageType["ASSIGNS_REMOVED"] = "ASSIGNS_REMOVED";
15
- DistributedMessageType["EVICT_USER"] = "EVICT_USER";
16
- })(DistributedMessageType || (exports.DistributedMessageType = DistributedMessageType = {}));
@@ -0,0 +1,20 @@
1
+ import { ChannelReceivers, EventParams, PondEvent, PondMessage, PondObject, UserAssigns, UserPresences } from '@eleven-am/pondsocket-common';
2
+ import { ChannelEngine } from '../engines/channelEngine';
3
+ import { Channel } from '../wrappers/channel';
4
+ export declare abstract class BaseContext<Path extends string> {
5
+ #private;
6
+ constructor(engine: ChannelEngine, params: EventParams<Path>, event: string, payload: PondMessage, sender: string);
7
+ get event(): PondEvent<Path>;
8
+ get channelName(): string;
9
+ get channel(): Channel;
10
+ get presences(): UserPresences;
11
+ get assigns(): UserAssigns;
12
+ get user(): import("@eleven-am/pondsocket-common").UserData<PondObject, PondObject>;
13
+ broadcast(event: string, payload: PondMessage): this;
14
+ broadcastFrom(event: string, payload: PondMessage): this;
15
+ broadcastTo(event: string, payload: PondMessage, userIds: string | string[]): this;
16
+ protected abstract _sendMessageToRecipients(recipient: ChannelReceivers, event: string, payload: PondObject): void;
17
+ protected get engine(): ChannelEngine;
18
+ protected get sender(): string;
19
+ protected updateParams(params: EventParams<Path>): void;
20
+ }
@@ -13,6 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var _BaseContext_engine, _BaseContext_params, _BaseContext_event, _BaseContext_sender, _BaseContext_payload;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BaseContext = void 0;
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
16
17
  const channel_1 = require("../wrappers/channel");
17
18
  class BaseContext {
18
19
  constructor(engine, params, event, payload, sender) {
@@ -27,9 +28,6 @@ class BaseContext {
27
28
  __classPrivateFieldSet(this, _BaseContext_payload, payload, "f");
28
29
  __classPrivateFieldSet(this, _BaseContext_sender, sender, "f");
29
30
  }
30
- /**
31
- * The event information
32
- */
33
31
  get event() {
34
32
  return {
35
33
  event: __classPrivateFieldGet(this, _BaseContext_event, "f"),
@@ -38,46 +36,40 @@ class BaseContext {
38
36
  payload: __classPrivateFieldGet(this, _BaseContext_payload, "f"),
39
37
  };
40
38
  }
41
- /**
42
- * The channel name
43
- */
44
39
  get channelName() {
45
40
  return __classPrivateFieldGet(this, _BaseContext_engine, "f").name;
46
41
  }
47
- /**
48
- * The channel instance
49
- */
50
42
  get channel() {
51
43
  return new channel_1.Channel(__classPrivateFieldGet(this, _BaseContext_engine, "f"));
52
44
  }
53
- /**
54
- * All current presences in the channel
55
- */
56
45
  get presences() {
57
46
  return __classPrivateFieldGet(this, _BaseContext_engine, "f").getPresence();
58
47
  }
59
- /**
60
- * All current assigns in the channel
61
- */
62
48
  get assigns() {
63
49
  return __classPrivateFieldGet(this, _BaseContext_engine, "f").getAssigns();
64
50
  }
65
- /**
66
- * The user who sent the request
67
- */
68
51
  get user() {
69
52
  return this.channel.getUserData(__classPrivateFieldGet(this, _BaseContext_sender, "f"));
70
53
  }
71
- /**
72
- * Gets the channel engine instance
73
- * @protected
74
- */
54
+ broadcast(event, payload) {
55
+ this._sendMessageToRecipients(pondsocket_common_1.ChannelReceiver.ALL_USERS, event, payload);
56
+ return this;
57
+ }
58
+ broadcastFrom(event, payload) {
59
+ this._sendMessageToRecipients(pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, event, payload);
60
+ return this;
61
+ }
62
+ broadcastTo(event, payload, userIds) {
63
+ const ids = Array.isArray(userIds) ? userIds : [userIds];
64
+ this._sendMessageToRecipients(ids, event, payload);
65
+ return this;
66
+ }
75
67
  get engine() {
76
68
  return __classPrivateFieldGet(this, _BaseContext_engine, "f");
77
69
  }
78
- /**
79
- * Updates the event parameters.
80
- */
70
+ get sender() {
71
+ return __classPrivateFieldGet(this, _BaseContext_sender, "f");
72
+ }
81
73
  updateParams(params) {
82
74
  __classPrivateFieldSet(this, _BaseContext_params, params, "f");
83
75
  }
@@ -0,0 +1,66 @@
1
+ import { IncomingHttpHeaders } from 'http';
2
+ import { PondAssigns, PondMessage, IncomingConnection, Params, EventParams } from '@eleven-am/pondsocket-common';
3
+ import { ConnectionResponseOptions } from '../abstracts/types';
4
+ /**
5
+ * ConnectionContext combines IncomingConnection data with ConnectionResponse functionality.
6
+ */
7
+ export declare class ConnectionContext<Path extends string> {
8
+ #private;
9
+ constructor(connectionData: IncomingConnection<Path>, { engine, params, webSocketServer }: ConnectionResponseOptions);
10
+ /**
11
+ * Whether the connection has been handled
12
+ */
13
+ get hasResponded(): boolean;
14
+ /**
15
+ * Connection details including headers, cookies, address, id, etc.
16
+ */
17
+ get connection(): IncomingConnection<Path>;
18
+ /**
19
+ * The request parameters
20
+ */
21
+ get requestId(): string;
22
+ /**
23
+ * The client ID
24
+ */
25
+ get clientId(): string;
26
+ /**
27
+ * The request headers
28
+ */
29
+ get headers(): IncomingHttpHeaders;
30
+ /**
31
+ * The request cookies
32
+ */
33
+ get cookies(): Record<string, string>;
34
+ /**
35
+ * The client address
36
+ */
37
+ get address(): string;
38
+ /**
39
+ * The event parameters
40
+ */
41
+ get event(): EventParams<Path>;
42
+ /**
43
+ * The query parameters
44
+ */
45
+ get query(): Record<string, string>;
46
+ /**
47
+ * The path parameters
48
+ */
49
+ get params(): Params<Path>;
50
+ /**
51
+ * Assigns data to the client
52
+ */
53
+ assign(assigns: PondAssigns): ConnectionContext<Path>;
54
+ /**
55
+ * Accepts the connection request
56
+ */
57
+ accept(): ConnectionContext<Path>;
58
+ /**
59
+ * Declines the connection request
60
+ */
61
+ decline(message?: string, errorCode?: number): ConnectionContext<Path>;
62
+ /**
63
+ * Sends a direct reply to the client
64
+ */
65
+ reply(event: string, payload: PondMessage): ConnectionContext<Path>;
66
+ }
@@ -0,0 +1,15 @@
1
+ import { ChannelReceivers, EventParams, PondAssigns, PondMessage, PondObject, PondPresence } from '@eleven-am/pondsocket-common';
2
+ import { BaseContext } from './baseContext';
3
+ import { BroadcastEvent } from '../abstracts/types';
4
+ import { ChannelEngine } from '../engines/channelEngine';
5
+ export declare class EventContext<Path extends string> extends BaseContext<Path> {
6
+ #private;
7
+ constructor(event: BroadcastEvent, params: EventParams<Path>, engine: ChannelEngine);
8
+ assign(assigns: PondAssigns): EventContext<Path>;
9
+ reply(event: string, payload: PondMessage): this;
10
+ trackPresence(presence: PondPresence, userId?: string): EventContext<Path>;
11
+ updatePresence(presence: PondPresence, userId?: string): EventContext<Path>;
12
+ evictUser(reason: string, userId?: string): EventContext<Path>;
13
+ removePresence(userId?: string): EventContext<Path>;
14
+ protected _sendMessageToRecipients(recipient: ChannelReceivers, event: string, payload: PondObject): void;
15
+ }