@tailuge/messaging 1.5.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MESSAGING_SPEC.md +51 -2
- package/dist/lobby.d.ts +7 -0
- package/dist/lobby.js +16 -17
- package/dist/lobby.js.map +1 -1
- package/dist/messagingclient.d.ts +2 -0
- package/dist/messagingclient.js +29 -29
- package/dist/messagingclient.js.map +1 -1
- package/dist/nchanclient.js +7 -3
- package/dist/nchanclient.js.map +1 -1
- package/dist/table.js +7 -12
- package/dist/table.js.map +1 -1
- package/dist/types.d.ts +2 -3
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/MESSAGING_SPEC.md
CHANGED
|
@@ -139,8 +139,7 @@ All messages published through the transport layer are automatically enriched by
|
|
|
139
139
|
interface Meta {
|
|
140
140
|
ts: string; // ISO timestamp of the request (Source of Truth for time)
|
|
141
141
|
ua: string; // User-Agent header
|
|
142
|
-
|
|
143
|
-
host: string; // Host header value
|
|
142
|
+
origin: string; // Origin header value
|
|
144
143
|
method: string; // HTTP method (always POST for publish)
|
|
145
144
|
country: string; // Country code from IP (e.g., "US", "GB", "XX")
|
|
146
145
|
city: string; // City from IP geolocation
|
|
@@ -172,6 +171,56 @@ interface PresenceMessage {
|
|
|
172
171
|
}
|
|
173
172
|
```
|
|
174
173
|
|
|
174
|
+
#### External Game Integration
|
|
175
|
+
|
|
176
|
+
When users are redirected from the lobby to an external game page (e.g., billiards), the game page can maintain the user's presence as "in a table" by passing `tableId` when joining the lobby:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// In the external game page
|
|
180
|
+
const client = new MessagingClient({ baseUrl: nchanUrl });
|
|
181
|
+
|
|
182
|
+
// Join lobby with tableId already set - lobby users see this player as "in game"
|
|
183
|
+
const lobby = await client.joinLobby({
|
|
184
|
+
messageType: "presence",
|
|
185
|
+
type: "join",
|
|
186
|
+
userId: "player1",
|
|
187
|
+
userName: "Player One",
|
|
188
|
+
tableId: "table-123", // Marks user as at table-123
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
This is useful when:
|
|
193
|
+
- The game was launched from a URL with tableId (e.g., after challenge acceptance)
|
|
194
|
+
- The new page creates a fresh MessagingClient but wants to preserve presence state
|
|
195
|
+
- Other lobby users should see this player as "currently in a game"
|
|
196
|
+
|
|
197
|
+
To clear the table status (e.g., when the game ends):
|
|
198
|
+
```typescript
|
|
199
|
+
await lobby.updatePresence({ tableId: undefined });
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Page unload:** When the lobby page unloads, a `leave` message is sent automatically. The external game page is expected to call `joinLobby()` with `tableId` to re-establish presence as "in game". This ensures no ghost users if the redirect fails.
|
|
203
|
+
|
|
204
|
+
#### Minimal Presence for Games
|
|
205
|
+
|
|
206
|
+
Games that only need online user count (no table joining):
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// Join without tableId - user appears as "available" in lobby
|
|
210
|
+
await client.joinLobby({
|
|
211
|
+
messageType: "presence",
|
|
212
|
+
type: "join",
|
|
213
|
+
userId: "player1",
|
|
214
|
+
userName: "Player One",
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Add tableId when starting a multiplayer game
|
|
218
|
+
await lobby.updatePresence({ tableId: "table-123" });
|
|
219
|
+
|
|
220
|
+
// Remove tableId when game ends
|
|
221
|
+
await lobby.updatePresence({ tableId: undefined });
|
|
222
|
+
```
|
|
223
|
+
|
|
175
224
|
### `ChallengeMessage`
|
|
176
225
|
|
|
177
226
|
Represents a peer-to-peer challenge request.
|
package/dist/lobby.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class Lobby {
|
|
|
15
15
|
private users;
|
|
16
16
|
private listeners;
|
|
17
17
|
private challengeListeners;
|
|
18
|
+
private pendingChallenges;
|
|
18
19
|
private subscription;
|
|
19
20
|
private isJoined;
|
|
20
21
|
private heartbeatTimer?;
|
|
@@ -71,6 +72,7 @@ export declare class Lobby {
|
|
|
71
72
|
cancelChallenge(userId: string, ruleType: string): Promise<void>;
|
|
72
73
|
/**
|
|
73
74
|
* Subscribe to incoming challenges directed at the current user.
|
|
75
|
+
* Delivers any pending challenges that were received while disconnected.
|
|
74
76
|
*/
|
|
75
77
|
onChallenge(callback: (challenge: ChallengeMessage) => void): void;
|
|
76
78
|
/**
|
|
@@ -80,6 +82,11 @@ export declare class Lobby {
|
|
|
80
82
|
isTeardown?: boolean;
|
|
81
83
|
}): Promise<void>;
|
|
82
84
|
private handleIncomingMessage;
|
|
85
|
+
/**
|
|
86
|
+
* Handles incoming presence updates.
|
|
87
|
+
* Note: Nchan guarantees ordered delivery, so we don't need to check meta.ts for ordering.
|
|
88
|
+
* The last message received for each userId will be the current state.
|
|
89
|
+
*/
|
|
83
90
|
private handlePresenceUpdate;
|
|
84
91
|
private handleChallenge;
|
|
85
92
|
private notifyListeners;
|
package/dist/lobby.js
CHANGED
|
@@ -5,21 +5,15 @@ import { getUID } from "./utils/uid.js";
|
|
|
5
5
|
* Manages the global lobby state, including real-time presence tracking and challenge flows.
|
|
6
6
|
*/
|
|
7
7
|
export class Lobby {
|
|
8
|
-
nchan;
|
|
9
|
-
currentUser;
|
|
10
|
-
users = new Map();
|
|
11
|
-
listeners = [];
|
|
12
|
-
challengeListeners = [];
|
|
13
|
-
subscription = null;
|
|
14
|
-
isJoined = false;
|
|
15
|
-
heartbeatTimer;
|
|
16
|
-
pruneTimer;
|
|
17
|
-
heartbeatInterval;
|
|
18
|
-
pruneInterval;
|
|
19
|
-
staleTtl;
|
|
20
8
|
constructor(nchan, currentUser, options = {}) {
|
|
21
9
|
this.nchan = nchan;
|
|
22
10
|
this.currentUser = currentUser;
|
|
11
|
+
this.users = new Map();
|
|
12
|
+
this.listeners = [];
|
|
13
|
+
this.challengeListeners = [];
|
|
14
|
+
this.pendingChallenges = [];
|
|
15
|
+
this.subscription = null;
|
|
16
|
+
this.isJoined = false;
|
|
23
17
|
this.heartbeatInterval = options.heartbeatInterval || 30000;
|
|
24
18
|
this.pruneInterval = options.pruneInterval || 10000;
|
|
25
19
|
this.staleTtl = options.staleTtl || 90000;
|
|
@@ -81,8 +75,7 @@ export class Lobby {
|
|
|
81
75
|
for (const [userId, user] of this.users.entries()) {
|
|
82
76
|
if (userId === this.currentUser.userId)
|
|
83
77
|
continue;
|
|
84
|
-
|
|
85
|
-
const lastSeen = user.lastSeen || now;
|
|
78
|
+
const lastSeen = user.meta.ts;
|
|
86
79
|
if (now - lastSeen > this.staleTtl) {
|
|
87
80
|
this.users.delete(userId);
|
|
88
81
|
changed = true;
|
|
@@ -182,9 +175,11 @@ export class Lobby {
|
|
|
182
175
|
}
|
|
183
176
|
/**
|
|
184
177
|
* Subscribe to incoming challenges directed at the current user.
|
|
178
|
+
* Delivers any pending challenges that were received while disconnected.
|
|
185
179
|
*/
|
|
186
180
|
onChallenge(callback) {
|
|
187
181
|
this.challengeListeners.push(callback);
|
|
182
|
+
this.pendingChallenges.forEach((challenge) => callback(challenge));
|
|
188
183
|
}
|
|
189
184
|
/**
|
|
190
185
|
* Gracefully leaves the lobby.
|
|
@@ -203,6 +198,7 @@ export class Lobby {
|
|
|
203
198
|
console.error("Error leaving lobby:", e);
|
|
204
199
|
}
|
|
205
200
|
this.users.clear();
|
|
201
|
+
this.pendingChallenges = [];
|
|
206
202
|
this.notifyListeners();
|
|
207
203
|
this.isJoined = false;
|
|
208
204
|
}
|
|
@@ -217,20 +213,23 @@ export class Lobby {
|
|
|
217
213
|
this.handleChallenge(rawMsg);
|
|
218
214
|
}
|
|
219
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Handles incoming presence updates.
|
|
218
|
+
* Note: Nchan guarantees ordered delivery, so we don't need to check meta.ts for ordering.
|
|
219
|
+
* The last message received for each userId will be the current state.
|
|
220
|
+
*/
|
|
220
221
|
handlePresenceUpdate(msg) {
|
|
221
222
|
if (msg.type === "leave") {
|
|
222
223
|
this.users.delete(msg.userId);
|
|
223
224
|
}
|
|
224
225
|
else {
|
|
225
|
-
// Use local time for real-time pruning to avoid clock skew
|
|
226
|
-
msg.lastSeen = Date.now();
|
|
227
226
|
this.users.set(msg.userId, msg);
|
|
228
227
|
}
|
|
229
228
|
this.notifyListeners();
|
|
230
229
|
}
|
|
231
230
|
handleChallenge(msg) {
|
|
232
|
-
// Filter messages directed at us (or broadcasted ones)
|
|
233
231
|
if (msg.recipientId === this.currentUser.userId) {
|
|
232
|
+
this.pendingChallenges.push(msg);
|
|
234
233
|
this.challengeListeners.forEach((cb) => cb(msg));
|
|
235
234
|
}
|
|
236
235
|
}
|
package/dist/lobby.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lobby.js","sourceRoot":"","sources":["../src/lobby.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC;;GAEG;AACH,MAAM,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"lobby.js","sourceRoot":"","sources":["../src/lobby.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ export declare class MessagingClient {
|
|
|
27
27
|
}): Promise<void>;
|
|
28
28
|
/**
|
|
29
29
|
* Enters the global lobby for presence broadcasting and tracking.
|
|
30
|
+
* Note: Nchan guarantees ordered message delivery, so the Lobby class does not need
|
|
31
|
+
* to implement message ordering or deduplication based on meta.ts timestamps.
|
|
30
32
|
*/
|
|
31
33
|
joinLobby(user: PresenceMessage, options?: LobbyOptions): Promise<Lobby>;
|
|
32
34
|
/**
|
package/dist/messagingclient.js
CHANGED
|
@@ -6,12 +6,34 @@ import { Table } from "./table.js";
|
|
|
6
6
|
* Encapsulates transport logic and provides access to lobby and table functionality.
|
|
7
7
|
*/
|
|
8
8
|
export class MessagingClient {
|
|
9
|
-
nchan;
|
|
10
|
-
activeLobbies = [];
|
|
11
|
-
activeTables = [];
|
|
12
|
-
lastLobbyConfig;
|
|
13
|
-
isStopping = false;
|
|
14
9
|
constructor(options) {
|
|
10
|
+
this.activeLobbies = [];
|
|
11
|
+
this.activeTables = [];
|
|
12
|
+
this.isStopping = false;
|
|
13
|
+
this.handlePageHide = () => {
|
|
14
|
+
// Stop all connections on page hide (prevent ghosting)
|
|
15
|
+
// Non-blocking call because pagehide might terminate the process
|
|
16
|
+
this.stop({ isTeardown: true });
|
|
17
|
+
};
|
|
18
|
+
this.handlePageShow = async (event) => {
|
|
19
|
+
// If returning via bfcache, restore connections
|
|
20
|
+
if (event.persisted && this.lastLobbyConfig) {
|
|
21
|
+
try {
|
|
22
|
+
await this.joinLobby(this.lastLobbyConfig.user, this.lastLobbyConfig.options);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
console.error("Failed to restore lobby on pageshow:", e);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
this.handleVisibilityChange = () => {
|
|
30
|
+
if (document.hidden) {
|
|
31
|
+
this.activeLobbies.forEach((l) => l.pauseHeartbeat());
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
this.activeLobbies.forEach((l) => l.resumeHeartbeat());
|
|
35
|
+
}
|
|
36
|
+
};
|
|
15
37
|
this.nchan = new NchanClient(options.baseUrl);
|
|
16
38
|
}
|
|
17
39
|
/**
|
|
@@ -52,6 +74,8 @@ export class MessagingClient {
|
|
|
52
74
|
}
|
|
53
75
|
/**
|
|
54
76
|
* Enters the global lobby for presence broadcasting and tracking.
|
|
77
|
+
* Note: Nchan guarantees ordered message delivery, so the Lobby class does not need
|
|
78
|
+
* to implement message ordering or deduplication based on meta.ts timestamps.
|
|
55
79
|
*/
|
|
56
80
|
async joinLobby(user, options) {
|
|
57
81
|
// Prevent duplicate joins if already in a lobby for this user
|
|
@@ -83,29 +107,5 @@ export class MessagingClient {
|
|
|
83
107
|
await lobby.updatePresence({ tableId });
|
|
84
108
|
return table;
|
|
85
109
|
}
|
|
86
|
-
handlePageHide = () => {
|
|
87
|
-
// Stop all connections on page hide (prevent ghosting)
|
|
88
|
-
// Non-blocking call because pagehide might terminate the process
|
|
89
|
-
this.stop({ isTeardown: true });
|
|
90
|
-
};
|
|
91
|
-
handlePageShow = async (event) => {
|
|
92
|
-
// If returning via bfcache, restore connections
|
|
93
|
-
if (event.persisted && this.lastLobbyConfig) {
|
|
94
|
-
try {
|
|
95
|
-
await this.joinLobby(this.lastLobbyConfig.user, this.lastLobbyConfig.options);
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
console.error("Failed to restore lobby on pageshow:", e);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
handleVisibilityChange = () => {
|
|
103
|
-
if (document.hidden) {
|
|
104
|
-
this.activeLobbies.forEach((l) => l.pauseHeartbeat());
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
this.activeLobbies.forEach((l) => l.resumeHeartbeat());
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
110
|
}
|
|
111
111
|
//# sourceMappingURL=messagingclient.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messagingclient.js","sourceRoot":"","sources":["../src/messagingclient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAgB,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC;;;GAGG;AACH,MAAM,OAAO,eAAe;
|
|
1
|
+
{"version":3,"file":"messagingclient.js","sourceRoot":"","sources":["../src/messagingclient.ts"],"names":[],"mappings":"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"}
|
package/dist/nchanclient.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
const PATHS = {
|
|
2
|
-
PRESENCE_PUBLISH: "/publish/
|
|
3
|
-
PRESENCE_SUBSCRIBE: "/subscribe/
|
|
2
|
+
PRESENCE_PUBLISH: "/publish/presence/lobby",
|
|
3
|
+
PRESENCE_SUBSCRIBE: "/subscribe/presence/lobby",
|
|
4
4
|
TABLE_PUBLISH: (tableId) => `/publish/table/${tableId}`,
|
|
5
5
|
TABLE_SUBSCRIBE: (tableId) => `/subscribe/table/${tableId}`,
|
|
6
6
|
};
|
|
7
7
|
export class NchanClient {
|
|
8
|
-
server;
|
|
9
8
|
constructor(server) {
|
|
10
9
|
// Ensure server string doesn't end with a slash
|
|
11
10
|
this.server = server.replace(/\/$/, "");
|
|
@@ -92,6 +91,11 @@ export class NchanClient {
|
|
|
92
91
|
};
|
|
93
92
|
ws.onopen = () => {
|
|
94
93
|
reconnectAttempts = 0;
|
|
94
|
+
// Clear any pending reconnect timer from previous disconnect
|
|
95
|
+
if (reconnectTimer) {
|
|
96
|
+
clearTimeout(reconnectTimer);
|
|
97
|
+
reconnectTimer = null;
|
|
98
|
+
}
|
|
95
99
|
resolveReady();
|
|
96
100
|
};
|
|
97
101
|
ws.onclose = () => {
|
package/dist/nchanclient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nchanclient.js","sourceRoot":"","sources":["../src/nchanclient.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG;IACZ,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"nchanclient.js","sourceRoot":"","sources":["../src/nchanclient.ts"],"names":[],"mappings":"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"}
|
package/dist/table.js
CHANGED
|
@@ -4,23 +4,18 @@ import { parseMessage } from "./types.js";
|
|
|
4
4
|
* Uses `any` as default for internal storage flexibility; consumers should use `unknown` or specific types.
|
|
5
5
|
*/
|
|
6
6
|
export class Table {
|
|
7
|
-
nchan;
|
|
8
|
-
tableId;
|
|
9
|
-
userId;
|
|
10
|
-
lobby;
|
|
11
|
-
subscription = null;
|
|
12
|
-
isJoined = false;
|
|
13
|
-
messageListeners = [];
|
|
14
|
-
spectatorListeners = [];
|
|
15
|
-
opponentLeftListeners = [];
|
|
16
|
-
lobbyUnsubscribe;
|
|
17
|
-
opponentLeft = false;
|
|
18
|
-
opponentSeen = false;
|
|
19
7
|
constructor(nchan, tableId, userId, lobby) {
|
|
20
8
|
this.nchan = nchan;
|
|
21
9
|
this.tableId = tableId;
|
|
22
10
|
this.userId = userId;
|
|
23
11
|
this.lobby = lobby;
|
|
12
|
+
this.subscription = null;
|
|
13
|
+
this.isJoined = false;
|
|
14
|
+
this.messageListeners = [];
|
|
15
|
+
this.spectatorListeners = [];
|
|
16
|
+
this.opponentLeftListeners = [];
|
|
17
|
+
this.opponentLeft = false;
|
|
18
|
+
this.opponentSeen = false;
|
|
24
19
|
if (this.lobby) {
|
|
25
20
|
const handler = (users) => this.handleLobbyUsersChange(users);
|
|
26
21
|
this.lobby.onUsersChange(handler);
|
package/dist/table.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,YAAY,EAAmB,MAAM,SAAS,CAAC;AAGtE;;;GAGG;AACH,MAAM,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* This is the absolute source of truth for timing.
|
|
4
4
|
*/
|
|
5
5
|
export interface Meta {
|
|
6
|
-
ts:
|
|
6
|
+
ts: number;
|
|
7
7
|
ua: string;
|
|
8
8
|
ip: string;
|
|
9
|
-
|
|
9
|
+
origin: string;
|
|
10
10
|
method: string;
|
|
11
11
|
country: string;
|
|
12
12
|
}
|
|
@@ -28,7 +28,6 @@ export interface PresenceMessage {
|
|
|
28
28
|
ruleType?: string;
|
|
29
29
|
opponentId?: string | null;
|
|
30
30
|
seek?: Seek;
|
|
31
|
-
lastSeen?: number;
|
|
32
31
|
meta?: Meta;
|
|
33
32
|
tableId?: string;
|
|
34
33
|
}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAuFA;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAQ;IACxC,OAAO,GAAG,EAAE,WAAW,KAAK,UAAU,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAQ;IACzC,OAAO,GAAG,EAAE,WAAW,KAAK,WAAW,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,aAAqB;IACzE,OAAO,MAAM,CAAC,MAAM,KAAK,aAAa,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAuB,EAAE,cAAuB;IAC1E,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,cAAc,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAwB;IAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,OAAO,EAAE,EAAE;oBACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC,CAAC;YACL,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC;gBACtC,EAAE,EAAE,IAAI,CAAC,MAAM;gBACf,IAAI,EAAE,IAAI,CAAC,QAAQ;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAI,IAAY;IAC1C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailuge/messaging",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A stateful messaging library for Nchan-powered real-time applications.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"esbuild": "^0.27.4",
|
|
52
52
|
"http-server": "^14.1.1",
|
|
53
53
|
"jest": "30.3.0",
|
|
54
|
-
"oxlint": "^1.
|
|
54
|
+
"oxlint": "^1.56.0",
|
|
55
55
|
"testcontainers": "^11.12.0",
|
|
56
56
|
"ts-jest": "^29.4.6",
|
|
57
57
|
"typescript": "5.9.3",
|