@baasix/sdk 0.1.7 → 0.1.8

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
@@ -1053,6 +1053,52 @@ const channel = baasix.realtime
1053
1053
  channel.unsubscribe();
1054
1054
  ```
1055
1055
 
1056
+ ### Custom Rooms
1057
+
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
+
1060
+ ```typescript
1061
+ // Join a room
1062
+ await baasix.realtime.joinRoom('game:lobby');
1063
+
1064
+ // Get current members (you must be in the room)
1065
+ const members = await baasix.realtime.getRoomMembers('game:lobby');
1066
+ // [{ socketId: string, userId: string|number, isCreator: boolean }, ...]
1067
+
1068
+ // Send a message to all room members
1069
+ await baasix.realtime.sendToRoom('game:lobby', 'chat', { text: 'Hello!' });
1070
+
1071
+ // Listen for room messages
1072
+ const unsubscribe = baasix.realtime.onRoomMessage('game:lobby', 'chat', (data) => {
1073
+ console.log(`${data.sender.userId}: ${data.payload.text}`);
1074
+ });
1075
+
1076
+ // Listen for users joining / leaving
1077
+ baasix.realtime.onRoomUserJoined('game:lobby', (data) => {
1078
+ console.log(`${data.userId} joined`);
1079
+ });
1080
+ baasix.realtime.onRoomUserLeft('game:lobby', (data) => {
1081
+ console.log(`${data.userId} left`);
1082
+ });
1083
+
1084
+ // Kick a user — only the room creator can do this
1085
+ await baasix.realtime.kickFromRoom('game:lobby', 'target-user-id');
1086
+
1087
+ // Listen for being kicked out (fires only on the kicked user's socket)
1088
+ baasix.realtime.onKicked('game:lobby', ({ kickedBy }) => {
1089
+ console.log(`You were kicked by user ${kickedBy}`);
1090
+ // Room listeners are automatically cleaned up after a kick
1091
+ });
1092
+
1093
+ // Listen for ownership changes (fires for all members when creator changes)
1094
+ baasix.realtime.onRoomCreatorChanged('game:lobby', ({ newCreatorUserId }) => {
1095
+ console.log(`New room owner: ${newCreatorUserId}`);
1096
+ });
1097
+
1098
+ // Leave the room
1099
+ await baasix.realtime.leaveRoom('game:lobby');
1100
+ ```
1101
+
1056
1102
  ### Connection Management
1057
1103
 
1058
1104
  ```typescript
package/dist/index.cjs CHANGED
@@ -3293,6 +3293,8 @@ var RealtimeModule = class {
3293
3293
  roomCallbacks = /* @__PURE__ */ new Map();
3294
3294
  // room -> event -> callbacks
3295
3295
  roomUserCallbacks = /* @__PURE__ */ new Map();
3296
+ kickCallbacks = /* @__PURE__ */ new Map();
3297
+ creatorChangedCallbacks = /* @__PURE__ */ new Map();
3296
3298
  connectionCallbacks = /* @__PURE__ */ new Set();
3297
3299
  reconnecting = false;
3298
3300
  connectionPromise = null;
@@ -3422,6 +3424,27 @@ var RealtimeModule = class {
3422
3424
  }
3423
3425
  });
3424
3426
  });
3427
+ this.socket.on("room:kicked", (data) => {
3428
+ const callbacks = this.kickCallbacks.get(data.room);
3429
+ callbacks?.forEach((cb) => {
3430
+ try {
3431
+ cb(data);
3432
+ } catch (e) {
3433
+ console.error("[Baasix Realtime] Error in room kicked callback:", e);
3434
+ }
3435
+ });
3436
+ this.cleanupRoomListeners(data.room);
3437
+ });
3438
+ this.socket.on("room:creator:changed", (data) => {
3439
+ const callbacks = this.creatorChangedCallbacks.get(data.room);
3440
+ callbacks?.forEach((cb) => {
3441
+ try {
3442
+ cb(data);
3443
+ } catch (e) {
3444
+ console.error("[Baasix Realtime] Error in room creator changed callback:", e);
3445
+ }
3446
+ });
3447
+ });
3425
3448
  this.socket.connect();
3426
3449
  } catch (error) {
3427
3450
  this.connectionPromise = null;
@@ -3451,6 +3474,8 @@ var RealtimeModule = class {
3451
3474
  this.workflowCallbacks.clear();
3452
3475
  this.roomCallbacks.clear();
3453
3476
  this.roomUserCallbacks.clear();
3477
+ this.kickCallbacks.clear();
3478
+ this.creatorChangedCallbacks.clear();
3454
3479
  }
3455
3480
  /**
3456
3481
  * Check if connected to the realtime server
@@ -3721,6 +3746,110 @@ var RealtimeModule = class {
3721
3746
  });
3722
3747
  });
3723
3748
  }
3749
+ /**
3750
+ * Get the list of users currently in a room.
3751
+ * You must already be a member of the room to call this.
3752
+ *
3753
+ * @example
3754
+ * ```typescript
3755
+ * const members = await baasix.realtime.getRoomMembers('game:lobby');
3756
+ * members.forEach(m => {
3757
+ * console.log(m.userId, m.isCreator ? '(owner)' : '');
3758
+ * });
3759
+ * ```
3760
+ */
3761
+ async getRoomMembers(roomName) {
3762
+ if (!this.socket?.connected) {
3763
+ throw new Error("Not connected. Call connect() first.");
3764
+ }
3765
+ return new Promise((resolve, reject) => {
3766
+ this.socket.emit("room:members", { room: roomName }, (response) => {
3767
+ if (response.status === "success") {
3768
+ resolve(response.members);
3769
+ } else {
3770
+ reject(new Error(response.message || "Failed to get room members"));
3771
+ }
3772
+ });
3773
+ });
3774
+ }
3775
+ /**
3776
+ * Kick a user from a custom room. Only the room creator may call this.
3777
+ *
3778
+ * @example
3779
+ * ```typescript
3780
+ * await baasix.realtime.kickFromRoom('game:lobby', 'user-id-123');
3781
+ * ```
3782
+ */
3783
+ async kickFromRoom(roomName, targetUserId) {
3784
+ if (!this.socket?.connected) {
3785
+ throw new Error("Not connected. Call connect() first.");
3786
+ }
3787
+ return new Promise((resolve, reject) => {
3788
+ this.socket.emit(
3789
+ "room:kick",
3790
+ { room: roomName, userId: targetUserId },
3791
+ (response) => {
3792
+ if (response.status === "success") {
3793
+ resolve();
3794
+ } else {
3795
+ reject(new Error(response.message || "Failed to kick user"));
3796
+ }
3797
+ }
3798
+ );
3799
+ });
3800
+ }
3801
+ /**
3802
+ * Listen for being kicked from a room.
3803
+ * The callback fires when the current user is removed by the room creator.
3804
+ * Room listeners are automatically cleaned up after the kick.
3805
+ *
3806
+ * @example
3807
+ * ```typescript
3808
+ * baasix.realtime.onKicked('game:lobby', ({ kickedBy }) => {
3809
+ * console.log(`You were kicked by user ${kickedBy}`);
3810
+ * });
3811
+ * ```
3812
+ */
3813
+ onKicked(roomName, callback) {
3814
+ if (!this.kickCallbacks.has(roomName)) {
3815
+ this.kickCallbacks.set(roomName, /* @__PURE__ */ new Set());
3816
+ }
3817
+ this.kickCallbacks.get(roomName).add(callback);
3818
+ return () => {
3819
+ const callbacks = this.kickCallbacks.get(roomName);
3820
+ if (callbacks) {
3821
+ callbacks.delete(callback);
3822
+ if (callbacks.size === 0) {
3823
+ this.kickCallbacks.delete(roomName);
3824
+ }
3825
+ }
3826
+ };
3827
+ }
3828
+ /**
3829
+ * Listen for room ownership changes (e.g. when the creator leaves).
3830
+ *
3831
+ * @example
3832
+ * ```typescript
3833
+ * baasix.realtime.onRoomCreatorChanged('game:lobby', ({ newCreatorUserId }) => {
3834
+ * console.log(`New room owner: ${newCreatorUserId}`);
3835
+ * });
3836
+ * ```
3837
+ */
3838
+ onRoomCreatorChanged(roomName, callback) {
3839
+ if (!this.creatorChangedCallbacks.has(roomName)) {
3840
+ this.creatorChangedCallbacks.set(roomName, /* @__PURE__ */ new Set());
3841
+ }
3842
+ this.creatorChangedCallbacks.get(roomName).add(callback);
3843
+ return () => {
3844
+ const callbacks = this.creatorChangedCallbacks.get(roomName);
3845
+ if (callbacks) {
3846
+ callbacks.delete(callback);
3847
+ if (callbacks.size === 0) {
3848
+ this.creatorChangedCallbacks.delete(roomName);
3849
+ }
3850
+ }
3851
+ };
3852
+ }
3724
3853
  /**
3725
3854
  * Send a message to a room
3726
3855
  *
@@ -3873,6 +4002,8 @@ var RealtimeModule = class {
3873
4002
  cleanupRoomListeners(roomName) {
3874
4003
  this.roomCallbacks.delete(roomName);
3875
4004
  this.roomUserCallbacks.delete(roomName);
4005
+ this.kickCallbacks.delete(roomName);
4006
+ this.creatorChangedCallbacks.delete(roomName);
3876
4007
  }
3877
4008
  // ===================
3878
4009
  // Channel (Room) API - Supabase-style