liveblocks icon indicating copy to clipboard operation
liveblocks copied to clipboard

Delete/Clear Rooms Button on the Dashboard

Open AbdullahAhmadAAK opened this issue 9 months ago • 4 comments

Is your feature request related to a problem? Please describe.

I have 255 rooms built during development on the production site. I want to be able to clear them all with the click of a button. Could you guys please incorporate that into the dashboard so that it's easier to do? It would mean a lot : )

Describe the solution you'd like

A button to remove all rooms.

Additional context

This is how my dashboard looks like :'D

Image

AbdullahAhmadAAK avatar Apr 08 '25 17:04 AbdullahAhmadAAK

We can add a "Select All" button to bulk delete all the rooms. Should I go ahead and try this?

imsidkg avatar Apr 20 '25 21:04 imsidkg

That would be great! I'm running into the same issue during development and would love a way to easily clear all rooms.

Flame1994 avatar May 07 '25 07:05 Flame1994

Oh btw if anyone does want to use this functionality, the following snippet will do wonders:

This is the fetch-all-rooms.ts file:

type FetchRoomFilters = {
  isDrawingCompleted?: MetadataBooleanStatusKey | null;
  isLive?: MetadataBooleanStatusKey | null;
  isPopular?: MetadataBooleanStatusKey | null;
  isRecentlyCompleted?: MetadataBooleanStatusKey | null;
};

/** 
 * This will continuously ping liveblocks for more rooms' data until liveblocks declares that these are indeed all the records in the db.
 * It will either fetch rooms marked according to the provided metadata keys.
 *  */
export const fetchAllRooms = async ({
  isDrawingCompleted = null,
  isLive = null,
  isPopular = null,
  isRecentlyCompleted = null,
}: FetchRoomFilters = {}): Promise<RoomData[]> => {
  let isLastPage = false;
  let nextCursor: NextCursor = null;
  const allRooms: RoomData[] = [];

  try {
    while (!isLastPage) {
      const queryMetadata = buildMetadataQuery({
        isDrawingCompleted,
        isLive,
        isPopular,
        isRecentlyCompleted,
      });

      const getRoomParams: GetRoomParams = {
        limit: 100,
        query: {
          /** This roomId is referenced in our codebase as the room identifier or the room name */
          roomId: { startsWith: ROOM_NAME_PREFIX },
          metadata: queryMetadata,
        },
        ...(nextCursor && { startingAfter: nextCursor }),
      };

      const { data: rooms, nextCursor: newCursor } = await liveblocks.getRooms(getRoomParams);
      allRooms.push(...rooms);
      nextCursor = newCursor;
      isLastPage = !newCursor;
    }

    return allRooms;
  } catch (error) {
    console.error("Error fetching rooms:", error);
    return [];
  }
};

// Helper to build metadata query object
const buildMetadataQuery = (filters: FetchRoomFilters) => {
  const metadataQuery: Record<string, MetadataBooleanStatusKey> = {};
  for (const [key, value] of Object.entries(filters)) {
    if (value !== null && value !== undefined) {
      metadataQuery[key] = value;
    }
  }
  return metadataQuery;
};

And then, in a DELETE endpoint, we can just use these:

   // Step 1 -- get all the incomplete rooms 
        const totalRooms = await fetchAllRooms()

        // Step 2 -- store their IDs in a list
        const filteredRoomsIds = totalRooms.map(room => room.id)

        // Step 3 -- delete all filtered rooms concurrently
        await Promise.all(
            filteredRoomsIds.map((roomId) => liveblocks.deleteRoom(roomId))
        );

AbdullahAhmadAAK avatar May 07 '25 08:05 AbdullahAhmadAAK

Using the latest @liveblocks/node, you can do it with this snippet:

import { Liveblocks } from "./index";

const liveblocks = new Liveblocks({ secret: "sk_xxx" });

for await (const room of liveblocks.iterRooms({/* filter criteria here */})) {
  await liveblocks.deleteRoom(room.id);
}

nvie avatar May 07 '25 08:05 nvie