From 6c1547a4fb37e191280f1524ad78261d85d8b5ad Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Wed, 13 Mar 2024 13:10:55 +0200 Subject: [PATCH] feat: add type definition to signal recipients follows more the notifications way of setting recipients and is more future proof Signed-off-by: Heikki Hellgren --- .changeset/dirty-hotels-sniff.md | 10 ++++++++++ plugins/notifications-backend/src/service/router.ts | 6 +++--- .../signals-backend/src/service/SignalManager.test.ts | 6 +++--- plugins/signals-backend/src/service/SignalManager.ts | 11 +++++++---- .../signals-backend/src/service/standaloneServer.ts | 2 +- plugins/signals-node/README.md | 6 +++--- plugins/signals-node/api-report.md | 9 ++++++++- .../signals-node/src/DefaultSignalsService.test.ts | 5 +++-- plugins/signals-node/src/types.ts | 4 +++- 9 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 .changeset/dirty-hotels-sniff.md diff --git a/.changeset/dirty-hotels-sniff.md b/.changeset/dirty-hotels-sniff.md new file mode 100644 index 0000000000..6d7e97da78 --- /dev/null +++ b/.changeset/dirty-hotels-sniff.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-signals-backend': minor +'@backstage/plugin-signals-node': minor +--- + +**BREAKING** Type definition added to signal recipients + +Update to use `{type: 'broadcast'}` instead `null` and `{type: 'user', entityRefs: ''}` +instead string entity references diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index 4a24763e40..84960176ab 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -286,7 +286,7 @@ export async function createRouter( if (signals) { await signals.publish({ - recipients: [user], + recipients: { type: 'user', entityRefs: [user] }, message: { action: 'notification_read', notification_ids: ids }, channel: 'notifications', }); @@ -296,7 +296,7 @@ export async function createRouter( if (signals) { await signals.publish({ - recipients: [user], + recipients: { type: 'user', entityRefs: [user] }, message: { action: 'notification_unread', notification_ids: ids }, channel: 'notifications', }); @@ -400,7 +400,7 @@ export async function createRouter( if (signals) { await signals.publish({ - recipients: user, + recipients: { type: 'user', entityRefs: [user] }, message: { action: 'new_notification', notification_id: ret.id, diff --git a/plugins/signals-backend/src/service/SignalManager.test.ts b/plugins/signals-backend/src/service/SignalManager.test.ts index e6d0cab21b..f76d18079a 100644 --- a/plugins/signals-backend/src/service/SignalManager.test.ts +++ b/plugins/signals-backend/src/service/SignalManager.test.ts @@ -89,7 +89,7 @@ describe('SignalManager', () => { await onEvent({ topic: 'signals', eventPayload: { - recipients: null, + recipients: { type: 'broadcast' }, channel: 'test', message: { msg: 'test' }, }, @@ -109,7 +109,7 @@ describe('SignalManager', () => { await onEvent({ topic: 'signals', eventPayload: { - recipients: null, + recipients: { type: 'broadcast' }, channel: 'test', message: { msg: 'test' }, }, @@ -152,7 +152,7 @@ describe('SignalManager', () => { await onEvent({ topic: 'signals', eventPayload: { - recipients: 'user:default/john.doe', + recipients: { type: 'user', entityRefs: 'user:default/john.doe' }, channel: 'test', message: { msg: 'test' }, }, diff --git a/plugins/signals-backend/src/service/SignalManager.ts b/plugins/signals-backend/src/service/SignalManager.ts index 775af143f4..46995ee27c 100644 --- a/plugins/signals-backend/src/service/SignalManager.ts +++ b/plugins/signals-backend/src/service/SignalManager.ts @@ -134,8 +134,10 @@ export class SignalManager { const { channel, recipients, message } = eventPayload; const jsonMessage = JSON.stringify({ channel, message }); let users: string[] = []; - if (recipients !== null) { - users = Array.isArray(recipients) ? recipients : [recipients]; + if (recipients.type === 'user') { + users = Array.isArray(recipients.entityRefs) + ? recipients.entityRefs + : [recipients.entityRefs]; } // Actual websocket message sending @@ -143,9 +145,10 @@ export class SignalManager { if (!conn.subscriptions.has(channel)) { return; } - // Sending to all users can be done with null + + // Sending to all users can be done with broadcast if ( - recipients !== null && + recipients.type !== 'broadcast' && !conn.ownershipEntityRefs.some((ref: string) => users.includes(ref)) ) { return; diff --git a/plugins/signals-backend/src/service/standaloneServer.ts b/plugins/signals-backend/src/service/standaloneServer.ts index c92ab3797e..efb7ecedee 100644 --- a/plugins/signals-backend/src/service/standaloneServer.ts +++ b/plugins/signals-backend/src/service/standaloneServer.ts @@ -97,7 +97,7 @@ export async function startStandaloneServer( setInterval(() => { signals.publish({ - recipients: null, + recipients: { type: 'broadcast' }, channel: 'test', message: { hello: 'world' }, }); diff --git a/plugins/signals-node/README.md b/plugins/signals-node/README.md index c8b056577a..8d536e3955 100644 --- a/plugins/signals-node/README.md +++ b/plugins/signals-node/README.md @@ -91,13 +91,13 @@ To allow connections from the frontend, you should also install the `@backstage/ Once you have both of the backend plugins installed, you can utilize the signal service by calling the `publish` method. This will publish the message to all subscribers in the frontend. To send message to -all subscribers, you can use `null` as `recipients` parameter. +all subscribers, you can use `broadcast` type: ```ts // Periodic sending example setInterval(async () => { await signals.publish({ - recipients: null, + recipients: { type: 'broadcast' }, channel: 'my_plugin', message: { message: 'hello world', @@ -118,7 +118,7 @@ to work: eventBroker.publish({ topic: 'signals', eventPayload: { - recipients: ['user:default/user1'], + recipients: { type: 'user', entityRefs: ['user:default/user1'] }, message: { message: 'hello world', }, diff --git a/plugins/signals-node/api-report.md b/plugins/signals-node/api-report.md index 16f6277ff2..4d94fb07d9 100644 --- a/plugins/signals-node/api-report.md +++ b/plugins/signals-node/api-report.md @@ -21,7 +21,14 @@ export class DefaultSignalsService implements SignalsService { // @public (undocumented) export type SignalPayload = { - recipients: string[] | string | null; + recipients: + | { + type: 'user'; + entityRefs: string | string[]; + } + | { + type: 'broadcast'; + }; channel: string; message: TMessage; }; diff --git a/plugins/signals-node/src/DefaultSignalsService.test.ts b/plugins/signals-node/src/DefaultSignalsService.test.ts index 194b3c0077..982ca20d53 100644 --- a/plugins/signals-node/src/DefaultSignalsService.test.ts +++ b/plugins/signals-node/src/DefaultSignalsService.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { DefaultSignalsService } from './DefaultSignalsService'; +import { SignalPayload } from './types'; describe('DefaultSignalsService', () => { const mockEvents = { @@ -24,9 +25,9 @@ describe('DefaultSignalsService', () => { const service = DefaultSignalsService.create({ events: mockEvents }); it('should publish signal', () => { - const signal = { + const signal: SignalPayload = { channel: 'test-channel', - recipients: null, + recipients: { type: 'broadcast' }, message: { msg: 'hello world' }, }; service.publish(signal); diff --git a/plugins/signals-node/src/types.ts b/plugins/signals-node/src/types.ts index 9ea5ffa031..0225e23916 100644 --- a/plugins/signals-node/src/types.ts +++ b/plugins/signals-node/src/types.ts @@ -25,7 +25,9 @@ export type SignalsServiceOptions = { /** @public */ export type SignalPayload = { - recipients: string[] | string | null; + recipients: + | { type: 'user'; entityRefs: string | string[] } + | { type: 'broadcast' }; channel: string; message: TMessage; };