@baasix/sdk 0.1.9 → 0.1.11

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 CHANGED
@@ -1058,21 +1058,41 @@ channel.unsubscribe();
1058
1058
  Custom rooms enable real-time communication between users for chat, games, or collaborative features. The **first user to join** a room becomes its creator. If the creator leaves temporarily, ownership transfers to the next member — but the **original creator automatically reclaims ownership** when they rejoin. If the room empties and is recreated, the next joiner becomes the new owner.
1059
1059
 
1060
1060
  ```typescript
1061
- // Join a room — pass optional metadata stored alongside your membership
1062
- await baasix.realtime.joinRoom('game:lobby', {
1061
+ // Join a room — pass optional metadata stored alongside your membership.
1062
+ // Returns { history } — the room's last 200 messages, replayed for late joiners.
1063
+ const { history } = await baasix.realtime.joinRoom('game:lobby', {
1063
1064
  username: 'Alice',
1064
1065
  avatar: 'https://example.com/alice.png',
1065
1066
  team: 'blue',
1066
1067
  });
1067
1068
 
1069
+ // Replay buffered messages so the user sees missed events immediately
1070
+ // Each entry: { event, payload, sender: { userId, socketId }, timestamp }
1071
+ history.forEach((msg) => {
1072
+ addMessageToUI(msg.sender.userId, msg.payload.text);
1073
+ });
1074
+
1068
1075
  // Get current members (you must be in the room)
1069
1076
  // Each entry includes userId, socketId, isCreator, and metadata
1070
1077
  const members = await baasix.realtime.getRoomMembers('game:lobby');
1071
1078
  // [{ socketId: string, userId: string|number, isCreator: boolean, metadata: Record<string,any> }, ...]
1072
1079
 
1073
- // Send a message to all room members
1080
+ // List all active rooms no membership required
1081
+ const rooms = await baasix.realtime.listRooms();
1082
+ // [{ name: 'game:lobby', memberCount: 4 }, { name: 'chat:general', memberCount: 12 }]
1083
+
1084
+ // Filter by name prefix — e.g. show only 'game:' rooms
1085
+ const gameRooms = await baasix.realtime.listRooms('game:');
1086
+ // [{ name: 'game:lobby', memberCount: 4 }, { name: 'game:arena', memberCount: 8 }]
1087
+
1088
+ // Send a persisted message — stored in the history buffer (default)
1074
1089
  await baasix.realtime.sendToRoom('game:lobby', 'chat', { text: 'Hello!' });
1075
1090
 
1091
+ // Send an ephemeral message — broadcast only, NOT stored in history
1092
+ // Ideal for high-frequency events: cursors, typing indicators, presence pings
1093
+ await baasix.realtime.sendToRoom('game:lobby', 'typing', { userId }, { history: false });
1094
+ await baasix.realtime.sendToRoom('game:lobby', 'cursor', { x: 120, y: 340 }, { history: false });
1095
+
1076
1096
  // Listen for room messages
1077
1097
  const unsubscribe = baasix.realtime.onRoomMessage('game:lobby', 'chat', (data) => {
1078
1098
  console.log(`${data.sender.userId}: ${data.payload.text}`);
package/dist/index.cjs CHANGED
@@ -3701,21 +3701,26 @@ var RealtimeModule = class {
3701
3701
  * will be visible to all other members via {@link getRoomMembers} and in
3702
3702
  * `room:user:joined` events.
3703
3703
  *
3704
+ * Returns the room's message history (up to 200 messages) so late joiners
3705
+ * can replay past messages immediately.
3706
+ *
3704
3707
  * @param roomName - The room to join.
3705
3708
  * @param metadata - Optional key/value pairs stored alongside this member.
3709
+ * @returns An object containing the buffered `history` for the room.
3706
3710
  *
3707
3711
  * @example
3708
3712
  * ```typescript
3709
- * // Join a room with metadata
3710
- * await baasix.realtime.joinRoom('game:lobby', {
3713
+ * const { history } = await baasix.realtime.joinRoom('game:lobby', {
3711
3714
  * username: 'Alice',
3712
3715
  * avatar: 'https://example.com/alice.png',
3713
- * team: 'blue',
3714
3716
  * });
3715
3717
  *
3716
- * // Listen for other users joining (includes their metadata)
3717
- * baasix.realtime.onUserJoined('game:lobby', (data) => {
3718
- * console.log(data.metadata.username, 'joined');
3718
+ * // Render past messages first
3719
+ * history.forEach((msg) => renderMessage(msg));
3720
+ *
3721
+ * // Then listen for new ones
3722
+ * baasix.realtime.onRoomMessage('game:lobby', 'chat', (data) => {
3723
+ * renderMessage(data);
3719
3724
  * });
3720
3725
  * ```
3721
3726
  */
@@ -3727,7 +3732,7 @@ var RealtimeModule = class {
3727
3732
  this.socket.emit("room:join", { room: roomName, metadata }, (response) => {
3728
3733
  if (response.status === "success") {
3729
3734
  this.setupRoomListeners(roomName);
3730
- resolve();
3735
+ resolve({ history: response.history ?? [] });
3731
3736
  } else {
3732
3737
  reject(new Error(response.message || "Failed to join room"));
3733
3738
  }
@@ -3786,6 +3791,39 @@ var RealtimeModule = class {
3786
3791
  });
3787
3792
  });
3788
3793
  }
3794
+ /**
3795
+ * List all active custom rooms, optionally filtered by a name prefix.
3796
+ *
3797
+ * Returns every room that currently has at least one member.
3798
+ * You do **not** need to be a member of a room to list it.
3799
+ *
3800
+ * @param prefix - Optional prefix to filter rooms. E.g. `"game:"` returns only
3801
+ * rooms whose name starts with `"game:"`.
3802
+ *
3803
+ * @example
3804
+ * ```typescript
3805
+ * // All active rooms
3806
+ * const rooms = await baasix.realtime.listRooms();
3807
+ * // [{ name: 'game:lobby', memberCount: 4 }, { name: 'chat:general', memberCount: 12 }]
3808
+ *
3809
+ * // Only rooms whose name starts with 'game:'
3810
+ * const gameRooms = await baasix.realtime.listRooms('game:');
3811
+ * ```
3812
+ */
3813
+ async listRooms(prefix) {
3814
+ if (!this.socket?.connected) {
3815
+ throw new Error("Not connected. Call connect() first.");
3816
+ }
3817
+ return new Promise((resolve, reject) => {
3818
+ this.socket.emit("room:list", { prefix: prefix ?? "" }, (response) => {
3819
+ if (response.status === "success") {
3820
+ resolve(response.rooms);
3821
+ } else {
3822
+ reject(new Error(response.message || "Failed to list rooms"));
3823
+ }
3824
+ });
3825
+ });
3826
+ }
3789
3827
  /**
3790
3828
  * Kick a user from a custom room. Only the room creator may call this.
3791
3829
  *
@@ -3865,25 +3903,33 @@ var RealtimeModule = class {
3865
3903
  };
3866
3904
  }
3867
3905
  /**
3868
- * Send a message to a room
3869
- *
3906
+ * Send a message to a room.
3907
+ *
3908
+ * By default the message is stored in the room's history buffer so late
3909
+ * joiners can replay it. Pass `{ history: false }` to broadcast without
3910
+ * persisting (e.g. ephemeral cursor positions, typing indicators).
3911
+ *
3870
3912
  * @example
3871
3913
  * ```typescript
3872
- * // Send a chat message
3914
+ * // Persisted replayed to future joiners
3873
3915
  * await baasix.realtime.sendToRoom('game:lobby', 'chat', { text: 'Hello!' });
3874
- *
3875
- * // Send a game event
3876
- * await baasix.realtime.sendToRoom('game:123', 'move', { x: 10, y: 20 });
3916
+ *
3917
+ * // Ephemeral broadcast only, never stored in history
3918
+ * await baasix.realtime.sendToRoom('game:lobby', 'typing', { userId }, { history: false });
3919
+ *
3920
+ * // Game move — skips history
3921
+ * await baasix.realtime.sendToRoom('game:123', 'move', { x: 10, y: 20 }, { history: false });
3877
3922
  * ```
3878
3923
  */
3879
- async sendToRoom(roomName, event, payload) {
3924
+ async sendToRoom(roomName, event, payload, options = {}) {
3880
3925
  if (!this.socket?.connected) {
3881
3926
  throw new Error("Not connected. Call connect() first.");
3882
3927
  }
3928
+ const history = options.history ?? true;
3883
3929
  return new Promise((resolve, reject) => {
3884
3930
  this.socket.emit(
3885
3931
  "room:message",
3886
- { room: roomName, event, payload },
3932
+ { room: roomName, event, payload, history },
3887
3933
  (response) => {
3888
3934
  if (response.status === "success") {
3889
3935
  resolve();