diff --git a/src/common/types.ts b/src/common/types.ts index 1a33e75..116709d 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -19,7 +19,9 @@ export type Connection = { } export type Exchange = { + connectionId: string name: string + hidden: boolean } export type Queue = { diff --git a/src/main/RabbitConnection.ts b/src/main/RabbitConnection.ts index 7a9bb36..3ea2566 100644 --- a/src/main/RabbitConnection.ts +++ b/src/main/RabbitConnection.ts @@ -1,4 +1,4 @@ -import { Connection, Queue } from '@common/types' +import { Connection, Exchange, Queue } from '@common/types' import { AMQPChannel, AMQPClient } from '@cloudamqp/amqp-client' import { ulid } from 'ulid' import axios from 'axios' @@ -9,6 +9,7 @@ export class RabbitConnection { private client: AMQPClient private channel: AMQPChannel | null = null private queues: Queue[] = [] + private exchanges: Exchange[] = [] constructor(private connection: Connection) { this.client = new AMQPClient( @@ -44,17 +45,22 @@ export class RabbitConnection { } }) - const exchanges = response.data + // this.exchanges might already have exchanges, so we need to merge some of them. + // But, we want to re-create the list of exchanges from the response. + this.exchanges = response.data .filter((exchange: any) => { return exchange.internal === false && exchange.name !== '' }) .map((exchange: any) => { return { - name: exchange.name + name: exchange.name, + connectionId: this.connection.id, + // Look up the hidden state from the existing exchanges + hidden: this.exchanges.find((e) => e.name === exchange.name)?.hidden || false } }) - return exchanges + return this.exchanges } public async createQueue({ name, exchange, bindOptions }) { @@ -112,17 +118,36 @@ export class RabbitConnection { this.queues = this.queues.filter((q) => q.id !== queue.id) } - public async loadState(state: { queues: Queue[] }) { + public async loadState(state: { queues: Queue[], exchanges: Exchange[] }) { for (const queue of state.queues) { await this.createQueue(queue) } + this.exchanges = state.exchanges || [] + return this.getState() } + public hideExchange(exchange: Exchange) { + const existingExchange = this.exchanges.find((e) => e.name === exchange.name) + if (!existingExchange) { + throw new Error('Exchange not found') + } + existingExchange.hidden = true + } + + public unhideExchange(exchange: Exchange) { + const existingExchange = this.exchanges.find((e) => e.name === exchange.name) + if (!existingExchange) { + throw new Error('Exchange not found') + } + existingExchange.hidden = false + } + public getState() { return { - queues: this.queues + queues: this.queues, + exchanges: this.exchanges } } } diff --git a/src/main/index.ts b/src/main/index.ts index 0a7438b..a5753a2 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -146,3 +146,19 @@ ipcMain.handle('rabbit-delete-queue', async (_, queue) => { return await rabbitConnection.deleteQueue(queue) }) + +ipcMain.handle('rabbit-exchange-hide', async (_, exchange) => { + if (!rabbitConnection) { + throw new Error('Not connected to RabbitMQ') + } + + return rabbitConnection.hideExchange(exchange) +}) + +ipcMain.handle('rabbit-exchange-unhide', async (_, exchange) => { + if (!rabbitConnection) { + throw new Error('Not connected to RabbitMQ') + } + + return rabbitConnection.unhideExchange(exchange) +}) diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index 62c5193..2c4a98e 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -14,9 +14,12 @@ declare global { connect(options: RabbitOptions): Promise<{ queues: Queue[] }> disconnect(): Promise listExchanges(): Promise + hideExchange(exchange: Exchange): Promise + unHideExchange(exchange: Exchange): Promise addQueue(name: string, exchange: string, bindOptions: any): Promise deleteQueue(queue: Queue): Promise onMessage(callback: (message: Message) => void): void + removeMessageListener(): void } } } diff --git a/src/preload/index.ts b/src/preload/index.ts index 08f3e92..aa7ef4e 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -1,6 +1,6 @@ import { contextBridge } from 'electron' import { electronAPI } from '@electron-toolkit/preload' -import { Connection, Queue, RabbitOptions } from '../common/types' +import { Connection, Exchange, Queue, RabbitOptions } from '../common/types' // Custom APIs for renderer const api = { @@ -25,6 +25,12 @@ const api = { async listExchanges() { return await electronAPI.ipcRenderer.invoke('rabbit-list-exchanges') }, + async hideExchange(exchange: Exchange) { + return await electronAPI.ipcRenderer.invoke('rabbit-exchange-hide', exchange) + }, + async unHideExchange(exchange: Exchange) { + return await electronAPI.ipcRenderer.invoke('rabbit-exchange-unhide', exchange) + }, async addQueue(name: string, exchange: string, bindOptions: any) { return await electronAPI.ipcRenderer.invoke('rabbit-add-queue', { name, exchange, bindOptions }) }, @@ -34,7 +40,8 @@ const api = { onMessage: (callback) => electronAPI.ipcRenderer.on('rabbit-message-received', (_, args) => { callback(args) - }) + }), + removeMessageListener: () => electronAPI.ipcRenderer.removeAllListeners('rabbit-message-received') } } diff --git a/src/renderer/src/components/ExchangeList.svelte b/src/renderer/src/components/ExchangeList.svelte index da92098..f4a88c7 100644 --- a/src/renderer/src/components/ExchangeList.svelte +++ b/src/renderer/src/components/ExchangeList.svelte @@ -1,14 +1,31 @@ - -{#each $exchanges as exchange} +{#each $exchanges.filter((e) => !e.hidden) as exchange} {/each} diff --git a/src/renderer/src/routes/Connections.svelte b/src/renderer/src/routes/Connections.svelte index 980321f..0b1d04d 100644 --- a/src/renderer/src/routes/Connections.svelte +++ b/src/renderer/src/routes/Connections.svelte @@ -74,7 +74,7 @@ // await api.rabbit.disconnect(connection) $selectedConnection = null } - $selectedExchange = $exchanges[0] || null + $selectedExchange = $exchanges.find((e) => !e.hidden) || null } catch (e) { error = `Failed to open connection '${connection.name}'. Check your details and try again.` } diff --git a/src/renderer/src/routes/QueueView.svelte b/src/renderer/src/routes/QueueView.svelte index 46e0fe1..8887f2b 100644 --- a/src/renderer/src/routes/QueueView.svelte +++ b/src/renderer/src/routes/QueueView.svelte @@ -1,13 +1,14 @@
@@ -55,6 +74,12 @@

Exchanges

+ {#if hiddenExchangeCount > 0} +
{hiddenExchangeCount} Exchanges + Hidden. + +
+ {/if}
@@ -79,7 +104,9 @@
{/each} - + {#if $selectedExchange} + + {/if} diff --git a/src/renderer/src/stores/exchange.ts b/src/renderer/src/stores/exchange.ts index e112d68..3a28a03 100644 --- a/src/renderer/src/stores/exchange.ts +++ b/src/renderer/src/stores/exchange.ts @@ -4,3 +4,4 @@ import { writable } from 'svelte/store' export const exchanges = writable([]) export const selectedExchange = writable(null) +